From patchwork Mon Oct 17 08:43:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 9378751 X-Patchwork-Delegate: neil.armstrong@linaro.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 62A7A60487 for ; Mon, 17 Oct 2016 08:43:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 541A129025 for ; Mon, 17 Oct 2016 08:43:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 484BA29028; Mon, 17 Oct 2016 08:43:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_LOW,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mx1.tuxfamily.net (mail.tuxfamily.net [212.85.158.8]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C42EE29025 for ; Mon, 17 Oct 2016 08:43:19 +0000 (UTC) Received: from listengine (helo=tuxfamily.org) by mx1.tuxfamily.net with local-bsmtp (Exim 4.84_2) (envelope-from ) id 1bw3Vt-000112-Kp for patchwork-linux-oxnas@patchwork.kernel.org; Mon, 17 Oct 2016 10:43:17 +0200 Received: from mail-lf0-x235.google.com ([2a00:1450:4010:c07::235]) by mx1.tuxfamily.net with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1bw3Vp-00010O-Mn for linux-oxnas@lists.tuxfamily.org; Mon, 17 Oct 2016 10:43:13 +0200 Received: by mail-lf0-x235.google.com with SMTP id b75so276765143lfg.3 for ; Mon, 17 Oct 2016 01:43:13 -0700 (PDT) Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xgMrUTXtAzWAvBtQW2nHrx4YBStY7iVunZQh41BlHiI=; b=RfCpRb6ezMpYJt/eMRcjGTGPrW+fCtdLE/AUpdk3yGiGSspA+Ma83cHu+P7Q2IN1cJ 4Rmj5yA/pSyIVnFW9nFUhlj4nZWVFNxczqmfMKyw6NDrabuUL6+t2wQnPngbh3kLLnA5 X7ddvvZgwXhbb0dfk/OrL/3/12lSgdjdpBzB++znQRf3mRp39hcxn8GdNbeiikTjF7q4 njMudsWET4ST8qpHs1N7sw63mgFy0OINRv+6WvYhIBSA86yM2pLnvzOm4geBH0qA298i yDsVew7WJUuChzzBSpVr3+W9wMqz75JPB1O5M7zMwwgQIv/tNJOfR3RFUpr21ACKs3e2 rChQ== X-Google-Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xgMrUTXtAzWAvBtQW2nHrx4YBStY7iVunZQh41BlHiI=; b=fHMcHm8aGDhsW8AaYCzY3ADMPuG1mW3QyEVW+7do9+2e2ComLfHtL5qqgXmYctAmrY 2+zitEf6iDTithGXGsAxqSkI0SuIoqFnjrI81c8+IdotE2GVTbO+ShGUkrWdzqZzwY05 0exe058kU9IPjADmzoJlzdt/s1KBG4KXYkQMpo2BeRGrpy3mkYWNBkT8bMy8aGZDTPVq 7tO1tDZdTKLSh8dB7IfTTy++Gnh+aoEi6RvfrWY7mgcBOl5kRjjS5Q5kAVslZjpw5mbI Cu5Do2f8tY0VjZ2EOb8FMfYJ3YnuQ3HHTjpQ0MxCAne59gYEL9CL4iYn09OTup9lbl/N SSAA== X-GM-Message-State: AA6/9Rn0EJBA+BCHpnKb67YTMPIJ/Y6kLD5xn99eYbx+o3TPvn08E9brYHQflmQkDaYdq/Qs X-Received: by 10.28.185.137 with SMTP id j131mr7055805wmf.73.1476693792709; Mon, 17 Oct 2016 01:43:12 -0700 (PDT) Received: from build.net (build.baylibre.com. [37.187.146.144]) by smtp.gmail.com with ESMTPSA id y2sm51136827wjx.20.2016.10.17.01.43.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Oct 2016 01:43:12 -0700 (PDT) From: Neil Armstrong To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-oxnas@lists.tuxfamily.org CC: Neil Armstrong Subject: [linux-oxnas] [PATCH 1/2] ARM: oxnas: Add OX820 SMP support Date: Mon, 17 Oct 2016 10:43:02 +0200 Message-ID: <20161017084303.20078-2-narmstrong@baylibre.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20161017084303.20078-1-narmstrong@baylibre.com> References: <20161017084303.20078-1-narmstrong@baylibre.com> List-Unsubscribe: List-Subscribe: List-Help: List-Software: Listengine, VHFFS 4.7-dev-4c39578052 List-ID: List-Post: List-Archive: Precedence: list Reply-To: linux-oxnas@lists.tuxfamily.org X-Virus-Scanned: ClamAV using ClamSMTP The Oxford Semiconductor OX820 is a ARM11MPcore based SoC sharing some features with the OX810 earlier SoC. This patch adds the core to wake up the second core. Signed-off-by: Neil Armstrong --- arch/arm/mach-oxnas/Makefile | 2 + arch/arm/mach-oxnas/headsmp.S | 28 ++++++++ arch/arm/mach-oxnas/hotplug.c | 111 +++++++++++++++++++++++++++++ arch/arm/mach-oxnas/platsmp.c | 161 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 arch/arm/mach-oxnas/Makefile create mode 100644 arch/arm/mach-oxnas/headsmp.S create mode 100644 arch/arm/mach-oxnas/hotplug.c create mode 100644 arch/arm/mach-oxnas/platsmp.c diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile new file mode 100644 index 0000000..b625906 --- /dev/null +++ b/arch/arm/mach-oxnas/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-oxnas/headsmp.S b/arch/arm/mach-oxnas/headsmp.S new file mode 100644 index 0000000..2a94dcb --- /dev/null +++ b/arch/arm/mach-oxnas/headsmp.S @@ -0,0 +1,28 @@ +/* + * linux/arch/arm/mach-oxnas/headsmp.S + * + * Copyright (C) 2013 Ma Haijun + * Copyright (c) 2003 ARM Limited + * 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 +#include + + __INIT + +/* + * OX820 specific entry point for secondary CPUs. + */ +ENTRY(ox820_secondary_startup) + mov r4, #0 + /* invalidate both caches and branch target cache */ + mcr p15, 0, r4, c7, c7, 0 + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup diff --git a/arch/arm/mach-oxnas/hotplug.c b/arch/arm/mach-oxnas/hotplug.c new file mode 100644 index 0000000..18fa814 --- /dev/null +++ b/arch/arm/mach-oxnas/hotplug.c @@ -0,0 +1,111 @@ +/* + * linux/arch/arm/mach-oxnas/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * 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 +#include +#include + +#include +#include + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + asm volatile( + " mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); +} + +static inline void platform_do_lowpower(unsigned int cpu, int *spurious) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + /* + * here's the WFI + */ + asm(".word 0xe320f003\n" + : + : + : "memory", "cc"); + + if (pen_release == cpu_logical_map(cpu)) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * Getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * Just note it happening - when we're woken, we can report + * its occurrence. + */ + (*spurious)++; + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void ox820_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu, &spurious); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); + + if (spurious) + pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); +} diff --git a/arch/arm/mach-oxnas/platsmp.c b/arch/arm/mach-oxnas/platsmp.c new file mode 100644 index 0000000..d2ff2c4 --- /dev/null +++ b/arch/arm/mach-oxnas/platsmp.c @@ -0,0 +1,161 @@ +/* + * arch/arm/mach-oxnas/platsmp.c + * + * Copyright (C) 2016 Neil Armstrong + * Copyright (C) 2013 Ma Haijun + * Copyright (C) 2002 ARM Ltd. + * 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 +#include +#include +#include + +#include +#include +#include +#include + +extern void ox820_secondary_startup(void); +extern void ox820_cpu_die(unsigned int cpu); + +static DEFINE_SPINLOCK(boot_lock); + +static void __iomem *cpu_ctrl; +static void __iomem *gic_cpu_ctrl; + +#define HOLDINGPEN_CPU_OFFSET 0xc8 +#define HOLDINGPEN_LOCATION_OFFSET 0xc4 + +#define GIC_NCPU_OFFSET(cpu) (0x100 + (cpu)*0x100) +#define GIC_CPU_CTRL 0x00 +#define GIC_CPU_CTRL_ENABLE 1 + +static inline void write_pen_release(int val) +{ + writel(val, cpu_ctrl + HOLDINGPEN_CPU_OFFSET); +} + +static inline int read_pen_release(void) +{ + return readl(cpu_ctrl + HOLDINGPEN_CPU_OFFSET); +} + +void ox820_secondary_init(unsigned int cpu) +{ + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int ox820_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu); + + /* + * Enable GIC cpu interface in CPU Interface Control Register + */ + writel(GIC_CPU_CTRL_ENABLE, + gic_cpu_ctrl + GIC_NCPU_OFFSET(cpu) + GIC_CPU_CTRL); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (read_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 read_pen_release() != -1 ? -ENOSYS : 0; +} + +static void __init ox820_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *np; + void __iomem *scu_base; + + np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-scu"); + scu_base = of_iomap(np, 0); + of_node_put(np); + if (!scu_base) + return; + + /* Remap CPU Interrupt Interface Registers */ + np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-gic"); + gic_cpu_ctrl = of_iomap(np, 1); + of_node_put(np); + if (!gic_cpu_ctrl) + goto unmap_scu; + + np = of_find_compatible_node(NULL, NULL, "oxsemi,ox820-sys-ctrl"); + cpu_ctrl = of_iomap(np, 0); + of_node_put(np); + if (!cpu_ctrl) + goto unmap_scu; + + scu_enable(scu_base); + flush_cache_all(); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The BootMonitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + writel(virt_to_phys(ox820_secondary_startup), + cpu_ctrl + HOLDINGPEN_LOCATION_OFFSET); + +unmap_scu: + iounmap(scu_base); +} + +static const struct smp_operations ox820_smp_ops __initconst = { + .smp_prepare_cpus = ox820_smp_prepare_cpus, + .smp_secondary_init = ox820_secondary_init, + .smp_boot_secondary = ox820_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = ox820_cpu_die, +#endif +}; + +CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops);