diff options
35 files changed, 1010 insertions, 80 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 109d49f57d..8f910f39a3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -450,9 +450,15 @@ config TARGET_SUN4I config TARGET_SUN5I bool "Support sun5i" +config TARGET_SUN6I + bool "Support sun6i" + config TARGET_SUN7I bool "Support sun7i" +config TARGET_SUN8I + bool "Support sun8i" + config TARGET_SNOWBALL bool "Support snowball" diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index e9721b27b6..24f1daee64 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -11,9 +11,13 @@ obj-y += timer.o obj-y += board.o obj-y += clock.o obj-y += pinmux.o +obj-$(CONFIG_SUN6I) += prcm.o +obj-$(CONFIG_SUN8I) += prcm.o obj-$(CONFIG_SUN4I) += clock_sun4i.o obj-$(CONFIG_SUN5I) += clock_sun4i.o +obj-$(CONFIG_SUN6I) += clock_sun6i.o obj-$(CONFIG_SUN7I) += clock_sun4i.o +obj-$(CONFIG_SUN8I) += clock_sun6i.o ifndef CONFIG_SPL_BUILD obj-y += cpu_info.o diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index f2cedbb156..06eb6768e8 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -50,18 +50,35 @@ u32 spl_boot_mode(void) int gpio_init(void) { -#if CONFIG_CONS_INDEX == 1 && (defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)) +#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F) +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I) + /* disable GPB22,23 as uart0 tx,rx to avoid conflict */ + sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUNXI_GPIO_INPUT); + sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUNXI_GPIO_INPUT); +#endif + sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUNXI_GPF2_UART0_TX); + sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF4_UART0_RX); + sunxi_gpio_set_pull(SUNXI_GPF(4), 1); +#elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)) sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB22_UART0_TX); sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB23_UART0_RX); - sunxi_gpio_set_pull(SUNXI_GPB(23), 1); + sunxi_gpio_set_pull(SUNXI_GPB(23), SUNXI_GPIO_PULL_UP); #elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN5I) sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN5I_GPB19_UART0_TX); sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN5I_GPB20_UART0_RX); - sunxi_gpio_set_pull(SUNXI_GPB(20), 1); + sunxi_gpio_set_pull(SUNXI_GPB(20), SUNXI_GPIO_PULL_UP); +#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN6I) + sunxi_gpio_set_cfgpin(SUNXI_GPH(20), SUN6I_GPH20_UART0_TX); + sunxi_gpio_set_cfgpin(SUNXI_GPH(21), SUN6I_GPH21_UART0_RX); + sunxi_gpio_set_pull(SUNXI_GPH(21), SUNXI_GPIO_PULL_UP); #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_SUN5I) sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG3_UART1_TX); sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG4_UART1_RX); - sunxi_gpio_set_pull(SUNXI_GPG(4), 1); + sunxi_gpio_set_pull(SUNXI_GPG(4), SUNXI_GPIO_PULL_UP); +#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_SUN8I) + sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL2_R_UART_TX); + sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL3_R_UART_RX); + sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP); #else #error Unsupported console port number. Please fix pin mux settings in board.c #endif @@ -71,6 +88,7 @@ int gpio_init(void) void reset_cpu(ulong addr) { +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) static const struct sunxi_wdog *wdog = &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; @@ -82,12 +100,22 @@ void reset_cpu(ulong addr) /* sun5i sometimes gets stuck without this */ writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); } +#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */ + static const struct sunxi_wdog *wdog = + ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; + + /* Set the watchdog for its shortest interval (.5s) and wait */ + writel(WDT_CFG_RESET, &wdog->cfg); + writel(WDT_MODE_EN, &wdog->mode); + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); +#endif } /* do some early init */ void s_init(void) { -#if !defined CONFIG_SPL_BUILD && (defined CONFIG_SUN7I || defined CONFIG_SUN6I) +#if !defined CONFIG_SPL_BUILD && (defined CONFIG_SUN7I || \ + defined CONFIG_SUN6I || defined CONFIG_SUN8I) /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */ asm volatile( "mrc p15, 0, r0, c1, c0, 1\n" diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c index ecbdb0162b..4a0d64fb30 100644 --- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c +++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c @@ -180,6 +180,17 @@ void clock_set_pll1(unsigned int hz) } #endif +unsigned int clock_get_pll5p(void) +{ + struct sunxi_ccm_reg *const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + uint32_t rval = readl(&ccm->pll5_cfg); + int n = ((rval & CCM_PLL5_CTRL_N_MASK) >> CCM_PLL5_CTRL_N_SHIFT); + int k = ((rval & CCM_PLL5_CTRL_K_MASK) >> CCM_PLL5_CTRL_K_SHIFT) + 1; + int p = ((rval & CCM_PLL5_CTRL_P_MASK) >> CCM_PLL5_CTRL_P_SHIFT); + return (24000000 * n * k) >> p; +} + unsigned int clock_get_pll6(void) { struct sunxi_ccm_reg *const ccm = diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c new file mode 100644 index 0000000000..1eae9767d0 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c @@ -0,0 +1,76 @@ +/* + * sun6i specific clock code + * + * (C) Copyright 2007-2012 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/prcm.h> +#include <asm/arch/sys_proto.h> + +void clock_init_uart(void) +{ + struct sunxi_ccm_reg *const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + +#if CONFIG_CONS_INDEX < 5 + /* uart clock source is apb2 */ + writel(APB2_CLK_SRC_OSC24M| + APB2_CLK_RATE_N_1| + APB2_CLK_RATE_M(1), + &ccm->apb2_div); + + /* open the clock for uart */ + setbits_le32(&ccm->apb2_gate, + CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT + + CONFIG_CONS_INDEX - 1)); + + /* deassert uart reset */ + setbits_le32(&ccm->apb2_reset_cfg, + 1 << (APB2_RESET_UART_SHIFT + + CONFIG_CONS_INDEX - 1)); +#else + /* enable R_PIO and R_UART clocks, and de-assert resets */ + prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART); +#endif + + /* Dup with clock_init_safe(), drop once sun6i SPL support lands */ + writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg); +} + +int clock_twi_onoff(int port, int state) +{ + struct sunxi_ccm_reg *const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + + if (port > 3) + return -1; + + /* set the apb clock gate for twi */ + if (state) + setbits_le32(&ccm->apb2_gate, + CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port)); + else + clrbits_le32(&ccm->apb2_gate, + CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port)); + + return 0; +} + +unsigned int clock_get_pll6(void) +{ + struct sunxi_ccm_reg *const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + uint32_t rval = readl(&ccm->pll6_cfg); + int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1; + int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1; + return 24000000 * n * k / 2; +} diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index 5cf35acc1e..4f2a09cd2e 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -23,8 +23,12 @@ int print_cpuinfo(void) case 7: puts("CPU: Allwinner A10s (SUN5I)\n"); break; default: puts("CPU: Allwinner A1X (SUN5I)\n"); } +#elif defined CONFIG_SUN6I + puts("CPU: Allwinner A31 (SUN6I)\n"); #elif defined CONFIG_SUN7I puts("CPU: Allwinner A20 (SUN7I)\n"); +#elif defined CONFIG_SUN8I + puts("CPU: Allwinner A23 (SUN8I)\n"); #else #warning Please update cpu_info.c with correct CPU information puts("CPU: SUNXI Family\n"); diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c index 584f7420d7..3cf3cbf19a 100644 --- a/arch/arm/cpu/armv7/sunxi/dram.c +++ b/arch/arm/cpu/armv7/sunxi/dram.c @@ -252,15 +252,9 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk) { u32 reg_val; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* PLL5P and PLL6 are the potential clock sources for MBUS */ - u32 pll6x_div, pll5p_div; - u32 pll6x_clk = clock_get_pll6() / 1000000; - u32 pll5p_clk = clk / 24 * 48; + u32 pll5p_clk, pll6x_clk; + u32 pll5p_div, pll6x_div; u32 pll5p_rate, pll6x_rate; -#ifdef CONFIG_SUN7I - pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */ -#endif /* setup DRAM PLL */ reg_val = readl(&ccm->pll5_cfg); @@ -268,33 +262,32 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk) reg_val &= ~CCM_PLL5_CTRL_K_MASK; /* set K to 0 (x1) */ reg_val &= ~CCM_PLL5_CTRL_N_MASK; /* set N to 0 (x0) */ reg_val &= ~CCM_PLL5_CTRL_P_MASK; /* set P to 0 (x1) */ +#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT + /* Old kernels are hardcoded to P=1 (divide by 2) */ + reg_val |= CCM_PLL5_CTRL_P(1); +#endif if (clk >= 540 && clk < 552) { - /* dram = 540MHz, pll5p = 1080MHz */ - pll5p_clk = 1080; + /* dram = 540MHz */ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15)); } else if (clk >= 512 && clk < 528) { - /* dram = 512MHz, pll5p = 1536MHz */ - pll5p_clk = 1536; + /* dram = 512MHz */ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3)); reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4)); reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16)); } else if (clk >= 496 && clk < 504) { - /* dram = 496MHz, pll5p = 1488MHz */ - pll5p_clk = 1488; + /* dram = 496MHz */ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3)); reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2)); reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31)); } else if (clk >= 468 && clk < 480) { - /* dram = 468MHz, pll5p = 936MHz */ - pll5p_clk = 936; + /* dram = 468MHz */ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13)); } else if (clk >= 396 && clk < 408) { - /* dram = 396MHz, pll5p = 792MHz */ - pll5p_clk = 792; + /* dram = 396MHz */ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11)); @@ -322,6 +315,13 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk) /* setup MBUS clock */ if (!mbus_clk) mbus_clk = 300; + + /* PLL5P and PLL6 are the potential clock sources for MBUS */ + pll6x_clk = clock_get_pll6() / 1000000; +#ifdef CONFIG_SUN7I + pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */ +#endif + pll5p_clk = clock_get_pll5p() / 1000000; pll6x_div = DIV_ROUND_UP(pll6x_clk, mbus_clk); pll5p_div = DIV_ROUND_UP(pll5p_clk, mbus_clk); pll6x_rate = pll6x_clk / pll6x_div; diff --git a/arch/arm/cpu/armv7/sunxi/prcm.c b/arch/arm/cpu/armv7/sunxi/prcm.c new file mode 100644 index 0000000000..19b4938dc9 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/prcm.c @@ -0,0 +1,35 @@ +/* + * Sunxi A31 Power Management Unit + * + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> + * http://linux-sunxi.org + * + * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work + * + * (C) Copyright 2006-2013 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Berg Xing <bergxing@allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/prcm.h> +#include <asm/arch/sys_proto.h> + +/* APB0 clock gate and reset bit offsets are the same. */ +void prcm_apb0_enable(u32 flags) +{ + struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; + + /* open the clock for module */ + setbits_le32(&prcm->apb0_gate, flags); + + /* deassert reset for module */ + setbits_le32(&prcm->apb0_reset, flags); +} diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h index 5669f392fa..c562f621c2 100644 --- a/arch/arm/include/asm/arch-sunxi/clock.h +++ b/arch/arm/include/asm/arch-sunxi/clock.h @@ -15,12 +15,17 @@ #define CLK_GATE_CLOSE 0x0 /* clock control module regs definition */ +#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I) +#include <asm/arch/clock_sun6i.h> +#else #include <asm/arch/clock_sun4i.h> +#endif #ifndef __ASSEMBLY__ int clock_init(void); int clock_twi_onoff(int port, int state); void clock_set_pll1(unsigned int hz); +unsigned int clock_get_pll5p(void); unsigned int clock_get_pll6(void); void clock_init_safe(void); void clock_init_uart(void); diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h index 1ba997adf9..90af8e2506 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h @@ -199,13 +199,16 @@ struct sunxi_ccm_reg { #define CCM_PLL5_CTRL_M1_MASK CCM_PLL5_CTRL_M1(0x3) #define CCM_PLL5_CTRL_M1_X(n) ((n) - 1) #define CCM_PLL5_CTRL_K(n) (((n) & 0x3) << 4) +#define CCM_PLL5_CTRL_K_SHIFT 4 #define CCM_PLL5_CTRL_K_MASK CCM_PLL5_CTRL_K(0x3) #define CCM_PLL5_CTRL_K_X(n) ((n) - 1) #define CCM_PLL5_CTRL_LDO (0x1 << 7) #define CCM_PLL5_CTRL_N(n) (((n) & 0x1f) << 8) +#define CCM_PLL5_CTRL_N_SHIFT 8 #define CCM_PLL5_CTRL_N_MASK CCM_PLL5_CTRL_N(0x1f) #define CCM_PLL5_CTRL_N_X(n) (n) #define CCM_PLL5_CTRL_P(n) (((n) & 0x3) << 16) +#define CCM_PLL5_CTRL_P_SHIFT 16 #define CCM_PLL5_CTRL_P_MASK CCM_PLL5_CTRL_P(0x3) #define CCM_PLL5_CTRL_P_X(n) ((n) - 1) #define CCM_PLL5_CTRL_BW (0x1 << 18) diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h new file mode 100644 index 0000000000..1397b35889 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -0,0 +1,205 @@ +/* + * sun6i clock register definitions + * + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_CLOCK_SUN6I_H +#define _SUNXI_CLOCK_SUN6I_H + +struct sunxi_ccm_reg { + u32 pll1_cfg; /* 0x00 pll1 control */ + u32 reserved0; + u32 pll2_cfg; /* 0x08 pll2 control */ + u32 reserved1; + u32 pll3_cfg; /* 0x10 pll3 control */ + u32 reserved2; + u32 pll4_cfg; /* 0x18 pll4 control */ + u32 reserved3; + u32 pll5_cfg; /* 0x20 pll5 control */ + u32 reserved4; + u32 pll6_cfg; /* 0x28 pll6 control */ + u32 reserved5; + u32 pll7_cfg; /* 0x30 pll7 control */ + u32 reserved6; + u32 pll8_cfg; /* 0x38 pll8 control */ + u32 reserved7; + u32 mipi_pll_cfg; /* 0x40 MIPI pll control */ + u32 pll9_cfg; /* 0x44 pll9 control */ + u32 pll10_cfg; /* 0x48 pll10 control */ + u32 reserved8; + u32 cpu_axi_cfg; /* 0x50 CPU/AXI divide ratio */ + u32 ahb1_apb1_div; /* 0x54 AHB1/APB1 divide ratio */ + u32 apb2_div; /* 0x58 APB2 divide ratio */ + u32 axi_gate; /* 0x5c axi module clock gating */ + u32 ahb_gate0; /* 0x60 ahb module clock gating 0 */ + u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */ + u32 apb1_gate; /* 0x68 apb1 module clock gating */ + u32 apb2_gate; /* 0x6c apb2 module clock gating */ + u32 reserved9[4]; + u32 nand0_clk_cfg; /* 0x80 nand0 clock control */ + u32 nand1_clk_cfg; /* 0x84 nand1 clock control */ + u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ + u32 sd1_clk_cfg; /* 0x8c sd1 clock control */ + u32 sd2_clk_cfg; /* 0x90 sd2 clock control */ + u32 sd3_clk_cfg; /* 0x94 sd3 clock control */ + u32 ts_clk_cfg; /* 0x98 transport stream clock control */ + u32 ss_clk_cfg; /* 0x9c security system clock control */ + u32 spi0_clk_cfg; /* 0xa0 spi0 clock control */ + u32 spi1_clk_cfg; /* 0xa4 spi1 clock control */ + u32 spi2_clk_cfg; /* 0xa8 spi2 clock control */ + u32 spi3_clk_cfg; /* 0xac spi3 clock control */ + u32 i2s0_clk_cfg; /* 0xb0 I2S0 clock control*/ + u32 i2s1_clk_cfg; /* 0xb4 I2S1 clock control */ + u32 reserved10[2]; + u32 spdif_clk_cfg; /* 0xc0 SPDIF clock control */ + u32 reserved11[2]; + u32 usb_clk_cfg; /* 0xcc USB clock control */ + u32 gmac_clk_cfg; /* 0xd0 GMAC clock control */ + u32 reserved12[7]; + u32 mdfs_clk_cfg; /* 0xf0 MDFS clock control */ + u32 dram_clk_cfg; /* 0xf4 DRAM configuration clock control */ + u32 reserved13[2]; + u32 dram_clk_gate; /* 0x100 DRAM module gating */ + u32 be0_clk_cfg; /* 0x104 BE0 module clock */ + u32 be1_clk_cfg; /* 0x108 BE1 module clock */ + u32 fe0_clk_cfg; /* 0x10c FE0 module clock */ + u32 fe1_clk_cfg; /* 0x110 FE1 module clock */ + u32 mp_clk_cfg; /* 0x114 MP module clock */ + u32 lcd0_ch0_clk_cfg; /* 0x118 LCD0 CH0 module clock */ + u32 lcd1_ch0_clk_cfg; /* 0x11c LCD1 CH0 module clock */ + u32 reserved14[3]; + u32 lcd0_ch1_clk_cfg; /* 0x12c LCD0 CH1 module clock */ + u32 lcd1_ch1_clk_cfg; /* 0x130 LCD1 CH1 module clock */ + u32 csi0_clk_cfg; /* 0x134 CSI0 module clock */ + u32 csi1_clk_cfg; /* 0x138 CSI1 module clock */ + u32 ve_clk_cfg; /* 0x13c VE module clock */ + u32 adda_clk_cfg; /* 0x140 ADDA module clock */ + u32 avs_clk_cfg; /* 0x144 AVS module clock */ + u32 dmic_clk_cfg; /* 0x148 Digital Mic module clock*/ + u32 reserved15; + u32 hdmi_clk_cfg; /* 0x150 HDMI module clock */ + u32 ps_clk_cfg; /* 0x154 PS module clock */ + u32 mtc_clk_cfg; /* 0x158 MTC module clock */ + u32 mbus0_clk_cfg; /* 0x15c MBUS0 module clock */ + u32 mbus1_clk_cfg; /* 0x160 MBUS1 module clock */ + u32 reserved16; + u32 mipi_dsi_clk_cfg; /* 0x168 MIPI DSI clock control */ + u32 mipi_csi_clk_cfg; /* 0x16c MIPI CSI clock control */ + u32 reserved17[4]; + u32 iep_drc0_clk_cfg; /* 0x180 IEP DRC0 module clock */ + u32 iep_drc1_clk_cfg; /* 0x184 IEP DRC1 module clock */ + u32 iep_deu0_clk_cfg; /* 0x188 IEP DEU0 module clock */ + u32 iep_deu1_clk_cfg; /* 0x18c IEP DEU1 module clock */ + u32 reserved18[4]; + u32 gpu_core_clk_cfg; /* 0x1a0 GPU core clock config */ + u32 gpu_mem_clk_cfg; /* 0x1a4 GPU memory clock config */ + u32 gpu_hyd_clk_cfg; /* 0x1a0 GPU HYD clock config */ + u32 reserved19[21]; + u32 pll_lock; /* 0x200 PLL Lock Time */ + u32 pll1_lock; /* 0x204 PLL1 Lock Time */ + u32 reserved20[6]; + u32 pll1_bias_cfg; /* 0x220 PLL1 Bias config */ + u32 pll2_bias_cfg; /* 0x224 PLL2 Bias config */ + u32 pll3_bias_cfg; /* 0x228 PLL3 Bias config */ + u32 pll4_bias_cfg; /* 0x22c PLL4 Bias config */ + u32 pll5_bias_cfg; /* 0x230 PLL5 Bias config */ + u32 pll6_bias_cfg; /* 0x234 PLL6 Bias config */ + u32 pll7_bias_cfg; /* 0x238 PLL7 Bias config */ + u32 pll8_bias_cfg; /* 0x23c PLL8 Bias config */ + u32 mipi_bias_cfg; /* 0x240 MIPI Bias config */ + u32 pll9_bias_cfg; /* 0x244 PLL9 Bias config */ + u32 pll10_bias_cfg; /* 0x248 PLL10 Bias config */ + u32 reserved21[13]; + u32 pll1_pattern_cfg; /* 0x280 PLL1 Pattern config */ + u32 pll2_pattern_cfg; /* 0x284 PLL2 Pattern config */ + u32 pll3_pattern_cfg; /* 0x288 PLL3 Pattern config */ + u32 pll4_pattern_cfg; /* 0x28c PLL4 Pattern config */ + u32 pll5_pattern_cfg; /* 0x290 PLL5 Pattern config */ + u32 pll6_pattern_cfg; /* 0x294 PLL6 Pattern config */ + u32 pll7_pattern_cfg; /* 0x298 PLL7 Pattern config */ + u32 pll8_pattern_cfg; /* 0x29c PLL8 Pattern config */ + u32 mipi_pattern_cfg; /* 0x2a0 MIPI Pattern config */ + u32 pll9_pattern_cfg; /* 0x2a4 PLL9 Pattern config */ + u32 pll10_pattern_cfg; /* 0x2a8 PLL10 Pattern config */ + u32 reserved22[5]; + u32 ahb_reset0_cfg; /* 0x2c0 AHB1 Reset 0 config */ + u32 ahb_reset1_cfg; /* 0x2c4 AHB1 Reset 1 config */ + u32 ahb_reset2_cfg; /* 0x2c8 AHB1 Reset 2 config */ + u32 reserved23; + u32 apb1_reset_cfg; /* 0x2d0 APB1 Reset config */ + u32 reserved24; + u32 apb2_reset_cfg; /* 0x2d8 APB2 Reset config */ +}; + +/* apb2 bit field */ +#define APB2_CLK_SRC_LOSC (0x0 << 24) +#define APB2_CLK_SRC_OSC24M (0x1 << 24) +#define APB2_CLK_SRC_PLL6 (0x2 << 24) +#define APB2_CLK_SRC_MASK (0x3 << 24) +#define APB2_CLK_RATE_N_1 (0x0 << 16) +#define APB2_CLK_RATE_N_2 (0x1 << 16) +#define APB2_CLK_RATE_N_4 (0x2 << 16) +#define APB2_CLK_RATE_N_8 (0x3 << 16) +#define APB2_CLK_RATE_N_MASK (3 << 16) +#define APB2_CLK_RATE_M(m) (((m)-1) << 0) +#define APB2_CLK_RATE_M_MASK (0x1f << 0) + +/* apb2 gate field */ +#define APB2_GATE_UART_SHIFT (16) +#define APB2_GATE_UART_MASK (0xff << APB2_GATE_UART_SHIFT) +#define APB2_GATE_TWI_SHIFT (0) +#define APB2_GATE_TWI_MASK (0xf << APB2_GATE_TWI_SHIFT) + +/* cpu_axi_cfg bits */ +#define AXI_DIV_SHIFT 0 +#define ATB_DIV_SHIFT 8 +#define CPU_CLK_SRC_SHIFT 16 + +#define AXI_DIV_1 0 +#define AXI_DIV_2 1 +#define AXI_DIV_3 2 +#define AXI_DIV_4 3 +#define ATB_DIV_1 0 +#define ATB_DIV_2 1 +#define ATB_DIV_4 2 +#define CPU_CLK_SRC_OSC24M 1 +#define CPU_CLK_SRC_PLL1 2 + +#define PLL1_CFG_DEFAULT 0x90011b21 + +#define PLL6_CFG_DEFAULT 0x90041811 + +#define CCM_PLL6_CTRL_N_SHIFT 8 +#define CCM_PLL6_CTRL_N_MASK (0x1f << CCM_PLL6_CTRL_N_SHIFT) +#define CCM_PLL6_CTRL_K_SHIFT 4 +#define CCM_PLL6_CTRL_K_MASK (0x3 << CCM_PLL6_CTRL_K_SHIFT) + +#define AHB_GATE_OFFSET_MMC3 11 +#define AHB_GATE_OFFSET_MMC2 10 +#define AHB_GATE_OFFSET_MMC1 9 +#define AHB_GATE_OFFSET_MMC0 8 +#define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n)) + +#define CCM_MMC_CTRL_OSCM24 (0x0 << 24) +#define CCM_MMC_CTRL_PLL6 (0x1 << 24) + +#define CCM_MMC_CTRL_ENABLE (0x1 << 31) + +#define AHB_RESET_OFFSET_MMC3 11 +#define AHB_RESET_OFFSET_MMC2 10 +#define AHB_RESET_OFFSET_MMC1 9 +#define AHB_RESET_OFFSET_MMC0 8 +#define AHB_RESET_OFFSET_MMC(n) (AHB_RESET_OFFSET_MMC0 + (n)) + +/* apb2 reset */ +#define APB2_RESET_UART_SHIFT (16) +#define APB2_RESET_UART_MASK (0xff << APB2_RESET_UART_SHIFT) +#define APB2_RESET_TWI_SHIFT (0) +#define APB2_RESET_TWI_MASK (0xf << APB2_RESET_TWI_SHIFT) + +#endif /* _SUNXI_CLOCK_SUN6I_H */ diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h index a987e51d57..0de79a0d50 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu.h +++ b/arch/arm/include/asm/arch-sunxi/cpu.h @@ -95,6 +95,11 @@ #define SUNXI_MALI400_BASE 0x01c40000 #define SUNXI_GMAC_BASE 0x01c50000 +#define SUNXI_DRAM_COM_BASE 0x01c62000 +#define SUNXI_DRAM_CTL_BASE 0x01c63000 +#define SUNXI_DRAM_PHY_CH1_BASE 0x01c65000 +#define SUNXI_DRAM_PHY_CH2_BASE 0x01c66000 + /* module sram */ #define SUNXI_SRAM_C_BASE 0x01d00000 @@ -105,6 +110,11 @@ #define SUNXI_MP_BASE 0x01e80000 #define SUNXI_AVG_BASE 0x01ea0000 +#define SUNXI_PRCM_BASE 0x01f01400 +#define SUNXI_R_UART_BASE 0x01f02800 +#define SUNXI_R_PIO_BASE 0x01f02c00 +#define SUNXI_P2WI_BASE 0x01f03400 + /* CoreSight Debug Module */ #define SUNXI_CSDM_BASE 0x3f500000 diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index f7f3d8c41a..7bb649950a 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -10,6 +10,7 @@ #define _SUNXI_GPIO_H #include <linux/types.h> +#include <asm/arch/cpu.h> /* * sunxi has 9 banks of gpio, they are: @@ -27,8 +28,27 @@ #define SUNXI_GPIO_G 6 #define SUNXI_GPIO_H 7 #define SUNXI_GPIO_I 8 + +/* + * This defines the number of GPIO banks for the _main_ GPIO controller. + * You should fix up the padding in struct sunxi_gpio_reg below if you + * change this. + */ #define SUNXI_GPIO_BANKS 9 +/* + * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO) + * at a different register offset. + * + * sun6i has 2 banks: + * PL0 - PL8 | PM0 - PM7 + * + * sun8i has 1 bank: + * PL0 - PL11 + */ +#define SUNXI_GPIO_L 11 +#define SUNXI_GPIO_M 12 + struct sunxi_gpio { u32 cfg[4]; u32 dat; @@ -50,8 +70,9 @@ struct sunxi_gpio_reg { struct sunxi_gpio_int gpio_int; }; -#define BANK_TO_GPIO(bank) \ - &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] +#define BANK_TO_GPIO(bank) (((bank) < SUNXI_GPIO_L) ? \ + &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \ + &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L]) #define GPIO_BANK(pin) ((pin) >> 5) #define GPIO_NUM(pin) ((pin) & 0x1f) @@ -75,6 +96,8 @@ struct sunxi_gpio_reg { #define SUNXI_GPIO_G_NR 32 #define SUNXI_GPIO_H_NR 32 #define SUNXI_GPIO_I_NR 32 +#define SUNXI_GPIO_L_NR 32 +#define SUNXI_GPIO_M_NR 32 #define SUNXI_GPIO_NEXT(__gpio) \ ((__gpio##_START) + (__gpio##_NR) + 0) @@ -89,6 +112,8 @@ enum sunxi_gpio_number { SUNXI_GPIO_G_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_F), SUNXI_GPIO_H_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_G), SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H), + SUNXI_GPIO_L_START = 352, + SUNXI_GPIO_M_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_L), }; /* SUNXI GPIO number definitions */ @@ -101,6 +126,8 @@ enum sunxi_gpio_number { #define SUNXI_GPG(_nr) (SUNXI_GPIO_G_START + (_nr)) #define SUNXI_GPH(_nr) (SUNXI_GPIO_H_START + (_nr)) #define SUNXI_GPI(_nr) (SUNXI_GPIO_I_START + (_nr)) +#define SUNXI_GPL(_nr) (SUNXI_GPIO_L_START + (_nr)) +#define SUNXI_GPM(_nr) (SUNXI_GPIO_M_START + (_nr)) /* GPIO pin function config */ #define SUNXI_GPIO_INPUT 0 @@ -117,6 +144,8 @@ enum sunxi_gpio_number { #define SUN5I_GPB19_UART0_TX 2 #define SUN5I_GPB20_UART0_RX 2 +#define SUN5I_GPG3_SDC1 2 + #define SUN5I_GPG3_UART1_TX 4 #define SUN5I_GPG4_UART1_RX 4 @@ -125,15 +154,27 @@ enum sunxi_gpio_number { #define SUNXI_GPF0_SDC0 2 #define SUNXI_GPF2_SDC0 2 + +#ifdef CONFIG_SUN8I +#define SUNXI_GPF2_UART0_TX 3 +#define SUNXI_GPF4_UART0_RX 3 +#else #define SUNXI_GPF2_UART0_TX 4 #define SUNXI_GPF4_UART0_RX 4 +#endif #define SUN4I_GPG0_SDC1 4 #define SUN4I_GPH22_SDC1 5 +#define SUN6I_GPH20_UART0_TX 2 +#define SUN6I_GPH21_UART0_RX 2 + #define SUN4I_GPI4_SDC3 2 +#define SUN8I_GPL2_R_UART_TX 2 +#define SUN8I_GPL3_R_UART_RX 2 + /* GPIO pin pull-up/down config */ #define SUNXI_GPIO_PULL_DISABLE 0 #define SUNXI_GPIO_PULL_UP 1 diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index 53196e3b02..8a216740a7 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -43,7 +43,10 @@ struct sunxi_mmc { u32 chda; /* 0x90 */ u32 cbda; /* 0x94 */ u32 res1[26]; - u32 fifo; /* 0x100 FIFO access address */ +#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I) + u32 res2[64]; +#endif + u32 fifo; /* 0x100 (0x200 on sun6i) FIFO access address */ }; #define SUNXI_MMC_CLK_POWERSAVE (0x1 << 17) @@ -120,5 +123,5 @@ struct sunxi_mmc { #define SUNXI_MMC_IDIE_TXIRQ (0x1 << 0) #define SUNXI_MMC_IDIE_RXIRQ (0x1 << 1) -int sunxi_mmc_init(int sdc_no); +struct mmc *sunxi_mmc_init(int sdc_no); #endif /* _SUNXI_MMC_H */ diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h new file mode 100644 index 0000000000..3d3bfa6cd1 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/prcm.h @@ -0,0 +1,238 @@ +/* + * Sunxi A31 Power Management Unit register definition. + * + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> + * http://linux-sunxi.org + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Berg Xing <bergxing@allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_PRCM_H +#define _SUNXI_PRCM_H + +#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4) +#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3) +#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1) +#define PRCM_CPUS_CFG_PRE_DIV(n) \ + __PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n)) +#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8) +#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f) +#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1) +#define PRCM_CPUS_CFG_POST_DIV(n) \ + __PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n)) +#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16) +#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3) +#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0 +#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1 +#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2 +#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3 +#define PRCM_CPUS_CFG_CLK_SRC_LOSC \ + __PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC) +#define PRCM_CPUS_CFG_CLK_SRC_HOSC \ + __PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC) +#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \ + __PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6) +#define PRCM_CPUS_CFG_CLK_SRC_PDIV \ + __PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV) + +#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0) +#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3) +#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1) +#define PRCM_APB0_RATIO_DIV(n) \ + __PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n)) + +#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0) +#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1) + +#define PRCM_APB0_GATE_PIO (0x1 << 0) +#define PRCM_APB0_GATE_IR (0x1 << 1) +#define PRCM_APB0_GATE_TIMER01 (0x1 << 2) +#define PRCM_APB0_GATE_P2WI (0x1 << 3) +#define PRCM_APB0_GATE_UART (0x1 << 4) +#define PRCM_APB0_GATE_1WIRE (0x1 << 5) +#define PRCM_APB0_GATE_I2C (0x1 << 6) + +#define PRCM_APB0_RESET_PIO (0x1 << 0) +#define PRCM_APB0_RESET_IR (0x1 << 1) +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2) +#define PRCM_APB0_RESET_P2WI (0x1 << 3) +#define PRCM_APB0_RESET_UART (0x1 << 4) +#define PRCM_APB0_RESET_1WIRE (0x1 << 5) +#define PRCM_APB0_RESET_I2C (0x1 << 6) + +#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0) +#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1) +#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4) +#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \ + __PRCM_PLL_CTRL_USB_CLK_SRC(0x3) +#define __PRCM_PLL_CTRL_USB_CLK_0 0x0 +#define __PRCM_PLL_CTRL_USB_CLK_1 0x1 +#define __PRCM_PLL_CTRL_USB_CLK_2 0x2 +#define __PRCM_PLL_CTRL_USB_CLK_3 0x3 +#define PRCM_PLL_CTRL_USB_CLK_0 \ + __PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0) +#define PRCM_PLL_CTRL_USB_CLK_1 \ + __PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1) +#define PRCM_PLL_CTRL_USB_CLK_2 \ + __PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2) +#define PRCM_PLL_CTRL_USB_CLK_3 \ + __PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3) +#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12) +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \ + __PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3) +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \ + __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) +#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20) +#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \ + __PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3) +#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0 +#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1 +#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2 +#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3 +#define PRCM_PLL_CTRL_HOSC_CLK_0 \ + __PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0) +#define PRCM_PLL_CTRL_HOSC_CLK_1 \ + __PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1) +#define PRCM_PLL_CTRL_HOSC_CLK_2 \ + __PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2) +#define PRCM_PLL_CTRL_HOSC_CLK_3 \ + __PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3) +#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24) +#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0) +#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1) +#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2) +#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3) +#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */ +#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16) +#define PRCM_PLL_CTRL_LDO_OUT_MASK \ + __PRCM_PLL_CTRL_LDO_OUT(0x7) +/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */ +#define PRCM_PLL_CTRL_LDO_OUT_L(n) \ + __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7) +#define PRCM_PLL_CTRL_LDO_OUT_H(n) \ + __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7) +#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \ + __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000) +#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \ + __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160) +#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24) + +#define PRCM_CLK_1WIRE_GATE (0x1 << 31) + +#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0) +#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf) +#define __PRCM_CLK_MOD0_M_X(n) (n - 1) +#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n)) +#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8) +#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7) +#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16) +#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3) +#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1) +#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n)) +#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20) +#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7) +#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24) +#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7) +#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31) + +#define PRCM_APB0_RESET_PIO (0x1 << 0) +#define PRCM_APB0_RESET_IR (0x1 << 1) +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2) +#define PRCM_APB0_RESET_P2WI (0x1 << 3) +#define PRCM_APB0_RESET_UART (0x1 << 4) +#define PRCM_APB0_RESET_1WIRE (0x1 << 5) +#define PRCM_APB0_RESET_I2C (0x1 << 6) + +#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8) +#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7) +#define __PRCM_CLK_OUTD_M_X() ((n) - 1) +#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n)) +#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20) +#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7) +#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1) +#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n) +#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24) +#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3) +#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0 +#define __PRCM_CLK_OUTD_SRC_LOSC 0x1 +#define __PRCM_CLK_OUTD_SRC_HOSC 0x2 +#define __PRCM_CLK_OUTD_SRC_ERR 0x3 +#define PRCM_CLK_OUTD_SRC_LOSC2 \ +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2) +#define PRCM_CLK_OUTD_SRC_LOSC \ +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC) +#define PRCM_CLK_OUTD_SRC_HOSC \ +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC) +#define PRCM_CLK_OUTD_SRC_ERR \ +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR) +#define PRCM_CLK_OUTD_EN (0x1 << 31) + +#define PRCM_CPU0_PWROFF (0x1 << 0) +#define PRCM_CPU1_PWROFF (0x1 << 1) +#define PRCM_CPU2_PWROFF (0x1 << 2) +#define PRCM_CPU3_PWROFF (0x1 << 3) +#define PRCM_CPU_ALL_PWROFF (0xf << 0) + +#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0) +#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1) +#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2) +#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3) + +#define PRCM_VDD_GPU_PWROFF (0x1 << 0) + +#define PRCM_VDD_SYS_RESET (0x1 << 0) + +#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0) +#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff) + +#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0) +#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff) + +#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0) +#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff) + +#ifndef __ASSEMBLY__ +struct sunxi_prcm_reg { + u32 cpus_cfg; /* 0x000 */ + u8 res0[0x8]; /* 0x004 */ + u32 apb0_ratio; /* 0x00c */ + u32 cpu0_cfg; /* 0x010 */ + u32 cpu1_cfg; /* 0x014 */ + u32 cpu2_cfg; /* 0x018 */ + u32 cpu3_cfg; /* 0x01c */ + u8 res1[0x8]; /* 0x020 */ + u32 apb0_gate; /* 0x028 */ + u8 res2[0x14]; /* 0x02c */ + u32 pll_ctrl0; /* 0x040 */ + u32 pll_ctrl1; /* 0x044 */ + u8 res3[0x8]; /* 0x048 */ + u32 clk_1wire; /* 0x050 */ + u32 clk_ir; /* 0x054 */ + u8 res4[0x58]; /* 0x058 */ + u32 apb0_reset; /* 0x0b0 */ + u8 res5[0x3c]; /* 0x0b4 */ + u32 clk_outd; /* 0x0f0 */ + u8 res6[0xc]; /* 0x0f4 */ + u32 cpu_pwroff; /* 0x100 */ + u8 res7[0xc]; /* 0x104 */ + u32 vdd_sys_pwroff; /* 0x110 */ + u8 res8[0x4]; /* 0x114 */ + u32 gpu_pwroff; /* 0x118 */ + u8 res9[0x4]; /* 0x11c */ + u32 vdd_pwr_reset; /* 0x120 */ + u8 res10[0x20]; /* 0x124 */ + u32 cpu1_pwr_clamp; /* 0x144 */ + u32 cpu2_pwr_clamp; /* 0x148 */ + u32 cpu3_pwr_clamp; /* 0x14c */ + u8 res11[0x30]; /* 0x150 */ + u32 dram_pwr; /* 0x180 */ + u8 res12[0xc]; /* 0x184 */ + u32 dram_tst; /* 0x190 */ +}; + +void prcm_apb0_enable(u32 flags); +#endif /* __ASSEMBLY__ */ +#endif /* _PRCM_H */ diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h index 58e14fd0f7..03a0684c79 100644 --- a/arch/arm/include/asm/arch-sunxi/timer.h +++ b/arch/arm/include/asm/arch-sunxi/timer.h @@ -11,14 +11,10 @@ #ifndef _SUNXI_TIMER_H_ #define _SUNXI_TIMER_H_ -#define WDT_CTRL_RESTART (0x1 << 0) -#define WDT_CTRL_KEY (0x0a57 << 1) -#define WDT_MODE_EN (0x1 << 0) -#define WDT_MODE_RESET_EN (0x1 << 1) - #ifndef __ASSEMBLY__ #include <linux/types.h> +#include <asm/arch/watchdog.h> /* General purpose timer */ struct sunxi_timer { @@ -43,12 +39,6 @@ struct sunxi_64cnt { u32 hi; /* 0xa8 */ }; -/* Watchdog */ -struct sunxi_wdog { - u32 ctl; /* 0x90 */ - u32 mode; /* 0x94 */ -}; - /* Rtc */ struct sunxi_rtc { u32 ctl; /* 0x100 */ @@ -77,15 +67,20 @@ struct sunxi_timer_reg { struct sunxi_timer timer[6]; /* We have 6 timers */ u8 res2[16]; struct sunxi_avs avs; - struct sunxi_wdog wdog; - u8 res3[8]; - struct sunxi_64cnt cnt64; +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) + struct sunxi_wdog wdog; /* 0x90 */ + /* XXX the following is not accurate for sun5i/sun7i */ + struct sunxi_64cnt cnt64; /* 0xa0 */ u8 res4[0x58]; struct sunxi_rtc rtc; struct sunxi_alarm alarm; struct sunxi_tgp tgp[4]; u8 res5[8]; u32 cpu_cfg; +#else /* CONFIG_SUN6I || CONFIG_SUN8I || ... */ + u8 res3[16]; + struct sunxi_wdog wdog[5]; /* We have 5 watchdogs */ +#endif }; #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/include/asm/arch-sunxi/watchdog.h b/arch/arm/include/asm/arch-sunxi/watchdog.h new file mode 100644 index 0000000000..ccc8fa32c4 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/watchdog.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2014 + * Chen-Yu Tsai <wens@csie.org> + * + * Watchdog register definitions + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_WATCHDOG_H_ +#define _SUNXI_WATCHDOG_H_ + +#define WDT_CTRL_RESTART (0x1 << 0) +#define WDT_CTRL_KEY (0x0a57 << 1) + +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) + +#define WDT_MODE_EN (0x1 << 0) +#define WDT_MODE_RESET_EN (0x1 << 1) + +struct sunxi_wdog { + u32 ctl; /* 0x00 */ + u32 mode; /* 0x04 */ + u32 res[2]; +}; + +#else + +#define WDT_CFG_RESET (0x1) +#define WDT_MODE_EN (0x1) + +struct sunxi_wdog { + u32 irq_en; /* 0x00 */ + u32 irq_sta; /* 0x04 */ + u32 res1[2]; + u32 ctl; /* 0x10 */ + u32 cfg; /* 0x14 */ + u32 mode; /* 0x18 */ + u32 res2; +}; + +#endif + +#endif /* _SUNXI_WATCHDOG_H_ */ diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index bcd0a55a1e..31a15037d0 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -1,25 +1,12 @@ -if TARGET_SUN4I +if TARGET_SUN4I || TARGET_SUN5I || TARGET_SUN6I || TARGET_SUN7I || TARGET_SUN8I config SYS_CONFIG_NAME - default "sun4i" - -endif - -if TARGET_SUN5I - -config SYS_CONFIG_NAME - default "sun5i" - -endif - -if TARGET_SUN7I - -config SYS_CONFIG_NAME - default "sun7i" - -endif - -if TARGET_SUN4I || TARGET_SUN5I || TARGET_SUN7I + string + default "sun4i" if TARGET_SUN4I + default "sun5i" if TARGET_SUN5I + default "sun6i" if TARGET_SUN6I + default "sun7i" if TARGET_SUN7I + default "sun8i" if TARGET_SUN8I config SYS_CPU default "armv7" @@ -33,4 +20,45 @@ config SYS_SOC config FDTFILE string "Default fdtfile env setting for this board" +config OLD_SUNXI_KERNEL_COMPAT + boolean "Enable workarounds for booting old kernels" + default n + ---help--- + Set this to enable various workarounds for old kernels, this results in + sub-optimal settings for newer kernels, only enable if needed. + +config MMC0_CD_PIN + string "Card detect pin for mmc0" + default "" + ---help--- + Set the card detect pin for mmc0, leave empty to not use cd. This + takes a string in the format understood by sunxi_name_to_gpio, e.g. + PH1 for pin 1 of port H. + +config MMC1_CD_PIN + string "Card detect pin for mmc1" + default "" + ---help--- + See MMC0_CD_PIN help text. + +config MMC2_CD_PIN + string "Card detect pin for mmc2" + default "" + ---help--- + See MMC0_CD_PIN help text. + +config MMC3_CD_PIN + string "Card detect pin for mmc3" + default "" + ---help--- + See MMC0_CD_PIN help text. + +config MMC_SUNXI_SLOT_EXTRA + int "mmc extra slot number" + default -1 + ---help--- + sunxi builds always enable mmc0, some boards also have a second sdcard + slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable + support for this. + endif diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS index 4f32195dcd..febd126cb8 100644 --- a/board/sunxi/MAINTAINERS +++ b/board/sunxi/MAINTAINERS @@ -8,6 +8,7 @@ F: configs/ba10_tv_box_defconfig F: configs/Cubieboard_defconfig F: configs/Mele_A1000_defconfig F: configs/Mele_A1000G_defconfig +F: configs/Mele_M3_defconfig F: configs/Mini-X_defconfig F: configs/Mini-X-1Gb_defconfig F: include/configs/sun5i.h @@ -38,3 +39,19 @@ M: FUKAUMI Naoki <naobsd@gmail.com> S: Maintained F: board/sunxi/dram_a20_olinuxino_l.c F: configs/A20-OLinuXino-Lime_defconfig + +A20-OLINUXINO-LIME2 BOARD +M: Iain Paton <ipaton0@gmail.com> +S: Maintained +F: board/sunxi/dram_a20_olinuxino_l2.c +F: configs/A20-OLinuXino-Lime2_defconfig + +COLOMBUS BOARD +M: Maxime Ripard <maxime.ripard@free-electrons.com> +S: Maintained +F: configs/Colombus_defconfig + +IPPO-Q8H-V5 BOARD +M: CHen-Yu Tsai <wens@csie.org> +S: Maintained +F: configs/Ippo_q8h_v5_defconfig diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 56073a024d..6a2e4c9d5b 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_A10S_OLINUXINO_M) += dram_a10s_olinuxino_m.o obj-$(CONFIG_A13_OLINUXINO) += dram_a13_olinuxino.o obj-$(CONFIG_A13_OLINUXINOM) += dram_a13_oli_micro.o obj-$(CONFIG_A20_OLINUXINO_L) += dram_a20_olinuxino_l.o +obj-$(CONFIG_A20_OLINUXINO_L2) += dram_a20_olinuxino_l2.o obj-$(CONFIG_A20_OLINUXINO_M) += dram_sun7i_384_1024_iow16.o # This is not a typo, uses the same mem settings as the a10s-olinuxino-m obj-$(CONFIG_AUXTEK_T004) += dram_a10s_olinuxino_m.o @@ -27,6 +28,7 @@ obj-$(CONFIG_CUBIETRUCK) += dram_cubietruck.o obj-$(CONFIG_I12_TVBOX) += dram_sun7i_384_1024_iow16.o obj-$(CONFIG_MELE_A1000) += dram_sun4i_360_512.o obj-$(CONFIG_MELE_A1000G) += dram_sun4i_360_1024_iow8.o +obj-$(CONFIG_MELE_M3) += dram_sun7i_384_1024_iow16.o obj-$(CONFIG_MINI_X) += dram_sun4i_360_512.o obj-$(CONFIG_MINI_X_1GB) += dram_sun4i_360_1024_iow16.o obj-$(CONFIG_PCDUINO3) += dram_linksprite_pcduino3.o diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2179e234e2..03890c8c9c 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -12,6 +12,7 @@ */ #include <common.h> +#include <mmc.h> #ifdef CONFIG_AXP152_POWER #include <axp152.h> #endif @@ -70,9 +71,9 @@ static void mmc_pinmux_setup(int sdc) break; case 1: - /* CMD-PH22, CLK-PH23, D0~D3-PH24~27 : 5 */ - for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN4I_GPH22_SDC1); + /* CMD-PG3, CLK-PG4, D0~D3-PG5-8 */ + for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) { + sunxi_gpio_set_cfgpin(pin, SUN5I_GPG3_SDC1); sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); sunxi_gpio_set_drv(pin, 2); } @@ -104,11 +105,36 @@ static void mmc_pinmux_setup(int sdc) int board_mmc_init(bd_t *bis) { + __maybe_unused struct mmc *mmc0, *mmc1; + __maybe_unused char buf[512]; + mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT); - sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT); -#if !defined (CONFIG_SPL_BUILD) && defined (CONFIG_MMC_SUNXI_SLOT_EXTRA) + mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT); + if (!mmc0) + return -1; + +#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1 mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA); - sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA); + mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA); + if (!mmc1) + return -1; +#endif + +#if CONFIG_MMC_SUNXI_SLOT == 0 && CONFIG_MMC_SUNXI_SLOT_EXTRA == 2 + /* + * Both mmc0 and mmc2 are bootable, figure out where we're booting + * from. Try mmc0 first, just like the brom does. + */ + if (mmc_getcd(mmc0) && mmc_init(mmc0) == 0 && + mmc0->block_dev.block_read(0, 16, 1, buf) == 1) { + buf[12] = 0; + if (strcmp(&buf[4], "eGON.BT0") == 0) + return 0; + } + + /* no bootable card in mmc0, so we must be booting from mmc2, swap */ + mmc0->block_dev.dev = 1; + mmc1->block_dev.dev = 0; #endif return 0; diff --git a/board/sunxi/dram_a20_olinuxino_l2.c b/board/sunxi/dram_a20_olinuxino_l2.c new file mode 100644 index 0000000000..2115d37470 --- /dev/null +++ b/board/sunxi/dram_a20_olinuxino_l2.c @@ -0,0 +1,31 @@ +/* this file is generated, don't edit it yourself */ + +#include <common.h> +#include <asm/arch/dram.h> + +static struct dram_para dram_para = { + .clock = 480, + .type = 3, + .rank_num = 1, + .density = 4096, + .io_width = 16, + .bus_width = 32, + .cas = 9, + .zq = 0x7f, + .odt_en = 0, + .size = 1024, + .tpr0 = 0x42d899b7, + .tpr1 = 0xa090, + .tpr2 = 0x22a00, + .tpr3 = 0, + .tpr4 = 0, + .tpr5 = 0, + .emr1 = 0x4, + .emr2 = 0x10, + .emr3 = 0, +}; + +unsigned long sunxi_dram_init(void) +{ + return dramc_init(&dram_para); +} diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig index a578c067d4..2aad834fa8 100644 --- a/configs/A10s-OLinuXino-M_defconfig +++ b/configs/A10s-OLinuXino-M_defconfig @@ -1,5 +1,8 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="A10S_OLINUXINO_M,AXP152_POWER,SUNXI_EMAC,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPB(10)" CONFIG_FDTFILE="sun5i-a10s-olinuxino-micro.dtb" +CONFIG_MMC_SUNXI_SLOT_EXTRA=1 ++S:CONFIG_MMC0_CD_PIN="PG1" ++S:CONFIG_MMC1_CD_PIN="PG13" +S:CONFIG_ARM=y +S:CONFIG_TARGET_SUN5I=y diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig new file mode 100644 index 0000000000..75ef872780 --- /dev/null +++ b/configs/A20-OLinuXino-Lime2_defconfig @@ -0,0 +1,5 @@ +CONFIG_SPL=y +CONFIG_SYS_EXTRA_OPTIONS="A20_OLINUXINO_L2,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPC(3),USB_EHCI" +CONFIG_FDTFILE="sun7i-a20-olinuxino-lime2.dtb" ++S:CONFIG_ARM=y ++S:CONFIG_TARGET_SUN7I=y diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig index 20a947ca72..0e0a7def2d 100644 --- a/configs/A20-OLinuXino_MICRO_defconfig +++ b/configs/A20-OLinuXino_MICRO_defconfig @@ -1,5 +1,8 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="A20_OLINUXINO_M,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" CONFIG_FDTFILE="sun7i-a20-olinuxino-micro.dtb" +CONFIG_MMC_SUNXI_SLOT_EXTRA=3 ++S:CONFIG_MMC0_CD_PIN="PH1" ++S:CONFIG_MMC3_CD_PIN="PH11" +S:CONFIG_ARM=y +S:CONFIG_TARGET_SUN7I=y diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig new file mode 100644 index 0000000000..16800de2bc --- /dev/null +++ b/configs/Colombus_defconfig @@ -0,0 +1,4 @@ +CONFIG_SYS_EXTRA_OPTIONS="COLOMBUS" +CONFIG_ARM=y +CONFIG_TARGET_SUN6I=y +CONFIG_FDTFILE="sun6i-a31-colombus.dtb" diff --git a/configs/Ippo_q8h_defconfig b/configs/Ippo_q8h_defconfig new file mode 100644 index 0000000000..781f13785b --- /dev/null +++ b/configs/Ippo_q8h_defconfig @@ -0,0 +1,4 @@ +CONFIG_SYS_EXTRA_OPTIONS="IPPO_Q8H_V5,CONS_INDEX=5" +CONFIG_ARM=y +CONFIG_TARGET_SUN8I=y +CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb" diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig new file mode 100644 index 0000000000..a043ad277d --- /dev/null +++ b/configs/Mele_M3_defconfig @@ -0,0 +1,7 @@ +CONFIG_SPL=y +CONFIG_SYS_EXTRA_OPTIONS="MELE_M3,AXP209_POWER,SUNXI_GMAC,USB_EHCI" +CONFIG_FDTFILE="sun7i-a20-m3.dtb" ++S:CONFIG_MMC_SUNXI_SLOT_EXTRA=2 ++S:CONFIG_MMC0_CD_PIN="PH1" ++S:CONFIG_ARM=y ++S:CONFIG_TARGET_SUN7I=y diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index d4e574fe19..16592e3d7c 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -14,12 +14,13 @@ #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/cpu.h> +#include <asm/arch/gpio.h> #include <asm/arch/mmc.h> +#include <asm-generic/gpio.h> struct sunxi_mmc_host { unsigned mmc_no; uint32_t *mclkreg; - unsigned database; unsigned fatal_err; unsigned mod_clk; struct sunxi_mmc *reg; @@ -57,7 +58,6 @@ static int mmc_resource_init(int sdc_no) printf("Wrong mmc number %d\n", sdc_no); return -1; } - mmchost->database = (unsigned int)mmchost->reg + 0x100; mmchost->mmc_no = sdc_no; return 0; @@ -75,6 +75,11 @@ static int mmc_clk_io_on(int sdc_no) /* config ahb clock */ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); +#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I) + /* unassert reset */ + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); +#endif + /* config mod clock */ pll_clk = clock_get_pll6(); /* should be close to 100 MHz but no more, so round up */ @@ -194,9 +199,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) } if (reading) - buff[i] = readl(mmchost->database); + buff[i] = readl(&mmchost->reg->fifo); else - writel(buff[i], mmchost->database); + writel(buff[i], &mmchost->reg->fifo); } return 0; @@ -343,13 +348,32 @@ out: return error; } +static int sunxi_mmc_getcd(struct mmc *mmc) +{ + struct sunxi_mmc_host *mmchost = mmc->priv; + int cd_pin = -1; + + switch (mmchost->mmc_no) { + case 0: cd_pin = sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN); break; + case 1: cd_pin = sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN); break; + case 2: cd_pin = sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN); break; + case 3: cd_pin = sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN); break; + } + + if (cd_pin == -1) + return 1; + + return !gpio_direction_input(cd_pin); +} + static const struct mmc_ops sunxi_mmc_ops = { .send_cmd = mmc_send_cmd, .set_ios = mmc_set_ios, .init = mmc_core_init, + .getcd = sunxi_mmc_getcd, }; -int sunxi_mmc_init(int sdc_no) +struct mmc *sunxi_mmc_init(int sdc_no) { struct mmc_config *cfg = &mmc_host[sdc_no].cfg; @@ -361,6 +385,9 @@ int sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; +#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN7I) || defined(CONFIG_SUN8I) + cfg->host_caps |= MMC_MODE_HC; +#endif cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000; @@ -369,8 +396,5 @@ int sunxi_mmc_init(int sdc_no) mmc_resource_init(sdc_no); mmc_clk_io_on(sdc_no); - if (mmc_create(cfg, &mmc_host[sdc_no]) == NULL) - return -1; - - return 0; + return mmc_create(cfg, &mmc_host[sdc_no]); } diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h index 5611ecc85f..d0191a32b1 100644 --- a/include/configs/sun4i.h +++ b/include/configs/sun4i.h @@ -15,6 +15,7 @@ #define CONFIG_CLK_FULL_SPEED 1008000000 #define CONFIG_SYS_PROMPT "sun4i# " +#define CONFIG_MACH_TYPE 4104 #ifdef CONFIG_USB_EHCI #define CONFIG_USB_EHCI_SUNXI diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h index 6066371a17..7b683e9c89 100644 --- a/include/configs/sun5i.h +++ b/include/configs/sun5i.h @@ -15,6 +15,7 @@ #define CONFIG_CLK_FULL_SPEED 1008000000 #define CONFIG_SYS_PROMPT "sun5i# " +#define CONFIG_MACH_TYPE 4138 #ifdef CONFIG_USB_EHCI #define CONFIG_USB_EHCI_SUNXI diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h new file mode 100644 index 0000000000..93a1d965ca --- /dev/null +++ b/include/configs/sun6i.h @@ -0,0 +1,26 @@ +/* + * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net> + * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * (C) Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> + * + * Configuration settings for the Allwinner A31 (sun6i) CPU + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * A31 specific configuration + */ +#define CONFIG_SUN6I /* sun6i SoC generation */ + +#define CONFIG_SYS_PROMPT "sun6i# " + +/* + * Include common sunxi configuration where most the settings are + */ +#include <configs/sunxi-common.h> + +#endif /* __CONFIG_H */ diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h index a902b84574..966cbd8e83 100644 --- a/include/configs/sun7i.h +++ b/include/configs/sun7i.h @@ -16,6 +16,7 @@ #define CONFIG_CLK_FULL_SPEED 912000000 #define CONFIG_SYS_PROMPT "sun7i# " +#define CONFIG_MACH_TYPE 4283 #ifdef CONFIG_USB_EHCI #define CONFIG_USB_EHCI_SUNXI diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h new file mode 100644 index 0000000000..1c1a7cde5e --- /dev/null +++ b/include/configs/sun8i.h @@ -0,0 +1,23 @@ +/* + * (C) Copyright 2014 Chen-Yu Tsai <wens@csie.org> + * + * Configuration settings for the Allwinner A23 (sun8i) CPU + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * A23 specific configuration + */ +#define CONFIG_SUN8I /* sun8i SoC generation */ +#define CONFIG_SYS_PROMPT "sun8i# " + +/* + * Include common sunxi configuration where most the settings are + */ +#include <configs/sunxi-common.h> + +#endif /* __CONFIG_H */ diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 0c117bc5e7..cc450e02e6 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -42,6 +42,7 @@ #define CONFIG_SYS_NS16550_COM2 SUNXI_UART1_BASE #define CONFIG_SYS_NS16550_COM3 SUNXI_UART2_BASE #define CONFIG_SYS_NS16550_COM4 SUNXI_UART3_BASE +#define CONFIG_SYS_NS16550_COM5 SUNXI_R_UART_BASE /* DRAM Base */ #define CONFIG_SYS_SDRAM_BASE 0x40000000 @@ -77,6 +78,7 @@ #define CONFIG_INITRD_TAG /* mmc config */ +#if !defined(CONFIG_UART0_PORT_F) #define CONFIG_MMC #define CONFIG_GENERIC_MMC #define CONFIG_CMD_MMC @@ -84,6 +86,7 @@ #define CONFIG_MMC_SUNXI_SLOT 0 #define CONFIG_ENV_IS_IN_MMC #define CONFIG_SYS_MMC_ENV_DEV 0 /* first detected MMC controller */ +#endif /* 4MB of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (4 << 20)) @@ -92,8 +95,8 @@ * Miscellaneous configurable options */ #define CONFIG_CMD_ECHO -#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ -#define CONFIG_SYS_PBSIZE 384 /* Print Buffer Size */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE 1024 /* Print Buffer Size */ #define CONFIG_SYS_MAXARGS 16 /* max number of command args */ #define CONFIG_SYS_GENERIC_BOARD @@ -181,6 +184,7 @@ /* GPIO */ #define CONFIG_SUNXI_GPIO +#define CONFIG_SPL_GPIO_SUPPORT #define CONFIG_CMD_GPIO /* Ethernet support */ @@ -225,16 +229,28 @@ "pxefile_addr_r=0x43200000\0" \ "ramdisk_addr_r=0x43300000\0" +#ifdef CONFIG_MMC +#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0) +#else +#define BOOT_TARGET_DEVICES_MMC(func) +#endif + #ifdef CONFIG_AHCI #define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0) #else #define BOOT_TARGET_DEVICES_SCSI(func) #endif +#ifdef CONFIG_USB_EHCI +#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0) +#else +#define BOOT_TARGET_DEVICES_USB(func) +#endif + #define BOOT_TARGET_DEVICES(func) \ - func(MMC, mmc, 0) \ + BOOT_TARGET_DEVICES_MMC(func) \ BOOT_TARGET_DEVICES_SCSI(func) \ - func(USB, usb, 0) \ + BOOT_TARGET_DEVICES_USB(func) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na) |