From patchwork Thu Jan 9 08:03:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anson Huang X-Patchwork-Id: 3457691 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 C428BC02DC for ; Thu, 9 Jan 2014 08:03:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8CC4820103 for ; Thu, 9 Jan 2014 08:03:55 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (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 1DC76200F3 for ; Thu, 9 Jan 2014 08:03:54 +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 1W1Aag-00083p-2B; Thu, 09 Jan 2014 08:03:46 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1W1Aad-0004WJ-KT; Thu, 09 Jan 2014 08:03:43 +0000 Received: from mail-db8lp0184.outbound.messaging.microsoft.com ([213.199.154.184] helo=db8outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W1Aaa-0004Vj-6T for linux-arm-kernel@lists.infradead.org; Thu, 09 Jan 2014 08:03:41 +0000 Received: from mail132-db8-R.bigfish.com (10.174.8.251) by DB8EHSOBE031.bigfish.com (10.174.4.94) with Microsoft SMTP Server id 14.1.225.22; Thu, 9 Jan 2014 08:03:18 +0000 Received: from mail132-db8 (localhost [127.0.0.1]) by mail132-db8-R.bigfish.com (Postfix) with ESMTP id 7B106440099; Thu, 9 Jan 2014 08:03:18 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 6 X-BigFish: VS6(zzc8kzz1f42h2148h208ch1ee6h1de0h1fdah2073h2146h1202h1e76h2189h1d1ah1d2ah1fc6h1082kzz1de098h8275bh1de097hz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh2222h224fh1fb3h1d0ch1d2eh1d3fh1dc1h1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h2327h2336h2438h1155h) Received: from mail132-db8 (localhost.localdomain [127.0.0.1]) by mail132-db8 (MessageSwitch) id 1389254597290260_24360; Thu, 9 Jan 2014 08:03:17 +0000 (UTC) Received: from DB8EHSMHS025.bigfish.com (unknown [10.174.8.227]) by mail132-db8.bigfish.com (Postfix) with ESMTP id 37C4860047; Thu, 9 Jan 2014 08:03:17 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by DB8EHSMHS025.bigfish.com (10.174.4.35) with Microsoft SMTP Server (TLS) id 14.16.227.3; Thu, 9 Jan 2014 08:03:17 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server (TLS) id 14.3.158.2; Thu, 9 Jan 2014 08:03:15 +0000 Received: from ubuntu.ap.freescale.net (ubuntu.ap.freescale.net [10.192.242.118]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s0983DVS008066; Thu, 9 Jan 2014 01:03:14 -0700 From: Anson Huang To: , Subject: [PATCH V3] ARM: imx: add cpuidle support for i.mx6sl Date: Thu, 9 Jan 2014 16:03:16 +0800 Message-ID: <1389254596-20173-1-git-send-email-b20788@freescale.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140109_030340_450352_58349D21 X-CRM114-Status: GOOD ( 22.27 ) X-Spam-Score: -1.9 (-) Cc: linux-arm-kernel@lists.infradead.org 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: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 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 Add cpuidle support for i.MX6SL, currently only support two cpuidle levels(ARM wfi and WAIT mode), and add software workaround for WAIT mode errata as below: ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken during WAIT mode entry process could cause cache memory corruption. Software workaround: To prevent this issue from occurring, software should ensure that the ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before entering WAIT mode. Signed-off-by: Anson Huang --- Changes since V2: Fix conflict when applying patch to shawnguo/for-next, as I generated it from linux-next before. arch/arm/mach-imx/Makefile | 1 + arch/arm/mach-imx/clk-imx6sl.c | 26 ++++++++++++++++ arch/arm/mach-imx/common.h | 1 + arch/arm/mach-imx/cpuidle-imx6sl.c | 57 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-imx/cpuidle.h | 5 ++++ arch/arm/mach-imx/mach-imx6sl.c | 3 ++ 6 files changed, 93 insertions(+) create mode 100644 arch/arm/mach-imx/cpuidle-imx6sl.c diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index befcaf5..8589032 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o endif ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c index 5877eea..f6c3b4f 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -66,6 +66,32 @@ static struct clk_div_table video_div_table[] = { static struct clk *clks[IMX6SL_CLK_END]; static struct clk_onecell_data clk_data; +/* + * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken + * during WAIT mode entry process could cause cache memory + * corruption. + * + * Software workaround: + * To prevent this issue from occurring, software should ensure that the + * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before + * entering WAIT mode. + * + * This function will set the ARM clk to max value within the 12:5 limit. + */ +void imx6sl_set_wait_clk(bool enter) +{ + static unsigned long saved_arm_rate; + + if (enter) { + unsigned long ipg_rate = clk_get_rate(clks[IMX6SL_CLK_IPG]); + unsigned long max_arm_wait_rate = (12 * ipg_rate) / 5; + saved_arm_rate = clk_get_rate(clks[IMX6SL_CLK_ARM]); + clk_set_rate(clks[IMX6SL_CLK_ARM], max_arm_wait_rate); + } else { + clk_set_rate(clks[IMX6SL_CLK_ARM], saved_arm_rate); + } +} + static void __init imx6sl_clocks_init(struct device_node *ccm_node) { struct device_node *np; diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 4f4a95c..1048248 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -140,6 +140,7 @@ void imx_anatop_pre_suspend(void); void imx_anatop_post_resume(void); int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); void imx6q_set_int_mem_clk_lpm(void); +void imx6sl_set_wait_clk(bool enter); void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c new file mode 100644 index 0000000..d4b6b81 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sl.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * 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 "common.h" +#include "cpuidle.h" + +static int imx6sl_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + /* + * Software workaround for ERR005311, see function + * description for details. + */ + imx6sl_set_wait_clk(true); + cpu_do_idle(); + imx6sl_set_wait_clk(false); + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sl_cpuidle_driver = { + .name = "imx6sl_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sl_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + +int __init imx6sl_cpuidle_init(void) +{ + return cpuidle_register(&imx6sl_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 786f98e..24e3367 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -13,6 +13,7 @@ #ifdef CONFIG_CPU_IDLE extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); +extern int imx6sl_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -22,4 +23,8 @@ static inline int imx6q_cpuidle_init(void) { return 0; } +static inline int imx6sl_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index 0f4fd4c..a26fdb2 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -17,6 +17,7 @@ #include #include "common.h" +#include "cpuidle.h" static void __init imx6sl_fec_init(void) { @@ -39,6 +40,8 @@ static void __init imx6sl_init_late(void) /* imx6sl reuses imx6q cpufreq driver */ if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); + + imx6sl_cpuidle_init(); } static void __init imx6sl_init_machine(void)