refactor code of mtk-scpsys

-----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCAA1FiEEiUuSfQSYnG8EMsBltDliWyzx00MFAl3JS8kXHG1hdHRoaWFz
 LmJnZ0BnbWFpbC5jb20ACgkQtDliWyzx00PvgxAAgIYOPkmQhwvpxhPYVDy5qlEE
 z5kGbUP4s1Rig9UBFP6OPE14nuy7g+hFM1PTgCHlVGv3/AIkHlQS5EU3WtYgu2Fi
 7fM8GfAY66G+FFoLq08T3TDudGnp9HyOS/tHF0wGtyjp7aeNx096FgFHfIBCeDsk
 8sARrKuFahrau/X3ev9nKctFRGu1VzCDKweqCmk9U7SPsGUUMziSdN3p9j7FPbeI
 DKxSLzp/TqFtgiAbGYUlMieQWAvP4XKvo6sxXXn/vlG/PRUpuZY2Nv3D0ZeU7kGv
 rbOe5Frt/2CL/EOrUJ5kPjwdkt1QUDEkZQHC2qIA7wDoKuPYoTkDzAeaFBvE7Eav
 DXCreOUzz3w8QgvNWNV/HMQa6b9O4uozPex9Ve4ugTnwDUR9UmGh7IbCnh8M0y4Z
 s+C/ducbV92hW4ZVpRJMDFm7SgPl5Dg9Bb7KkEEvwQh4tp49rq8bobNyJTI+uUVi
 +seMLI9EtWM4fT2VWSpOepyfDNYYAYXSpWpjznePCBAvdyN2SUYQdwI+sCqQOonX
 g1mg+oWVEUBXbAW70ztBkmPHywPV4pX18yEBDZYQNuOBvChzclGCbiOsUbv3FtX2
 LQuEcYK0BA4NVtXuOb1Nfc7ge7Om/OSFJC4II+CzuO74gMqHrT8Vbu758WooMWVZ
 UigZJy1oBbzYyzcaAbY=
 =Zp8l
 -----END PGP SIGNATURE-----

Merge tag 'v5.4-next-soc' of https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux into arm/drivers

refactor code of mtk-scpsys

* tag 'v5.4-next-soc' of https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux:
  soc: mediatek: Refactor bus protection control
  soc: mediatek: Refactor sram control
  soc: mediatek: Refactor clock control
  soc: mediatek: Refactor regulator control
  soc: mediatek: Refactor polling timeout and documentation

Link: https://lore.kernel.org/r/294422a4-37b2-def5-5d32-8988f27c3a5b@gmail.com
Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2019-11-11 13:09:02 -08:00
commit 01d1a860a5
1 changed files with 147 additions and 69 deletions

View File

@ -21,7 +21,7 @@
#include <dt-bindings/power/mt8173-power.h>
#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;
@ -180,32 +191,132 @@ 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 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_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_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);
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;
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]);
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;
/* subsys power on */
val = readl(ctl_addr);
val |= PWR_ON_BIT;
writel(val, ctl_addr);
@ -227,43 +338,20 @@ 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);
ret = scpsys_sram_enable(scpd, ctl_addr);
if (ret < 0)
goto err_pwr_ack;
/* 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;
}
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;
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:
if (scpd->supply)
regulator_disable(scpd->supply);
scpsys_regulator_disable(scpd);
dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
@ -275,29 +363,19 @@ 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;
int i;
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;
}
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_bus_protect_enable(scpd);
if (ret < 0)
goto out;
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);
@ -319,11 +397,11 @@ 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);
if (scpd->supply)
regulator_disable(scpd->supply);
ret = scpsys_regulator_disable(scpd);
if (ret < 0)
goto out;
return 0;