From patchwork Wed Apr 17 05:27:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacky Bai X-Patchwork-Id: 10904515 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43A0013B5 for ; Wed, 17 Apr 2019 05:28:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2948C2871C for ; Wed, 17 Apr 2019 05:28:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1CA4128A00; Wed, 17 Apr 2019 05:28:11 +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=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham 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 59B4C2871C for ; Wed, 17 Apr 2019 05:28:10 +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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:In-Reply-To:References: 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: List-Owner; bh=lDIyLU+G/MZuz7GE2baP1q3AGDaTR97CSLm7FZGGLxI=; b=KtdinfHnSmtdB5 bwauT9QIkTXlzHk1NdEoaoD13ZFrijD63p9iS9PR0gt1jCGbcYDw+6hilzETW1/SpjC8EtHMc0vKc o1WGxWjLCiPkxDnEjFd8MblYZcoTshM0U1Fx4Mlgr7d4VgFiEXaLzUCMDKoCV+cOIFLcocEPd7/Le 2GHh4zejSD8BxkjIkLZDNt0OkfH4t+5Xvff96CGYF+lekEnWKBzIR2XUOUSSEp50mMHgxpf9c7Oyt QoVZaI5aisz915Zo4nNR2uELma4z7K3hlRYISRI1qgGpJvL5x/tPatWU9hzNIMRLROKbq8VmrQt4C GS42J2lFpd4ebdI4HNCw==; 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 1hGd78-0003ZJ-L9; Wed, 17 Apr 2019 05:28:06 +0000 Received: from mail-eopbgr10084.outbound.protection.outlook.com ([40.107.1.84] helo=EUR02-HE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hGd6k-0002wM-Hn for linux-arm-kernel@lists.infradead.org; Wed, 17 Apr 2019 05:27:46 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CPZw2ptnwN7UKPuLXzTbp9YWA/KMzgNk+ai8akHtxNQ=; b=nE6JbXC44BOKzvKCgQZB84KQUzN/71SRIV3XAlGT1ETw7r+0n8o5N/h7j1tvjcXFMdrqu6UvYtfRvM+HGrve+DEFDCECzGZsxtbVCfH/0wyPKJB9F4WM7qymQTvHv5WgBrA5vFFmOO6SH/ZpOS9Uk+oKWcN6lLD9g4wLmVygF0Q= Received: from VI1PR0402MB3519.eurprd04.prod.outlook.com (52.134.4.24) by VI1PR0402MB3552.eurprd04.prod.outlook.com (52.134.4.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1813.12; Wed, 17 Apr 2019 05:27:35 +0000 Received: from VI1PR0402MB3519.eurprd04.prod.outlook.com ([fe80::f830:3f53:72c1:b14f]) by VI1PR0402MB3519.eurprd04.prod.outlook.com ([fe80::f830:3f53:72c1:b14f%3]) with mapi id 15.20.1792.018; Wed, 17 Apr 2019 05:27:35 +0000 From: Jacky Bai To: "robh+dt@kernel.org" , "mark.rutland@arm.com" , "shawnguo@kernel.org" , "s.hauer@pengutronix.de" , "kernel@pengutronix.de" , "l.stach@pengutronix.de" , Aisheng Dong Subject: [PATCH 2/3] soc: imx: Add power domain driver support for i.mx8m family Thread-Topic: [PATCH 2/3] soc: imx: Add power domain driver support for i.mx8m family Thread-Index: AQHU9N5DLnv5iEp5m06xTdfwxsn8Hg== Date: Wed, 17 Apr 2019 05:27:35 +0000 Message-ID: <20190417053211.2195-3-ping.bai@nxp.com> References: <20190417053211.2195-1-ping.bai@nxp.com> In-Reply-To: <20190417053211.2195-1-ping.bai@nxp.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.21.0 x-clientproxiedby: HK0PR01CA0031.apcprd01.prod.exchangelabs.com (2603:1096:203:3e::19) To VI1PR0402MB3519.eurprd04.prod.outlook.com (2603:10a6:803:8::24) authentication-results: spf=none (sender IP is ) smtp.mailfrom=ping.bai@nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [119.31.174.71] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 98294e18-1470-45b1-b4fe-08d6c2f565de x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600140)(711020)(4605104)(4618075)(2017052603328)(7193020); SRVR:VI1PR0402MB3552; x-ms-traffictypediagnostic: VI1PR0402MB3552: x-microsoft-antispam-prvs: x-forefront-prvs: 0010D93EFE x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(346002)(396003)(136003)(39860400002)(376002)(366004)(199004)(189003)(71200400001)(71190400001)(106356001)(6512007)(53936002)(66066001)(105586002)(36756003)(6116002)(3846002)(6436002)(5660300002)(50226002)(8936002)(8676002)(7736002)(81156014)(81166006)(305945005)(6636002)(97736004)(6486002)(486006)(14454004)(478600001)(14444005)(256004)(2501003)(102836004)(4326008)(2906002)(76176011)(86362001)(25786009)(54906003)(110136005)(1076003)(476003)(99286004)(52116002)(6506007)(386003)(2201001)(186003)(68736007)(26005)(2616005)(316002)(446003)(11346002); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR0402MB3552; H:VI1PR0402MB3519.eurprd04.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: vFQXUaZDm3XsRFkWaV0eOCdYeJJyppz2w0xMPbHvkQu7W1tzuGCilmE+gwOFf0PvmmzEMu7KxxsOCdH8WgNF+yI40mVCn7PHeQt8M6TMDlFgCuddPjTTR7KIFUr1mUkPibQY8jK4T7HA0x8ZlkaH/s6oPmPAjVRjfxTuT2+aFeLCWMkVBNrr+P0p0AYjdiBb5pIoDshbdH5rmIF5tXfXjlEl9/OsnalZMuiUOkgi/J1NSknweCOPbyLyyAnR8HVty2h3Lcaw8UELHChevh26/TwVgHhRzA6pHd0XXeotFCWNyko2//gEVVx6MAqp9m7vAAaufg9LwUmbj2Kd6gjTk1Rsu/1kvVJvc+roC2WEBXmpBFHQl7BWll8rd6KtDXI2EadsDS+YmN7VDaJhOpA3XfS8KGnPJc/tkbYS2XTwNtU= MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 98294e18-1470-45b1-b4fe-08d6c2f565de X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Apr 2019 05:27:35.6307 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0402MB3552 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190416_222743_078758_58CCC4C6 X-CRM114-Status: GOOD ( 24.32 ) 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: "devicetree@vger.kernel.org" , "festevam@gmail.com" , dl-linux-imx , "linux-arm-kernel@lists.infradead.org" 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 The i.MX8M family is a set of NXP product focus on delivering the latest and greatest video and audio experience combining state-of-the-art media-specific features with high-performance processing while optimized for lowest power consumption. i.MX8MQ, i.MX8MM, i.MX8MN, even the furture i.MX8MP are all belong to this family. A GPC module is used to manage all the PU power domain on/off. But the situation is that the number of power domains & the power up sequence has significate difference on those SoCs. Even on the same SoC. The power up sequence still has big difference. It makes us hard to reuse the GPCv2 driver to cover the whole i.MX8M family. Each time a new SoC is supported in the mainline kernel, we need to modify the GPCv2 driver to support it. We need to add or modify hundred lines of code in worst case. It is a bad practice for the driver maintainability. This driver add a more generic power domain driver that the actual power on/off is done by TF-A code. the abstraction give us the possibility that using one driver to cover the whole i.MX8M family in kernel side. Signed-off-by: Jacky Bai --- drivers/soc/imx/Kconfig | 6 + drivers/soc/imx/Makefile | 1 + drivers/soc/imx/imx8m_pm_domains.c | 224 +++++++++++++++++++++++++++++ include/soc/imx/imx_sip.h | 12 ++ 4 files changed, 243 insertions(+) create mode 100644 drivers/soc/imx/imx8m_pm_domains.c create mode 100644 include/soc/imx/imx_sip.h diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index d80f899d22f9..9a5a9cb77214 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -7,4 +7,10 @@ config IMX_GPCV2_PM_DOMAINS select PM_GENERIC_DOMAINS default y if SOC_IMX7D +config IMX8M_PM_DOMAINS + bool "i.MX8M PM domains" + depends on ARCH_MXC || (COMPILE_TEST && OF) + depends on PM + select PM_GENERIC_DOMAINS + endmenu diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 506a6f3c2b9b..627a54f228e5 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o +obj-$(CONFIG_IMX8M_PM_DOMAINS) += imx8m_pm_domains.o diff --git a/drivers/soc/imx/imx8m_pm_domains.c b/drivers/soc/imx/imx8m_pm_domains.c new file mode 100644 index 000000000000..ce06a059eaaa --- /dev/null +++ b/drivers/soc/imx/imx8m_pm_domains.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_CLK_NUM 6 +#define to_imx8m_pm_domain(_genpd) container_of(_genpd, struct imx8m_pm_domain, pd) + + +struct imx8m_pm_domain { + struct device *dev; + struct generic_pm_domain pd; + u32 domain_index; + struct clk *clk[MAX_CLK_NUM]; + unsigned int num_clks; + struct regulator *reg; +}; + +enum imx8m_pm_domain_state { + PD_STATE_OFF, + PD_STATE_ON, +}; + +static DEFINE_MUTEX(gpc_pd_mutex); + +static int imx8m_pd_power_on(struct generic_pm_domain *genpd) +{ + struct imx8m_pm_domain *domain = to_imx8m_pm_domain(genpd); + struct arm_smccc_res res; + int index, ret = 0; + + /* power on the external supply */ + if (!IS_ERR(domain->reg)) { + ret = regulator_enable(domain->reg); + if (ret) { + dev_warn(domain->dev, "failed to power up the reg%d\n", ret); + return ret; + } + } + + /* enable the necessary clks needed by the power domain */ + if (domain->num_clks) { + for (index = 0; index < domain->num_clks; index++) + clk_prepare_enable(domain->clk[index]); + } + + mutex_lock(&gpc_pd_mutex); + arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_CONFIG_GPC_PM_DOMAIN, domain->domain_index, + PD_STATE_ON, 0, 0, 0, 0, &res); + mutex_unlock(&gpc_pd_mutex); + + return 0; +} + +static int imx8m_pd_power_off(struct generic_pm_domain *genpd) +{ + struct imx8m_pm_domain *domain = to_imx8m_pm_domain(genpd); + struct arm_smccc_res res; + int index, ret = 0; + + mutex_lock(&gpc_pd_mutex); + arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_CONFIG_GPC_PM_DOMAIN, domain->domain_index, + PD_STATE_OFF, 0, 0, 0, 0, &res); + mutex_unlock(&gpc_pd_mutex); + + /* power off the external supply */ + if (!IS_ERR(domain->reg)) { + ret = regulator_disable(domain->reg); + if (ret) { + dev_warn(domain->dev, "failed to power off the reg%d\n", ret); + return ret; + } + } + + /* disable clks when power domain is off */ + if (domain->num_clks) { + for (index = 0; index < domain->num_clks; index++) + clk_disable_unprepare(domain->clk[index]); + } + + return ret; +}; + +static int imx8m_pd_get_clocks(struct imx8m_pm_domain *domain) +{ + int i, ret; + + for (i = 0; ; i++) { + struct clk *clk = of_clk_get(domain->dev->of_node, i); + if (IS_ERR(clk)) + break; + if (i >= MAX_CLK_NUM) { + dev_err(domain->dev, "more than %d clocks\n", + MAX_CLK_NUM); + ret = -EINVAL; + goto clk_err; + } + domain->clk[i] = clk; + } + domain->num_clks = i; + + return 0; + +clk_err: + while (i--) + clk_put(domain->clk[i]); + + return ret; +} + +static void imx8m_pd_put_clocks(struct imx8m_pm_domain *domain) +{ + int i; + + for (i = domain->num_clks - 1; i >= 0; i--) + clk_put(domain->clk[i]); +} + +static const struct of_device_id imx8m_pm_domain_ids[] = { + {.compatible = "fsl,imx8m-pm-domain"}, + {}, +}; + +static int imx8m_pm_domain_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct imx8m_pm_domain *domain; + struct of_phandle_args parent, child; + int ret; + + domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); + if (!domain) + return -ENOMEM; + + child.np = np; + domain->dev = dev; + + ret = of_property_read_string(np, "domain-name", &domain->pd.name); + if (ret) { + dev_err(dev, "failed to get the domain name\n"); + return -EINVAL; + } + + ret = of_property_read_u32(np, "domain-index", &domain->domain_index); + if (ret) { + dev_err(dev, "failed to get the domain index\n"); + return -EINVAL; + } + + domain->reg = devm_regulator_get_optional(dev, "power"); + if (IS_ERR(domain->reg)) { + if (PTR_ERR(domain->reg) != -ENODEV) { + if (PTR_ERR(domain->reg) != -EPROBE_DEFER) + dev_err(dev, "failed to get domain's regulator\n"); + return PTR_ERR(domain->reg); + } + } + + ret = imx8m_pd_get_clocks(domain); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get domain's clocks\n"); + return ret; + } + + domain->pd.power_off = imx8m_pd_power_off; + domain->pd.power_on = imx8m_pd_power_on; + + pm_genpd_init(&domain->pd, NULL, true); + + ret = of_genpd_add_provider_simple(np, &domain->pd); + if (ret) { + dev_err(dev, "failed to add the domain provider\n"); + pm_genpd_remove(&domain->pd); + imx8m_pd_put_clocks(domain); + return ret; + } + + /* add it as subdomain if necessary */ + if (!of_parse_phandle_with_args(np, "parent-domains", + "#power-domain-cells", 0, &parent)) { + ret = of_genpd_add_subdomain(&parent, &child); + of_node_put(parent.np); + + if (ret < 0) { + dev_dbg(dev, "failed to add the subdomain: %s: %d", + domain->pd.name, ret); + of_genpd_del_provider(np); + pm_genpd_remove(&domain->pd); + imx8m_pd_put_clocks(domain); + return driver_deferred_probe_check_state(dev); + } + } + + return 0; +} + +static struct platform_driver imx8m_pm_domain_driver = { + .driver = { + .name = "imx8m_pm_domain", + .owner = THIS_MODULE, + .of_match_table = imx8m_pm_domain_ids, + }, + .probe = imx8m_pm_domain_probe, +}; +module_platform_driver(imx8m_pm_domain_driver); + +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("NXP i.MX8M power domain driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/soc/imx/imx_sip.h b/include/soc/imx/imx_sip.h new file mode 100644 index 000000000000..6b96b33c870e --- /dev/null +++ b/include/soc/imx/imx_sip.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 NXP + */ + +#ifndef __IMX_SIP_H__ +#define __IMX_SIP_H__ + +#define IMX_SIP_GPC 0xC2000000 +#define IMX_SIP_CONFIG_GPC_PM_DOMAIN 0x03 + +#endif /* __IMX_SIP_H__ */