From patchwork Tue Apr 8 08:00:47 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 28020 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f197.google.com (mail-vc0-f197.google.com [209.85.220.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id AFBEB20447 for ; Tue, 8 Apr 2014 15:32:27 +0000 (UTC) Received: by mail-vc0-f197.google.com with SMTP id if11sf3092702vcb.0 for ; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=wAbtBl9U3I8Dz/cD/ke+YKpEGA1XiGW8YzMh5Y56qyY=; b=l1d4teETX3v1xDE/1TvjMXlQOtRIZ5LLpDd8g4ZJQdnlAMqJY2vIDglWdlHx2WlknU IjGH9ECYCqHvWyUOiocS9tDkOKKmRz4cvvBsgqz7Ql1UptcuV83jW+16bu+Jdz2svGyL k5OVc14hGK66bRRfyEGSDHPgDwYMQTqdSNYQdInIqlLVLKfIhN+O8f4swJXH0TTg9K/J LMdptkPj1gGlbfRgLE2+728Yr9tMjpp8sZ1PYBgHvRfaAogQVwPtiglnIo6p3cum/tLA GITOMzb6IjNgKYh9/JrKE5fYHXaYKT84cBj+wvcCdSfV7/SnEuyFcA+xXuDeod5VqTMh B6nQ== X-Gm-Message-State: ALoCoQnDoW0TSNt23qM4lT3qnGc/SDwIzKVSoBFMDhgHRHvU9Xys6UE8a0pk78wQsjkHb33l4h+7 X-Received: by 10.58.112.1 with SMTP id im1mr1704357veb.33.1396971147485; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.85.82 with SMTP id m76ls241279qgd.62.gmail; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) X-Received: by 10.220.11.208 with SMTP id u16mr3710963vcu.19.1396971147305; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) Received: from mail-ve0-f174.google.com (mail-ve0-f174.google.com [209.85.128.174]) by mx.google.com with ESMTPS id ys8si461459veb.52.2014.04.08.08.32.27 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 08 Apr 2014 08:32:27 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.174; Received: by mail-ve0-f174.google.com with SMTP id oz11so899627veb.5 for ; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) X-Received: by 10.220.147.16 with SMTP id j16mr3791484vcv.14.1396971147211; Tue, 08 Apr 2014 08:32:27 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.12.8 with SMTP id v8csp255452vcv; Tue, 8 Apr 2014 08:32:26 -0700 (PDT) X-Received: by 10.180.87.233 with SMTP id bb9mr5248235wib.10.1396971145879; Tue, 08 Apr 2014 08:32:25 -0700 (PDT) Received: from casper.infradead.org (casper.infradead.org. [2001:770:15f::2]) by mx.google.com with ESMTPS id cy9si1071003wib.121.2014.04.08.08.32.25 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Apr 2014 08:32:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:770:15f::2 as permitted sender) client-ip=2001:770:15f::2; Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WXXx5-0007jQ-5m; Tue, 08 Apr 2014 15:28:44 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WXXwc-0005gC-51; Tue, 08 Apr 2014 15:28:14 +0000 Received: from bombadil.infradead.org ([2001:1868:205::9]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WXXjy-0003gg-1K for linux-arm-kernel@merlin.infradead.org; Tue, 08 Apr 2014 15:15:10 +0000 Received: from mail-pd0-f169.google.com ([209.85.192.169]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WXQyt-0000tY-IG for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2014 08:02:09 +0000 Received: by mail-pd0-f169.google.com with SMTP id fp1so663382pdb.14 for ; Tue, 08 Apr 2014 01:01:43 -0700 (PDT) X-Received: by 10.68.196.202 with SMTP id io10mr2619178pbc.149.1396944103524; Tue, 08 Apr 2014 01:01:43 -0700 (PDT) Received: from localhost.localdomain ([162.243.130.63]) by mx.google.com with ESMTPSA id it4sm2764630pbd.48.2014.04.08.01.01.38 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 08 Apr 2014 01:01:42 -0700 (PDT) From: Haojian Zhuang To: linux-arm-kernel@lists.infradead.org, tglx@linutronix.de, linux@arm.linux.org.uk, arnd@arndb.de, olof@lixom.net, khilman@kernel.org, xuwei5@hisilicon.com Subject: [PATCH v2 07/12] ARM: hisi: add hip04 SoC support Date: Tue, 8 Apr 2014 16:00:47 +0800 Message-Id: <1396944052-9887-8-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1396944052-9887-1-git-send-email-haojian.zhuang@linaro.org> References: <1396944052-9887-1-git-send-email-haojian.zhuang@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140408_010207_692197_8A2411DD X-CRM114-Status: GOOD ( 17.40 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.3.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.192.169 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record Cc: 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+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: haojian.zhuang@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Hisilicon Hi3xxx is based on Cortex A9 Core. Now HiP04 SoC is based on Cortex A15 Core. Since multiple clusters is used in HiP04 SoC, it could be based on MCPM. And HiP04 supports LPAE to support large memory. Signed-off-by: Haojian Zhuang --- arch/arm/Kconfig | 2 +- arch/arm/mach-hisi/Kconfig | 7 ++ arch/arm/mach-hisi/core.h | 6 + arch/arm/mach-hisi/hisilicon.c | 19 +++ arch/arm/mach-hisi/platsmp.c | 259 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 292 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a8b2b45..6af6609 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1113,7 +1113,7 @@ source arch/arm/mm/Kconfig config ARM_NR_BANKS int - default 16 if ARCH_EP93XX + default 16 if ARCH_EP93XX || ARCH_HIP04 default 8 config IWMMXT diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index da16efd..4dd966a 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -19,6 +19,13 @@ config ARCH_HI3xxx help Support for Hisilicon Hi36xx/Hi37xx processor family +config ARCH_HIP04 + bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7_LPAE + select HAVE_ARM_ARCH_TIMER + select MCPM if SMP + help + Support for Hisilicon HiP04 processor family + endmenu endif diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h index af23ec2..e008c7a 100644 --- a/arch/arm/mach-hisi/core.h +++ b/arch/arm/mach-hisi/core.h @@ -12,4 +12,10 @@ extern void hi3xxx_cpu_die(unsigned int cpu); extern int hi3xxx_cpu_kill(unsigned int cpu); extern void hi3xxx_set_cpu(int cpu, bool enable); +#define HIP04_BOOTWRAPPER_PHYS 0x10c00000 +#define HIP04_BOOTWRAPPER_MAGIC 0xa5a5a5a5 +#define HIP04_BOOTWRAPPER_SIZE 0x00010000 + +extern bool __init hip04_smp_init_ops(void); + #endif diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c index 741faf3..10a605f 100644 --- a/arch/arm/mach-hisi/hisilicon.c +++ b/arch/arm/mach-hisi/hisilicon.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -88,3 +89,21 @@ DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)") .smp = smp_ops(hi3xxx_smp_ops), .restart = hi3xxx_restart, MACHINE_END + +static const char *hip04_compat[] __initconst = { + "hisilicon,hip04-d01", + NULL, +}; + +static void __init hip04_reserve(void) +{ + memblock_reserve(HIP04_BOOTWRAPPER_PHYS, HIP04_BOOTWRAPPER_SIZE); +} + +DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") + .dt_compat = hip04_compat, +#ifdef CONFIG_MCPM + .smp_init = smp_init_ops(hip04_smp_init_ops), +#endif + .reserve = hip04_reserve, +MACHINE_END diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c index 471f1ee..3a5833f 100644 --- a/arch/arm/mach-hisi/platsmp.c +++ b/arch/arm/mach-hisi/platsmp.c @@ -9,9 +9,13 @@ */ #include #include +#include #include #include +#include +#include +#include #include #include @@ -87,3 +91,258 @@ struct smp_operations hi3xxx_smp_ops __initdata = { .cpu_kill = hi3xxx_cpu_kill, #endif }; + +#ifdef CONFIG_MCPM +/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x] + * 1 -- unreset; 0 -- reset + */ +#define CORE_RESET_BIT(x) (1 << x) +#define NEON_RESET_BIT(x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_BIT(x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_BIT (1 << 8) +#define CLUSTER_DEBUG_RESET_BIT (1 << 13) + +/* + * bits definition in SC_CPU_RESET_STATUS[x] + * 1 -- reset status; 0 -- unreset status + */ +#define CORE_RESET_STATUS(x) (1 << x) +#define NEON_RESET_STATUS(x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_STATUS(x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_STATUS (1 << 8) +#define CLUSTER_DEBUG_RESET_STATUS (1 << 13) +#define CORE_WFI_STATUS(x) (1 << (x + 16)) +#define CORE_WFE_STATUS(x) (1 << (x + 20)) +#define CORE_DEBUG_ACK(x) (1 << (x + 24)) + +#define SC_CPU_RESET_REQ(x) (0x520 + (x << 3)) /* reset */ +#define SC_CPU_RESET_DREQ(x) (0x524 + (x << 3)) /* unreset */ +#define SC_CPU_RESET_STATUS(x) (0x1520 + (x << 3)) + +#define FAB_SF_MODE 0x0c +#define FAB_SF_INVLD 0x10 + +/* bits definition in FB_SF_INVLD */ +#define FB_SF_INVLD_START (1 << 8) + +#define HIP04_MAX_CLUSTERS 4 +#define HIP04_MAX_CPUS_PER_CLUSTER 4 + +static void __iomem *relocation, *sysctrl, *fabric; +static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER]; +static DEFINE_SPINLOCK(boot_lock); + +static bool hip04_cluster_down(unsigned int cluster) +{ + int i; + + for (i = 0; i < HIP04_MAX_CPUS_PER_CLUSTER; i++) + if (hip04_cpu_table[cluster][i]) + return false; + return true; +} + +static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on) +{ + unsigned long data; + + if (!fabric) + return; + data = readl_relaxed(fabric + FAB_SF_MODE); + if (on) + data |= 1 << cluster; + else + data &= ~(1 << cluster); + writel_relaxed(data, fabric + FAB_SF_MODE); + while (1) { + if (data == readl_relaxed(fabric + FAB_SF_MODE)) + break; + } +} + +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster) +{ + unsigned long data, mask; + + if (!relocation || !sysctrl) + return -ENODEV; + if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER) + return -EINVAL; + + spin_lock(&boot_lock); + writel_relaxed(HIP04_BOOTWRAPPER_PHYS, relocation); + writel_relaxed(HIP04_BOOTWRAPPER_MAGIC, relocation + 4); + writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8); + writel_relaxed(0, relocation + 12); + + if (hip04_cluster_down(cluster)) { + data = CLUSTER_L2_RESET_BIT | CLUSTER_DEBUG_RESET_BIT; + writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster)); + do { + mask = CLUSTER_L2_RESET_STATUS | \ + CLUSTER_DEBUG_RESET_STATUS; + data = readl_relaxed(sysctrl + \ + SC_CPU_RESET_STATUS(cluster)); + } while (data & mask); + hip04_set_snoop_filter(cluster, 1); + } + + hip04_cpu_table[cluster][cpu]++; + + data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \ + CORE_DEBUG_RESET_BIT(cpu); + writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster)); + spin_unlock(&boot_lock); + + return 0; +} + +static void hip04_mcpm_power_down(void) +{ + unsigned int mpidr, cpu, cluster; + unsigned int v; + + spin_lock(&boot_lock); + spin_unlock(&boot_lock); + + mpidr = read_cpuid_mpidr(); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + + local_irq_disable(); + gic_cpu_if_down(); + + __mcpm_cpu_down(cpu, cluster); + + asm volatile( + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); + + flush_cache_louis(); + + asm volatile( + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (0x40) + : "cc"); + + isb(); + dsb(); +} + +static int hip04_mcpm_power_down_finish(unsigned int cpu, unsigned int cluster) +{ + int ret = -EBUSY; + + spin_lock(&boot_lock); + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP); + __mcpm_cpu_going_down(cpu, cluster); + + hip04_cpu_table[cluster][cpu]--; + if (hip04_cpu_table[cluster][cpu]) { + pr_err("Cluster %d CPU%d is still running\n", cluster, cpu); + goto out; + } + ret = 0; +out: + spin_unlock(&boot_lock); + return ret; +} + +static void hip04_mcpm_powered_up(void) +{ + if (!relocation) + return; + spin_lock(&boot_lock); + writel_relaxed(0, relocation); + writel_relaxed(0, relocation + 4); + writel_relaxed(0, relocation + 8); + writel_relaxed(0, relocation + 12); + spin_unlock(&boot_lock); +} + +static const struct mcpm_platform_ops hip04_mcpm_ops = { + .power_up = hip04_mcpm_power_up, + .power_down = hip04_mcpm_power_down, + .power_down_finish = hip04_mcpm_power_down_finish, + .powered_up = hip04_mcpm_powered_up, +}; + +static bool __init hip04_cpu_table_init(void) +{ + unsigned int mpidr, cpu, cluster; + + mpidr = read_cpuid_mpidr(); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + + if (cluster >= HIP04_MAX_CLUSTERS || + cpu >= HIP04_MAX_CPUS_PER_CLUSTER) { + pr_err("%s: boot CPU is out of bound!\n", __func__); + return false; + } + hip04_set_snoop_filter(cluster, 1); + hip04_cpu_table[cluster][cpu] = 1; + return true; +} + +static int __init hip04_mcpm_init(void) +{ + struct device_node *np; + int ret = -ENODEV; + + np = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-mcpm"); + if (!np) { + pr_err("failed to find hisilicon,hip04-mcpm node\n"); + goto err; + } + relocation = of_iomap(np, 0); + if (!relocation) { + pr_err("failed to get relocation space\n"); + ret = -ENOMEM; + goto err; + } + sysctrl = of_iomap(np, 1); + if (!sysctrl) { + pr_err("failed to get sysctrl base\n"); + ret = -ENOMEM; + goto err_sysctrl; + } + fabric = of_iomap(np, 2); + if (!fabric) { + pr_err("failed to get fabric base\n"); + ret = -ENOMEM; + goto err_fabric; + } + if (!hip04_cpu_table_init()) + return -EINVAL; + ret = mcpm_platform_register(&hip04_mcpm_ops); + if (!ret) { + mcpm_sync_init(NULL); + pr_info("HiP04 MCPM initialized\n"); + } + return ret; +err_fabric: + iounmap(sysctrl); +err_sysctrl: + iounmap(relocation); +err: + return ret; +} +early_initcall(hip04_mcpm_init); + +bool __init hip04_smp_init_ops(void) +{ + mcpm_smp_set_ops(); + return true; +} +#endif /* CONFIG_MCPM */