* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-17 19:18 [PATCHv1] arm:socfpga: Enable SMP for socfpga dinguyen at altera.com
@ 2012-10-17 19:07 ` Rob Herring
2012-10-17 23:02 ` Pavel Machek
2012-10-18 3:34 ` Dinh Nguyen
0 siblings, 2 replies; 7+ messages in thread
From: Rob Herring @ 2012-10-17 19:07 UTC (permalink / raw)
To: linux-arm-kernel
On 10/17/2012 02:18 PM, dinguyen at altera.com wrote:
> From: Dinh Nguyen <dinguyen@altera.com>
>
> Enable SMP for the SOCFPGA platform.
>
> Signed-off-by: Pavel Machek <pavel@denx.de>
> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> ---
> arch/arm/boot/dts/socfpga.dtsi | 10 ++
> arch/arm/configs/socfpga_defconfig | 9 +-
Does the multi_v7_defconfig not work for you?
> arch/arm/mach-socfpga/Kconfig | 1 +
> arch/arm/mach-socfpga/Makefile | 3 +
> arch/arm/mach-socfpga/headsmp.S | 64 +++++++++++
> arch/arm/mach-socfpga/include/mach/core.h | 33 ++++++
Move core.h to mach-socfpga.
> arch/arm/mach-socfpga/platsmp.c | 166 +++++++++++++++++++++++++++++
> arch/arm/mach-socfpga/socfpga.c | 33 +++++-
> 8 files changed, 315 insertions(+), 4 deletions(-)
> create mode 100644 arch/arm/mach-socfpga/headsmp.S
> create mode 100644 arch/arm/mach-socfpga/include/mach/core.h
> create mode 100644 arch/arm/mach-socfpga/platsmp.c
>
> diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
> index 0772f57..19aec42 100644
> --- a/arch/arm/boot/dts/socfpga.dtsi
> +++ b/arch/arm/boot/dts/socfpga.dtsi
> @@ -143,5 +143,15 @@
> reg-shift = <2>;
> reg-io-width = <4>;
> };
> +
> + rstmgr at ffd05000 {
> + compatible = "altr,rst-mgr";
> + reg = <0xffd05000 0x1000>;
> + };
> +
> + sysmgr at ffd08000 {
> + compatible = "altr,sys-mgr";
> + reg = <0xffd08000 0x4000>;
> + };
Bindings need documentation.
> };
> };
> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> index 0ac1293..349ac22 100644
> --- a/arch/arm/configs/socfpga_defconfig
> +++ b/arch/arm/configs/socfpga_defconfig
> @@ -1,5 +1,5 @@
> CONFIG_EXPERIMENTAL=y
> -CONFIG_SYSVIPC=y
> +CONFIG_NO_HZ=y
> CONFIG_IKCONFIG=y
> CONFIG_IKCONFIG_PROC=y
> CONFIG_LOG_BUF_SHIFT=14
> @@ -16,10 +16,13 @@ CONFIG_MODULE_UNLOAD=y
> # CONFIG_IOSCHED_DEADLINE is not set
> # CONFIG_IOSCHED_CFQ is not set
> CONFIG_ARCH_SOCFPGA=y
> -CONFIG_MACH_SOCFPGA_CYCLONE5=y
> -CONFIG_ARM_THUMBEE=y
> +# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
> # CONFIG_CACHE_L2X0 is not set
> CONFIG_HIGH_RES_TIMERS=y
> +CONFIG_SMP=y
> +CONFIG_ARM_ARCH_TIMER=y
> +CONFIG_HIGHMEM=y
> +CONFIG_HIGHPTE=y
> CONFIG_VMSPLIT_2G=y
> CONFIG_NR_CPUS=2
> CONFIG_AEABI=y
> diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
> index 803a328..566e804 100644
> --- a/arch/arm/mach-socfpga/Kconfig
> +++ b/arch/arm/mach-socfpga/Kconfig
> @@ -12,5 +12,6 @@ config ARCH_SOCFPGA
> select GENERIC_CLOCKEVENTS
> select GPIO_PL061 if GPIOLIB
> select HAVE_ARM_SCU
> + select HAVE_SMP
> select SPARSE_IRQ
> select USE_OF
> diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
> index 4fb9324..61b1266 100644
> --- a/arch/arm/mach-socfpga/Makefile
> +++ b/arch/arm/mach-socfpga/Makefile
> @@ -2,4 +2,7 @@
> # Makefile for the linux kernel.
> #
>
> +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
> +
This can be removed if core.h is moved.
> obj-y := socfpga.o
> +obj-$(CONFIG_SMP) += headsmp.o platsmp.o
> diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
> new file mode 100644
> index 0000000..b3a24db
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/headsmp.S
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2003 ARM Limited
> + * Copyright (c) u-boot contributors
> + * Copyright (c) 2012 Pavel Machek <pavel@denx.de>
> + *
> + * 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>
> +
> + __INIT
> +
> +#define CPU1_START_ADDR 0xffd08010
> +
> +ENTRY(secondary_trampoline)
This appears to be your reset code at phys addr 0. How does core 0 boot
if you are copying this to 0?
> + /* From u-boot: start.S */
> + mrs r0, cpsr
> + bic r0, r0, #0x1f
> + orr r0, r0, #0xd3
> + msr cpsr,r0
> +
> +/*************************************************************************
> + *
> + * cpu_init_cp15
> + ** Copyright (c) u-boot contributors
> + * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
> + * CONFIG_SYS_ICACHE_OFF is defined.
> + *
> + *************************************************************************/
> +ENTRY(cpu_init_cp15)
> + /*
> + * Invalidate L1 I/D
> + */
> + mov r0, #0 @ set up for MCR
> + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
> + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
> + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
> + mcr p15, 0, r0, c7, c10, 4 @ DSB
> + mcr p15, 0, r0, c7, c5, 4 @ ISB
> +
> + /*
> + * disable MMU stuff and caches
> + */
> + mrc p15, 0, r0, c1, c0, 0
> + bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
> + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
> + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
> + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
> + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
All this should get done by v7_setup.
> + mcr p15, 0, r0, c1, c0, 0
> +
> + movw r0, #:lower16:CPU1_START_ADDR
> + movt r0, #:upper16:CPU1_START_ADDR
> +
> + ldr r1, [r0]
> + bx r1
> +
> +ENTRY(secondary_trampoline_end)
> +
> + .align
> + .long pen_release
> +
> diff --git a/arch/arm/mach-socfpga/include/mach/core.h b/arch/arm/mach-socfpga/include/mach/core.h
> new file mode 100644
> index 0000000..74a4949
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/include/mach/core.h
> @@ -0,0 +1,33 @@
> +/*
> + * Copyright 2012 Pavel Machek <pavel@denx.de>
> + * Copyright (C) 2012 Altera 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; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#ifndef __MACH_CORE_H
> +#define __MACH_CORE_H
> +
> +extern void secondary_startup(void);
> +extern void __iomem *socfpga_scu_base_addr;
> +
> +extern void socfpga_init_clocks(void);
> +extern void socfpga_sysmgr_init(void);
> +
> +extern struct smp_operations socfpga_smp_ops;
> +
> +#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
> +
> +#endif
> diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
> new file mode 100644
> index 0000000..59d7069
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/platsmp.c
> @@ -0,0 +1,166 @@
> +/*
> + * Copyright 2010-2011 Calxeda, Inc.
> + * Copyright 2012 Pavel Machek <pavel@denx.de>
> + * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
> + * Copyright (C) 2012 Altera Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/smp.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/hardware/gic.h>
> +#include <asm/smp_scu.h>
> +#include <asm/smp_plat.h>
> +
> +#include <mach/core.h>
> +
> +static void __iomem *sys_manager_base_addr;
> +static void __iomem *rst_manager_base_addr;
> +
> +static DEFINE_SPINLOCK(boot_lock);
> +
> +static void __cpuinit socfpga_secondary_init(unsigned int cpu)
> +{
> + /*
> + * if any interrupts are already enabled for the primary
> + * core (e.g. timer irq), then they will not have been enabled
> + * for us: do so
> + */
> + gic_secondary_init(0);
> +
> + /*
> + * let the primary processor know we're out of the
> + * pen, then head off into the C entry point
> + */
> + pen_release = -1;
> + smp_wmb();
> +
> + /*
> + * Synchronise with the boot thread.
> + */
> + spin_lock(&boot_lock);
> + spin_unlock(&boot_lock);
> +}
> +
> +static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
> +{
> + unsigned long timeout;
> + extern char secondary_trampoline, secondary_trampoline_end;
> +
> + int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
> +
> + /*
> + * Set synchronisation state between this boot processor
> + * and the secondary one
> + */
> + spin_lock(&boot_lock);
> +
> + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
> +
> + __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
> +
> + pen_release = 0;
> + flush_cache_all();
> + smp_wmb();
> + outer_clean_range(0, trampoline_size);
> +
> + /* This will release CPU #1 out of reset.*/
> + __raw_writel(0, rst_manager_base_addr + 0x10);
> +
> + timeout = jiffies + (1 * HZ);
> + while (time_before(jiffies, timeout)) {
> + smp_rmb();
> + if (pen_release == -1)
> + break;
> +
> + udelay(10);
> + }
> +
> + /*
> + * now the secondary core is starting up let it run its
> + * calibrations, then wait for it to finish
> + */
> + spin_unlock(&boot_lock);
> + return pen_release != -1 ? -ENOSYS : 0;
You don't need any of this if you can reset secondary cores on hotplug.
Rob
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
@ 2012-10-17 19:18 dinguyen at altera.com
2012-10-17 19:07 ` Rob Herring
0 siblings, 1 reply; 7+ messages in thread
From: dinguyen at altera.com @ 2012-10-17 19:18 UTC (permalink / raw)
To: linux-arm-kernel
From: Dinh Nguyen <dinguyen@altera.com>
Enable SMP for the SOCFPGA platform.
Signed-off-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
---
arch/arm/boot/dts/socfpga.dtsi | 10 ++
arch/arm/configs/socfpga_defconfig | 9 +-
arch/arm/mach-socfpga/Kconfig | 1 +
arch/arm/mach-socfpga/Makefile | 3 +
arch/arm/mach-socfpga/headsmp.S | 64 +++++++++++
arch/arm/mach-socfpga/include/mach/core.h | 33 ++++++
arch/arm/mach-socfpga/platsmp.c | 166 +++++++++++++++++++++++++++++
arch/arm/mach-socfpga/socfpga.c | 33 +++++-
8 files changed, 315 insertions(+), 4 deletions(-)
create mode 100644 arch/arm/mach-socfpga/headsmp.S
create mode 100644 arch/arm/mach-socfpga/include/mach/core.h
create mode 100644 arch/arm/mach-socfpga/platsmp.c
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 0772f57..19aec42 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -143,5 +143,15 @@
reg-shift = <2>;
reg-io-width = <4>;
};
+
+ rstmgr at ffd05000 {
+ compatible = "altr,rst-mgr";
+ reg = <0xffd05000 0x1000>;
+ };
+
+ sysmgr at ffd08000 {
+ compatible = "altr,sys-mgr";
+ reg = <0xffd08000 0x4000>;
+ };
};
};
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index 0ac1293..349ac22 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -1,5 +1,5 @@
CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -16,10 +16,13 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_SOCFPGA=y
-CONFIG_MACH_SOCFPGA_CYCLONE5=y
-CONFIG_ARM_THUMBEE=y
+# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
# CONFIG_CACHE_L2X0 is not set
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
CONFIG_VMSPLIT_2G=y
CONFIG_NR_CPUS=2
CONFIG_AEABI=y
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 803a328..566e804 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -12,5 +12,6 @@ config ARCH_SOCFPGA
select GENERIC_CLOCKEVENTS
select GPIO_PL061 if GPIOLIB
select HAVE_ARM_SCU
+ select HAVE_SMP
select SPARSE_IRQ
select USE_OF
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 4fb9324..61b1266 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -2,4 +2,7 @@
# Makefile for the linux kernel.
#
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
obj-y := socfpga.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
new file mode 100644
index 0000000..b3a24db
--- /dev/null
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003 ARM Limited
+ * Copyright (c) u-boot contributors
+ * Copyright (c) 2012 Pavel Machek <pavel@denx.de>
+ *
+ * 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>
+
+ __INIT
+
+#define CPU1_START_ADDR 0xffd08010
+
+ENTRY(secondary_trampoline)
+ /* From u-boot: start.S */
+ mrs r0, cpsr
+ bic r0, r0, #0x1f
+ orr r0, r0, #0xd3
+ msr cpsr,r0
+
+/*************************************************************************
+ *
+ * cpu_init_cp15
+ ** Copyright (c) u-boot contributors
+ * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
+ * CONFIG_SYS_ICACHE_OFF is defined.
+ *
+ *************************************************************************/
+ENTRY(cpu_init_cp15)
+ /*
+ * Invalidate L1 I/D
+ */
+ mov r0, #0 @ set up for MCR
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
+ mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
+ mcr p15, 0, r0, c7, c10, 4 @ DSB
+ mcr p15, 0, r0, c7, c5, 4 @ ISB
+
+ /*
+ * disable MMU stuff and caches
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
+ bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
+ orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
+ orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
+ orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
+ mcr p15, 0, r0, c1, c0, 0
+
+ movw r0, #:lower16:CPU1_START_ADDR
+ movt r0, #:upper16:CPU1_START_ADDR
+
+ ldr r1, [r0]
+ bx r1
+
+ENTRY(secondary_trampoline_end)
+
+ .align
+ .long pen_release
+
diff --git a/arch/arm/mach-socfpga/include/mach/core.h b/arch/arm/mach-socfpga/include/mach/core.h
new file mode 100644
index 0000000..74a4949
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/core.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Copyright (C) 2012 Altera 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MACH_CORE_H
+#define __MACH_CORE_H
+
+extern void secondary_startup(void);
+extern void __iomem *socfpga_scu_base_addr;
+
+extern void socfpga_init_clocks(void);
+extern void socfpga_sysmgr_init(void);
+
+extern struct smp_operations socfpga_smp_ops;
+
+#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
+
+#endif
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
new file mode 100644
index 0000000..59d7069
--- /dev/null
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+
+#include <mach/core.h>
+
+static void __iomem *sys_manager_base_addr;
+static void __iomem *rst_manager_base_addr;
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static void __cpuinit socfpga_secondary_init(unsigned int cpu)
+{
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ pen_release = -1;
+ smp_wmb();
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+ extern char secondary_trampoline, secondary_trampoline_end;
+
+ int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+
+ /*
+ * Set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+
+ __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
+
+ pen_release = 0;
+ flush_cache_all();
+ smp_wmb();
+ outer_clean_range(0, trampoline_size);
+
+ /* This will release CPU #1 out of reset.*/
+ __raw_writel(0, rst_manager_base_addr + 0x10);
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ smp_rmb();
+ if (pen_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+ return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init socfpga_smp_init_cpus(void)
+{
+ unsigned int i, ncores;
+
+ ncores = scu_get_core_count(socfpga_scu_base_addr);
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ /* sanity check */
+ if (ncores > num_possible_cpus()) {
+ pr_warn("socfpga: no. of cores (%d) greater than configured"
+ "maximum of %d - clipping\n", ncores, num_possible_cpus());
+ ncores = num_possible_cpus();
+ }
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
+{
+ scu_enable(socfpga_scu_base_addr);
+}
+
+void __init socfpga_sysmgr_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
+ sys_manager_base_addr = of_iomap(np, 0);
+
+ np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
+ rst_manager_base_addr = of_iomap(np, 0);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void socfpga_cpu_die(unsigned int cpu)
+{
+ cpu_do_idle();
+
+ /* We should have never returned from idle */
+ panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+struct smp_operations socfpga_smp_ops __initdata = {
+ .smp_init_cpus = socfpga_smp_init_cpus,
+ .smp_prepare_cpus = socfpga_smp_prepare_cpus,
+ .smp_secondary_init = socfpga_secondary_init,
+ .smp_boot_secondary = socfpga_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = socfpga_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index f01e1eb..20cdfdf 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -21,8 +21,34 @@
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
-extern void socfpga_init_clocks(void);
+#include <mach/core.h>
+
+void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+ .virtual = SOCFPGA_SCU_VIRT_BASE,
+ .pfn = 0, /* run-time */
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+};
+
+static void __init socfpga_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+}
+
+static void __init socfpga_map_io(void)
+{
+ socfpga_scu_map_io();
+}
const static struct of_device_id irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
@@ -32,6 +58,9 @@ const static struct of_device_id irq_match[] = {
static void __init gic_init_irq(void)
{
of_irq_init(irq_match);
+#ifdef CONFIG_SMP
+ socfpga_sysmgr_init();
+#endif
}
static void socfpga_cyclone5_restart(char mode, const char *cmd)
@@ -53,6 +82,8 @@ static const char *altera_dt_match[] = {
};
DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+ .smp = smp_ops(socfpga_smp_ops),
+ .map_io = socfpga_map_io,
.init_irq = gic_init_irq,
.handle_irq = gic_handle_irq,
.timer = &dw_apb_timer,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-17 19:07 ` Rob Herring
@ 2012-10-17 23:02 ` Pavel Machek
2012-10-17 23:30 ` Rob Herring
2012-10-18 3:34 ` Dinh Nguyen
1 sibling, 1 reply; 7+ messages in thread
From: Pavel Machek @ 2012-10-17 23:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi!
> > arch/arm/mach-socfpga/Kconfig | 1 +
> > arch/arm/mach-socfpga/Makefile | 3 +
> > arch/arm/mach-socfpga/headsmp.S | 64 +++++++++++
> > arch/arm/mach-socfpga/include/mach/core.h | 33 ++++++
>
> Move core.h to mach-socfpga.
> > +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
> > +
>
> This can be removed if core.h is moved.
Ok, makes code nicer. Sorry for copying picoxcell too much.
> > + __INIT
> > +
> > +#define CPU1_START_ADDR 0xffd08010
> > +
> > +ENTRY(secondary_trampoline)
>
> This appears to be your reset code at phys addr 0. How does core 0 boot
> if you are copying this to 0?
Yes, this is reset code, goes at zero. Core 0 has already booted by
the time we are trying to boot Core 1 (we don't support CPU hotplug,
yet). Is that a problem?
> > + /* From u-boot: start.S */
> > + mrs r0, cpsr
> > + bic r0, r0, #0x1f
> > + orr r0, r0, #0xd3
> > + msr cpsr,r0
...
> > + * disable MMU stuff and caches
> > + */
> > + mrc p15, 0, r0, c1, c0, 0
> > + bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
> > + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
> > + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
> > + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
> > + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
>
> All this should get done by v7_setup.
It seems it is, as (emulated) system still boots with that code
disabled.
> > +static DEFINE_SPINLOCK(boot_lock);
> > +
> > +static void __cpuinit socfpga_secondary_init(unsigned int cpu)
> > +{
> > + /*
> > + * if any interrupts are already enabled for the primary
> > + * core (e.g. timer irq), then they will not have been enabled
> > + * for us: do so
> > + */
> > + gic_secondary_init(0);
> > +
> > + /*
> > + * let the primary processor know we're out of the
> > + * pen, then head off into the C entry point
> > + */
> > + pen_release = -1;
> > + smp_wmb();
> > +
> > + /*
> > + * Synchronise with the boot thread.
> > + */
> > + spin_lock(&boot_lock);
> > + spin_unlock(&boot_lock);
> > +}
> > +
> > +static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
> > +{
> > + unsigned long timeout;
> > + extern char secondary_trampoline, secondary_trampoline_end;
> > +
> > + int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
> > +
> > + /*
> > + * Set synchronisation state between this boot processor
> > + * and the secondary one
> > + */
> > + spin_lock(&boot_lock);
> > +
> > + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
> > +
> > + __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
> > +
> > + pen_release = 0;
> > + flush_cache_all();
> > + smp_wmb();
> > + outer_clean_range(0, trampoline_size);
> > +
> > + /* This will release CPU #1 out of reset.*/
> > + __raw_writel(0, rst_manager_base_addr + 0x10);
> > +
> > + timeout = jiffies + (1 * HZ);
> > + while (time_before(jiffies, timeout)) {
> > + smp_rmb();
> > + if (pen_release == -1)
> > + break;
> > +
> > + udelay(10);
> > + }
> > +
> > + /*
> > + * now the secondary core is starting up let it run its
> > + * calibrations, then wait for it to finish
> > + */
> > + spin_unlock(&boot_lock);
> > + return pen_release != -1 ? -ENOSYS : 0;
>
> You don't need any of this if you can reset secondary cores on
> hotplug.
What exactly is unneccessary? I'd like to wait for secondary to come
up so we can raise an error if it does not...?
Thanks,
Pavel
PS: I have this so far...
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 659fd27..a0fc372 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -2,7 +2,5 @@
# Makefile for the linux kernel.
#
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
-
obj-y := socfpga.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o hotplug.o
diff --git a/arch/arm/mach-socfpga/include/mach/core.h b/arch/arm/mach-socfpga/core.h
similarity index 100%
rename from arch/arm/mach-socfpga/include/mach/core.h
rename to arch/arm/mach-socfpga/core.h
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
index 9597ff7..081b4d1 100644
--- a/arch/arm/mach-socfpga/headsmp.S
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -20,42 +20,6 @@
#define CONFIG_CPU1_START_ADDR (CONFIG_SYSTEM_MANAGER + 0x10)
ENTRY(secondary_trampoline)
- /* From u-boot: start.S */
- mrs r0, cpsr
- bic r0, r0, #0x1f
- orr r0, r0, #0xd3
- msr cpsr,r0
-
-/*************************************************************************
- *
- * cpu_init_cp15
- *
- * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
- * CONFIG_SYS_ICACHE_OFF is defined.
- *
- *************************************************************************/
-ENTRY(cpu_init_cp15)
- /*
- * Invalidate L1 I/D
- */
- mov r0, #0 @ set up for MCR
- mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
- mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
- mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
- mcr p15, 0, r0, c7, c10, 4 @ DSB
- mcr p15, 0, r0, c7, c5, 4 @ ISB
-
- /*
- * disable MMU stuff and caches
- */
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
- bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
- orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
- orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
- orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
- mcr p15, 0, r0, c1, c0, 0
-
movw r0, #:lower16:CONFIG_CPU1_START_ADDR
movt r0, #:upper16:CONFIG_CPU1_START_ADDR
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 34440aa..60c2b4a 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -26,7 +26,7 @@
#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
-#include <mach/core.h>
+#include "core.h"
static void __iomem *sys_manager_base_addr;
static void __iomem *rst_manager_base_addr;
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index 68d32cd..741b9ba 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -23,7 +23,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/core.h>
+#include "core.h"
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
void __iomem *rst_manager_base_addr = ((void __iomem *)(SOCFPGA_RST_MANAGER_VIRT_BASE));
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-17 23:02 ` Pavel Machek
@ 2012-10-17 23:30 ` Rob Herring
2012-10-18 10:09 ` Pavel Machek
0 siblings, 1 reply; 7+ messages in thread
From: Rob Herring @ 2012-10-17 23:30 UTC (permalink / raw)
To: linux-arm-kernel
On 10/17/2012 06:02 PM, Pavel Machek wrote:
> Hi!
>
>>> arch/arm/mach-socfpga/Kconfig | 1 +
>>> arch/arm/mach-socfpga/Makefile | 3 +
>>> arch/arm/mach-socfpga/headsmp.S | 64 +++++++++++
>>> arch/arm/mach-socfpga/include/mach/core.h | 33 ++++++
>>
>> Move core.h to mach-socfpga.
>
>>> +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
>>> +
>>
>> This can be removed if core.h is moved.
>
> Ok, makes code nicer. Sorry for copying picoxcell too much.
>
>>> + __INIT
>>> +
>>> +#define CPU1_START_ADDR 0xffd08010
>>> +
>>> +ENTRY(secondary_trampoline)
>>
>> This appears to be your reset code at phys addr 0. How does core 0 boot
>> if you are copying this to 0?
>
> Yes, this is reset code, goes at zero. Core 0 has already booted by
> the time we are trying to boot Core 1 (we don't support CPU hotplug,
> yet). Is that a problem?
It would be better to do both at the same time as the code is
intertwined. More below on this...
>>> +static void __cpuinit socfpga_secondary_init(unsigned int cpu)
>>> +{
>>> + /*
>>> + * if any interrupts are already enabled for the primary
>>> + * core (e.g. timer irq), then they will not have been enabled
>>> + * for us: do so
>>> + */
>>> + gic_secondary_init(0);
>>> +
>>> + /*
>>> + * let the primary processor know we're out of the
>>> + * pen, then head off into the C entry point
>>> + */
>>> + pen_release = -1;
>>> + smp_wmb();
>>> +
>>> + /*
>>> + * Synchronise with the boot thread.
>>> + */
>>> + spin_lock(&boot_lock);
>>> + spin_unlock(&boot_lock);
>>> +}
>>> +
>>> +static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
>>> +{
>>> + unsigned long timeout;
>>> + extern char secondary_trampoline, secondary_trampoline_end;
>>> +
>>> + int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
>>> +
>>> + /*
>>> + * Set synchronisation state between this boot processor
>>> + * and the secondary one
>>> + */
>>> + spin_lock(&boot_lock);
>>> +
>>> + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
>>> +
>>> + __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
>>> +
>>> + pen_release = 0;
>>> + flush_cache_all();
>>> + smp_wmb();
>>> + outer_clean_range(0, trampoline_size);
>>> +
>>> + /* This will release CPU #1 out of reset.*/
>>> + __raw_writel(0, rst_manager_base_addr + 0x10);
>>> +
>>> + timeout = jiffies + (1 * HZ);
>>> + while (time_before(jiffies, timeout)) {
>>> + smp_rmb();
>>> + if (pen_release == -1)
>>> + break;
>>> +
>>> + udelay(10);
>>> + }
>>> +
>>> + /*
>>> + * now the secondary core is starting up let it run its
>>> + * calibrations, then wait for it to finish
>>> + */
>>> + spin_unlock(&boot_lock);
>>> + return pen_release != -1 ? -ENOSYS : 0;
>>
>> You don't need any of this if you can reset secondary cores on
>> hotplug.
>
> What exactly is unneccessary? I'd like to wait for secondary to come
> up so we can raise an error if it does not...?
>
Look at the highbank code.
If hotplug will cause a reset of the core, then none of this pen code is
needed. If hotplug just does a wfi and returns from the wfi when
onlining the core like Versatile Express, then you need this pen code.
There's been several prior discussions about this on the list.
If you will never support hotplug (and therefore suspend), then you
don't need this pen code either.
Rob
> Thanks,
> Pavel
>
> PS: I have this so far...
>
> diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
> index 659fd27..a0fc372 100644
> --- a/arch/arm/mach-socfpga/Makefile
> +++ b/arch/arm/mach-socfpga/Makefile
> @@ -2,7 +2,5 @@
> # Makefile for the linux kernel.
> #
>
> -ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
> -
> obj-y := socfpga.o
> obj-$(CONFIG_SMP) += headsmp.o platsmp.o hotplug.o
> diff --git a/arch/arm/mach-socfpga/include/mach/core.h b/arch/arm/mach-socfpga/core.h
> similarity index 100%
> rename from arch/arm/mach-socfpga/include/mach/core.h
> rename to arch/arm/mach-socfpga/core.h
> diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
> index 9597ff7..081b4d1 100644
> --- a/arch/arm/mach-socfpga/headsmp.S
> +++ b/arch/arm/mach-socfpga/headsmp.S
> @@ -20,42 +20,6 @@
> #define CONFIG_CPU1_START_ADDR (CONFIG_SYSTEM_MANAGER + 0x10)
>
> ENTRY(secondary_trampoline)
> - /* From u-boot: start.S */
> - mrs r0, cpsr
> - bic r0, r0, #0x1f
> - orr r0, r0, #0xd3
> - msr cpsr,r0
> -
> -/*************************************************************************
> - *
> - * cpu_init_cp15
> - *
> - * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
> - * CONFIG_SYS_ICACHE_OFF is defined.
> - *
> - *************************************************************************/
> -ENTRY(cpu_init_cp15)
> - /*
> - * Invalidate L1 I/D
> - */
> - mov r0, #0 @ set up for MCR
> - mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
> - mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
> - mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
> - mcr p15, 0, r0, c7, c10, 4 @ DSB
> - mcr p15, 0, r0, c7, c5, 4 @ ISB
> -
> - /*
> - * disable MMU stuff and caches
> - */
> - mrc p15, 0, r0, c1, c0, 0
> - bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
> - bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
> - orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
> - orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
> - orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
> - mcr p15, 0, r0, c1, c0, 0
> -
> movw r0, #:lower16:CONFIG_CPU1_START_ADDR
> movt r0, #:upper16:CONFIG_CPU1_START_ADDR
>
> diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
> index 34440aa..60c2b4a 100644
> --- a/arch/arm/mach-socfpga/platsmp.c
> +++ b/arch/arm/mach-socfpga/platsmp.c
> @@ -26,7 +26,7 @@
> #include <asm/smp_scu.h>
> #include <asm/smp_plat.h>
>
> -#include <mach/core.h>
> +#include "core.h"
>
> static void __iomem *sys_manager_base_addr;
> static void __iomem *rst_manager_base_addr;
> diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
> index 68d32cd..741b9ba 100644
> --- a/arch/arm/mach-socfpga/socfpga.c
> +++ b/arch/arm/mach-socfpga/socfpga.c
> @@ -23,7 +23,7 @@
> #include <asm/mach/arch.h>
> #include <asm/mach/map.h>
>
> -#include <mach/core.h>
> +#include "core.h"
>
> void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
> void __iomem *rst_manager_base_addr = ((void __iomem *)(SOCFPGA_RST_MANAGER_VIRT_BASE));
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-17 19:07 ` Rob Herring
2012-10-17 23:02 ` Pavel Machek
@ 2012-10-18 3:34 ` Dinh Nguyen
2012-10-18 20:52 ` Rob Herring
1 sibling, 1 reply; 7+ messages in thread
From: Dinh Nguyen @ 2012-10-18 3:34 UTC (permalink / raw)
To: linux-arm-kernel
Hi Rob,
On Wed, Oct 17, 2012 at 2:07 PM, Rob Herring <robherring2@gmail.com> wrote:
>
> On 10/17/2012 02:18 PM, dinguyen at altera.com wrote:
> > From: Dinh Nguyen <dinguyen@altera.com>
> >
> > Enable SMP for the SOCFPGA platform.
> >
> > Signed-off-by: Pavel Machek <pavel@denx.de>
> > Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> > ---
> > arch/arm/boot/dts/socfpga.dtsi | 10 ++
> > arch/arm/configs/socfpga_defconfig | 9 +-
>
> Does the multi_v7_defconfig not work for you?
It does. Are you planning to remove the defconfigs the platforms that
are part of
multi_v7_defconfig soon? socfpga_defconfig is broken with SMP enabled because
it needs +# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set.
>
> > arch/arm/mach-socfpga/Kconfig | 1 +
> > arch/arm/mach-socfpga/Makefile | 3 +
> > arch/arm/mach-socfpga/headsmp.S | 64 +++++++++++
> > arch/arm/mach-socfpga/include/mach/core.h | 33 ++++++
>
> Move core.h to mach-socfpga.
Will do.
>
> > arch/arm/mach-socfpga/platsmp.c | 166
> > +++++++++++++++++++++++++++++
> > arch/arm/mach-socfpga/socfpga.c | 33 +++++-
> > 8 files changed, 315 insertions(+), 4 deletions(-)
> > create mode 100644 arch/arm/mach-socfpga/headsmp.S
> > create mode 100644 arch/arm/mach-socfpga/include/mach/core.h
> > create mode 100644 arch/arm/mach-socfpga/platsmp.c
> >
> > diff --git a/arch/arm/boot/dts/socfpga.dtsi
> > b/arch/arm/boot/dts/socfpga.dtsi
> > index 0772f57..19aec42 100644
> > --- a/arch/arm/boot/dts/socfpga.dtsi
> > +++ b/arch/arm/boot/dts/socfpga.dtsi
> > @@ -143,5 +143,15 @@
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > };
> > +
> > + rstmgr at ffd05000 {
> > + compatible = "altr,rst-mgr";
> > + reg = <0xffd05000 0x1000>;
> > + };
> > +
> > + sysmgr at ffd08000 {
> > + compatible = "altr,sys-mgr";
> > + reg = <0xffd08000 0x4000>;
> > + };
>
> Bindings need documentation.
Will add..
>
> > };
> > };
> > diff --git a/arch/arm/configs/socfpga_defconfig
> > b/arch/arm/configs/socfpga_defconfig
> > index 0ac1293..349ac22 100644
> > --- a/arch/arm/configs/socfpga_defconfig
> > +++ b/arch/arm/configs/socfpga_defconfig
> > @@ -1,5 +1,5 @@
> > CONFIG_EXPERIMENTAL=y
> > -CONFIG_SYSVIPC=y
> > +CONFIG_NO_HZ=y
> > CONFIG_IKCONFIG=y
> > CONFIG_IKCONFIG_PROC=y
> > CONFIG_LOG_BUF_SHIFT=14
> > @@ -16,10 +16,13 @@ CONFIG_MODULE_UNLOAD=y
> > # CONFIG_IOSCHED_DEADLINE is not set
> > # CONFIG_IOSCHED_CFQ is not set
> > CONFIG_ARCH_SOCFPGA=y
> > -CONFIG_MACH_SOCFPGA_CYCLONE5=y
> > -CONFIG_ARM_THUMBEE=y
> > +# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
> > # CONFIG_CACHE_L2X0 is not set
> > CONFIG_HIGH_RES_TIMERS=y
> > +CONFIG_SMP=y
> > +CONFIG_ARM_ARCH_TIMER=y
> > +CONFIG_HIGHMEM=y
> > +CONFIG_HIGHPTE=y
> > CONFIG_VMSPLIT_2G=y
> > CONFIG_NR_CPUS=2
> > CONFIG_AEABI=y
> > diff --git a/arch/arm/mach-socfpga/Kconfig
> > b/arch/arm/mach-socfpga/Kconfig
> > index 803a328..566e804 100644
> > --- a/arch/arm/mach-socfpga/Kconfig
> > +++ b/arch/arm/mach-socfpga/Kconfig
> > @@ -12,5 +12,6 @@ config ARCH_SOCFPGA
> > select GENERIC_CLOCKEVENTS
> > select GPIO_PL061 if GPIOLIB
> > select HAVE_ARM_SCU
> > + select HAVE_SMP
> > select SPARSE_IRQ
> > select USE_OF
> > diff --git a/arch/arm/mach-socfpga/Makefile
> > b/arch/arm/mach-socfpga/Makefile
> > index 4fb9324..61b1266 100644
> > --- a/arch/arm/mach-socfpga/Makefile
> > +++ b/arch/arm/mach-socfpga/Makefile
> > @@ -2,4 +2,7 @@
> > # Makefile for the linux kernel.
> > #
> >
> > +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
> > +
>
> This can be removed if core.h is moved.
>
> > obj-y := socfpga.o
> > +obj-$(CONFIG_SMP) += headsmp.o platsmp.o
> > diff --git a/arch/arm/mach-socfpga/headsmp.S
> > b/arch/arm/mach-socfpga/headsmp.S
> > new file mode 100644
> > index 0000000..b3a24db
> > --- /dev/null
> > +++ b/arch/arm/mach-socfpga/headsmp.S
> > @@ -0,0 +1,64 @@
> > +/*
> > + * Copyright (c) 2003 ARM Limited
> > + * Copyright (c) u-boot contributors
> > + * Copyright (c) 2012 Pavel Machek <pavel@denx.de>
> > + *
> > + * 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>
> > +
> > + __INIT
> > +
> > +#define CPU1_START_ADDR 0xffd08010
> > +
> > +ENTRY(secondary_trampoline)
>
> This appears to be your reset code at phys addr 0. How does core 0 boot
> if you are copying this to 0?
>
> > + /* From u-boot: start.S */
> > + mrs r0, cpsr
> > + bic r0, r0, #0x1f
> > + orr r0, r0, #0xd3
> > + msr cpsr,r0
> > +
> >
> > +/*************************************************************************
> > + *
> > + * cpu_init_cp15
> > + ** Copyright (c) u-boot contributors
> > + * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on
> > unless
> > + * CONFIG_SYS_ICACHE_OFF is defined.
> > + *
> > +
> > *************************************************************************/
> > +ENTRY(cpu_init_cp15)
> > + /*
> > + * Invalidate L1 I/D
> > + */
> > + mov r0, #0 @ set up for MCR
> > + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
> > + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
> > + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
> > + mcr p15, 0, r0, c7, c10, 4 @ DSB
> > + mcr p15, 0, r0, c7, c5, 4 @ ISB
> > +
> > + /*
> > + * disable MMU stuff and caches
> > + */
> > + mrc p15, 0, r0, c1, c0, 0
> > + bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
> > + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
> > + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
> > + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
> > + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
>
> All this should get done by v7_setup.
>
> > + mcr p15, 0, r0, c1, c0, 0
> > +
> > + movw r0, #:lower16:CPU1_START_ADDR
> > + movt r0, #:upper16:CPU1_START_ADDR
> > +
> > + ldr r1, [r0]
> > + bx r1
> > +
> > +ENTRY(secondary_trampoline_end)
> > +
> > + .align
> > + .long pen_release
> > +
> > diff --git a/arch/arm/mach-socfpga/include/mach/core.h
> > b/arch/arm/mach-socfpga/include/mach/core.h
> > new file mode 100644
> > index 0000000..74a4949
> > --- /dev/null
> > +++ b/arch/arm/mach-socfpga/include/mach/core.h
> > @@ -0,0 +1,33 @@
> > +/*
> > + * Copyright 2012 Pavel Machek <pavel@denx.de>
> > + * Copyright (C) 2012 Altera 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; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> > USA
> > + */
> > +
> > +#ifndef __MACH_CORE_H
> > +#define __MACH_CORE_H
> > +
> > +extern void secondary_startup(void);
> > +extern void __iomem *socfpga_scu_base_addr;
> > +
> > +extern void socfpga_init_clocks(void);
> > +extern void socfpga_sysmgr_init(void);
> > +
> > +extern struct smp_operations socfpga_smp_ops;
> > +
> > +#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
> > +
> > +#endif
> > diff --git a/arch/arm/mach-socfpga/platsmp.c
> > b/arch/arm/mach-socfpga/platsmp.c
> > new file mode 100644
> > index 0000000..59d7069
> > --- /dev/null
> > +++ b/arch/arm/mach-socfpga/platsmp.c
> > @@ -0,0 +1,166 @@
> > +/*
> > + * Copyright 2010-2011 Calxeda, Inc.
> > + * Copyright 2012 Pavel Machek <pavel@denx.de>
> > + * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
> > + * Copyright (C) 2012 Altera Corporation
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > it
> > + * under the terms and conditions of the GNU General Public License,
> > + * version 2, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> > License for
> > + * more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > along with
> > + * this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +#include <linux/delay.h>
> > +#include <linux/init.h>
> > +#include <linux/smp.h>
> > +#include <linux/io.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +
> > +#include <asm/cacheflush.h>
> > +#include <asm/hardware/gic.h>
> > +#include <asm/smp_scu.h>
> > +#include <asm/smp_plat.h>
> > +
> > +#include <mach/core.h>
> > +
> > +static void __iomem *sys_manager_base_addr;
> > +static void __iomem *rst_manager_base_addr;
> > +
> > +static DEFINE_SPINLOCK(boot_lock);
> > +
> > +static void __cpuinit socfpga_secondary_init(unsigned int cpu)
> > +{
> > + /*
> > + * if any interrupts are already enabled for the primary
> > + * core (e.g. timer irq), then they will not have been enabled
> > + * for us: do so
> > + */
> > + gic_secondary_init(0);
> > +
> > + /*
> > + * let the primary processor know we're out of the
> > + * pen, then head off into the C entry point
> > + */
> > + pen_release = -1;
> > + smp_wmb();
> > +
> > + /*
> > + * Synchronise with the boot thread.
> > + */
> > + spin_lock(&boot_lock);
> > + spin_unlock(&boot_lock);
> > +}
> > +
> > +static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct
> > task_struct *idle)
> > +{
> > + unsigned long timeout;
> > + extern char secondary_trampoline, secondary_trampoline_end;
> > +
> > + int trampoline_size = &secondary_trampoline_end -
> > &secondary_trampoline;
> > +
> > + /*
> > + * Set synchronisation state between this boot processor
> > + * and the secondary one
> > + */
> > + spin_lock(&boot_lock);
> > +
> > + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
> > +
> > + __raw_writel(virt_to_phys(secondary_startup),
> > (sys_manager_base_addr+0x10));
> > +
> > + pen_release = 0;
> > + flush_cache_all();
> > + smp_wmb();
> > + outer_clean_range(0, trampoline_size);
> > +
> > + /* This will release CPU #1 out of reset.*/
> > + __raw_writel(0, rst_manager_base_addr + 0x10);
> > +
> > + timeout = jiffies + (1 * HZ);
> > + while (time_before(jiffies, timeout)) {
> > + smp_rmb();
> > + if (pen_release == -1)
> > + break;
> > +
> > + udelay(10);
> > + }
> > +
> > + /*
> > + * now the secondary core is starting up let it run its
> > + * calibrations, then wait for it to finish
> > + */
> > + spin_unlock(&boot_lock);
> > + return pen_release != -1 ? -ENOSYS : 0;
>
> You don't need any of this if you can reset secondary cores on hotplug.
Will investigate with your latest comments.
Thanks for the quick turnaround on the review.
Dinh
>
> Rob
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-17 23:30 ` Rob Herring
@ 2012-10-18 10:09 ` Pavel Machek
0 siblings, 0 replies; 7+ messages in thread
From: Pavel Machek @ 2012-10-18 10:09 UTC (permalink / raw)
To: linux-arm-kernel
Hi!
> >>> + timeout = jiffies + (1 * HZ);
> >>> + while (time_before(jiffies, timeout)) {
> >>> + smp_rmb();
> >>> + if (pen_release == -1)
> >>> + break;
> >>> +
> >>> + udelay(10);
> >>> + }
> >>> +
> >>> + /*
> >>> + * now the secondary core is starting up let it run its
> >>> + * calibrations, then wait for it to finish
> >>> + */
> >>> + spin_unlock(&boot_lock);
> >>> + return pen_release != -1 ? -ENOSYS : 0;
> >>
> >> You don't need any of this if you can reset secondary cores on
> >> hotplug.
> >
> > What exactly is unneccessary? I'd like to wait for secondary to come
> > up so we can raise an error if it does not...?
> >
>
> Look at the highbank code.
>
> If hotplug will cause a reset of the core, then none of this pen code is
> needed. If hotplug just does a wfi and returns from the wfi when
> onlining the core like Versatile Express, then you need this pen code.
> There's been several prior discussions about this on the list.
>
> If you will never support hotplug (and therefore suspend), then you
> don't need this pen code either.
Ok, so I guess we should go with the simple code for now? Something
like...
BTW... I wonder if I should put socfpga_smp_init_cpus(void) into the
library somewhere? (Where?) Same code is used on highbank, imx,
socfpga, spear13xx, tegra and ct-ca9x4...
Signed-off-by: Pavel Machek <pavel@denx.de>
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
index 081b4d1..ee19ce9 100644
--- a/arch/arm/mach-socfpga/headsmp.S
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/plat-socfpga5xs1/headsmp.S
+ * Trampoline to bring CPU from reset.
*
* Copyright (c) 2012 Pavel Machek <pavel@denx.de>
* Copyright (c) u-boot contributors
@@ -15,9 +15,9 @@
__INIT
-#define HPS_SYSMGR_ADDRESS 0xffd08000
-#define CONFIG_SYSTEM_MANAGER HPS_SYSMGR_ADDRESS
-#define CONFIG_CPU1_START_ADDR (CONFIG_SYSTEM_MANAGER + 0x10)
+#define HPS_SYSMGR_ADDRESS 0xffd08000
+#define CONFIG_SYSTEM_MANAGER HPS_SYSMGR_ADDRESS
+#define CONFIG_CPU1_START_ADDR (CONFIG_SYSTEM_MANAGER + 0x10)
ENTRY(secondary_trampoline)
movw r0, #:lower16:CONFIG_CPU1_START_ADDR
@@ -25,9 +25,4 @@ ENTRY(secondary_trampoline)
ldr r1, [r0]
bx r1
-
ENTRY(secondary_trampoline_end)
-
- .align
- .long pen_release
-
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 60c2b4a..fb3c58c 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -1,4 +1,7 @@
-/* Copyright 2010-2011 Calxeda, Inc.
+/*
+ * SMP support.
+ *
+ * Copyright 2010-2011 Calxeda, Inc.
* Copyright 2012 Pavel Machek <pavel@denx.de>
* Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
*
@@ -31,8 +34,6 @@
static void __iomem *sys_manager_base_addr;
static void __iomem *rst_manager_base_addr;
-static DEFINE_SPINLOCK(boot_lock);
-
static void __cpuinit socfpga_secondary_init(unsigned int cpu)
{
/*
@@ -41,41 +42,20 @@ static void __cpuinit socfpga_secondary_init(unsigned int cpu)
* for us: do so
*/
gic_secondary_init(0);
-
- /*
- * let the primary processor know we're out of the
- * pen, then head off into the C entry point
- */
- pen_release = -1;
- smp_wmb();
-
- /*
- * Synchronise with the boot thread.
- */
- spin_lock(&boot_lock);
- spin_unlock(&boot_lock);
-
- early_printk("Secondary ready.\n");
+ early_printk("Started secondary.\n");
}
static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- unsigned long timeout;
extern char secondary_trampoline, secondary_trampoline_end;
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
early_printk("Boot secondary...\n");
- /*
- * Set synchronisation state between this boot processor
- * and the secondary one
- */
- spin_lock(&boot_lock);
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
__raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
- pen_release = 0;
flush_cache_all();
smp_wmb();
outer_clean_range(0, trampoline_size);
@@ -83,21 +63,7 @@ static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct
in u-boot */
__raw_writel(0, rst_manager_base_addr + 0x10);
- timeout = jiffies + (1 * HZ);
- while (time_before(jiffies, timeout)) {
- smp_rmb();
- if (pen_release == -1)
- break;
-
- udelay(10);
- }
-
- /*
- * now the secondary core is starting up let it run its
- * calibrations, then wait for it to finish
- */
- spin_unlock(&boot_lock);
- return pen_release != -1 ? -ENOSYS : 0;
+ return 0;
}
/*
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv1] arm:socfpga: Enable SMP for socfpga
2012-10-18 3:34 ` Dinh Nguyen
@ 2012-10-18 20:52 ` Rob Herring
0 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2012-10-18 20:52 UTC (permalink / raw)
To: linux-arm-kernel
On 10/17/2012 10:34 PM, Dinh Nguyen wrote:
> Hi Rob,
>
> On Wed, Oct 17, 2012 at 2:07 PM, Rob Herring <robherring2@gmail.com> wrote:
>>
>> On 10/17/2012 02:18 PM, dinguyen at altera.com wrote:
>>> From: Dinh Nguyen <dinguyen@altera.com>
>>>
>>> Enable SMP for the SOCFPGA platform.
>>>
>>> Signed-off-by: Pavel Machek <pavel@denx.de>
>>> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
>>> ---
>>> arch/arm/boot/dts/socfpga.dtsi | 10 ++
>>> arch/arm/configs/socfpga_defconfig | 9 +-
>>
>> Does the multi_v7_defconfig not work for you?
>
> It does. Are you planning to remove the defconfigs the platforms that
> are part of
> multi_v7_defconfig soon? socfpga_defconfig is broken with SMP enabled because
> it needs +# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set.
I don't plan to remove them. I'll leave it up to the platform
maintainers as the new multi_v7 config is not exactly the same selections.
That's strange that you care about the errata setting. I think it should
work either way. We do need to scrub the errata list and enable all the
ones which have no runtime impact and are conditioned on the core
revision. I'm not sure what we'll do with the ones that could have a
negative impact on performance of rev's without an errata.
Rob
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-10-18 20:52 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-17 19:18 [PATCHv1] arm:socfpga: Enable SMP for socfpga dinguyen at altera.com
2012-10-17 19:07 ` Rob Herring
2012-10-17 23:02 ` Pavel Machek
2012-10-17 23:30 ` Rob Herring
2012-10-18 10:09 ` Pavel Machek
2012-10-18 3:34 ` Dinh Nguyen
2012-10-18 20:52 ` Rob Herring
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).