From patchwork Mon Aug 6 13:57:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dongjin Kim X-Patchwork-Id: 1279461 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id A8A1D40AC9 for ; Mon, 6 Aug 2012 14:01:55 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SyNpV-0002BV-Nc; Mon, 06 Aug 2012 13:58:45 +0000 Received: from mail-gg0-f177.google.com ([209.85.161.177]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1SyNpR-00029s-Pk for linux-arm-kernel@lists.infradead.org; Mon, 06 Aug 2012 13:58:43 +0000 Received: by mail-gg0-f177.google.com with SMTP id m2so401878ggn.36 for ; Mon, 06 Aug 2012 06:58:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=xNaUm23JjKIwDM/v3O8jB/04EvcKNFBM9W75SB+Rj3w=; b=qkcQ4otK7gY9hGfOoLvsnuzA8vSbwzrZ2YCzYLA+mFdKwi7cRJWpDfWSfArYMNBPMB rZb/QmooDmAhdoHFMvn3sa9JOfJfIy/ENSuJTwJ5CkTzMLglZ9s0P6BLlgCPAgaBvh34 X355AqxeIWumv3tUf3RauW/H0Hj0HtoRVri9HTHOuG0xhMjbME8g9rlQeGa1VjvvCeYv I/Fss59km7nlxJoKqGlseBYD+e268EVDHJJIsaqlVSbIPJbGfkNE/209GmIUH06S0MCS Osqxg9ul49sszgl99c1XOVwKpLTldsXcY6tUrRzi0vdgqTSn7jdtzQlN3+kkhXkiEIdm YLQA== Received: by 10.68.220.231 with SMTP id pz7mr19108762pbc.110.1344261521187; Mon, 06 Aug 2012 06:58:41 -0700 (PDT) Received: from localhost.localdomain ([210.113.108.23]) by mx.google.com with ESMTPS id qi8sm9016134pbc.36.2012.08.06.06.58.37 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 06 Aug 2012 06:58:40 -0700 (PDT) From: Dongjin Kim To: Subject: [PATCH] ARM: EXYNOS: Enable multiple cores on Exynos4 Date: Mon, 6 Aug 2012 22:57:41 +0900 Message-Id: <1344261462-14183-4-git-send-email-dongjin.kim@agreeyamobility.net> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1344261462-14183-1-git-send-email-dongjin.kim@agreeyamobility.net> References: <1344261462-14183-1-git-send-email-dongjin.kim@agreeyamobility.net> X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.161.177 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (tobetter[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Tomasz Stanislawski , Kukjin Kim , Russell King , linux-kernel@vger.kernel.org, Kyungmin Park , linux-samsung-soc@vger.kernel.org, Jongpill Lee , linux-arm-kernel@lists.infradead.org, Dongjin Kim X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch enables CPU cores on Exynos4, on Exynos4412 secondary CPU cores are power-gated, therefore we must turn on the CPU cores on the system boot. Shows below log message on boot. [ 0.045000] CPU: Testing write buffer coherency: ok [ 0.045000] CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00 [ 0.045000] hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7 counters e [ 0.045000] Setting up static identity map for 0x40370790 - 0x403707e8 [ 0.045000] L310 cache controller enabled [ 0.045000] l2x0: 16 ways, CACHE_ID 0x4100c4c8, AUX_CTRL 0x7e470001, Cache sizeB [ 0.070000] CPU1: Booted secondary processor [ 0.090000] CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01 [ 0.090000] CPU1: Unknown IPI message 0x1 [ 0.100000] CPU2: Booted secondary processor [ 0.120000] CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02 [ 0.120000] CPU2: Unknown IPI message 0x1 [ 0.130000] CPU3: Booted secondary processor [ 0.150000] CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03 [ 0.150000] CPU3: Unknown IPI message 0x1 [ 0.150000] Brought up 4 CPUs [ 0.150000] SMP: Total of 4 processors activated (7969.17 BogoMIPS). Change-Id: I61615c5b719d3646698f114fc3777eb304694099 Signed-off-by: Dongjin Kim --- arch/arm/mach-exynos/hotplug.c | 4 +- arch/arm/mach-exynos/include/mach/regs-pmu.h | 11 ++- arch/arm/mach-exynos/platsmp.c | 100 +++++++++++++++++--------- 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 9c17a0a..cd53497 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -66,8 +66,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) for (;;) { /* make cpu1 to be turned off at next WFI command */ - if (cpu == 1) - __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION); + if ((cpu >= 1) && (cpu < num_possible_cpus())) + __raw_writel(0, S5P_ARM_CORE_CONFIGURATION(cpu)); /* * here's the WFI diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h index d4e392b..0bb21e2 100644 --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h @@ -123,10 +123,15 @@ #define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0) #define S5P_ARM_CORE0_CONFIGURATION S5P_PMUREG(0x2000) +#define S5P_ARM_CORE0_STATUS S5P_PMUREG(0x2004) #define S5P_ARM_CORE0_OPTION S5P_PMUREG(0x2008) -#define S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080) -#define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084) -#define S5P_ARM_CORE1_OPTION S5P_PMUREG(0x2088) + +#define S5P_ARM_CORE_OPTION(_nr) (S5P_ARM_CORE0_OPTION + ((_nr) * 0x80)) +#define S5P_ARM_CORE_STATUS(_nr) (S5P_ARM_CORE0_STATUS + ((_nr) * 0x80)) +#define S5P_ARM_CORE_CONFIGURATION(_nr) \ + (S5P_ARM_CORE0_CONFIGURATION + ((_nr) * 0x80)) + +#define S5P_CORE_OPTION_DIS (1 << 8) #define S5P_ARM_COMMON_OPTION S5P_PMUREG(0x2408) #define S5P_TOP_PWR_OPTION S5P_PMUREG(0x2C48) diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 36c3984..68ca26f 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -34,9 +34,6 @@ extern void exynos4_secondary_startup(void); -#define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ - S5P_INFORM5 : S5P_VA_SYSRAM) - /* * control for which core is the next to come out of the secondary * boot "holding pen" @@ -59,6 +56,9 @@ static void write_pen_release(int val) static void __iomem *scu_base_addr(void) { + if (soc_is_exynos5250()) + return 0; + return (void __iomem *)(S5P_VA_SCU); } @@ -86,9 +86,41 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } +static int exynos_power_up_cpu(unsigned int cpu) +{ + unsigned long timeout; + unsigned int val; + void __iomem *power_base = S5P_ARM_CORE_CONFIGURATION(cpu); + + val = __raw_readl(power_base); + if (!(val & S5P_CORE_LOCAL_PWR_EN)) { + __raw_writel(S5P_CORE_LOCAL_PWR_EN, power_base); + + timeout = 10; + + /* wait max 10 ms until cpu is on */ + while ((__raw_readl(power_base + 0x4) + & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { + if (timeout-- == 0) + break; + + mdelay(1); + } + + if (timeout == 0) { + pr_err("cpu%d power enable failed", cpu); + return -ETIMEDOUT; + } + } + + return 0; +} + int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; + void __iomem *boot_base; + int ret; /* * Set synchronisation state between this boot processor @@ -96,6 +128,12 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ spin_lock(&boot_lock); + ret = exynos_power_up_cpu(cpu); + if (ret) { + spin_unlock(&boot_lock); + return ret; + } + /* * The secondary processor is waiting to be released from * the holding pen - release it, then wait for it to flag @@ -106,39 +144,33 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ write_pen_release(cpu_logical_map(cpu)); - if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { - __raw_writel(S5P_CORE_LOCAL_PWR_EN, - S5P_ARM_CORE1_CONFIGURATION); - - timeout = 10; - - /* wait max 10 ms until cpu1 is on */ - while ((__raw_readl(S5P_ARM_CORE1_STATUS) - & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { - if (timeout-- == 0) - break; - - mdelay(1); - } - - if (timeout == 0) { - printk(KERN_ERR "cpu1 power enable failed"); - spin_unlock(&boot_lock); - return -ETIMEDOUT; - } - } /* * 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. */ - timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { smp_rmb(); + if (soc_is_exynos4210() && + (samsung_rev() == EXYNOS4210_REV_1_1)) + boot_base = S5P_INFORM5; + else + boot_base = S5P_VA_SYSRAM; + + if (soc_is_exynos4412()) + boot_base += (0x4 * cpu); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The boot monitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ __raw_writel(virt_to_phys(exynos4_secondary_startup), - CPU1_BOOT_REG); + boot_base); + gic_raise_softirq(cpumask_of(cpu), 1); if (pen_release == -1) @@ -186,15 +218,15 @@ void __init smp_init_cpus(void) void __init platform_smp_prepare_cpus(unsigned int max_cpus) { - if (!soc_is_exynos5250()) - scu_enable(scu_base_addr()); + int i; /* - * Write the address of secondary startup into the - * system-wide flags register. The boot monitor waits - * until it receives a soft interrupt, and then the - * secondary CPU branches to this address. + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. */ - __raw_writel(virt_to_phys(exynos4_secondary_startup), - CPU1_BOOT_REG); + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + if (!soc_is_exynos5250()) + scu_enable(scu_base_addr()); }