diff options
Diffstat (limited to 'arch/arm/cpu/armv7/sunxi')
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/board.c | 38 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/clock_sun4i.c | 11 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 76 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/cpu_info.c | 4 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/dram.c | 36 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/prcm.c | 35 |
7 files changed, 181 insertions, 23 deletions
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); +} |