summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7/sunxi
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu/armv7/sunxi')
-rw-r--r--arch/arm/cpu/armv7/sunxi/Makefile3
-rw-r--r--arch/arm/cpu/armv7/sunxi/board.c102
-rw-r--r--arch/arm/cpu/armv7/sunxi/clock_sun6i.c5
-rw-r--r--arch/arm/cpu/armv7/sunxi/clock_sun9i.c68
-rw-r--r--arch/arm/cpu/armv7/sunxi/rsb.c22
5 files changed, 142 insertions, 58 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 1720f7d..48db744 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -15,13 +15,16 @@ obj-y += pinmux.o
obj-y += usbc.o
obj-$(CONFIG_MACH_SUN6I) += prcm.o
obj-$(CONFIG_MACH_SUN8I) += prcm.o
+obj-$(CONFIG_MACH_SUN9I) += prcm.o
obj-$(CONFIG_MACH_SUN6I) += p2wi.o
obj-$(CONFIG_MACH_SUN8I) += rsb.o
+obj-$(CONFIG_MACH_SUN9I) += rsb.o
obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o
obj-$(CONFIG_MACH_SUN7I) += clock_sun4i.o
obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
+obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o
ifndef CONFIG_SPL_BUILD
ifdef CONFIG_ARMV7_PSCI
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index bc98c56..6e28bcd 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -27,28 +27,7 @@
#include <linux/compiler.h>
-#ifdef CONFIG_SPL_BUILD
-/* Pointer to the global data structure for SPL */
-DECLARE_GLOBAL_DATA_PTR;
-
-/* The sunxi internal brom will try to loader external bootloader
- * from mmc0, nand flash, mmc2.
- * Unfortunately we can't check how SPL was loaded so assume
- * it's always the first SD/MMC controller
- */
-u32 spl_boot_device(void)
-{
- return BOOT_DEVICE_MMC1;
-}
-
-/* No confirmation data available in SPL yet. Hardcode bootmode */
-u32 spl_boot_mode(void)
-{
- return MMCSD_MODE_RAW;
-}
-#endif
-
-int gpio_init(void)
+static int gpio_init(void)
{
#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
@@ -86,36 +65,9 @@ int gpio_init(void)
return 0;
}
-void reset_cpu(ulong addr)
-{
-#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
- 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);
- }
-#else /* CONFIG_MACH_SUN6I || CONFIG_MACH_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_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
/* Magic (undocmented) value taken from boot0, without this DRAM
* access gets messed up (seems cache related) */
setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
@@ -133,9 +85,27 @@ void s_init(void)
timer_init();
gpio_init();
i2c_init_board();
+}
#ifdef CONFIG_SPL_BUILD
- gd = &gdata;
+/* The sunxi internal brom will try to loader external bootloader
+ * from mmc0, nand flash, mmc2.
+ * Unfortunately we can't check how SPL was loaded so assume
+ * it's always the first SD/MMC controller
+ */
+u32 spl_boot_device(void)
+{
+ return BOOT_DEVICE_MMC1;
+}
+
+/* No confirmation data available in SPL yet. Hardcode bootmode */
+u32 spl_boot_mode(void)
+{
+ return MMCSD_MODE_RAW;
+}
+
+void board_init_f(ulong dummy)
+{
preloader_console_init();
#ifdef CONFIG_SPL_I2C_SUPPORT
@@ -143,6 +113,36 @@ void s_init(void)
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
sunxi_board_init();
+
+ /* Clear the BSS. */
+ memset(__bss_start, 0, __bss_end - __bss_start);
+
+ board_init_r(NULL, 0);
+}
+#endif
+
+void reset_cpu(ulong addr)
+{
+#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
+ 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);
+ }
+#else /* CONFIG_MACH_SUN6I || CONFIG_MACH_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
}
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index d7a7040..e2a7867 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -45,10 +45,10 @@ void clock_init_safe(void)
void clock_init_uart(void)
{
+#if CONFIG_CONS_INDEX < 5
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|
@@ -68,9 +68,6 @@ void clock_init_uart(void)
/* 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)
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun9i.c b/arch/arm/cpu/armv7/sunxi/clock_sun9i.c
new file mode 100644
index 0000000..27179ba
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun9i.c
@@ -0,0 +1,68 @@
+/*
+ * sun9i specific clock code
+ *
+ * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * 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;
+
+ /* open the clock for uart */
+ setbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
+ /* deassert uart reset */
+ setbits_le32(&ccm->apb1_reset_cfg,
+ 1 << (APB1_RESET_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
+
+ /* Dup with clock_init_safe(), drop once sun9i SPL support lands */
+ writel(PLL4_CFG_DEFAULT, &ccm->pll4_periph0_cfg);
+}
+
+int clock_twi_onoff(int port, int state)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ if (port > 4)
+ return -1;
+
+ /* set the apb reset and clock gate for twi */
+ if (state) {
+ setbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port));
+ setbits_le32(&ccm->apb1_reset_cfg,
+ 1 << (APB1_RESET_UART_SHIFT + port));
+ } else {
+ clrbits_le32(&ccm->apb1_reset_cfg,
+ 1 << (APB1_RESET_UART_SHIFT + port));
+ clrbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port));
+ }
+
+ return 0;
+}
+
+unsigned int clock_get_pll4_periph0(void)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ uint32_t rval = readl(&ccm->pll4_periph0_cfg);
+ int n = ((rval & CCM_PLL4_CTRL_N_MASK) >> CCM_PLL4_CTRL_N_SHIFT);
+ int p = ((rval & CCM_PLL4_CTRL_P_MASK) >> CCM_PLL4_CTRL_P_SHIFT);
+ int m = ((rval & CCM_PLL4_CTRL_M_MASK) >> CCM_PLL4_CTRL_M_SHIFT) + 1;
+ const int k = 1;
+
+ return ((24000000 * n * k) >> p) / m;
+}
diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
index b72bb9d..b00befb 100644
--- a/arch/arm/cpu/armv7/sunxi/rsb.c
+++ b/arch/arm/cpu/armv7/sunxi/rsb.c
@@ -16,14 +16,27 @@
#include <asm/arch/prcm.h>
#include <asm/arch/rsb.h>
+static int rsb_set_device_mode(void);
+
static void rsb_cfg_io(void)
{
+#ifdef CONFIG_MACH_SUN8I
sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
+#elif defined CONFIG_MACH_SUN9I
+ sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN0_R_RSB_SCK);
+ sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN1_R_RSB_SDA);
+ sunxi_gpio_set_pull(SUNXI_GPN(0), 1);
+ sunxi_gpio_set_pull(SUNXI_GPN(1), 1);
+ sunxi_gpio_set_drv(SUNXI_GPN(0), 2);
+ sunxi_gpio_set_drv(SUNXI_GPN(1), 2);
+#else
+#error unsupported MACH_SUNXI
+#endif
}
static void rsb_set_clk(void)
@@ -42,7 +55,7 @@ static void rsb_set_clk(void)
writel((cd_odly << 8) | div, &rsb->ccr);
}
-void rsb_init(void)
+int rsb_init(void)
{
struct sunxi_rsb_reg * const rsb =
(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
@@ -54,6 +67,8 @@ void rsb_init(void)
writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);
rsb_set_clk();
+
+ return rsb_set_device_mode();
}
static int rsb_await_trans(void)
@@ -88,13 +103,14 @@ static int rsb_await_trans(void)
return ret;
}
-int rsb_set_device_mode(u32 device_mode_data)
+static int rsb_set_device_mode(void)
{
struct sunxi_rsb_reg * const rsb =
(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
unsigned long tmo = timer_get_us() + 1000000;
- writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
+ writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA,
+ &rsb->dmcr);
while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
if (timer_get_us() > tmo)