From patchwork Sat Apr 21 14:19:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 10354177 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AA852601E7 for ; Sat, 21 Apr 2018 14:20:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 967DD28917 for ; Sat, 21 Apr 2018 14:20:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8AC8D2891C; Sat, 21 Apr 2018 14:20:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D55822891A for ; Sat, 21 Apr 2018 14:20:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=NJZtZjyuVxl9vayPR3I9TncoUX77UAJKLjh93MVjCoI=; b=GgA J8C5znGAppkZSB22vCuazSFSt97wk9RClEcpC9PsG5/90HC/oWmRdF0zEpuHe8IaKObGYi+pCJYhR 37GdHQm5hB68czG9pXCO5VjVqve2fA3uFjggh0ur2wC9v8WzUeNE/SqR/GLPg2CdPy7Cy9z3GsPck RULPk1NkL4GgqFI3oFtsQvgCZj+KKGZnyO2iy2Iv8etz9Enne/AtbriX7p2+7XYMiuz0R4FPXxomi /SGuvI2bCIdVwY09GXdd1mLXLqiMdZwjGm/x5tSZ3qE94D3aMqqACCWtll1QKgMjhPfrVM+ca3hsJ Dm8nTx1Nn8KYi59gQecBCHpt4QMigbw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f9tNI-0000GB-GY; Sat, 21 Apr 2018 14:20:24 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f9tN0-0007L8-OW for linux-arm-kernel@lists.infradead.org; Sat, 21 Apr 2018 14:20:22 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 3B06E207E1; Sat, 21 Apr 2018 16:19:55 +0200 (CEST) Received: from localhost.localdomain (unknown [91.224.148.103]) by mail.bootlin.com (Postfix) with ESMTPSA id 785EF2073D; Sat, 21 Apr 2018 16:19:44 +0200 (CEST) From: Miquel Raynal To: Gregory Clement , Jason Cooper , Andrew Lunn , Sebastian Hesselbarth , "Rafael J . Wysocki" , Viresh Kumar Subject: [PATCH] cpufreq: add suspend/resume support in Armada 37xx DVFS driver Date: Sat, 21 Apr 2018 16:19:43 +0200 Message-Id: <20180421141943.25705-1-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.14.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180421_072007_179903_B35242D4 X-CRM114-Status: GOOD ( 19.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pm@vger.kernel.org, Antoine Tenart , Maxime Chevallier , Nadav Haklai , Thomas Petazzoni , Miquel Raynal , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add suspend/resume hooks in Armada 37xx DVFS driver to handle S2RAM operations. As there is currently no 'driver' structure, create one to store both the regmap and the register values during suspend operation. A syscore_ops is used to export the suspend/resume hooks. Signed-off-by: Miquel Raynal --- drivers/cpufreq/armada-37xx-cpufreq.c | 73 ++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c index 72a2975499db..9c9c3673cbbe 100644 --- a/drivers/cpufreq/armada-37xx-cpufreq.c +++ b/drivers/cpufreq/armada-37xx-cpufreq.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Power management in North Bridge register set */ #define ARMADA_37XX_NB_L0L1 0x18 @@ -56,6 +57,18 @@ */ #define LOAD_LEVEL_NR 4 +#if defined(CONFIG_PM) +struct armada37xx_cpufreq_state { + struct regmap *regmap; + u32 nb_l0l1; + u32 nb_l2l3; + u32 nb_dyn_mod; + u32 nb_cpu_load; +}; + +static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state; +#endif /* CONFIG_PM */ + struct armada_37xx_dvfs { u32 cpu_freq_max; u8 divider[LOAD_LEVEL_NR]; @@ -136,7 +149,7 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, clk_set_parent(clk, parent); } -static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base) +static void armada37xx_cpufreq_disable_dvfs(struct regmap *base) { unsigned int reg = ARMADA_37XX_NB_DYN_MOD, mask = ARMADA_37XX_NB_DFS_EN; @@ -162,6 +175,46 @@ static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base) regmap_update_bits(base, reg, mask, mask); } +#if defined(CONFIG_PM) +static int armada37xx_cpufreq_suspend(void) +{ + struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state; + + regmap_read(state->regmap, ARMADA_37XX_NB_L0L1, &state->nb_l0l1); + regmap_read(state->regmap, ARMADA_37XX_NB_L2L3, &state->nb_l2l3); + regmap_read(state->regmap, ARMADA_37XX_NB_CPU_LOAD, + &state->nb_cpu_load); + regmap_read(state->regmap, ARMADA_37XX_NB_DYN_MOD, &state->nb_dyn_mod); + + return 0; +} + +static void armada37xx_cpufreq_resume(void) +{ + struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state; + + /* Ensure DVFS is disabled otherwise the following registers are RO */ + armada37xx_cpufreq_disable_dvfs(state->regmap); + + regmap_write(state->regmap, ARMADA_37XX_NB_L0L1, state->nb_l0l1); + regmap_write(state->regmap, ARMADA_37XX_NB_L2L3, state->nb_l2l3); + regmap_write(state->regmap, ARMADA_37XX_NB_CPU_LOAD, + state->nb_cpu_load); + + /* + * NB_DYN_MOD register is the one that actually enable back DVFS if it + * was enabled before the suspend operation. This must be done last + * otherwise other registers are not writable. + */ + regmap_write(state->regmap, ARMADA_37XX_NB_DYN_MOD, state->nb_dyn_mod); +} + +static struct syscore_ops armada37xx_cpufreq_syscore_pm_ops = { + .suspend = armada37xx_cpufreq_suspend, + .resume = armada37xx_cpufreq_resume, +}; +#endif /* CONFIG_PM */ + static int __init armada37xx_cpufreq_driver_init(void) { struct armada_37xx_dvfs *dvfs; @@ -231,9 +284,25 @@ static int __init armada37xx_cpufreq_driver_init(void) /* Now that everything is setup, enable the DVFS at hardware level */ armada37xx_cpufreq_enable_dvfs(nb_pm_base); + armada37xx_cpufreq_state = kmalloc(sizeof(*armada37xx_cpufreq_state), + GFP_KERNEL); + if (!armada37xx_cpufreq_state) + return -ENOMEM; + + armada37xx_cpufreq_state->regmap = nb_pm_base; + +#if defined(CONFIG_PM) + /* Register suspend/resume hooks */ + register_syscore_ops(&armada37xx_cpufreq_syscore_pm_ops); +#endif /* CONFIG_PM */ + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); - return PTR_ERR_OR_ZERO(pdev); + ret = PTR_ERR_OR_ZERO(pdev); + if (ret) + kfree(armada37xx_cpufreq_state); + + return ret; } /* late_initcall, to guarantee the driver is loaded after A37xx clock driver */ late_initcall(armada37xx_cpufreq_driver_init);