From patchwork Thu Jun 19 12:40:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhilash Kesavan X-Patchwork-Id: 4383051 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4D95A9F1D6 for ; Thu, 19 Jun 2014 12:45:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4BD7420340 for ; Thu, 19 Jun 2014 12:45:19 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 313D9202EB for ; Thu, 19 Jun 2014 12:45:18 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WxbeA-000807-8H; Thu, 19 Jun 2014 12:40:54 +0000 Received: from mail-pb0-x231.google.com ([2607:f8b0:400e:c01::231]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wxbe6-0007z8-Jo for linux-arm-kernel@lists.infradead.org; Thu, 19 Jun 2014 12:40:51 +0000 Received: by mail-pb0-f49.google.com with SMTP id rr13so1875288pbb.22 for ; Thu, 19 Jun 2014 05:40:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=sBf6HVPB+lIDjgBKNiAr0q1KmjiRP0WLFf28L3vAShw=; b=dRZei2pV7etcNtEzZ2dLhqsHL2UiLyjTQac7MUQUbOBZEMmaalPqSu1zx6ZIEBHN5Q 0xHhr5v2WHGIyxV0O3ve9jOpUi74y3pB2/pNJzZM8fmwrEAZpiyLyGYhrL0SvJu0NQQf jBbKv+bfW0K5uHF7+pKAPYaL5d7E0HSO5G1S7uXN5a9rx8y5DnUlxoT9cW703FWFqN9/ IiEB6b/ZepFBSn0dtMmIc6j1XIowbxL+FhPRwGAN1ki+YbRNETLDLQYKWik0HhMKiOpg vZexiM71GvUnJw0GzJOJAfGkaljb8W8ozrJZaUdzQplPKUPRUozRnqtT21PrMTY3lAh8 AFnw== X-Received: by 10.68.231.229 with SMTP id tj5mr5097648pbc.101.1403181629418; Thu, 19 Jun 2014 05:40:29 -0700 (PDT) Received: from localhost.localdomain ([122.172.40.61]) by mx.google.com with ESMTPSA id vy5sm26494176pac.13.2014.06.19.05.40.25 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 19 Jun 2014 05:40:28 -0700 (PDT) From: Abhilash Kesavan To: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, kgene.kim@samsung.com, nicolas.pitre@linaro.org Subject: [PATCH v2] arm: exynos: Support cluster power off on exynos5420/5800 Date: Thu, 19 Jun 2014 18:10:17 +0530 Message-Id: <1403181617-19743-1-git-send-email-a.kesavan@samsung.com> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1403104722-14848-1-git-send-email-a.kesavan@samsung.com> References: <1403104722-14848-1-git-send-email-a.kesavan@samsung.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140619_054050_725789_9A2EBA77 X-CRM114-Status: GOOD ( 24.15 ) X-Spam-Score: 0.0 (/) Cc: abrestic@chromium.org, kesavan.abhilash@gmail.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=no 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 Turning off a cluster when all 4 cores of the cluster are powered off saves power significantly. Powering off the A15 L2 alone gives around 100mW in savings. Add support for powering off the A15/A7 clusters on exynos5420/5800. The patch enables specific register bits which ensure that: - cluster L2 will be turned on before the first man is powered up. - last man will be turned off before the cluster L2 is turned off. - core is powered down before powering it up. Remove the exynos_cluster_power_control function completely as we can rely on the above mentioned bits rather than polling the cluster power status register. Signed-off-by: Abhilash Kesavan Acked-by: Nicolas Pitre Tested-by: Kevin Hilman --- Change in v2: Added a macro for the COMMON_OPTION register and used it in the MCPM back-end. The patch is based on Linux-next 20140619. It has been tested on an exynos5420-based chromebook using the "/dev/bL_switcher" interface as well as the script provided by Nicolas Pitre and Dave Martin [1]. Patch depends on: [v2] ARM: EXYNOS: mcpm: Don't rely on firmware's secondary_cpu_start [1] http://www.spinics.net/lists/linux-samsung-soc/msg31257.html arch/arm/mach-exynos/mcpm-exynos.c | 66 +++++++++++++++++------------------- arch/arm/mach-exynos/regs-pmu.h | 2 ++ 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c index ace0ed6..619cbc6 100644 --- a/arch/arm/mach-exynos/mcpm-exynos.c +++ b/arch/arm/mach-exynos/mcpm-exynos.c @@ -26,6 +26,10 @@ #define EXYNOS5420_CPUS_PER_CLUSTER 4 #define EXYNOS5420_NR_CLUSTERS 2 +#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9) +#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) +#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) + /* * The common v7_exit_coherency_flush API could not be used because of the * Erratum 799270 workaround. This macro is the same as the common one (in @@ -73,36 +77,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS]; #define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster) -static int exynos_cluster_power_control(unsigned int cluster, int enable) -{ - unsigned int tries = 100; - unsigned int val; - - if (enable) { - exynos_cluster_power_up(cluster); - val = S5P_CORE_LOCAL_PWR_EN; - } else { - exynos_cluster_power_down(cluster); - val = 0; - } - - /* Wait until cluster power control is applied */ - while (tries--) { - if (exynos_cluster_power_state(cluster) == val) - return 0; - - cpu_relax(); - } - pr_debug("timed out waiting for cluster %u to power %s\n", cluster, - enable ? "on" : "off"); - - return -ETIMEDOUT; -} - static int exynos_power_up(unsigned int cpu, unsigned int cluster) { unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER); - int err = 0; pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER || @@ -126,12 +103,9 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster) * cores. */ if (was_cluster_down) - err = exynos_cluster_power_control(cluster, 1); + exynos_cluster_power_up(cluster); - if (!err) - exynos_cpu_power_up(cpunr); - else - exynos_cluster_power_control(cluster, 0); + exynos_cpu_power_up(cpunr); } else if (cpu_use_count[cpu][cluster] != 2) { /* * The only possible values are: @@ -147,7 +121,7 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster) arch_spin_unlock(&exynos_mcpm_lock); local_irq_enable(); - return err; + return 0; } /* @@ -178,9 +152,10 @@ static void exynos_power_down(void) if (cpu_use_count[cpu][cluster] == 0) { exynos_cpu_power_down(cpunr); - if (exynos_cluster_unused(cluster)) - /* TODO: Turn off the cluster here to save power. */ + if (exynos_cluster_unused(cluster)) { + exynos_cluster_power_down(cluster); last_man = true; + } } else if (cpu_use_count[cpu][cluster] == 1) { /* * A power_up request went ahead of us. @@ -299,6 +274,7 @@ static int __init exynos_mcpm_init(void) { struct device_node *node; void __iomem *ns_sram_base_addr; + unsigned int value, i; int ret; node = of_find_matching_node(NULL, exynos_dt_mcpm_match); @@ -342,6 +318,26 @@ static int __init exynos_mcpm_init(void) pr_info("Exynos MCPM support installed\n"); /* + * On Exynos5420/5800 for the A15 and A7 clusters: + * + * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores + * in a cluster are turned off before turning off the cluster L2. + * + * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered + * off before waking it up. + * + * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be + * turned on before the first man is powered up. + */ + for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) { + value = __raw_readl(EXYNOS_COMMON_OPTION(i)); + value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | + EXYNOS5420_USE_ARM_CORE_DOWN_STATE | + EXYNOS5420_USE_L2_COMMON_UP_STATE; + __raw_writel(value, EXYNOS_COMMON_OPTION(i)); + } + + /* * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr * as part of secondary_cpu_start(). Let's redirect it to the * mcpm_entry_point(). diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 1d13b08..bda8df0 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -117,6 +117,8 @@ (EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr))) #define EXYNOS_COMMON_STATUS(_nr) \ (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4) +#define EXYNOS_COMMON_OPTION(_nr) \ + (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8) #define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028) #define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)