On Wed, Oct 14, 2015 at 06:40:04PM -0400, Jon Mason wrote: > On Thu, Oct 15, 2015 at 12:26:25AM +0200, Hauke Mehrtens wrote: > > On 10/14/2015 07:47 PM, Kapil Hali wrote: > > > Add SMP support for Broadcom's Northstar Plus SoC, > > > cpu enable method and pen_release procedures. This > > > changes also consolidates iProc family's - BCM NSP > > > and BCM Kona, SMP handling in a common file. > > > > This will probably also work on normal Northstar CPUs without changes. > > I think all that needs to be changed is adding to > arch/arm/boot/dts/bcm4708.dts > > + enable-method = "brcm,bcm-nsp-smp"; > + secondary-boot-reg = <0xffff0400>; > > But I have not been able to confirm that yet. I was able to confirm it on my BCM94708 SVK. I'll send out the patch which enables it shortly. Thanks, Jon > > Thanks, > Jon > > > > > > Northstar Plus SoC is based on ARM Cortex-A9 > > > revision r3p0 which requires configuration for ARM > > > Errata 764369 for SMP. This change adds the needed > > > configuration option. > > > > > > Signed-off-by: Kapil Hali <kapilh@xxxxxxxxxxxx> > > > --- > > > arch/arm/mach-bcm/Kconfig | 2 + > > > arch/arm/mach-bcm/Makefile | 8 +- > > > arch/arm/mach-bcm/bcm_nsp.h | 19 ++++ > > > arch/arm/mach-bcm/headsmp.S | 37 ++++++++ > > > arch/arm/mach-bcm/{kona_smp.c => platsmp.c} | 142 ++++++++++++++++++++++++++-- > > > 5 files changed, 197 insertions(+), 11 deletions(-) > > > create mode 100644 arch/arm/mach-bcm/bcm_nsp.h > > > create mode 100644 arch/arm/mach-bcm/headsmp.S > > > rename arch/arm/mach-bcm/{kona_smp.c => platsmp.c} (63%) > > > > > > diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig > > > index 1679fa4..2e9dbb5 100644 > > > --- a/arch/arm/mach-bcm/Kconfig > > > +++ b/arch/arm/mach-bcm/Kconfig > > > @@ -40,6 +40,8 @@ config ARCH_BCM_NSP > > > select ARCH_BCM_IPROC > > > select ARM_ERRATA_754322 > > > select ARM_ERRATA_775420 > > > + select ARM_ERRATA_764369 if SMP > > > + select HAVE_SMP > > > help > > > Support for Broadcom Northstar Plus SoC. > > > Broadcom Northstar Plus family of SoCs are used for switching control > > > diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile > > > index 892261f..36a4ca30 100644 > > > --- a/arch/arm/mach-bcm/Makefile > > > +++ b/arch/arm/mach-bcm/Makefile > > > @@ -14,7 +14,11 @@ > > > obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o > > > > > > # Northstar Plus > > > -obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o > > > +obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o > > > + > > > +ifeq ($(CONFIG_ARCH_BCM_NSP),y) > > > +obj-$(CONFIG_SMP) += headsmp.o platsmp.o > > > +endif > > > > > > # BCM281XX > > > obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o > > > @@ -23,7 +27,7 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o > > > obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o > > > > > > # BCM281XX and BCM21664 SMP support > > > -obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += kona_smp.o > > > +obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o > > > > > > # BCM281XX and BCM21664 L2 cache control > > > obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o > > > diff --git a/arch/arm/mach-bcm/bcm_nsp.h b/arch/arm/mach-bcm/bcm_nsp.h > > > new file mode 100644 > > > index 0000000..58e1e80 > > > --- /dev/null > > > +++ b/arch/arm/mach-bcm/bcm_nsp.h > > > @@ -0,0 +1,19 @@ > > > +/* > > > + * Copyright (C) 2015 Broadcom Corporation > > > + * > > > + * This program is free software; you can redistribute it and/or > > > + * modify it under the terms of the GNU General Public License as > > > + * published by the Free Software Foundation version 2. > > > + * > > > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > > > + * kind, whether express or implied; without even the implied warranty > > > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + */ > > > + > > > +#ifndef __BCM_NSP_H > > > +#define __BCM_NSP_H > > > + > > > +extern void nsp_secondary_startup(void); > > > + > > > +#endif /* __BCM_NSP_H */ > > > diff --git a/arch/arm/mach-bcm/headsmp.S b/arch/arm/mach-bcm/headsmp.S > > > new file mode 100644 > > > index 0000000..0da13b2 > > > --- /dev/null > > > +++ b/arch/arm/mach-bcm/headsmp.S > > > @@ -0,0 +1,37 @@ > > > +/* > > > + * Copyright (C) 2015 Broadcom Corporation > > > + * > > > + * This program is free software; you can redistribute it and/or > > > + * modify it under the terms of the GNU General Public License as > > > + * published by the Free Software Foundation version 2. > > > + * > > > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > > > + * kind, whether express or implied; without even the implied warranty > > > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + */ > > > + > > > +#include <linux/linkage.h> > > > + > > > +/* > > > + * iProc specific entry point for secondary CPUs. This provides > > > + * a "holding pen" into which all secondary cores are held until > > > + * we are ready for them to initialise. > > > + */ > > > +ENTRY(nsp_secondary_startup) > > > + mrc p15, 0, r0, c0, c0, 5 > > > + and r0, r0, #15 > > > + adr r4, 1f > > > + ldmia r4, {r5, r6} > > > + sub r4, r4, r5 > > > + add r6, r6, r4 > > > +pen: ldr r7, [r6] > > > + cmp r7, r0 > > > + bne pen > > > + > > > + b secondary_startup > > > + > > > +1: .long . > > > + .long pen_release > > > + > > > +ENDPROC(nsp_secondary_startup) > > > diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/platsmp.c > > > similarity index 63% > > > rename from arch/arm/mach-bcm/kona_smp.c > > > rename to arch/arm/mach-bcm/platsmp.c > > > index 66a0465..619030e 100644 > > > --- a/arch/arm/mach-bcm/kona_smp.c > > > +++ b/arch/arm/mach-bcm/platsmp.c > > > @@ -1,5 +1,5 @@ > > > /* > > > - * Copyright (C) 2014 Broadcom Corporation > > > + * Copyright (C) 2014-2015 Broadcom Corporation > > > * Copyright 2014 Linaro Limited > > > * > > > * This program is free software; you can redistribute it and/or > > > @@ -12,16 +12,23 @@ > > > * GNU General Public License for more details. > > > */ > > > > > > -#include <linux/init.h> > > > +#include <linux/cpumask.h> > > > +#include <linux/delay.h> > > > #include <linux/errno.h> > > > +#include <linux/init.h> > > > #include <linux/io.h> > > > +#include <linux/jiffies.h> > > > #include <linux/of.h> > > > #include <linux/sched.h> > > > +#include <linux/smp.h> > > > > > > +#include <asm/cacheflush.h> > > > #include <asm/smp.h> > > > #include <asm/smp_plat.h> > > > #include <asm/smp_scu.h> > > > > > > +#include "bcm_nsp.h" > > > + > > > /* Size of mapped Cortex A9 SCU address space */ > > > #define CORTEX_A9_SCU_SIZE 0x58 > > > > > > @@ -34,6 +41,24 @@ > > > /* I/O address of register used to coordinate secondary core startup */ > > > static u32 secondary_boot; > > > > > > +static DEFINE_SPINLOCK(boot_lock); > > > + > > > +/* > > > + * Write pen_release in a way that is guaranteed to be visible to all > > > + * observers, irrespective of whether they're taking part in coherency > > > + * or not. This is necessary for the hotplug code to work reliably. > > > + */ > > > +static void write_pen_release(int val) > > > +{ > > > + pen_release = val; > > > + /* > > > + * Ensure write to pen_release is visible to the other cores, > > > + * here - primary core > > > + */ > > > + smp_wmb(); > > > + sync_cache_w(&pen_release); > > > +} > > > + > > > /* > > > * Enable the Cortex A9 Snoop Control Unit > > > * > > > @@ -75,6 +100,51 @@ static int __init scu_a9_enable(void) > > > return 0; > > > } > > > > > > +static int nsp_write_lut(void (*secondary_startup) (void)) > > > +{ > > > + void __iomem *sku_rom_lut; > > > + phys_addr_t secondary_startup_phy; > > > + > > > + if (!secondary_boot) { > > > + pr_warn("required secondary boot register not specified\n"); > > > + return -EINVAL; > > > + } > > > + > > > + sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot, > > > + sizeof(secondary_boot)); > > > + if (!sku_rom_lut) { > > > + pr_warn("unable to ioremap SKU-ROM LUT register\n"); > > > + return -ENOMEM; > > > + } > > > + > > > + secondary_startup_phy = virt_to_phys(secondary_startup); > > > + BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX); > > > + > > > + writel_relaxed(secondary_startup_phy, sku_rom_lut); > > > + /* > > > + * Ensure the write is visible to the secondary core. > > > + */ > > > + smp_wmb(); > > > + > > > + iounmap(sku_rom_lut); > > > + > > > + return 0; > > > +} > > > + > > > +static void nsp_secondary_init(unsigned int cpu) > > > +{ > > > + /* > > > + * Let the primary cpu know we are out of holding pen. > > > + */ > > > + write_pen_release(-1); > > > + > > > + /* > > > + * Synchronise with the boot thread. > > > + */ > > > + spin_lock(&boot_lock); > > > + spin_unlock(&boot_lock); > > > +} > > > + > > > static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) > > > { > > > static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; > > > @@ -95,11 +165,11 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) > > > /* > > > * Our secondary enable method requires a "secondary-boot-reg" > > > * property to specify a register address used to request the > > > - * ROM code boot a secondary code. If we have any trouble > > > + * ROM code boot a secondary core. If we have any trouble > > > * getting this we fall back to uniprocessor mode. > > > */ > > > if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) { > > > - pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", > > > + pr_warn("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", > > > node->name); > > > ret = -ENOENT; /* Arrange to disable SMP */ > > > goto out; > > > @@ -115,7 +185,6 @@ out: > > > of_node_put(node); > > > if (ret) { > > > /* Update the CPU present map to reflect uniprocessor mode */ > > > - BUG_ON(ret != -ENOENT); > > > pr_warn("disabling SMP\n"); > > > init_cpu_present(&only_cpu_0); > > > } > > > @@ -139,7 +208,7 @@ out: > > > * - Wait for the secondary boot register to be re-written, which > > > * indicates the secondary core has started. > > > */ > > > -static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) > > > +static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) > > > { > > > void __iomem *boot_reg; > > > phys_addr_t boot_func; > > > @@ -162,7 +231,7 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) > > > boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32)); > > > if (!boot_reg) { > > > pr_err("unable to map boot register for cpu %u\n", cpu_id); > > > - return -ENOSYS; > > > + return -ENOMEM; > > > } > > > > > > /* > > > @@ -191,12 +260,67 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) > > > > > > pr_err("timeout waiting for cpu %u to start\n", cpu_id); > > > > > > - return -ENOSYS; > > > + return -ENXIO; > > > +} > > > + > > > +static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) > > > +{ > > > + unsigned long timeout; > > > + int ret; > > > + > > > + /* > > > + * After wake up, secondary core branches to the startup > > > + * address programmed at SKU ROM LUT location. > > > + */ > > > + ret = nsp_write_lut(nsp_secondary_startup); > > > + if (ret) { > > > + pr_err("unable to write startup addr to SKU ROM LUT\n"); > > > + goto out; > > > + } > > > + > > > + /* > > > + * The secondary processor is waiting to be released from > > > + * the holding pen - release it, then wait for it to flag > > > + * that it has been released by resetting pen_release. > > > + */ > > > + spin_lock(&boot_lock); > > > + > > > + write_pen_release(cpu_logical_map(cpu)); > > > + /* > > > + * Send an Event to wake up the secondary core which is in > > > + * WFE state. Updated pen_release should also be visible to > > > + * the secondary core. > > > + */ > > > + dsb_sev(); > > > + > > > + timeout = jiffies + (1 * HZ); > > > + while (time_before(jiffies, timeout)) { > > > + /* Make sure loads on other CPU is visible */ > > > + smp_rmb(); > > > + if (pen_release == -1) > > > + break; > > > + > > > + udelay(10); > > > + } > > > + > > > + spin_unlock(&boot_lock); > > > > Why is this boot_lock needed? As far as I understand it asserts that > > both CPUs leave nsp_boot_secondary() and nsp_secondary_init() at the > > same time. > > > > > + > > > + ret = pen_release != -1 ? -ENXIO : 0; > > > + > > > +out: > > > + return ret; > > > } > > > > > > static struct smp_operations bcm_smp_ops __initdata = { > > > .smp_prepare_cpus = bcm_smp_prepare_cpus, > > > - .smp_boot_secondary = bcm_boot_secondary, > > > + .smp_boot_secondary = kona_boot_secondary, > > > }; > > > CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", > > > &bcm_smp_ops); > > > + > > > +struct smp_operations nsp_smp_ops __initdata = { > > > + .smp_prepare_cpus = bcm_smp_prepare_cpus, > > > + .smp_secondary_init = nsp_secondary_init, > > > + .smp_boot_secondary = nsp_boot_secondary, > > > +}; > > > +CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); > > > > > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html