From patchwork Fri Dec 18 02:42:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "fan.chen" X-Patchwork-Id: 7879371 Return-Path: X-Original-To: patchwork-linux-mediatek@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5CB0ABEEE5 for ; Fri, 18 Dec 2015 02:52:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5863020445 for ; Fri, 18 Dec 2015 02:52:33 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 47AC5201ED for ; Fri, 18 Dec 2015 02:52:32 +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 1a9l9j-0003oW-Fh; Fri, 18 Dec 2015 02:52:31 +0000 Received: from [210.61.82.184] (helo=mailgw02.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a9l2f-0003AD-BS; Fri, 18 Dec 2015 02:45:39 +0000 X-Listener-Flag: 11101 Received: from mtkhts09.mediatek.inc [(172.21.101.70)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 59970939; Fri, 18 Dec 2015 10:44:51 +0800 Received: from mtkslt301.mediatek.inc (10.21.14.114) by mtkhts09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 14.3.266.1; Fri, 18 Dec 2015 10:44:49 +0800 From: Fan Chen To: Sascha Hauer , Matthias Brugger , Lorenzo Pieralisi , Mark Rutland Subject: [PATCH 2/4] soc: mediatek: To move power control logic to ARM TF Date: Fri, 18 Dec 2015 10:42:29 +0800 Message-ID: <1450406551-1741-3-git-send-email-fan.chen@mediatek.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1450406551-1741-1-git-send-email-fan.chen@mediatek.com> References: <1450406551-1741-1-git-send-email-fan.chen@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151217_184514_402394_12BE781D X-CRM114-Status: GOOD ( 19.95 ) X-Spam-Score: -1.1 (-) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: James Liao , Koro Chen , linux-kernel@vger.kernel.org, Weiyi Lu , Pawel Moll , Ian Campbell , Catalin Marinas , Will Deacon , Flora Fu , "yt.lee" , Fan Chen , devicetree@vger.kernel.org, Rob Herring , linux-mediatek@lists.infradead.org, Kumar Gala , Yingjoe Chen , Eddie Huang , jens.wiklander@linaro.org, linux-arm-kernel@lists.infradead.org Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_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 From: "yt.lee" Add an option to test if ARM TF supports non-cpus power control and do it in firmware. Otherwise, fallback to legecy way handling it in kernel driver. Regarding time consumption of sip call for the power control. In 52051 times of sip calls with power_LoadTest, the maximum cost is 433us and the average cost is 118us. Signed-off-by: yt.lee Signed-off-by: Fan Chen --- drivers/soc/mediatek/mtk-scpsys.c | 122 ++++++++++++++++++++++------------ include/linux/soc/mediatek/mtk-sip.h | 4 ++ 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 4d4203c..cc8d0c8 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define SPM_VDE_PWR_CON 0x0210 @@ -187,6 +188,7 @@ struct scp { struct device *dev; void __iomem *base; struct regmap *infracfg; + bool sip_support; }; static int scpsys_domain_is_on(struct scp_domain *scpd) @@ -209,9 +211,8 @@ static int scpsys_domain_is_on(struct scp_domain *scpd) return -EINVAL; } -static int scpsys_power_on(struct generic_pm_domain *genpd) +static int scpsys_power_on_mtcmos(struct scp_domain *scpd) { - struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); struct scp *scp = scpd->scp; unsigned long timeout; bool expired; @@ -219,17 +220,6 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) u32 sram_pdn_ack = scpd->sram_pdn_ack_bits; u32 val; int ret; - int i; - - for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { - ret = clk_prepare_enable(scpd->clk[i]); - if (ret) { - for (--i; i >= 0; i--) - clk_disable_unprepare(scpd->clk[i]); - - goto err_clk; - } - } val = readl(ctl_addr); val |= PWR_ON_BIT; @@ -245,10 +235,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) if (ret > 0) break; - if (expired) { - ret = -ETIMEDOUT; - goto err_pwr_ack; - } + if (expired) + return -ETIMEDOUT; cpu_relax(); @@ -273,10 +261,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) expired = false; while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) { - if (expired) { - ret = -ETIMEDOUT; - goto err_pwr_ack; - } + if (expired) + return -ETIMEDOUT; cpu_relax(); @@ -288,25 +274,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) ret = mtk_infracfg_clear_bus_protection(scp->infracfg, scpd->bus_prot_mask); if (ret) - goto err_pwr_ack; + return ret; } return 0; - -err_pwr_ack: - for (i = MAX_CLKS - 1; i >= 0; i--) { - if (scpd->clk[i]) - clk_disable_unprepare(scpd->clk[i]); - } -err_clk: - dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); - - return ret; } -static int scpsys_power_off(struct generic_pm_domain *genpd) +static int scpsys_power_off_mtcmos(struct scp_domain *scpd) { - struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); struct scp *scp = scpd->scp; unsigned long timeout; bool expired; @@ -314,13 +289,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) u32 pdn_ack = scpd->sram_pdn_ack_bits; u32 val; int ret; - int i; if (scpd->bus_prot_mask) { ret = mtk_infracfg_set_bus_protection(scp->infracfg, scpd->bus_prot_mask); if (ret) - goto out; + return ret; } val = readl(ctl_addr); @@ -331,10 +305,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) timeout = jiffies + HZ; expired = false; while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) { - if (expired) { - ret = -ETIMEDOUT; - goto out; - } + + if (expired) + return -ETIMEDOUT; cpu_relax(); @@ -365,10 +338,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) if (ret == 0) break; - if (expired) { - ret = -ETIMEDOUT; - goto out; - } + if (expired) + return -ETIMEDOUT; cpu_relax(); @@ -376,6 +347,62 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) expired = true; } + return 0; +} + +static int scpsys_power_on(struct generic_pm_domain *genpd) +{ + struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); + struct scp *scp = scpd->scp; + int ret; + int i; + + for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { + ret = clk_prepare_enable(scpd->clk[i]); + if (ret) { + for (--i; i >= 0; i--) + clk_disable_unprepare(scpd->clk[i]); + + goto err_clk; + } + } + + if (!scp->sip_support) + ret = scpsys_power_on_mtcmos(scpd); + else + ret = mtk_sip_simple_call(MTK_SIP_PWR_ON_MTCMOS, + scpd->ctl_addr - scp->base, 0, 0); + if (ret) + goto err_pwr_ack; + + return 0; + +err_pwr_ack: + for (i = MAX_CLKS - 1; i >= 0; i--) { + if (scpd->clk[i]) + clk_disable_unprepare(scpd->clk[i]); + } +err_clk: + dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); + + return ret; +} + +static int scpsys_power_off(struct generic_pm_domain *genpd) +{ + struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); + struct scp *scp = scpd->scp; + int ret; + int i; + + if (!scp->sip_support) + ret = scpsys_power_off_mtcmos(scpd); + else + ret = mtk_sip_simple_call(MTK_SIP_PWR_OFF_MTCMOS, + scpd->ctl_addr - scp->base, 0, 0); + if (ret) + goto out; + for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) clk_disable_unprepare(scpd->clk[i]); @@ -503,6 +530,13 @@ static int __init scpsys_probe(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); + ret = mtk_sip_simple_call(MTK_SIP_PWR_MTCMOS_SUPPORT, 0, 0, 0); + if (ret) { + scp->sip_support = false; + dev_info(&pdev->dev, "SIP call is not supported: %d\n", ret); + } else + scp->sip_support = true; + return 0; } diff --git a/include/linux/soc/mediatek/mtk-sip.h b/include/linux/soc/mediatek/mtk-sip.h index dce1818..c803490 100644 --- a/include/linux/soc/mediatek/mtk-sip.h +++ b/include/linux/soc/mediatek/mtk-sip.h @@ -1,6 +1,10 @@ #ifndef __SOC_MEDIATEK_MTKSIP_H #define __SOC_MEDIATEK_MTKSIP_H +#define MTK_SIP_PWR_ON_MTCMOS 0x82000402 +#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403 +#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404 + #ifdef CONFIG_MTK_SIP int mtk_sip_simple_call(unsigned long func_id, unsigned long a1,