diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/board.c | 41 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/clock_sun4i.c | 3 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/cpu_info.c | 15 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/dram.c | 102 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds | 5 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/u-boot-spl.lds | 6 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-kirkwood/config.h | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/gpio.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/i2c.h | 15 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/timer.h | 5 |
11 files changed, 194 insertions, 7 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index a64bfa18e0..6c706393d3 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -11,6 +11,8 @@ obj-y += timer.o obj-y += board.o obj-y += clock.o obj-y += pinmux.o +obj-$(CONFIG_SUN4I) += clock_sun4i.o +obj-$(CONFIG_SUN5I) += clock_sun4i.o obj-$(CONFIG_SUN7I) += clock_sun4i.o ifndef CONFIG_SPL_BUILD @@ -18,6 +20,8 @@ obj-y += cpu_info.o endif ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_SUN4I) += dram.o +obj-$(CONFIG_SUN5I) += dram.o obj-$(CONFIG_SUN7I) += dram.o ifdef CONFIG_SPL_FEL obj-y += start.o diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 49c94489ee..8f2cef332f 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -11,6 +11,7 @@ */ #include <common.h> +#include <i2c.h> #include <netdev.h> #include <miiphy.h> #include <serial.h> @@ -24,6 +25,8 @@ #include <asm/arch/sys_proto.h> #include <asm/arch/timer.h> +#include <linux/compiler.h> + #ifdef CONFIG_SPL_BUILD /* Pointer to the global data structure for SPL */ DECLARE_GLOBAL_DATA_PTR; @@ -47,15 +50,38 @@ u32 spl_boot_mode(void) int gpio_init(void) { +#if 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); +#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); +#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); +#else +#error Unsupported console port number. Please fix pin mux settings in board.c +#endif return 0; } void reset_cpu(ulong addr) { + 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_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); + + while (1) { + /* sun5i sometimes gets stuck without this */ + writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); + } } /* do some early init */ @@ -72,11 +98,16 @@ void s_init(void) clock_init(); timer_init(); gpio_init(); + i2c_init_board(); #ifdef CONFIG_SPL_BUILD gd = &gdata; preloader_console_init(); +#ifdef CONFIG_SPL_I2C_SUPPORT + /* Needed early by sunxi_board_init if PMU is enabled */ + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif sunxi_board_init(); #endif } @@ -96,7 +127,15 @@ void enable_caches(void) */ int cpu_eth_init(bd_t *bis) { - int rc; + __maybe_unused int rc; + +#ifdef CONFIG_SUNXI_EMAC + rc = sunxi_emac_initialize(bis); + if (rc < 0) { + printf("sunxi: failed to initialize emac\n"); + return rc; + } +#endif #ifdef CONFIG_SUNXI_GMAC rc = sunxi_gmac_initialize(bis); diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c index 5a7da3c6bf..b8b16cff95 100644 --- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c +++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c @@ -36,8 +36,7 @@ void clock_init_safe(void) CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT, &ccm->cpu_ahb_apb0_cfg); #ifdef CONFIG_SUN7I - writel(0x1 << AHB_GATE_OFFSET_DMA | readl(&ccm->ahb_gate0), - &ccm->ahb_gate0); + setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_DMA); #endif writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg); } diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index b4c3d5c6dd..5cf35acc1e 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -13,7 +13,22 @@ #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { +#ifdef CONFIG_SUN4I + puts("CPU: Allwinner A10 (SUN4I)\n"); +#elif defined CONFIG_SUN5I + u32 val = readl(SUNXI_SID_BASE + 0x08); + switch ((val >> 12) & 0xf) { + case 0: puts("CPU: Allwinner A12 (SUN5I)\n"); break; + case 3: puts("CPU: Allwinner A13 (SUN5I)\n"); break; + case 7: puts("CPU: Allwinner A10s (SUN5I)\n"); break; + default: puts("CPU: Allwinner A1X (SUN5I)\n"); + } +#elif defined CONFIG_SUN7I puts("CPU: Allwinner A20 (SUN7I)\n"); +#else +#warning Please update cpu_info.c with correct CPU information + puts("CPU: SUNXI Family\n"); +#endif return 0; } #endif diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c index b43c4b41d3..0f1ceecc1d 100644 --- a/arch/arm/cpu/armv7/sunxi/dram.c +++ b/arch/arm/cpu/armv7/sunxi/dram.c @@ -53,16 +53,37 @@ static void mctl_ddr3_reset(void) struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - clrbits_le32(&dram->mcr, DRAM_MCR_RESET); - udelay(2); - setbits_le32(&dram->mcr, DRAM_MCR_RESET); +#ifdef CONFIG_SUN4I + struct sunxi_timer_reg *timer = + (struct sunxi_timer_reg *)SUNXI_TIMER_BASE; + u32 reg_val; + + writel(0, &timer->cpu_cfg); + reg_val = readl(&timer->cpu_cfg); + + if ((reg_val & CPU_CFG_CHIP_VER_MASK) != + CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) { + setbits_le32(&dram->mcr, DRAM_MCR_RESET); + udelay(2); + clrbits_le32(&dram->mcr, DRAM_MCR_RESET); + } else +#endif + { + clrbits_le32(&dram->mcr, DRAM_MCR_RESET); + udelay(2); + setbits_le32(&dram->mcr, DRAM_MCR_RESET); + } } static void mctl_set_drive(void) { struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; +#ifdef CONFIG_SUN7I clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28), +#else + clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3), +#endif DRAM_MCR_MODE_EN(0x3) | 0xffc); } @@ -134,6 +155,26 @@ static void mctl_enable_dllx(u32 phase) } static u32 hpcr_value[32] = { +#ifdef CONFIG_SUN5I + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0x1031, 0x1031, 0x0735, 0x1035, + 0x1035, 0x0731, 0x1031, 0, + 0x0301, 0x0301, 0x0301, 0x0301, + 0x0301, 0x0301, 0x0301, 0 +#endif +#ifdef CONFIG_SUN4I + 0x0301, 0x0301, 0x0301, 0x0301, + 0x0301, 0x0301, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0x1031, 0x1031, 0x0735, 0x5031, + 0x1035, 0x0731, 0x1031, 0x0735, + 0x1035, 0x1031, 0x0731, 0x1035, + 0x1031, 0x0301, 0x0301, 0x0731 +#endif #ifdef CONFIG_SUN7I 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, @@ -223,22 +264,38 @@ static void mctl_setup_dram_clock(u32 clk) clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS); #endif +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) /* setup MBUS clock */ reg_val = CCM_MBUS_CTRL_GATE | +#ifdef CONFIG_SUN7I CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) | CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) | CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2)); +#else /* defined(CONFIG_SUN5I) */ + CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) | + CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) | + CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2)); +#endif writel(reg_val, &ccm->mbus_clk_cfg); +#endif /* * open DRAMC AHB & DLL register clock * close it first */ +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); +#else + clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); +#endif udelay(22); /* then open it */ +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); +#else + setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); +#endif udelay(22); } @@ -385,6 +442,13 @@ static void dramc_clock_output_en(u32 on) else clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT); #endif +#ifdef CONFIG_SUN4I + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (on) + setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); + else + clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); +#endif } static const u16 tRFC_table[2][6] = { @@ -420,12 +484,25 @@ unsigned long dramc_init(struct dram_para *para) /* setup DRAM relative clock */ mctl_setup_dram_clock(para->clock); +#ifdef CONFIG_SUN5I + /* Disable any pad power save control */ + writel(0, &dram->ppwrsctl); +#endif + /* reset external DRAM */ +#ifndef CONFIG_SUN7I + mctl_ddr3_reset(); +#endif mctl_set_drive(); /* dram clock off */ dramc_clock_output_en(0); +#ifdef CONFIG_SUN4I + /* select dram controller 1 */ + writel(DRAM_CSEL_MAGIC, &dram->csel); +#endif + mctl_itm_disable(); mctl_enable_dll0(para->tpr3); @@ -482,6 +559,9 @@ unsigned long dramc_init(struct dram_para *para) mctl_ddr3_reset(); else setbits_le32(&dram->mcr, DRAM_MCR_RESET); +#else + /* dram clock on */ + dramc_clock_output_en(1); #endif udelay(1); @@ -490,6 +570,22 @@ unsigned long dramc_init(struct dram_para *para) mctl_enable_dllx(para->tpr3); +#ifdef CONFIG_SUN4I + /* set odt impedance divide ratio */ + reg_val = ((para->zq) >> 8) & 0xfffff; + reg_val |= ((para->zq) & 0xff) << 20; + reg_val |= (para->zq) & 0xf0000000; + writel(reg_val, &dram->zqcr0); +#endif + +#ifdef CONFIG_SUN4I + /* set I/O configure register */ + reg_val = 0x00cc0000; + reg_val |= (para->odt_en) & 0x3; + reg_val |= ((para->odt_en) & 0x3) << 30; + writel(reg_val, &dram->iocr); +#endif + /* set refresh period */ dramc_set_autorefresh_cycle(para->clock, para->type - 2, density); diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds index 364e35c32f..928b7c19e0 100644 --- a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds @@ -27,6 +27,11 @@ SECTIONS } . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); . = .; . = ALIGN(4); diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds index 5008028aae..53f0cbd2b7 100644 --- a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds @@ -27,6 +27,7 @@ SECTIONS .text : { __start = .; + *(.vectors) arch/arm/cpu/armv7/start.o (.text) *(.text*) } > .sram @@ -38,6 +39,11 @@ SECTIONS .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .sram + + . = ALIGN(4); __image_copy_end = .; _end = .; diff --git a/arch/arm/include/asm/arch-kirkwood/config.h b/arch/arm/include/asm/arch-kirkwood/config.h index 7a688e46b0..f7bfa0e74d 100644 --- a/arch/arm/include/asm/arch-kirkwood/config.h +++ b/arch/arm/include/asm/arch-kirkwood/config.h @@ -129,7 +129,8 @@ */ #ifdef CONFIG_CMD_I2C #ifndef CONFIG_SYS_I2C_SOFT -#define CONFIG_I2C_MVTWSI +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MVTWSI #endif #define CONFIG_SYS_I2C_SLAVE 0x0 #define CONFIG_SYS_I2C_SPEED 100000 diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 892479c183..f7f3d8c41a 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -143,5 +143,7 @@ int sunxi_gpio_set_cfgpin(u32 pin, u32 val); int sunxi_gpio_get_cfgpin(u32 pin); int sunxi_gpio_set_drv(u32 pin, u32 val); int sunxi_gpio_set_pull(u32 pin, u32 val); +int sunxi_name_to_gpio(const char *name); +#define name_to_gpio(name) sunxi_name_to_gpio(name) #endif /* _SUNXI_GPIO_H */ diff --git a/arch/arm/include/asm/arch-sunxi/i2c.h b/arch/arm/include/asm/arch-sunxi/i2c.h new file mode 100644 index 0000000000..dc5406b213 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/i2c.h @@ -0,0 +1,15 @@ +/* + * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _SUNXI_I2C_H_ +#define _SUNXI_I2C_H_ + +#include <asm/arch/cpu.h> + +#define CONFIG_I2C_MVTWSI_BASE SUNXI_TWI0_BASE +/* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */ +#define CONFIG_SYS_TCLK 24000000 + +#endif diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h index 6aacfd7b39..58e14fd0f7 100644 --- a/arch/arm/include/asm/arch-sunxi/timer.h +++ b/arch/arm/include/asm/arch-sunxi/timer.h @@ -11,6 +11,11 @@ #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> |