From patchwork Wed Aug 28 13:10:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 2850759 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AFBE1BF546 for ; Wed, 28 Aug 2013 13:32:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3E8B82041C for ; Wed, 28 Aug 2013 13:32:05 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9306C202B3 for ; Wed, 28 Aug 2013 13:32:03 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VEfZa-0007AT-5O; Wed, 28 Aug 2013 13:14:12 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VEfYs-0004vf-LM; Wed, 28 Aug 2013 13:13:26 +0000 Received: from mail-pa0-f42.google.com ([209.85.220.42]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VEfYE-0004rG-7C for linux-arm-kernel@lists.infradead.org; Wed, 28 Aug 2013 13:12:48 +0000 Received: by mail-pa0-f42.google.com with SMTP id lj1so6273907pab.1 for ; Wed, 28 Aug 2013 06:12:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mpGiiG4iXgDBj2VWmg9ORj9dcqJXhe/3CLNBcYjgMCM=; b=WIY/TX3UD3OL9+kaRPZj2HCf29O//NUXwPQoSzg78q6CikLUfz6NYp6bsoK/2PFKSE uKD8MyqxCls/F5QgZJvKEqUOemuZA+YdTgX6e6l1/Aiy5z+3WfkEyEIn51m52lnNVl9X C/333/EfBIuRQIzRZ0EjuJQONhqSrAXmbWzTGQ6caTh3IwfbgvIQModlqomG9WOoJFiT 2+inwMCo3v1UT3TLfY4Pkxg3mDRM0KzTq600NCvIYTJfrashaG64yia8YrikQd7Pf/GV L/XbLZ9hf04ARC9iMR3YtMtyaJ4lRjn6IZL2e/8nCTx0hhvnbCbH+iIl0LYM+pkPH/87 zhMw== X-Gm-Message-State: ALoCoQn8NBonEgvHUX9OKa6msJ3onJ47j8PZj8SGmtooTbJ7AYEaxTgPjBquEgMJEwvvSsCqb46l X-Received: by 10.66.225.239 with SMTP id rn15mr3252658pac.179.1377695545155; Wed, 28 Aug 2013 06:12:25 -0700 (PDT) Received: from localhost.localdomain ([27.115.121.40]) by mx.google.com with ESMTPSA id vz4sm33857518pab.11.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 28 Aug 2013 06:12:24 -0700 (PDT) From: Haojian Zhuang To: arnd@arndb.de, linux@arm.linux.org.uk, linus.walleij@linaro.org, olof@lixom.net, rob.herring@calxeda.com, linux-arm-kernel@lists.infradead.org, tglx@linutronix.de, john.stultz@linaro.org, mturquette@linaro.org, grant.likely@linaro.org, mark.rutland@arm.com, khilman@linaro.org, swarren@wwwdotorg.org, shaojie.sun@linaro.org Subject: [PATCH v9 7/7] ARM: hi3xxx: add hotplug support Date: Wed, 28 Aug 2013 21:10:54 +0800 Message-Id: <1377695454-29109-8-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1377695454-29109-1-git-send-email-haojian.zhuang@linaro.org> References: <1377695454-29109-1-git-send-email-haojian.zhuang@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130828_091246_532130_415E31CE X-CRM114-Status: GOOD ( 18.58 ) X-Spam-Score: -2.6 (--) Cc: Zhangfei Gao , Haojian Zhuang X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Zhangfei Gao Enable hotplug support on hi3xxx platform How to test: cat proc/interrupts echo 0 > /sys/devices/system/cpu/cpuX/online cat proc/interrupts echo 1 > /sys/devices/system/cpu/cpuX/online Signed-off-by: Zhangfei Gao Tested-by: Zhang Mingjun Signed-off-by: Haojian Zhuang --- arch/arm/mach-hi3xxx/Makefile | 1 + arch/arm/mach-hi3xxx/core.h | 5 ++ arch/arm/mach-hi3xxx/hi3xxx.c | 1 + arch/arm/mach-hi3xxx/hotplug.c | 168 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-hi3xxx/platsmp.c | 5 ++ 5 files changed, 180 insertions(+) create mode 100644 arch/arm/mach-hi3xxx/hotplug.c diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile index 0917f1c..c597cbf 100644 --- a/arch/arm/mach-hi3xxx/Makefile +++ b/arch/arm/mach-hi3xxx/Makefile @@ -4,3 +4,4 @@ obj-y += hi3xxx.o system.o obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h index 3a9c50a..095d1d4 100644 --- a/arch/arm/mach-hi3xxx/core.h +++ b/arch/arm/mach-hi3xxx/core.h @@ -10,4 +10,9 @@ extern void hs_map_io(void); extern void hs_restart(enum reboot_mode, const char *cmd); extern struct smp_operations hs_smp_ops; +extern void __init hs_hotplug_init(void); +extern void hs_cpu_die(unsigned int cpu); +extern int hs_cpu_kill(unsigned int cpu); +extern void hs_set_cpu(int cpu, bool enable); + #endif diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c index 567a0d5..01ac68b 100644 --- a/arch/arm/mach-hi3xxx/hi3xxx.c +++ b/arch/arm/mach-hi3xxx/hi3xxx.c @@ -24,6 +24,7 @@ static void __init hi3xxx_timer_init(void) { hs_map_io(); + hs_hotplug_init(); of_clk_init(NULL); clocksource_of_init(); } diff --git a/arch/arm/mach-hi3xxx/hotplug.c b/arch/arm/mach-hi3xxx/hotplug.c new file mode 100644 index 0000000..3262788 --- /dev/null +++ b/arch/arm/mach-hi3xxx/hotplug.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2013 Hisilicon Limited. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include "core.h" + +enum { + HI3620_CTRL, + HI3716_CTRL, +}; + +static void __iomem *ctrl_base; +static int id; + +static void hs_set_cpu_hi3620(int cpu, bool enable) +{ + u32 val = 0; + + if (enable) { + /* MTCMOS set */ + writel_relaxed(0x8 << cpu, ctrl_base + 0xd0); + /* unreset */ + writel_relaxed(0x1011 << cpu, ctrl_base + 0x414); + /* reset */ + writel_relaxed(0x401011 << cpu, ctrl_base + 0x410); + + /* ISO disable */ + writel(0x8 << cpu, ctrl_base + 0xc4); + + /* WFI Mask */ + val = readl(ctrl_base + 0x200); + val &= ~(0x10000000 << cpu); + writel(val, ctrl_base + 0x200); + + /* Enable core */ + writel_relaxed(0x01 << cpu, ctrl_base + 0xf4); + /* Unreset */ + writel_relaxed(0x401011 << cpu, ctrl_base + 0x414); + } else { + /* iso enable */ + writel_relaxed(0x8 << cpu, ctrl_base + 0xc0); + + /* MTCMOS unset */ + writel_relaxed(0x8 << cpu, ctrl_base + 0xd4); + + /* wfi mask */ + val = readl_relaxed(ctrl_base + 0x200); + val |= (0x10000000 << cpu); + writel_relaxed(val, ctrl_base + 0x200); + + /* disable core*/ + writel_relaxed(0x01 << cpu, ctrl_base + 0xf8); + /* reset */ + writel_relaxed(0x401011 << cpu, ctrl_base + 0x410); + } +} + +static void hs_set_cpu_hi3716(int cpu, bool enable) +{ + u32 val = 0; + + if (enable) { + /* power on cpu1 */ + val = readl_relaxed(ctrl_base + 0x1000); + val &= ~(0x1 << 8); + val |= (0x1 << 7); + val &= ~(0x1 << 3); + writel_relaxed(val, ctrl_base + 0x1000); + + /* unreset */ + val = readl_relaxed(ctrl_base + 0x50); + val &= ~(0x1 << 17); + writel_relaxed(val, ctrl_base + 0x50); + } else { + /* power down cpu1 */ + val = readl_relaxed(ctrl_base + 0x1000); + val &= ~(0x1 << 8); + val |= (0x1 << 7); + val |= (0x1 << 3); + writel_relaxed(val, ctrl_base + 0x1000); + + /* reset */ + val = readl_relaxed(ctrl_base + 0x50); + val |= (0x1 << 17); + writel_relaxed(val, ctrl_base + 0x50); + } +} + +void hs_set_cpu(int cpu, bool enable) +{ + if (!ctrl_base) + return; + + if (id == HI3620_CTRL) + hs_set_cpu_hi3620(cpu, enable); + else if (id == HI3716_CTRL) + hs_set_cpu_hi3716(cpu, enable); +} + +void __init hs_hotplug_init(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "hisilicon,hi3716-cpuctrl"); + if (node) { + ctrl_base = of_iomap(node, 0); + id = HI3716_CTRL; + return; + } + node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); + if (node) { + ctrl_base = of_iomap(node, 0); + id = HI3620_CTRL; + return; + } +} + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + + /* + * Turn off coherency and L1 D-cache + */ + asm volatile( + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0) + : "cc"); +} + +void hs_cpu_die(unsigned int cpu) +{ + cpu_enter_lowpower(); + hs_set_cpu_jump(cpu, phys_to_virt(0)); + cpu_do_idle(); + + /* We should have never returned from idle */ + panic("cpu %d unexpectedly exit from shutdown\n", cpu); +} + +int hs_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (hs_get_cpu_jump(cpu)) + if (time_after(jiffies, timeout)) + return 0; + hs_set_cpu(cpu, false); + return 1; +} diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c index a76a3cc..6a08630 100644 --- a/arch/arm/mach-hi3xxx/platsmp.c +++ b/arch/arm/mach-hi3xxx/platsmp.c @@ -32,6 +32,7 @@ static void __init hs_smp_prepare_cpus(unsigned int max_cpus) static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle) { + hs_set_cpu(cpu, true); hs_set_cpu_jump(cpu, secondary_startup); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; @@ -40,4 +41,8 @@ static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle) struct smp_operations hs_smp_ops __initdata = { .smp_prepare_cpus = hs_smp_prepare_cpus, .smp_boot_secondary = hs_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = hs_cpu_die, + .cpu_kill = hs_cpu_kill, +#endif };