From patchwork Wed Aug 23 16:10:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 9917759 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 CFF05608A6 for ; Wed, 23 Aug 2017 16:11:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C1044289C4 for ; Wed, 23 Aug 2017 16:11:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BEEFA289EA; Wed, 23 Aug 2017 16:11:38 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E6545289DF for ; Wed, 23 Aug 2017 16:11:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932182AbdHWQLH (ORCPT ); Wed, 23 Aug 2017 12:11:07 -0400 Received: from mail-cys01nam02on0078.outbound.protection.outlook.com ([104.47.37.78]:63852 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932449AbdHWQKv (ORCPT ); Wed, 23 Aug 2017 12:10:51 -0400 Received: from DM5PR03CA0038.namprd03.prod.outlook.com (10.174.189.155) by CO2PR03MB2261.namprd03.prod.outlook.com (10.166.92.142) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1362.18; Wed, 23 Aug 2017 16:10:41 +0000 Received: from BY2FFO11OLC001.protection.gbl (2a01:111:f400:7c0c::135) by DM5PR03CA0038.outlook.office365.com (2603:10b6:4:3b::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1362.18 via Frontend Transport; Wed, 23 Aug 2017 16:10:41 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11OLC001.mail.protection.outlook.com (10.1.15.185) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1341.15 via Frontend Transport; Wed, 23 Aug 2017 16:10:41 +0000 Received: from b29396-OptiPlex-7040.ap.freescale.net (b29396-OptiPlex-7040.ap.freescale.net [10.192.242.182]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id v7NGABgj021744; Wed, 23 Aug 2017 09:10:37 -0700 From: Dong Aisheng To: CC: , , , , , , , , , Dong Aisheng Subject: [PATCH 7/7] cpufreq: add imx7ulp cpufreq driver Date: Thu, 24 Aug 2017 00:10:10 +0800 Message-ID: <1503504610-12880-8-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1503504610-12880-1-git-send-email-aisheng.dong@nxp.com> References: <1503504610-12880-1-git-send-email-aisheng.dong@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131479782413662612; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(336005)(39860400002)(39380400002)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(97736004)(50466002)(48376002)(2351001)(33646002)(356003)(68736007)(7416002)(5003940100001)(305945005)(6916009)(36756003)(106466001)(54906002)(4326008)(105606002)(189998001)(2906002)(77096006)(110136004)(53936002)(50986999)(76176999)(81166006)(47776003)(8676002)(626005)(6666003)(50226002)(8656003)(8936002)(498600001)(104016004)(85426001)(5660300001)(2950100002)(86362001)(81156014)(2004002); DIR:OUT; SFP:1101; SCL:1; SRVR:CO2PR03MB2261; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11OLC001; 1:7g4xoVVUnOXhe+x3EPE0tdbnR4KLoJcWKXNBvbKVMGf6GfkkVcc4fwM83/VVpB9oPPopgs9X56/+OM4sJxNpCNVqyBvOH9bWlGF9BAecQE/TLk3bWce01UVsn6AUyv9y MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5ae14b7f-16d9-4880-7994-08d4ea418060 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(300000503095)(300135400095)(2017052603186)(201703131430075)(201703131517081)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095); SRVR:CO2PR03MB2261; X-Microsoft-Exchange-Diagnostics: 1; CO2PR03MB2261; 3:dAw5HFivQ1VYtLLLnCywPIdR2SlOb0Y/TdaKDtCcL7WEYKZBccGE/3UvhOJJzgB4mBDyUM2XrFLiJwXqRbl3ftprmfXQvAuDW1dHpsOtCIghwQCe2ZNVc19kABZ2KMpOgnkPt/qGWZ4FuCPoN4ToUhaRJcDBAOnIVEkJVWsixTju9k3Pu27XZv+anuXbRe7smjHL9nrQ788GPfmh8ZeQZtESQuZ/Uu+7A4JuhMfIYIMaCRxq0LrtNea3RP0ToR00A3xYmBXqA9djV4ZmNuTzjTmVE5YXMJE8eCTzGTutSY5sLxEUPi/w9em7rm9xWyfdyujU+VekTE/ECB4NMbZyzruMwKfU0IkmPPx0uo/WJGs=; 25:tFjuEYrE6JqQku6M16ju64pDCw+2QBPVep2I9/z7yW7mODzTHNj24gkZnjfv0DbD5i3iEumfaxiJWGb09Q1UJ3Xz1TaAsxHhNE9/3VFlEF0G+qzht6BUQjfEAzQETT1Vd//Q1VgAd6BzaydyA6lg9BfjcQm8rSyxWrOhVtvWEY+NQaV+v9ZO2pGrlzbrCMxjvtBQtbeeKa24fa+OBrt5oa1cTyJ7toBYbC6n0apbKsxMrjAsf1WC/LcnPlzqIJatqCWBmRDFToHBrufkmq1MCrGNzmn7rMFhvUJJryyUQCeeoBrv+1G91SLylgGDeERNqOcarSLHRz97vyNsSCcvtw== X-MS-TrafficTypeDiagnostic: CO2PR03MB2261: X-Microsoft-Exchange-Diagnostics: 1; CO2PR03MB2261; 31:/aoNavpq3v9UKaKA+7+/ajLnZhUYscgtuGOubHKoB713xZooEH/cHA2J6Y39mfeDKdoLc77XtVOO6W05FHEBxJrffeVSiDcyQs0dhG9lDJYi5BzBESdPPfPOLssKq2oVGeVDOX0egkQOTNxRnwZPo50jsEyU70XLaSABmdBM+nHecauNJr5vrIPlmtuCtfE1PwsoGlcNUU0sE1xVFAfulonaUi4vgv6OajOJVsw7zmY=; 4:CCj3xIJ8vJCJBMQhpzBpdbf9smjDtoQDnybRxmDye4b+QIZjJIOIIWhSph/87c1u1tLfm6ti1t3faUGEP8QCXGW5zo03532yyiK/nwuqbwmh616rg+y5rD4pIYHctoPPvDdcBKinbX5/7yTLro6IqAUD8odt+zKxYzRpr8O4B4h5hV2NQUP8mgP2xnL5LW1xFjSO+FphOq4ZmG7hPL9eijYntFQbxtKrSw/uegLK2UGhR/7dWDnl/EQ2p9yxGxadDBeCKIw6ejXjlIpeQFqV4eklKrfh9DdpXu4SDt9lupqn1aL5eeJNE2bHEPdm2eqhWj6bQFIdJjWdlZA5IaKNwQ== X-Exchange-Antispam-Report-Test: UriScan:(31051911155226)(185117386973197); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6095135)(601004)(2401047)(13018025)(8121501046)(5005006)(13016025)(10201501046)(93006095)(93001095)(100000703101)(100105400095)(3002001)(6055026)(6096035)(20161123559100)(20161123563025)(20161123556025)(201703131430075)(201703131433075)(201703131441075)(201703131448075)(201703161259150)(20161123561025)(20161123565025)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:CO2PR03MB2261; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(400006)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:CO2PR03MB2261; X-Forefront-PRVS: 040866B734 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CO2PR03MB2261; 23:oH5SLzroe4HI3c+ZrFJf9zpw4bTFAy7XvrJ/pnnSQ?= =?us-ascii?Q?kaMI3+BXNqfwNnbVFBQR1B0pNgd0KdCJS9VZ9S7wTjWwxAQkmH1OUvG6nwx6?= =?us-ascii?Q?Pc7ZTm1YjGXPBRaNpBIVK3Vsye3aoD3GJ623eq4UiLFoBQX5BUw8Mjzi9Bi9?= =?us-ascii?Q?vMDZ/Vi+PeQsYbtUusOw8klTJXLeRKjMZBl1d41KdvFptjd6lpF9o8C/ETSV?= =?us-ascii?Q?sZ6zIrzPCuXZAmRH0fPP3+TWzyODgGc9VC+P4UzTqKc7BhXy6K24J6WN/0G/?= =?us-ascii?Q?RzRuecj4SejKbfVPNoucHS4nbvtzeQMWlkveBTvsnLez37WLMCjfYLYk+uG+?= =?us-ascii?Q?E5Becknl6RYT0LSe+WxNKjcPe1rk7KUVDNtRy/fk7sZZMIkroTRjKm83t4nm?= =?us-ascii?Q?NurtlXdDmhFBJJ72l5/bmW/SgRF7DGaPMEPc7FqKlbaZrF21K/k8HTK+4wSP?= =?us-ascii?Q?9XKeYsr9taQDVgNpWC907CNUIT8ZFjKeiNgHGSDiME1JvSIeIvjnEdRiTp3a?= =?us-ascii?Q?EshGzRwvcWORbdYvxQwzmYk401EHOlzwrQcuhyZQJ5tPeubtQMOyUjA6cc+b?= =?us-ascii?Q?Rb2ORz/xLNPFPT2py7gDRf8HCaFeG3YMhTmJy7Bqwmv3J+Ac/wp0irR3Plie?= =?us-ascii?Q?h19erxkf0S5sKYG3qgZnNVl+5LKPJQSROUFJcUtv+4noQG/jEu+S/mrQ8ze7?= =?us-ascii?Q?s7r2kaI1jAETlTaCdHgdH8ox/gP/4H2v9NAqGHPaDBm6Uqv7aoV1U1jKpSKt?= =?us-ascii?Q?avNSDH85RTlCTXc7pmNbRXsQ0g7z0hLcyNFHUiDqRdb8Z1Gp0zAv1k4DGnCD?= =?us-ascii?Q?m6BBdU/h0SNeqlFUynlDStHLaZDMXNEMLVdTZohB/yp8+dg2gFaJ2uqfAbLI?= =?us-ascii?Q?y7SZq5O1una2WZJHA1StOZ8Jk2DRVz4vJCUrGif6q5RRrtttOxtOzH3M7gCP?= =?us-ascii?Q?J36alCyIhPUfiVzUcJlqq0si9/U3vkyzjmh+ePvhPzWeKu7g34lvbvihUq/Y?= =?us-ascii?Q?8gelOTvXih/oRqcIc3Gt+anaBjTyjhBzM6F3+6UtThGhAfTCBgFv4vy9M0VX?= =?us-ascii?Q?9KpCFt+EmraYLRMvISUDYvjMI3u5oSObbjfw8ism0gRByOiFdbPD3E1UYuB4?= =?us-ascii?Q?B2O3pRGXINAkNcQD1WM9bsHd+Cfzqm0PvklTSLYdyKhXeXVndaL4w=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; CO2PR03MB2261; 6:StC2ImQmDH3p0P0RfJzC41Ec/NvwdCDmNYkqi+KwAP9ZYkyf5wWWDWa0OFoyqvKPjUpQoYe1rw2EGYQFriA+RGi4ipvMDrO+xoF51twhY6HldGD+oSuifJRUxbUGc2jaZiawxDSk7BwOUuOUN+m+vaael4XfMrF2TPA50NfKYDQWx9JGon37DQ+Vzmwl2Tro+8wq1zn8U3sJjFDa8+EClWWTYPLMU3LL9Z/WfzI3jo84DiBsBgOuoPUmIpUhhFPDoklJDqPjwlDKt9cdb36xrjfoma/YicdBtghyzH9ux6K1rnIHlnvCo+Xx1MhZEKCvc8F5qjN5GlEFbB7bqFLV2w==; 5:Iy1brc3WsMFxxJt7Wtldee0+/xsStaUlt9MvDkgYxvunQril+MBl9TSxc5eLeeJGoSbN5G/HXIk8vvVzsz/0gWHLu5a2pMPIhPc0qgKlfyfvGNdTPKoIRRZ2Kdo/YrzX+hWG2oJvfr+RcIFrIuRQuQ==; 24:Vu8OxZ5sQc3kuQlTdpmIblwhFO+/zvplxP/kv7z9bOd4DjuxRRFDoMVpuoO8ExWMDOY+ySqTXGtQ2sDHFNsyHxKVWdUeAq9cVfdnIQEL96A=; 7:bUogsFKujWJTsTtwu6HZn0InEX6gZvWO67ivJxuylHqA+t88SbMqBay1p7bF51p5DclyaA9qbJ5F8WB6QlwVLdhcFD7lX8mDHCczwtXy+b71psvtD0h2a/KqtRtbtKs635K9Ao0mPrf1FBt81jnkB1alqcdrXG4OsOfg61W+eZ8Px4iba4sR3XoMDeZsJXirDXddD8hep/MhUfa4JLv/4uknwtN3dsM8r3j+OK1BN7s= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Aug 2017 16:10:41.1634 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO2PR03MB2261 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP MX7ULP supports HSRUN mode (528 Mhz), RUN mode (413 Mhz) and VLPR mode (restricted to FIRC clock, usually 48 Mhz). This patch adds the cpufreq driver support for HSRUN and RUN mode. When in different modes, the A7 core is using different clocks: RUN: clk run_divcore HSRUN: clk hsrun_divcore Thus, this driver replies on the newly added features in OPP core framework in former patches: "PM / OPP: use OPP node clock to set CPU frequency" And since IMX7ULP CPU clock setting is different from the generic set OPP clock, we also implemented a private set_clk function. Cc: Viresh Kumar Cc: Nishanth Menon Cc: Stephen Boyd Cc: "Rafael J. Wysocki" Cc: Anson Huang Cc: Bai Ping Signed-off-by: Dong Aisheng --- drivers/cpufreq/Kconfig.arm | 8 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/imx7ulp-cpufreq.c | 234 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 drivers/cpufreq/imx7ulp-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 2011fec..53664b5 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -90,6 +90,14 @@ config ARM_IMX6Q_CPUFREQ If in doubt, say N. +config ARM_IMX7ULP_CPUFREQ + tristate "NXP i.MX7ULP cpufreq support" + depends on ARCH_MXC + help + This adds cpufreq driver support for NXP i.MX7ULP series SoCs. + + If in doubt, say N. + config ARM_KIRKWOOD_CPUFREQ def_bool MACH_KIRKWOOD help diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index ab3a42c..25a1ebd 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_ARM_DB8500_CPUFREQ) += dbx500-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o +obj-$(CONFIG_ARM_IMX7ULP_CPUFREQ) += imx7ulp-cpufreq.o obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o diff --git a/drivers/cpufreq/imx7ulp-cpufreq.c b/drivers/cpufreq/imx7ulp-cpufreq.c new file mode 100644 index 0000000..92374c6 --- /dev/null +++ b/drivers/cpufreq/imx7ulp-cpufreq.c @@ -0,0 +1,234 @@ +/* + * Copyright 2017 NXP. + * + * Author: Dong Aisheng + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HSRUN_FREQ 528000000 +#define SMC_PMPROT 0x8 +#define SMC_PMCTRL 0x10 + +static void __iomem *smc_base; + +static struct device *cpu_dev; +static struct opp_table *opp_table; +static struct cpufreq_frequency_table *freq_table; + +enum IMX7ULP_CPUFREQ_CLKS { + RUN_DIVCORE, + RUN_SCS_SEL, + HSRUN_DIVCORE, + HSRUN_SCS_SEL, + SPLL_PFD0, + SPLL_SEL, + FIRC, +}; + +static struct clk_bulk_data clks[] = { + { .id = "run_divcore" }, + { .id = "run_scs_sel" }, + { .id = "hsrun_divcore" }, + { .id = "hsrun_scs_sel" }, + { .id = "spll_pfd0" }, + { .id = "spll_sel" }, + { .id = "firc" }, +}; + +static int imx7ulp_set_clk(struct device *dev, struct clk *clk, + unsigned long old_freq, unsigned long new_freq) +{ + u32 val; + + /* + * Before changing the ARM core PLL, change the ARM clock soure + * to FIRC first. + */ + if (new_freq >= HSRUN_FREQ) { + clk_set_parent(clks[RUN_SCS_SEL].clk, clks[FIRC].clk); + + /* switch to HSRUN mode */ + val = readl_relaxed(smc_base + SMC_PMCTRL); + val |= (0x3 << 8); + writel_relaxed(val, smc_base + SMC_PMCTRL); + + /* change the clock rate in HSRUN */ + clk_set_rate(clks[SPLL_PFD0].clk, new_freq); + clk_set_parent(clks[HSRUN_SCS_SEL].clk, clks[SPLL_SEL].clk); + } else { + /* change the HSRUN clock to firc */ + clk_set_parent(clks[HSRUN_SCS_SEL].clk, clks[FIRC].clk); + + /* switch to RUN mode */ + val = readl_relaxed(smc_base + SMC_PMCTRL); + val &= ~(0x3 << 8); + writel_relaxed(val, smc_base + SMC_PMCTRL); + + clk_set_rate(clks[SPLL_PFD0].clk, new_freq); + clk_set_parent(clks[RUN_SCS_SEL].clk, clks[SPLL_SEL].clk); + } + + return 0; +} + +static int imx7ulp_set_target(struct cpufreq_policy *policy, unsigned int index) +{ + int ret; + + ret = dev_pm_opp_set_rate(cpu_dev, + policy->freq_table[index].frequency * 1000); + if (ret) + return ret; + + policy->clk = dev_pm_opp_get_cur_clk(cpu_dev); + if (IS_ERR(policy->clk)) + ret = PTR_ERR(policy->clk); + + return ret; +} + +static int imx7ulp_cpufreq_init(struct cpufreq_policy *policy) +{ + unsigned int transition_latency; + int ret; + + policy->clk = clks[RUN_DIVCORE].clk; + policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000; + transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev); + if (!transition_latency) + transition_latency = CPUFREQ_ETERNAL; + + ret = cpufreq_generic_init(policy, freq_table, transition_latency); + if (ret) { + dev_err(cpu_dev, "imx7ulp cpufreq init failed\n"); + return ret; + } + + return 0; +} + +static struct cpufreq_driver imx7ulp_cpufreq_driver = { + .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = imx7ulp_set_target, + .get = cpufreq_generic_get, + .init = imx7ulp_cpufreq_init, + .name = "imx7ulp-cpufreq", + .attr = cpufreq_generic_attr, + .suspend = cpufreq_generic_suspend, +}; + +static int imx7ulp_cpufreq_probe(struct platform_device *pdev) +{ + const char *name = "cpu"; + struct device_node *np; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) { + pr_err("failed to get cpu0 device\n"); + return -ENOENT; + } + + np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1"); + smc_base = of_iomap(np, 0); + of_node_put(np); + if (!smc_base) + return -ENOMEM; + + ret = clk_bulk_get(cpu_dev, ARRAY_SIZE(clks), clks); + if (ret) + return ret; + + opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + dev_err(cpu_dev, "failed to set regulator %d\n", ret); + goto put_clk; + } + + opp_table = dev_pm_opp_register_set_clk_helper(cpu_dev, + imx7ulp_set_clk); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + dev_err(cpu_dev, "failed to set opp clk %d\n", ret); + goto put_reg; + } + + ret = dev_pm_opp_of_add_table(cpu_dev); + if (ret < 0) { + dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); + goto put_clk_helper; + } + + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); + if (ret) { + dev_err(cpu_dev, "failed to init cpufreq table\n"); + goto free_opp_table; + } + + ret = cpufreq_register_driver(&imx7ulp_cpufreq_driver); + if (ret) { + dev_err(cpu_dev, "failed to register cpufreq driver\n"); + goto free_freq_table; + } + + return 0; + +free_freq_table: + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); +free_opp_table: + dev_pm_opp_of_remove_table(cpu_dev); +put_clk_helper: + dev_pm_opp_register_put_clk_helper(opp_table); +put_reg: + dev_pm_opp_put_regulators(opp_table); +put_clk: + clk_bulk_put(ARRAY_SIZE(clks), clks); + + return ret; +} + +static int imx7ulp_cpufreq_remove(struct platform_device *pdev) +{ + cpufreq_unregister_driver(&imx7ulp_cpufreq_driver); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); + dev_pm_opp_of_remove_table(cpu_dev); + dev_pm_opp_register_put_clk_helper(opp_table); + dev_pm_opp_put_regulators(opp_table); + clk_bulk_put(ARRAY_SIZE(clks), clks); + + return 0; +} + +static struct platform_driver imx7ulp_cpufreq_platdrv = { + .driver = { + .name = "imx7ulp-cpufreq", + .owner = THIS_MODULE, + }, + .probe = imx7ulp_cpufreq_probe, + .remove = imx7ulp_cpufreq_remove, +}; + +module_platform_driver(imx7ulp_cpufreq_platdrv); + +MODULE_AUTHOR("Dong Aisheng "); +MODULE_DESCRIPTION("NXP i.MX7ULP cpufreq driver"); +MODULE_LICENSE("GPL v2");