From a85d80b8eed0ef2a8db8e685d0c668d20ee59146 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 24 Sep 2013 11:09:55 +0300 Subject: ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER The A31 has a reset controller, and we have to select this option to have access to the reset controller framework. Signed-off-by: Maxime Ripard Acked-by: Philipp Zabel --- arch/arm/mach-sunxi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-sunxi') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index c9e72c89066a..e3457b94b024 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1,5 +1,6 @@ config ARCH_SUNXI bool "Allwinner A1X SOCs" if ARCH_MULTI_V7 + select ARCH_HAS_RESET_CONTROLLER select ARCH_REQUIRE_GPIOLIB select ARM_GIC select CLKSRC_MMIO -- cgit From 751b2ac4a21331cb353f2e6211d090f881b18bf5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 5 Oct 2013 14:53:48 +0200 Subject: ARM: sunxi: Register the A31 reset IP in init_time The A31 has a reset IP that maintains a few other IPs in reset by default. Among these IPs are the UARTs, and most notably the timers. We thus need to register the reset driver before initializing the timers so that the reset timer can use the reset framework. Signed-off-by: Maxime Ripard Acked-by: Philipp Zabel --- arch/arm/mach-sunxi/sunxi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/arm/mach-sunxi') diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 61d3a387f01c..594ac48fc029 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -10,6 +10,8 @@ * warranty of any kind, whether express or implied. */ +#include +#include #include #include #include @@ -132,8 +134,17 @@ static const char * const sun6i_board_dt_compat[] = { NULL, }; +extern void __init sun6i_reset_init(void); +static void __init sun6i_timer_init(void) +{ + of_clk_init(NULL); + sun6i_reset_init(); + clocksource_of_init(); +} + DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") .init_machine = sunxi_dt_init, + .init_time = sun6i_timer_init, .dt_compat = sun6i_board_dt_compat, .restart = sun6i_restart, MACHINE_END -- cgit From 73346794b48237b7b4c2a5c02b12e3c4f1da7551 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 3 Nov 2013 10:30:13 +0100 Subject: ARM: sun6i: Add SMP support for the Allwinner A31 The A31 is a quad Cortex-A7. Add the logic to use the IPs used to control the CPU configuration and the CPU power so that we can bring up secondary CPUs at boot. Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/Makefile | 1 + arch/arm/mach-sunxi/common.h | 19 +++++++ arch/arm/mach-sunxi/headsmp.S | 9 +++ arch/arm/mach-sunxi/platsmp.c | 124 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-sunxi/sunxi.c | 3 + 5 files changed, 156 insertions(+) create mode 100644 arch/arm/mach-sunxi/common.h create mode 100644 arch/arm/mach-sunxi/headsmp.S create mode 100644 arch/arm/mach-sunxi/platsmp.c (limited to 'arch/arm/mach-sunxi') diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 93bebfc3ff9f..d9397202d6ec 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ARCH_SUNXI) += sunxi.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-sunxi/common.h b/arch/arm/mach-sunxi/common.h new file mode 100644 index 000000000000..9e5ac4756cbb --- /dev/null +++ b/arch/arm/mach-sunxi/common.h @@ -0,0 +1,19 @@ +/* + * Core functions for Allwinner SoCs + * + * Copyright (C) 2013 Maxime Ripard + * + * Maxime Ripard + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARCH_SUNXI_COMMON_H_ +#define __ARCH_SUNXI_COMMON_H_ + +void sun6i_secondary_startup(void); +extern struct smp_operations sun6i_smp_ops; + +#endif /* __ARCH_SUNXI_COMMON_H_ */ diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S new file mode 100644 index 000000000000..a10d494fb37b --- /dev/null +++ b/arch/arm/mach-sunxi/headsmp.S @@ -0,0 +1,9 @@ +#include +#include + + .section ".text.head", "ax" + +ENTRY(sun6i_secondary_startup) + msr cpsr_fsxc, #0xd3 + b secondary_startup +ENDPROC(sun6i_secondary_startup) diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c new file mode 100644 index 000000000000..7b141d8342a1 --- /dev/null +++ b/arch/arm/mach-sunxi/platsmp.c @@ -0,0 +1,124 @@ +/* + * SMP support for Allwinner SoCs + * + * Copyright (C) 2013 Maxime Ripard + * + * Maxime Ripard + * + * Based on code + * Copyright (C) 2012-2013 Allwinner Ltd. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define CPUCFG_CPU_PWR_CLAMP_STATUS_REG(cpu) ((cpu) * 0x40 + 0x64) +#define CPUCFG_CPU_RST_CTRL_REG(cpu) (((cpu) + 1) * 0x40) +#define CPUCFG_CPU_CTRL_REG(cpu) (((cpu) + 1) * 0x40 + 0x04) +#define CPUCFG_CPU_STATUS_REG(cpu) (((cpu) + 1) * 0x40 + 0x08) +#define CPUCFG_GEN_CTRL_REG 0x184 +#define CPUCFG_PRIVATE0_REG 0x1a4 +#define CPUCFG_PRIVATE1_REG 0x1a8 +#define CPUCFG_DBG_CTL0_REG 0x1e0 +#define CPUCFG_DBG_CTL1_REG 0x1e4 + +#define PRCM_CPU_PWROFF_REG 0x100 +#define PRCM_CPU_PWR_CLAMP_REG(cpu) (((cpu) * 4) + 0x140) + +static void __iomem *cpucfg_membase; +static void __iomem *prcm_membase; + +static DEFINE_SPINLOCK(cpu_lock); + +static void __init sun6i_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "allwinner,sun6i-a31-prcm"); + if (!node) { + pr_err("Missing A31 PRCM node in the device tree\n"); + return; + } + + prcm_membase = of_iomap(node, 0); + if (!prcm_membase) { + pr_err("Couldn't map A31 PRCM registers\n"); + return; + } + + node = of_find_compatible_node(NULL, NULL, + "allwinner,sun6i-a31-cpuconfig"); + if (!node) { + pr_err("Missing A31 CPU config node in the device tree\n"); + return; + } + + cpucfg_membase = of_iomap(node, 0); + if (!cpucfg_membase) + pr_err("Couldn't map A31 CPU config registers\n"); + +} + +static int sun6i_smp_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + u32 reg; + int i; + + if (!(prcm_membase && cpucfg_membase)) + return -EFAULT; + + spin_lock(&cpu_lock); + + /* Set CPU boot address */ + writel(virt_to_phys(sun6i_secondary_startup), + cpucfg_membase + CPUCFG_PRIVATE0_REG); + + /* Assert the CPU core in reset */ + writel(0, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + /* Assert the L1 cache in reset */ + reg = readl(cpucfg_membase + CPUCFG_GEN_CTRL_REG); + writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_GEN_CTRL_REG); + + /* Disable external debug access */ + reg = readl(cpucfg_membase + CPUCFG_DBG_CTL1_REG); + writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_DBG_CTL1_REG); + + /* Power up the CPU */ + for (i = 0; i <= 8; i++) + writel(0xff >> i, prcm_membase + PRCM_CPU_PWR_CLAMP_REG(cpu)); + mdelay(10); + + /* Clear CPU power-off gating */ + reg = readl(prcm_membase + PRCM_CPU_PWROFF_REG); + writel(reg & ~BIT(cpu), prcm_membase + PRCM_CPU_PWROFF_REG); + mdelay(1); + + /* Deassert the CPU core reset */ + writel(3, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + /* Enable back the external debug accesses */ + reg = readl(cpucfg_membase + CPUCFG_DBG_CTL1_REG); + writel(reg | BIT(cpu), cpucfg_membase + CPUCFG_DBG_CTL1_REG); + + spin_unlock(&cpu_lock); + + return 0; +} + +struct smp_operations sun6i_smp_ops __initdata = { + .smp_prepare_cpus = sun6i_smp_prepare_cpus, + .smp_boot_secondary = sun6i_smp_boot_secondary, +}; diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 594ac48fc029..aeea6ceea725 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -25,6 +25,8 @@ #include #include +#include "common.h" + #define SUN4I_WATCHDOG_CTRL_REG 0x00 #define SUN4I_WATCHDOG_CTRL_RESTART BIT(0) #define SUN4I_WATCHDOG_MODE_REG 0x04 @@ -147,6 +149,7 @@ DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") .init_time = sun6i_timer_init, .dt_compat = sun6i_board_dt_compat, .restart = sun6i_restart, + .smp = smp_ops(sun6i_smp_ops), MACHINE_END static const char * const sun7i_board_dt_compat[] = { -- cgit From 070330d3d45468a3f91b7c895903f2b566145d51 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 30 Dec 2013 16:37:29 +0100 Subject: ARM: sunxi: Select RESET_CONTROLLER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code selects ARCH_HAS_RESET_CONTROLLER, that enables the RESET_CONTROLLER option by default, but doesn't select it, so a configuration might unselect it, leading to compilation error. Explictly select RESET_CONTROLLER so that we can't have this breakage anymore. Reported-by: Emilio López Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-sunxi') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index e3457b94b024..8dea30ffe1ec 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -11,5 +11,6 @@ config ARCH_SUNXI select HAVE_SMP select PINCTRL select PINCTRL_SUNXI + select RESET_CONTROLLER select SPARSE_IRQ select SUN4I_TIMER -- cgit From 75cac6abe756fde529a000e725dceed2b908f61a Mon Sep 17 00:00:00 2001 From: Zalan Blenessy Date: Wed, 1 Jan 2014 18:02:55 +0100 Subject: ARM: sunxi: select ARM_PSCI On Allwinner sun7i (A20) SoCs, the SMP operations are implemented in u-boot, and exposed to the kernel through PSCI. We thus need to enable PSCI support for Allwinner SoCs so that the kernel uses it to bring up the additionnal cores. Signed-off-by: Signed-off-by: Zalan Blenessy Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-sunxi') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 8dea30ffe1ec..8053b1befc5e 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -3,6 +3,7 @@ config ARCH_SUNXI select ARCH_HAS_RESET_CONTROLLER select ARCH_REQUIRE_GPIOLIB select ARM_GIC + select ARM_PSCI select CLKSRC_MMIO select CLKSRC_OF select COMMON_CLK -- cgit