From 90a943145e2ef17b559ef9e98a7c12a1abc9ae84 Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Wed, 28 Aug 2019 17:11:36 +0800 Subject: soc: mediatek: Refactor polling timeout and documentation Use USEC_PER_SEC to indicate the polling timeout directly. And add documentation of scp_domain_data. Signed-off-by: Weiyi Lu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 503222d0d0da..e97fc0e45400 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -21,7 +21,7 @@ #include #define MTK_POLL_DELAY_US 10 -#define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ)) +#define MTK_POLL_TIMEOUT USEC_PER_SEC #define MTK_SCPD_ACTIVE_WAKEUP BIT(0) #define MTK_SCPD_FWAIT_SRAM BIT(1) @@ -108,6 +108,17 @@ static const char * const clk_names[] = { #define MAX_CLKS 3 +/** + * struct scp_domain_data - scp domain data for power on/off flow + * @name: The domain name. + * @sta_mask: The mask for power on/off status bit. + * @ctl_offs: The offset for main power control register. + * @sram_pdn_bits: The mask for sram power control bits. + * @sram_pdn_ack_bits: The mask for sram power control acked bits. + * @bus_prot_mask: The mask for single step bus protection. + * @clk_id: The basic clocks required by this power domain. + * @caps: The flag for active wake-up action. + */ struct scp_domain_data { const char *name; u32 sta_mask; -- cgit From d744d035ecb57decf0ae1711228756445708545a Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Wed, 28 Aug 2019 17:11:37 +0800 Subject: soc: mediatek: Refactor regulator control Put regulator enable and disable control in separate functions. Signed-off-by: Weiyi Lu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index e97fc0e45400..aed540d2686c 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -191,6 +191,22 @@ static int scpsys_domain_is_on(struct scp_domain *scpd) return -EINVAL; } +static int scpsys_regulator_enable(struct scp_domain *scpd) +{ + if (!scpd->supply) + return 0; + + return regulator_enable(scpd->supply); +} + +static int scpsys_regulator_disable(struct scp_domain *scpd) +{ + if (!scpd->supply) + return 0; + + return regulator_disable(scpd->supply); +} + static int scpsys_power_on(struct generic_pm_domain *genpd) { struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); @@ -201,11 +217,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) int ret, tmp; int i; - if (scpd->supply) { - ret = regulator_enable(scpd->supply); - if (ret) - return ret; - } + ret = scpsys_regulator_enable(scpd); + if (ret < 0) + return ret; for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { ret = clk_prepare_enable(scpd->clk[i]); @@ -273,8 +287,7 @@ err_pwr_ack: clk_disable_unprepare(scpd->clk[i]); } err_clk: - if (scpd->supply) - regulator_disable(scpd->supply); + scpsys_regulator_disable(scpd); dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); @@ -333,8 +346,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) clk_disable_unprepare(scpd->clk[i]); - if (scpd->supply) - regulator_disable(scpd->supply); + ret = scpsys_regulator_disable(scpd); + if (ret < 0) + goto out; return 0; -- cgit From cef021e2f5cb8a1c8cd23ebc77232e6563ce251d Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Wed, 28 Aug 2019 17:11:38 +0800 Subject: soc: mediatek: Refactor clock control Put clock enable and disable control in separate function. Signed-off-by: Weiyi Lu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 45 ++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index aed540d2686c..73e4a1aace2f 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -207,6 +207,29 @@ static int scpsys_regulator_disable(struct scp_domain *scpd) return regulator_disable(scpd->supply); } +static void scpsys_clk_disable(struct clk *clk[], int max_num) +{ + int i; + + for (i = max_num - 1; i >= 0; i--) + clk_disable_unprepare(clk[i]); +} + +static int scpsys_clk_enable(struct clk *clk[], int max_num) +{ + int i, ret = 0; + + for (i = 0; i < max_num && clk[i]; i++) { + ret = clk_prepare_enable(clk[i]); + if (ret) { + scpsys_clk_disable(clk, i); + break; + } + } + + return ret; +} + static int scpsys_power_on(struct generic_pm_domain *genpd) { struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); @@ -215,21 +238,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) u32 pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret, tmp; - int i; ret = scpsys_regulator_enable(scpd); if (ret < 0) return ret; - 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; - } - } + ret = scpsys_clk_enable(scpd->clk, MAX_CLKS); + if (ret) + goto err_clk; val = readl(ctl_addr); val |= PWR_ON_BIT; @@ -282,10 +298,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) return 0; err_pwr_ack: - for (i = MAX_CLKS - 1; i >= 0; i--) { - if (scpd->clk[i]) - clk_disable_unprepare(scpd->clk[i]); - } + scpsys_clk_disable(scpd->clk, MAX_CLKS); err_clk: scpsys_regulator_disable(scpd); @@ -302,7 +315,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) u32 pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret, tmp; - int i; if (scpd->data->bus_prot_mask) { ret = mtk_infracfg_set_bus_protection(scp->infracfg, @@ -343,8 +355,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) if (ret < 0) goto out; - for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) - clk_disable_unprepare(scpd->clk[i]); + scpsys_clk_disable(scpd->clk, MAX_CLKS); ret = scpsys_regulator_disable(scpd); if (ret < 0) -- cgit From 0545aa1b7a1472a4d0499ccc7666634c8cf47305 Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Wed, 28 Aug 2019 17:11:39 +0800 Subject: soc: mediatek: Refactor sram control Put sram enable and disable control in separate functions. Signed-off-by: Weiyi Lu Reviewed-by: Nicolas Boichat [mb: fix coding style of reading register and changing the read value] Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 80 ++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 27 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 73e4a1aace2f..fafc0d311cf8 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -230,12 +230,57 @@ static int scpsys_clk_enable(struct clk *clk[], int max_num) return ret; } +static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr) +{ + u32 val; + u32 pdn_ack = scpd->data->sram_pdn_ack_bits; + int tmp; + + val = readl(ctl_addr); + val &= ~scpd->data->sram_pdn_bits; + writel(val, ctl_addr); + + /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */ + if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) { + /* + * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for + * MT7622_POWER_DOMAIN_WB and thus just a trivial setup + * is applied here. + */ + usleep_range(12000, 12100); + } else { + /* Either wait until SRAM_PDN_ACK all 1 or 0 */ + int ret = readl_poll_timeout(ctl_addr, tmp, + (tmp & pdn_ack) == 0, + MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); + if (ret < 0) + return ret; + } + + return 0; +} + +static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) +{ + u32 val; + u32 pdn_ack = scpd->data->sram_pdn_ack_bits; + int tmp; + + val = readl(ctl_addr); + val |= scpd->data->sram_pdn_bits; + writel(val, ctl_addr); + + /* Either wait until SRAM_PDN_ACK all 1 or 0 */ + return readl_poll_timeout(ctl_addr, tmp, + (tmp & pdn_ack) == pdn_ack, + MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); +} + 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; void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; - u32 pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret, tmp; @@ -247,6 +292,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) if (ret) goto err_clk; + /* subsys power on */ val = readl(ctl_addr); val |= PWR_ON_BIT; writel(val, ctl_addr); @@ -268,24 +314,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) val |= PWR_RST_B_BIT; writel(val, ctl_addr); - val &= ~scpd->data->sram_pdn_bits; - writel(val, ctl_addr); - - /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */ - if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) { - /* - * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for - * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is - * applied here. - */ - usleep_range(12000, 12100); - - } else { - ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret < 0) - goto err_pwr_ack; - } + ret = scpsys_sram_enable(scpd, ctl_addr); + if (ret < 0) + goto err_pwr_ack; if (scpd->data->bus_prot_mask) { ret = mtk_infracfg_clear_bus_protection(scp->infracfg, @@ -312,7 +343,6 @@ 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; void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; - u32 pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret, tmp; @@ -324,16 +354,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) goto out; } - val = readl(ctl_addr); - val |= scpd->data->sram_pdn_bits; - writel(val, ctl_addr); - - /* wait until SRAM_PDN_ACK all 1 */ - ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); + ret = scpsys_sram_disable(scpd, ctl_addr); if (ret < 0) goto out; + /* subsys power off */ + val = readl(ctl_addr); val |= PWR_ISO_BIT; writel(val, ctl_addr); -- cgit From 662c9d55c5ccb37f3920ecab9720f2ebf2a6ca18 Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Wed, 28 Aug 2019 17:11:40 +0800 Subject: soc: mediatek: Refactor bus protection control Put bus protection enable and disable control in separate functions. Signed-off-by: Weiyi Lu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 44 ++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index fafc0d311cf8..f669d3754627 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -276,6 +276,30 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); } +static int scpsys_bus_protect_enable(struct scp_domain *scpd) +{ + struct scp *scp = scpd->scp; + + if (!scpd->data->bus_prot_mask) + return 0; + + return mtk_infracfg_set_bus_protection(scp->infracfg, + scpd->data->bus_prot_mask, + scp->bus_prot_reg_update); +} + +static int scpsys_bus_protect_disable(struct scp_domain *scpd) +{ + struct scp *scp = scpd->scp; + + if (!scpd->data->bus_prot_mask) + return 0; + + return mtk_infracfg_clear_bus_protection(scp->infracfg, + scpd->data->bus_prot_mask, + scp->bus_prot_reg_update); +} + static int scpsys_power_on(struct generic_pm_domain *genpd) { struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); @@ -318,13 +342,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) if (ret < 0) goto err_pwr_ack; - if (scpd->data->bus_prot_mask) { - ret = mtk_infracfg_clear_bus_protection(scp->infracfg, - scpd->data->bus_prot_mask, - scp->bus_prot_reg_update); - if (ret) - goto err_pwr_ack; - } + ret = scpsys_bus_protect_disable(scpd); + if (ret < 0) + goto err_pwr_ack; return 0; @@ -346,13 +366,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) u32 val; int ret, tmp; - if (scpd->data->bus_prot_mask) { - ret = mtk_infracfg_set_bus_protection(scp->infracfg, - scpd->data->bus_prot_mask, - scp->bus_prot_reg_update); - if (ret) - goto out; - } + ret = scpsys_bus_protect_enable(scpd); + if (ret < 0) + goto out; ret = scpsys_sram_disable(scpd, ctl_addr); if (ret < 0) -- cgit