Message ID | 1426649042-30547-3-git-send-email-wens@csie.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Mar 18, 2015 at 11:24:01AM +0800, Chen-Yu Tsai wrote: > The A23 is a dual 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: Chen-Yu Tsai <wens@csie.org> > --- > > We can't use of_io_request_and_map() here, as it will conflict > with PRCM, and leave us without a serial console. > > I think a proper way to solve this would be a syscon device or > something like the mfd-simple device posted by Arnd. > > --- > Documentation/devicetree/bindings/arm/cpus.txt | 1 + > arch/arm/mach-sunxi/platsmp.c | 69 ++++++++++++++++++++++++++ > 2 files changed, 70 insertions(+) > > diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt > index 8b9e0a95de31..40202d85b132 100644 > --- a/Documentation/devicetree/bindings/arm/cpus.txt > +++ b/Documentation/devicetree/bindings/arm/cpus.txt > @@ -188,6 +188,7 @@ nodes to be present and contain the properties described below. > # On ARM 32-bit systems this property is optional and > can be one of: > "allwinner,sun6i-a31" > + "allwinner,sun8i-a23" > "arm,psci" > "brcm,brahma-b15" > "marvell,armada-375-smp" > diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c > index 587b0468efcc..e8483ec79d67 100644 > --- a/arch/arm/mach-sunxi/platsmp.c > +++ b/arch/arm/mach-sunxi/platsmp.c > @@ -121,3 +121,72 @@ static struct smp_operations sun6i_smp_ops __initdata = { > .smp_boot_secondary = sun6i_smp_boot_secondary, > }; > CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); > + > +static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus) > +{ > + struct device_node *node; > + > + node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm"); > + if (!node) { > + pr_err("Missing A23 PRCM node in the device tree\n"); > + return; > + } > + > + prcm_membase = of_iomap(node, 0); > + if (!prcm_membase) { > + pr_err("Couldn't map A23 PRCM registers\n"); > + return; > + } > + > + node = of_find_compatible_node(NULL, NULL, > + "allwinner,sun8i-a23-cpuconfig"); > + if (!node) { > + pr_err("Missing A23 CPU config node in the device tree\n"); > + return; > + } > + > + cpucfg_membase = of_iomap(node, 0); > + if (!cpucfg_membase) > + pr_err("Couldn't map A23 CPU config registers\n"); > + > +} > + > +static int sun8i_smp_boot_secondary(unsigned int cpu, > + struct task_struct *idle) > +{ > + u32 reg; > + > + if (!(prcm_membase && cpucfg_membase)) > + return -EFAULT; > + > + spin_lock(&cpu_lock); > + > + /* Set CPU boot address */ > + writel(virt_to_phys(secondary_startup), > + cpucfg_membase + CPUCFG_PRIVATE0_REG); One question I couldn't find any answer to is that does the SMP bit is set in secondary_startup? I couldn't find where it was set, but it still looks like the right thing to do, so I would expect the code to do that. Thanks! Maxime
On Wed, Mar 18, 2015 at 6:29 PM, Maxime Ripard <maxime.ripard@free-electrons.com> wrote: > On Wed, Mar 18, 2015 at 11:24:01AM +0800, Chen-Yu Tsai wrote: >> The A23 is a dual 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: Chen-Yu Tsai <wens@csie.org> >> --- >> >> We can't use of_io_request_and_map() here, as it will conflict >> with PRCM, and leave us without a serial console. >> >> I think a proper way to solve this would be a syscon device or >> something like the mfd-simple device posted by Arnd. >> >> --- >> Documentation/devicetree/bindings/arm/cpus.txt | 1 + >> arch/arm/mach-sunxi/platsmp.c | 69 ++++++++++++++++++++++++++ >> 2 files changed, 70 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt >> index 8b9e0a95de31..40202d85b132 100644 >> --- a/Documentation/devicetree/bindings/arm/cpus.txt >> +++ b/Documentation/devicetree/bindings/arm/cpus.txt >> @@ -188,6 +188,7 @@ nodes to be present and contain the properties described below. >> # On ARM 32-bit systems this property is optional and >> can be one of: >> "allwinner,sun6i-a31" >> + "allwinner,sun8i-a23" >> "arm,psci" >> "brcm,brahma-b15" >> "marvell,armada-375-smp" >> diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c >> index 587b0468efcc..e8483ec79d67 100644 >> --- a/arch/arm/mach-sunxi/platsmp.c >> +++ b/arch/arm/mach-sunxi/platsmp.c >> @@ -121,3 +121,72 @@ static struct smp_operations sun6i_smp_ops __initdata = { >> .smp_boot_secondary = sun6i_smp_boot_secondary, >> }; >> CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); >> + >> +static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus) >> +{ >> + struct device_node *node; >> + >> + node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm"); >> + if (!node) { >> + pr_err("Missing A23 PRCM node in the device tree\n"); >> + return; >> + } >> + >> + prcm_membase = of_iomap(node, 0); >> + if (!prcm_membase) { >> + pr_err("Couldn't map A23 PRCM registers\n"); >> + return; >> + } >> + >> + node = of_find_compatible_node(NULL, NULL, >> + "allwinner,sun8i-a23-cpuconfig"); >> + if (!node) { >> + pr_err("Missing A23 CPU config node in the device tree\n"); >> + return; >> + } >> + >> + cpucfg_membase = of_iomap(node, 0); >> + if (!cpucfg_membase) >> + pr_err("Couldn't map A23 CPU config registers\n"); >> + >> +} >> + >> +static int sun8i_smp_boot_secondary(unsigned int cpu, >> + struct task_struct *idle) >> +{ >> + u32 reg; >> + >> + if (!(prcm_membase && cpucfg_membase)) >> + return -EFAULT; >> + >> + spin_lock(&cpu_lock); >> + >> + /* Set CPU boot address */ >> + writel(virt_to_phys(secondary_startup), >> + cpucfg_membase + CPUCFG_PRIVATE0_REG); > > One question I couldn't find any answer to is that does the SMP bit is > set in secondary_startup? > > I couldn't find where it was set, but it still looks like the right > thing to do, so I would expect the code to do that. I don't see it either. The sun8i code is just the sun6i code with the power clamps removed. And sun6i secondary_startup was removed some time ago in commit 1146b600044d ("ARM: sunxi: fix build for THUMB2_KERNEL"). ChenYu
Hi Kevin, On Thu, Mar 19, 2015 at 12:05:06PM +0800, kevin.z.m.zh@gmail.com wrote: > >> One question I couldn't find any answer to is that does the SMP bit is > >> set in secondary_startup? > >> > >> I couldn't find where it was set, but it still looks like the right > >> thing to do, so I would expect the code to do that. > > > > I don't see it either. The sun8i code is just the sun6i code with the > > power clamps removed. And sun6i secondary_startup was removed some time > > ago in commit 1146b600044d ("ARM: sunxi: fix build for THUMB2_KERNEL"). > > > > ChenYu > > The SMP bit should be set in the function of "__v7_ca7mp_setup", which is located > in the file: > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S?id=refs/tags/v4.0-rc4 > I'm not sure if this is your discussion. It is, but I wasn't seeing it called anywhere in the secondary_startup code path. I was expecting a direct call, but it looks like it's a dynamic call, with a function-pointer like call, that is indeed run both in the kernel entry point and the secondary_startup. https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/head.S?id=refs/tags/v4.0-rc4#n389 Thanks! Maxime
Hi Maxime, On Thu, Mar 19, 2015 at 2:18 AM, maxime.ripard <maxime.ripard@free-electrons.com> wrote: > Hi Kevin, > > On Thu, Mar 19, 2015 at 12:05:06PM +0800, kevin.z.m.zh@gmail.com wrote: >> >> One question I couldn't find any answer to is that does the SMP bit is >> >> set in secondary_startup? >> >> >> >> I couldn't find where it was set, but it still looks like the right >> >> thing to do, so I would expect the code to do that. >> > >> > I don't see it either. The sun8i code is just the sun6i code with the >> > power clamps removed. And sun6i secondary_startup was removed some time >> > ago in commit 1146b600044d ("ARM: sunxi: fix build for THUMB2_KERNEL"). >> > >> > ChenYu >> >> The SMP bit should be set in the function of "__v7_ca7mp_setup", which is located >> in the file: >> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S?id=refs/tags/v4.0-rc4 >> I'm not sure if this is your discussion. > > It is, but I wasn't seeing it called anywhere in the secondary_startup > code path. > > I was expecting a direct call, but it looks like it's a dynamic call, > with a function-pointer like call, that is indeed run both in the > kernel entry point and the secondary_startup. > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/head.S?id=refs/tags/v4.0-rc4#n389 Are we waiting for Marc's input on this? ChenYu
On Wed, Mar 25, 2015 at 04:39:08PM -0700, Chen-Yu Tsai wrote: > Hi Maxime, > > On Thu, Mar 19, 2015 at 2:18 AM, maxime.ripard > <maxime.ripard@free-electrons.com> wrote: > > Hi Kevin, > > > > On Thu, Mar 19, 2015 at 12:05:06PM +0800, kevin.z.m.zh@gmail.com wrote: > >> >> One question I couldn't find any answer to is that does the SMP bit is > >> >> set in secondary_startup? > >> >> > >> >> I couldn't find where it was set, but it still looks like the right > >> >> thing to do, so I would expect the code to do that. > >> > > >> > I don't see it either. The sun8i code is just the sun6i code with the > >> > power clamps removed. And sun6i secondary_startup was removed some time > >> > ago in commit 1146b600044d ("ARM: sunxi: fix build for THUMB2_KERNEL"). > >> > > >> > ChenYu > >> > >> The SMP bit should be set in the function of "__v7_ca7mp_setup", which is located > >> in the file: > >> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S?id=refs/tags/v4.0-rc4 > >> I'm not sure if this is your discussion. > > > > It is, but I wasn't seeing it called anywhere in the secondary_startup > > code path. > > > > I was expecting a direct call, but it looks like it's a dynamic call, > > with a function-pointer like call, that is indeed run both in the > > kernel entry point and the secondary_startup. > > > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/head.S?id=refs/tags/v4.0-rc4#n389 > > Are we waiting for Marc's input on this? Hmm, no, not really, I just forgot about it :) I'll merge the patches. Maxime
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 8b9e0a95de31..40202d85b132 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -188,6 +188,7 @@ nodes to be present and contain the properties described below. # On ARM 32-bit systems this property is optional and can be one of: "allwinner,sun6i-a31" + "allwinner,sun8i-a23" "arm,psci" "brcm,brahma-b15" "marvell,armada-375-smp" diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index 587b0468efcc..e8483ec79d67 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -121,3 +121,72 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_boot_secondary = sun6i_smp_boot_secondary, }; CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); + +static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm"); + if (!node) { + pr_err("Missing A23 PRCM node in the device tree\n"); + return; + } + + prcm_membase = of_iomap(node, 0); + if (!prcm_membase) { + pr_err("Couldn't map A23 PRCM registers\n"); + return; + } + + node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a23-cpuconfig"); + if (!node) { + pr_err("Missing A23 CPU config node in the device tree\n"); + return; + } + + cpucfg_membase = of_iomap(node, 0); + if (!cpucfg_membase) + pr_err("Couldn't map A23 CPU config registers\n"); + +} + +static int sun8i_smp_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + u32 reg; + + if (!(prcm_membase && cpucfg_membase)) + return -EFAULT; + + spin_lock(&cpu_lock); + + /* Set CPU boot address */ + writel(virt_to_phys(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); + + /* 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)); + + spin_unlock(&cpu_lock); + + return 0; +} + +struct smp_operations sun8i_smp_ops __initdata = { + .smp_prepare_cpus = sun8i_smp_prepare_cpus, + .smp_boot_secondary = sun8i_smp_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(sun8i_a23_smp, "allwinner,sun8i-a23", &sun8i_smp_ops);
The A23 is a dual 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: Chen-Yu Tsai <wens@csie.org> --- We can't use of_io_request_and_map() here, as it will conflict with PRCM, and leave us without a serial console. I think a proper way to solve this would be a syscon device or something like the mfd-simple device posted by Arnd. --- Documentation/devicetree/bindings/arm/cpus.txt | 1 + arch/arm/mach-sunxi/platsmp.c | 69 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+)