Hi Fang, On Sun, Sep 22, 2013 at 08:21:26PM +0800, Fan Rong wrote: > Signed-off-by: Fan Rong <cin...@gmail.com> > --- > arch/arm/mach-sunxi/Makefile | 2 + > arch/arm/mach-sunxi/headsmp.S | 17 +++++++++ > arch/arm/mach-sunxi/platsmp.c | 86 > +++++++++++++++++++++++++++++++++++++++++++ > arch/arm/mach-sunxi/sunxi.c | 31 ++++++++++++++++ > 4 files changed, 136 insertions(+) > create mode 100644 arch/arm/mach-sunxi/headsmp.S > create mode 100644 arch/arm/mach-sunxi/platsmp.c > > diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile > index 93bebfc..d7f1ef4 100644 > --- a/arch/arm/mach-sunxi/Makefile > +++ b/arch/arm/mach-sunxi/Makefile > @@ -1 +1,3 @@ > obj-$(CONFIG_ARCH_SUNXI) += sunxi.o > +obj-$(CONFIG_ARCH_SUNXI) += platsmp.o > +obj-$(CONFIG_ARCH_SUNXI) += headsmp.o > diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S > new file mode 100644 > index 0000000..5899399 > --- /dev/null > +++ b/arch/arm/mach-sunxi/headsmp.S > @@ -0,0 +1,17 @@ > +/* > + * SMP support for A20 > + * > + * Copyright (C) 2013 Fan Rong <cin...@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/linkage.h> > +#include <linux/init.h> > + > +.section ".text.head", "ax" ENTRY(sun7i_secondary_startup) > +msr cpsr_fsxc, > +#0xd3 > +b secondary_startup ENDPROC(sun7i_secondary_startup) > diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c > new file mode 100644 > index 0000000..5e3e994 > --- /dev/null > +++ b/arch/arm/mach-sunxi/platsmp.c > @@ -0,0 +1,86 @@ > +/* > + * linux/arch/arm/mach-sun7i/platsmp.c > + * > + * Copyright (C) 2013 Fan Rong <cin...@gmail.com> > + * All Rights Reserved > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#include <linux/init.h> > +#include <linux/errno.h> > +#include <linux/smp.h> > +#include <linux/io.h> > +#include <linux/delay.h> > +#include <linux/smp.h> > + > +extern void __iomem *sunxi7i_cc_base;
Please use sun7i here as well. > +void sun7i_secondary_startup(void); > + > +/* > + * CPUCFG > + */ > +#define SUN7I_CPUCFG_BOOTADDR 0x01a4 > + > +#define SUN7I_CPUCFG_GENCTL 0x0184 > +#define SUN7I_CPUCFG_DBGCTL0 0x01e0 > +#define SUN7I_CPUCFG_DBGCTL1 0x01e4 > + > +#define SUN7I_CPU1_PWR_CLAMP 0x01b0 > +#define SUN7I_CPU1_PWROFF_REG 0x01b4 > +#define SUN7I_CPUX_RESET_CTL(x) (0x40 + (x)*0x40) > + > +static int sun7i_boot_secondary(unsigned int cpu, struct task_struct *idle) > +{ > + long paddr; > + uint32_t pwr_reg; > + uint32_t j = 0xff << 1; > + if (!sunxi7i_cc_base) { > + pr_debug("error map cpu configure\n"); > + return -ENOSYS; > + } > + /* Set boot addr */ > + paddr = virt_to_phys(sun7i_secondary_startup); > + writel(paddr, sunxi7i_cc_base + SUN7I_CPUCFG_BOOTADDR); > + > + /* Assert cpu core reset */ > + writel(0, sunxi7i_cc_base + SUN7I_CPUX_RESET_CTL(cpu)); > + > + /* Ensure CPU reset also invalidates L1 caches */ > + pwr_reg = readl(sunxi7i_cc_base + SUN7I_CPUCFG_GENCTL); > + pwr_reg &= ~ BIT(cpu); > + writel(pwr_reg, sunxi7i_cc_base + SUN7I_CPUCFG_GENCTL); > + > + /* DBGPWRDUP hold low */ > + pwr_reg = readl(sunxi7i_cc_base + SUN7I_CPUCFG_DBGCTL1); > + pwr_reg &= ~ BIT(cpu); > + writel(pwr_reg, sunxi7i_cc_base + SUN7I_CPUCFG_DBGCTL1); > + > + /* Ramp up power to CPU1 */ > + do { > + writel(j, sunxi7i_cc_base + SUN7I_CPU1_PWR_CLAMP); > + j = j >> 1; > + } while (j != 0); > + > + mdelay(10); > + > + pwr_reg = readl(sunxi7i_cc_base + SUN7I_CPU1_PWROFF_REG); > + pwr_reg &= ~1; > + writel(pwr_reg, sunxi7i_cc_base + SUN7I_CPU1_PWROFF_REG); > + mdelay(1); > + > + /* Release CPU reset */ > + writel(3, sunxi7i_cc_base + SUN7I_CPUX_RESET_CTL(cpu)); > + > + /* Unlock CPU */ > + pwr_reg = readl(sunxi7i_cc_base + SUN7I_CPUCFG_DBGCTL1); > + pwr_reg |= BIT(cpu); > + writel(pwr_reg, sunxi7i_cc_base + SUN7I_CPUCFG_DBGCTL1); > + > + return 0; > +} > + > +struct smp_operations sun7i_smp_ops __initdata = { > + .smp_boot_secondary = sun7i_boot_secondary, > +}; > diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c > index e79fb34..a692350 100644 > --- a/arch/arm/mach-sunxi/sunxi.c > +++ b/arch/arm/mach-sunxi/sunxi.c > @@ -26,6 +26,8 @@ > #include <asm/mach/map.h> > #include <asm/system_misc.h> > > +extern struct smp_operations sun7i_smp_ops; > + > #define SUN4I_WATCHDOG_CTRL_REG 0x00 > #define SUN4I_WATCHDOG_CTRL_RESTART BIT(0) > #define SUN4I_WATCHDOG_MODE_REG 0x04 > @@ -42,6 +44,14 @@ > #define SUN6I_WATCHDOG1_MODE_ENABLE BIT(0) > > static void __iomem *wdt_base; > +/* > + * CPU Configure module support > + * 1: Software reset for smp cpus > + * 2: Configure for smp cpus including boot. > + * 3: Three 64-bit idle counters and two 64-bit common counters > + * it is needed for smp cpus > + */ > +void __iomem *sunxi7i_cc_base; /*CPU Configure Base*/ > > static void sun4i_restart(enum reboot_mode mode, const char *cmd) > { > @@ -98,6 +108,11 @@ static struct of_device_id sunxi_restart_ids[] = { > { /*sentinel*/ } > }; > > +static struct of_device_id sunxi_cc_ids[] = { > + { .compatible = "allwinner,sun7i-a20-cpuconfig"}, > + { /*sentinel*/ } > +}; > + > static void sunxi_setup_restart(void) > { > const struct of_device_id *of_id; > @@ -138,7 +153,23 @@ static const char * const sunxi_board_dt_compat[] = { > NULL, > }; > > +static int __init sunxi_init_cpuconfig_map(void) > +{ > + struct device_node *np; > + > + np = of_find_matching_node(NULL, sunxi_cc_ids); > + if (WARN(!np, "unable to setup cup configure")) > + return -ENOSYS; > + sunxi7i_cc_base = of_iomap(np, 0); > + if (WARN(!sunxi7i_cc_base, "failed to map cup configure base address")) > + return -ENOSYS; > + return 0; > +} > + > +early_initcall(sunxi_init_cpuconfig_map); You still haven't said why you don't want to use smp_init_cpus there. > + > DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") > + .smp = smp_ops(sun7i_smp_ops), Please align the "=" with the rest of the structure, and please rebase on top of my "ARM: sunxi: Split out the DT machines for sun6i and sun7i" patch. Thanks a lot, Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
signature.asc
Description: Digital signature