2024-03-25 15:17:11

by Yu-chang Lee (李禹璋)

[permalink] [raw]
Subject: [PATCH 0/2] soc: mediatek: pm-domains: solve power domain glitch issue

Hi,

This series aims to solve power-off failures and occasional SMI hang issues that
occur during camera stress tests. The issue arises because, when MTCMOS powers on
or off, signal glitches are sometimes produced. This is fairly normal, but the
software must address it to avoid mistaking the glitch for a transaction signal.

The solutions in these patches can be summarized as follows:

1. Disable the sub-common port after turning off the Larb CG and before turning
off the Larb MTCMOS.
2. Use CLAMP to disable/enable the SMI common port.
3. Implement an AXI reset.
For previous discussion on the direction of the code modifications, please refer
to: https://lore.kernel.org/linux-arm-kernel/[email protected]/


yu-chang.lee (2):
soc: mediatek: pm-domains: add smi_larb_reset function when power on
soc: mediatek: pm-domains: support smi clamp protection

drivers/pmdomain/mediatek/mt8188-pm-domains.h | 69 +++++-
drivers/pmdomain/mediatek/mtk-pm-domains.c | 206 +++++++++++++++---
drivers/pmdomain/mediatek/mtk-pm-domains.h | 13 ++
3 files changed, 255 insertions(+), 33 deletions(-)

--
2.18.0



2024-03-25 15:17:26

by Yu-chang Lee (李禹璋)

[permalink] [raw]
Subject: [PATCH 1/2] soc: mediatek: pm-domains: add smi_larb_reset function when power on

This patch avoid mtcmos power glitch from happening by set and clear
smi larb reset.

Signed-off-by: yu-chang.lee <[email protected]>
---
drivers/pmdomain/mediatek/mt8188-pm-domains.h | 28 +++++++++
drivers/pmdomain/mediatek/mtk-pm-domains.c | 59 +++++++++++++++++++
drivers/pmdomain/mediatek/mtk-pm-domains.h | 12 ++++
3 files changed, 99 insertions(+)

diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
index 06834ab6597c..7bbba4d56a77 100644
--- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
@@ -573,6 +573,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .reset_smi = {
+ SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
+ MT8188_SMI_LARB10_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB11A_RESET,
+ MT8188_SMI_LARB11A_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB11C_RESET,
+ MT8188_SMI_LARB11C_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB11B_RESET,
+ MT8188_SMI_LARB11B_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
+ MT8188_SMI_LARB15_RESET_ADDR),
+ },
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8188_POWER_DOMAIN_IPE] = {
@@ -583,6 +595,10 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .reset_smi = {
+ SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
+ MT8188_SMI_LARB12_RESET_ADDR),
+ },
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8188_POWER_DOMAIN_CAM_VCORE] = {
@@ -660,6 +676,12 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .reset_smi = {
+ SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
+ MT8188_SMI_LARB16A_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
+ MT8188_SMI_LARB17A_RESET_ADDR),
+ },
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8188_POWER_DOMAIN_CAM_SUBB] = {
@@ -670,6 +692,12 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .reset_smi = {
+ SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
+ MT8188_SMI_LARB16B_RESET_ADDR),
+ SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
+ MT8188_SMI_LARB17B_RESET_ADDR),
+ },
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
};
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index e274e3315fe7..9ab6fa105c8c 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -48,6 +48,8 @@ struct scpsys_domain {
struct regmap *infracfg_nao;
struct regmap *infracfg;
struct regmap *smi;
+ struct regmap **larb;
+ int num_larb;
struct regulator *supply;
};

@@ -230,6 +232,39 @@ static int scpsys_regulator_disable(struct regulator *supply)
return supply ? regulator_disable(supply) : 0;
}

+static int _scpsys_smi_larb_reset(const struct smi_reset_data bpd,
+ struct regmap *regmap)
+{
+ int ret;
+ u32 mask = bpd.smi_reset_mask;
+
+ if (!mask)
+ return 0;
+
+ ret = regmap_set_bits(regmap, bpd.smi_reset_addr, mask);
+ if (ret)
+ return ret;
+
+ ret = regmap_clear_bits(regmap, bpd.smi_reset_addr, mask);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int scpsys_smi_larb_reset(struct scpsys_domain *pd)
+{
+ int ret, i;
+
+ for (i = 0; i < pd->num_larb; i++) {
+ ret = _scpsys_smi_larb_reset(pd->data->reset_smi[i], pd->larb[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int scpsys_power_on(struct generic_pm_domain *genpd)
{
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
@@ -279,6 +314,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (ret < 0)
goto err_disable_subsys_clks;

+ ret = scpsys_smi_larb_reset(pd);
+ if (ret < 0)
+ goto err_disable_subsys_clks;
+
ret = scpsys_bus_protect_disable(pd);
if (ret < 0)
goto err_disable_sram;
@@ -355,6 +394,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
struct scpsys_domain *pd;
struct device_node *root_node = scpsys->dev->of_node;
struct device_node *smi_node;
+ struct device_node *larb_node;
struct property *prop;
const char *clk_name;
int i, ret, num_clks;
@@ -418,6 +458,25 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
return ERR_CAST(pd->smi);
}

+ pd->num_larb = of_count_phandle_with_args(node, "mediatek,larb", NULL);
+ if (pd->num_larb > 0) {
+ pd->larb = devm_kcalloc(scpsys->dev, pd->num_larb, sizeof(*pd->larb), GFP_KERNEL);
+ if (!pd->larb)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < pd->num_larb; i++) {
+ larb_node = of_parse_phandle(node, "mediatek,larb", i);
+ if (!larb_node)
+ return ERR_PTR(-EINVAL);
+
+ pd->larb[i] = device_node_to_regmap(larb_node);
+ if (IS_ERR(pd->larb[i]))
+ return ERR_CAST(pd->larb[i]);
+ }
+ } else {
+ pd->num_larb = 0;
+ }
+
if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
if (IS_ERR(pd->infracfg_nao))
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
index aaba5e6b0536..31c2a1bb500f 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -43,6 +43,7 @@
#define PWR_STATUS_USB BIT(25)

#define SPM_MAX_BUS_PROT_DATA 6
+#define SPM_MAX_SMI_RESET_DATA 6

enum scpsys_bus_prot_flags {
BUS_PROT_REG_UPDATE = BIT(1),
@@ -79,6 +80,16 @@ enum scpsys_bus_prot_flags {
INFRA_TOPAXI_PROTECTEN, \
INFRA_TOPAXI_PROTECTSTA1)

+#define SMI_RESET_WR(_mask, _addr) { \
+ .smi_reset_mask = (_mask), \
+ .smi_reset_addr = _addr, \
+ }
+
+struct smi_reset_data {
+ u32 smi_reset_mask;
+ u32 smi_reset_addr;
+};
+
struct scpsys_bus_prot_data {
u32 bus_prot_set_clr_mask;
u32 bus_prot_set;
@@ -110,6 +121,7 @@ struct scpsys_domain_data {
u32 ext_buck_iso_mask;
u16 caps;
const struct scpsys_bus_prot_data bp_cfg[SPM_MAX_BUS_PROT_DATA];
+ const struct smi_reset_data reset_smi[SPM_MAX_SMI_RESET_DATA];
int pwr_sta_offs;
int pwr_sta2nd_offs;
};
--
2.18.0


Subject: Re: [PATCH 0/2] soc: mediatek: pm-domains: solve power domain glitch issue

Il 25/03/24 13:19, yu-chang.lee ha scritto:
> Hi,
>
> This series aims to solve power-off failures and occasional SMI hang issues that
> occur during camera stress tests. The issue arises because, when MTCMOS powers on
> or off, signal glitches are sometimes produced. This is fairly normal, but the
> software must address it to avoid mistaking the glitch for a transaction signal.
>
> The solutions in these patches can be summarized as follows:
>
> 1. Disable the sub-common port after turning off the Larb CG and before turning
> off the Larb MTCMOS.
> 2. Use CLAMP to disable/enable the SMI common port.
> 3. Implement an AXI reset.
> For previous discussion on the direction of the code modifications, please refer
> to: https://lore.kernel.org/linux-arm-kernel/[email protected]/
>
>
> yu-chang.lee (2):
> soc: mediatek: pm-domains: add smi_larb_reset function when power on
> soc: mediatek: pm-domains: support smi clamp protection

Can you please change both commit titles to use "pmdomain: mediatek:" instead of
"soc: mediatek:"?

Thanks
Angelo

>
> drivers/pmdomain/mediatek/mt8188-pm-domains.h | 69 +++++-
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 206 +++++++++++++++---
> drivers/pmdomain/mediatek/mtk-pm-domains.h | 13 ++
> 3 files changed, 255 insertions(+), 33 deletions(-)
>


Subject: Re: [PATCH 1/2] soc: mediatek: pm-domains: add smi_larb_reset function when power on

Il 25/03/24 13:19, yu-chang.lee ha scritto:
> This patch avoid mtcmos power glitch from happening by set and clear
> smi larb reset.
>
> Signed-off-by: yu-chang.lee <[email protected]>
> ---
> drivers/pmdomain/mediatek/mt8188-pm-domains.h | 28 +++++++++
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 59 +++++++++++++++++++
> drivers/pmdomain/mediatek/mtk-pm-domains.h | 12 ++++
> 3 files changed, 99 insertions(+)
>
> diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> index 06834ab6597c..7bbba4d56a77 100644
> --- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> +++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> @@ -573,6 +573,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .reset_smi = {
> + SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
> + MT8188_SMI_LARB10_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB11A_RESET,
> + MT8188_SMI_LARB11A_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB11C_RESET,
> + MT8188_SMI_LARB11C_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB11B_RESET,
> + MT8188_SMI_LARB11B_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
> + MT8188_SMI_LARB15_RESET_ADDR),
> + },
> .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> },
> [MT8188_POWER_DOMAIN_IPE] = {
> @@ -583,6 +595,10 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .reset_smi = {
> + SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
> + MT8188_SMI_LARB12_RESET_ADDR),
> + },
> .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> },
> [MT8188_POWER_DOMAIN_CAM_VCORE] = {
> @@ -660,6 +676,12 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .reset_smi = {
> + SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
> + MT8188_SMI_LARB16A_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
> + MT8188_SMI_LARB17A_RESET_ADDR),
> + },
> .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> },
> [MT8188_POWER_DOMAIN_CAM_SUBB] = {
> @@ -670,6 +692,12 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .reset_smi = {
> + SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
> + MT8188_SMI_LARB16B_RESET_ADDR),
> + SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
> + MT8188_SMI_LARB17B_RESET_ADDR),
> + },
> .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> },
> };
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> index e274e3315fe7..9ab6fa105c8c 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> @@ -48,6 +48,8 @@ struct scpsys_domain {
> struct regmap *infracfg_nao;
> struct regmap *infracfg;
> struct regmap *smi;
> + struct regmap **larb;
> + int num_larb;
> struct regulator *supply;
> };
>
> @@ -230,6 +232,39 @@ static int scpsys_regulator_disable(struct regulator *supply)
> return supply ? regulator_disable(supply) : 0;
> }
>
> +static int _scpsys_smi_larb_reset(const struct smi_reset_data bpd,
> + struct regmap *regmap)
> +{
> + int ret;
> + u32 mask = bpd.smi_reset_mask;
> +
> + if (!mask)
> + return 0;
> +
> + ret = regmap_set_bits(regmap, bpd.smi_reset_addr, mask);
> + if (ret)
> + return ret;
> +
> + ret = regmap_clear_bits(regmap, bpd.smi_reset_addr, mask);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int scpsys_smi_larb_reset(struct scpsys_domain *pd)
> +{
> + int ret, i;
> +
> + for (i = 0; i < pd->num_larb; i++) {
> + ret = _scpsys_smi_larb_reset(pd->data->reset_smi[i], pd->larb[i]);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static int scpsys_power_on(struct generic_pm_domain *genpd)
> {
> struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
> @@ -279,6 +314,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> if (ret < 0)
> goto err_disable_subsys_clks;
>
> + ret = scpsys_smi_larb_reset(pd);
> + if (ret < 0)
> + goto err_disable_subsys_clks;
> +
> ret = scpsys_bus_protect_disable(pd);
> if (ret < 0)
> goto err_disable_sram;
> @@ -355,6 +394,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
> struct scpsys_domain *pd;
> struct device_node *root_node = scpsys->dev->of_node;
> struct device_node *smi_node;
> + struct device_node *larb_node;
> struct property *prop;
> const char *clk_name;
> int i, ret, num_clks;
> @@ -418,6 +458,25 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
> return ERR_CAST(pd->smi);
> }
>
> + pd->num_larb = of_count_phandle_with_args(node, "mediatek,larb", NULL);

You must update bindings/power/mediatek,power-controller.yaml to allow the
mediatek,larb property in the power controller binding, otherwise this will
be unusable. Please do so.

Cheers,
Angelo


2024-03-25 17:12:22

by Yu-chang Lee (李禹璋)

[permalink] [raw]
Subject: [PATCH 2/2] soc: mediatek: pm-domains: support smi clamp protection

In order to avoid power glitch, this patch use smi clamp
to disable/enable smi common port.

Signed-off-by: yu-chang.lee <[email protected]>
---
drivers/pmdomain/mediatek/mt8188-pm-domains.h | 41 ++++-
drivers/pmdomain/mediatek/mtk-pm-domains.c | 147 ++++++++++++++----
drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
3 files changed, 156 insertions(+), 33 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
index 7bbba4d56a77..39f057dca92c 100644
--- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
@@ -573,6 +573,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VDO0,
+ MT8188_SMI_COMMON_CLAMP_EN_SET,
+ MT8188_SMI_COMMON_CLAMP_EN_CLR,
+ MT8188_SMI_COMMON_CLAMP_EN_STA),
+ BUS_PROT_WR(SMI,
+ MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VPP1,
+ MT8188_SMI_COMMON_CLAMP_EN_SET,
+ MT8188_SMI_COMMON_CLAMP_EN_CLR,
+ MT8188_SMI_COMMON_CLAMP_EN_STA),
+ },
.reset_smi = {
SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
MT8188_SMI_LARB10_RESET_ADDR),
@@ -585,7 +597,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
MT8188_SMI_LARB15_RESET_ADDR),
},
- .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
},
[MT8188_POWER_DOMAIN_IPE] = {
.name = "ipe",
@@ -595,11 +607,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_VPP1,
+ MT8188_SMI_COMMON_CLAMP_EN_SET,
+ MT8188_SMI_COMMON_CLAMP_EN_CLR,
+ MT8188_SMI_COMMON_CLAMP_EN_STA),
+ },
.reset_smi = {
SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
MT8188_SMI_LARB12_RESET_ADDR),
},
- .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
},
[MT8188_POWER_DOMAIN_CAM_VCORE] = {
.name = "cam_vcore",
@@ -676,13 +695,20 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_VPP1,
+ MT8188_SMI_COMMON_CLAMP_EN_SET,
+ MT8188_SMI_COMMON_CLAMP_EN_CLR,
+ MT8188_SMI_COMMON_CLAMP_EN_STA),
+ },
.reset_smi = {
SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
MT8188_SMI_LARB16A_RESET_ADDR),
SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
MT8188_SMI_LARB17A_RESET_ADDR),
},
- .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
},
[MT8188_POWER_DOMAIN_CAM_SUBB] = {
.name = "cam_subb",
@@ -692,13 +718,20 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
.pwr_sta2nd_offs = 0x170,
.sram_pdn_bits = BIT(8),
.sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUBB_TO_VDO0,
+ MT8188_SMI_COMMON_CLAMP_EN_SET,
+ MT8188_SMI_COMMON_CLAMP_EN_CLR,
+ MT8188_SMI_COMMON_CLAMP_EN_STA),
+ },
.reset_smi = {
SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
MT8188_SMI_LARB16B_RESET_ADDR),
SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
MT8188_SMI_LARB17B_RESET_ADDR),
},
- .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
},
};

diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index 9ab6fa105c8c..3c797e136c0e 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -47,9 +47,10 @@ struct scpsys_domain {
struct clk_bulk_data *subsys_clks;
struct regmap *infracfg_nao;
struct regmap *infracfg;
- struct regmap *smi;
+ struct regmap **smi;
struct regmap **larb;
int num_larb;
+ int num_smi;
struct regulator *supply;
};

@@ -122,29 +123,19 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
MTK_POLL_TIMEOUT);
}

-static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
- const struct scpsys_bus_prot_data *bpd)
-{
- if (bpd->flags & BUS_PROT_COMPONENT_SMI)
- return pd->smi;
- else
- return pd->infracfg;
-}
-
static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
const struct scpsys_bus_prot_data *bpd)
{
if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
return pd->infracfg_nao;
else
- return scpsys_bus_protect_get_regmap(pd, bpd);
+ return pd->infracfg;
}

static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
- const struct scpsys_bus_prot_data *bpd)
+ const struct scpsys_bus_prot_data *bpd,
+ struct regmap *sta_regmap, struct regmap *regmap)
{
- struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
- struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
u32 sta_mask = bpd->bus_prot_sta_mask;
u32 expected_ack;
u32 val;
@@ -165,10 +156,9 @@ static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
}

static int scpsys_bus_protect_set(struct scpsys_domain *pd,
- const struct scpsys_bus_prot_data *bpd)
+ const struct scpsys_bus_prot_data *bpd,
+ struct regmap *sta_regmap, struct regmap *regmap)
{
- struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
- struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
u32 sta_mask = bpd->bus_prot_sta_mask;
u32 val;

@@ -182,19 +172,32 @@ static int scpsys_bus_protect_set(struct scpsys_domain *pd,
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
}

-static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
+static int _scpsys_clamp_bus_protection_enable(struct scpsys_domain *pd, bool is_smi)
{
+ int smi_count = 0;
+
for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
+ struct regmap *sta_regmap, *regmap;
+ bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
int ret;

if (!bpd->bus_prot_set_clr_mask)
break;

+ if (is_smi) {
+ sta_regmap = pd->smi[smi_count];
+ regmap = pd->smi[smi_count];
+ smi_count++;
+ } else {
+ sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
+ regmap = pd->infracfg;
+ }
+
if (bpd->flags & BUS_PROT_INVERTED)
- ret = scpsys_bus_protect_clear(pd, bpd);
+ ret = scpsys_bus_protect_clear(pd, bpd, sta_regmap, regmap);
else
- ret = scpsys_bus_protect_set(pd, bpd);
+ ret = scpsys_bus_protect_set(pd, bpd, sta_regmap, regmap);
if (ret)
return ret;
}
@@ -202,19 +205,32 @@ static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
return 0;
}

-static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
+static int _scpsys_clamp_bus_protection_disable(struct scpsys_domain *pd, bool is_smi)
{
+ int smi_count = pd->num_smi - 1;
+
for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
+ struct regmap *sta_regmap, *regmap;
+ bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
int ret;

if (!bpd->bus_prot_set_clr_mask)
continue;

+ if (is_smi) {
+ sta_regmap = pd->smi[smi_count];
+ regmap = pd->smi[smi_count];
+ smi_count--;
+ } else {
+ sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
+ regmap = pd->infracfg;
+ }
+
if (bpd->flags & BUS_PROT_INVERTED)
- ret = scpsys_bus_protect_set(pd, bpd);
+ ret = scpsys_bus_protect_set(pd, bpd, sta_regmap, regmap);
else
- ret = scpsys_bus_protect_clear(pd, bpd);
+ ret = scpsys_bus_protect_clear(pd, bpd, sta_regmap, regmap);
if (ret)
return ret;
}
@@ -222,6 +238,50 @@ static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
return 0;
}

+static int scpsys_clamp_protection(struct scpsys_domain *pd)
+{
+ int ret;
+
+ ret = _scpsys_clamp_bus_protection_enable(pd, true);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int scpsys_clamp_protection_disable(struct scpsys_domain *pd)
+{
+ int ret;
+
+ ret = _scpsys_clamp_bus_protection_disable(pd, true);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
+{
+ int ret;
+
+ ret = _scpsys_clamp_bus_protection_enable(pd, false);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
+{
+ int ret;
+
+ ret = _scpsys_clamp_bus_protection_disable(pd, false);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int scpsys_regulator_enable(struct regulator *supply)
{
return supply ? regulator_enable(supply) : 0;
@@ -272,6 +332,12 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
bool tmp;
int ret;

+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
+ ret = scpsys_clamp_protection(pd);
+ if (ret)
+ return ret;
+ }
+
ret = scpsys_regulator_enable(pd->supply);
if (ret)
return ret;
@@ -318,6 +384,12 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (ret < 0)
goto err_disable_subsys_clks;

+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
+ ret = scpsys_clamp_protection_disable(pd);
+ if (ret)
+ return ret;
+ }
+
ret = scpsys_bus_protect_disable(pd);
if (ret < 0)
goto err_disable_sram;
@@ -353,6 +425,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
bool tmp;
int ret;

+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
+ ret = scpsys_clamp_protection(pd);
+ if (ret)
+ return ret;
+ }
+
ret = scpsys_bus_protect_enable(pd);
if (ret < 0)
return ret;
@@ -450,12 +528,23 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
if (IS_ERR(pd->infracfg))
return ERR_CAST(pd->infracfg);

- smi_node = of_parse_phandle(node, "mediatek,smi", 0);
- if (smi_node) {
- pd->smi = device_node_to_regmap(smi_node);
- of_node_put(smi_node);
- if (IS_ERR(pd->smi))
- return ERR_CAST(pd->smi);
+ pd->num_smi = of_count_phandle_with_args(node, "mediatek,smi", NULL);
+ if (pd->num_smi > 0) {
+ pd->smi = devm_kcalloc(scpsys->dev, pd->num_smi, sizeof(*pd->smi), GFP_KERNEL);
+ if (!pd->smi)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < pd->num_smi; i++) {
+ smi_node = of_parse_phandle(node, "mediatek,smi", i);
+ if (!smi_node)
+ return ERR_PTR(-EINVAL);
+
+ pd->smi[i] = device_node_to_regmap(smi_node);
+ if (IS_ERR(pd->smi[i]))
+ return ERR_CAST(pd->smi[i]);
+ }
+ } else {
+ pd->num_smi = 0;
}

pd->num_larb = of_count_phandle_with_args(node, "mediatek,larb", NULL);
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
index 31c2a1bb500f..e0eb7214719e 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -13,6 +13,7 @@
#define MTK_SCPD_EXT_BUCK_ISO BIT(6)
#define MTK_SCPD_HAS_INFRA_NAO BIT(7)
#define MTK_SCPD_STRICT_BUS_PROTECTION BIT(8)
+#define MTK_SCPD_CLAMP_PROTECTION BIT(9)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))

#define SPM_VDE_PWR_CON 0x0210
--
2.18.0


Subject: Re: [PATCH 2/2] soc: mediatek: pm-domains: support smi clamp protection

Il 25/03/24 13:19, yu-chang.lee ha scritto:
> In order to avoid power glitch, this patch use smi clamp
> to disable/enable smi common port.
>
> Signed-off-by: yu-chang.lee <[email protected]>
> ---
> drivers/pmdomain/mediatek/mt8188-pm-domains.h | 41 ++++-
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 147 ++++++++++++++----
> drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
> 3 files changed, 156 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> index 7bbba4d56a77..39f057dca92c 100644
> --- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> +++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> @@ -573,6 +573,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .bp_cfg = {
> + BUS_PROT_WR(SMI,
> + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VDO0,
> + MT8188_SMI_COMMON_CLAMP_EN_SET,
> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> + MT8188_SMI_COMMON_CLAMP_EN_STA),
> + BUS_PROT_WR(SMI,
> + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_VPP1,
> + MT8188_SMI_COMMON_CLAMP_EN_SET,
> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> + MT8188_SMI_COMMON_CLAMP_EN_STA),
> + },
> .reset_smi = {
> SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
> MT8188_SMI_LARB10_RESET_ADDR),
> @@ -585,7 +597,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
> MT8188_SMI_LARB15_RESET_ADDR),
> },
> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
> },
> [MT8188_POWER_DOMAIN_IPE] = {
> .name = "ipe",
> @@ -595,11 +607,18 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .bp_cfg = {
> + BUS_PROT_WR(SMI,
> + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_VPP1,
> + MT8188_SMI_COMMON_CLAMP_EN_SET,
> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> + MT8188_SMI_COMMON_CLAMP_EN_STA),
> + },
> .reset_smi = {
> SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
> MT8188_SMI_LARB12_RESET_ADDR),
> },
> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
> },
> [MT8188_POWER_DOMAIN_CAM_VCORE] = {
> .name = "cam_vcore",
> @@ -676,13 +695,20 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .bp_cfg = {
> + BUS_PROT_WR(SMI,
> + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_VPP1,
> + MT8188_SMI_COMMON_CLAMP_EN_SET,
> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> + MT8188_SMI_COMMON_CLAMP_EN_STA),
> + },
> .reset_smi = {
> SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
> MT8188_SMI_LARB16A_RESET_ADDR),
> SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
> MT8188_SMI_LARB17A_RESET_ADDR),
> },
> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
> },
> [MT8188_POWER_DOMAIN_CAM_SUBB] = {
> .name = "cam_subb",
> @@ -692,13 +718,20 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
> .pwr_sta2nd_offs = 0x170,
> .sram_pdn_bits = BIT(8),
> .sram_pdn_ack_bits = BIT(12),
> + .bp_cfg = {
> + BUS_PROT_WR(SMI,
> + MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUBB_TO_VDO0,
> + MT8188_SMI_COMMON_CLAMP_EN_SET,
> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> + MT8188_SMI_COMMON_CLAMP_EN_STA),
> + },
> .reset_smi = {
> SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
> MT8188_SMI_LARB16B_RESET_ADDR),
> SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
> MT8188_SMI_LARB17B_RESET_ADDR),
> },
> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_CLAMP_PROTECTION,
> },
> };
>
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> index 9ab6fa105c8c..3c797e136c0e 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> @@ -47,9 +47,10 @@ struct scpsys_domain {
> struct clk_bulk_data *subsys_clks;
> struct regmap *infracfg_nao;
> struct regmap *infracfg;
> - struct regmap *smi;
> + struct regmap **smi;
> struct regmap **larb;
> int num_larb;
> + int num_smi;
> struct regulator *supply;
> };
>
> @@ -122,29 +123,19 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
> MTK_POLL_TIMEOUT);
> }
>
> -static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
> - const struct scpsys_bus_prot_data *bpd)
> -{
> - if (bpd->flags & BUS_PROT_COMPONENT_SMI)
> - return pd->smi;
> - else
> - return pd->infracfg;
> -}
> -
> static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
> const struct scpsys_bus_prot_data *bpd)
> {
> if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
> return pd->infracfg_nao;
> else
> - return scpsys_bus_protect_get_regmap(pd, bpd);
> + return pd->infracfg;
> }
>
> static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
> - const struct scpsys_bus_prot_data *bpd)
> + const struct scpsys_bus_prot_data *bpd,
> + struct regmap *sta_regmap, struct regmap *regmap)
> {
> - struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
> - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
> u32 sta_mask = bpd->bus_prot_sta_mask;
> u32 expected_ack;
> u32 val;
> @@ -165,10 +156,9 @@ static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
> }
>
> static int scpsys_bus_protect_set(struct scpsys_domain *pd,
> - const struct scpsys_bus_prot_data *bpd)
> + const struct scpsys_bus_prot_data *bpd,
> + struct regmap *sta_regmap, struct regmap *regmap)
> {
> - struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
> - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
> u32 sta_mask = bpd->bus_prot_sta_mask;
> u32 val;
>
> @@ -182,19 +172,32 @@ static int scpsys_bus_protect_set(struct scpsys_domain *pd,
> MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> }
>
> -static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
> +static int _scpsys_clamp_bus_protection_enable(struct scpsys_domain *pd, bool is_smi)
> {
> + int smi_count = 0;
> +
> for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
> const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
> + struct regmap *sta_regmap, *regmap;
> + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
> int ret;
>
> if (!bpd->bus_prot_set_clr_mask)
> break;
>
> + if (is_smi) {
> + sta_regmap = pd->smi[smi_count];
> + regmap = pd->smi[smi_count];
> + smi_count++;
> + } else {
> + sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
> + regmap = pd->infracfg;
> + }
> +
> if (bpd->flags & BUS_PROT_INVERTED)
> - ret = scpsys_bus_protect_clear(pd, bpd);
> + ret = scpsys_bus_protect_clear(pd, bpd, sta_regmap, regmap);
> else
> - ret = scpsys_bus_protect_set(pd, bpd);
> + ret = scpsys_bus_protect_set(pd, bpd, sta_regmap, regmap);
> if (ret)
> return ret;
> }
> @@ -202,19 +205,32 @@ static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
> return 0;
> }
>
> -static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
> +static int _scpsys_clamp_bus_protection_disable(struct scpsys_domain *pd, bool is_smi)
> {
> + int smi_count = pd->num_smi - 1;
> +
> for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
> const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
> + struct regmap *sta_regmap, *regmap;
> + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
> int ret;
>
> if (!bpd->bus_prot_set_clr_mask)
> continue;
>
> + if (is_smi) {
> + sta_regmap = pd->smi[smi_count];
> + regmap = pd->smi[smi_count];
> + smi_count--;
> + } else {
> + sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
> + regmap = pd->infracfg;
> + }
> +
> if (bpd->flags & BUS_PROT_INVERTED)
> - ret = scpsys_bus_protect_set(pd, bpd);
> + ret = scpsys_bus_protect_set(pd, bpd, sta_regmap, regmap);
> else
> - ret = scpsys_bus_protect_clear(pd, bpd);
> + ret = scpsys_bus_protect_clear(pd, bpd, sta_regmap, regmap);
> if (ret)
> return ret;
> }
> @@ -222,6 +238,50 @@ static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
> return 0;
> }
>
> +static int scpsys_clamp_protection(struct scpsys_domain *pd)
> +{
> + int ret;
> +

You can directly call _scpsys_clamp_bus_protection_enable(), no need for a helper.

> + ret = _scpsys_clamp_bus_protection_enable(pd, true);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int scpsys_clamp_protection_disable(struct scpsys_domain *pd)
> +{
> + int ret;
> +
> + ret = _scpsys_clamp_bus_protection_disable(pd, true);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int scpsys_bus_protect_enable(struct scpsys_domain *pd)

Unused function, please remove.

> +{
> + int ret;
> +
> + ret = _scpsys_clamp_bus_protection_enable(pd, false);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
> +{

Unused function, please remove.

> + int ret;
> +
> + ret = _scpsys_clamp_bus_protection_disable(pd, false);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> static int scpsys_regulator_enable(struct regulator *supply)
> {
> return supply ? regulator_enable(supply) : 0;
> @@ -272,6 +332,12 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> bool tmp;
> int ret;
>
> + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> + ret = scpsys_clamp_protection(pd);

ret = scpsys_clamp_bus_protection_enable(pd, true);

> + if (ret)
> + return ret;
> + }
> +
> ret = scpsys_regulator_enable(pd->supply);
> if (ret)
> return ret;
> @@ -318,6 +384,12 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> if (ret < 0)
> goto err_disable_subsys_clks;
>
> + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> + ret = scpsys_clamp_protection_disable(pd);

ret = scpsys_clamp_bus_protection_disable(pd, true);

> + if (ret)
> + return ret;
> + }
> +
> ret = scpsys_bus_protect_disable(pd);
> if (ret < 0)
> goto err_disable_sram;
> @@ -353,6 +425,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> bool tmp;
> int ret;
>
> + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> + ret = scpsys_clamp_protection(pd);

ret = scpsys_clamp_bus_protection_enable(pd, true);

> + if (ret)
> + return ret;
> + }
> +
> ret = scpsys_bus_protect_enable(pd);
> if (ret < 0)
> return ret;

Regards,
Angelo



2024-03-26 02:14:56

by Yu-chang Lee (李禹璋)

[permalink] [raw]
Subject: Re: [PATCH 2/2] soc: mediatek: pm-domains: support smi clamp protection

On Mon, 2024-03-25 at 14:05 +0100, AngeloGioacchino Del Regno wrote:
> Il 25/03/24 13:19, yu-chang.lee ha scritto:
> > In order to avoid power glitch, this patch use smi clamp
> > to disable/enable smi common port.
> >
> > Signed-off-by: yu-chang.lee <[email protected]>
> > ---
> > drivers/pmdomain/mediatek/mt8188-pm-domains.h | 41 ++++-
> > drivers/pmdomain/mediatek/mtk-pm-domains.c | 147
> > ++++++++++++++----
> > drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
> > 3 files changed, 156 insertions(+), 33 deletions(-)
> >
> > diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> > b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> > index 7bbba4d56a77..39f057dca92c 100644
> > --- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> > +++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
> > @@ -573,6 +573,18 @@ static const struct scpsys_domain_data
> > scpsys_domain_data_mt8188[] = {
> > .pwr_sta2nd_offs = 0x170,
> > .sram_pdn_bits = BIT(8),
> > .sram_pdn_ack_bits = BIT(12),
> > + .bp_cfg = {
> > + BUS_PROT_WR(SMI,
> > + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_
> > VDO0,
> > + MT8188_SMI_COMMON_CLAMP_EN_SET,
> > + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> > + MT8188_SMI_COMMON_CLAMP_EN_STA),
> > + BUS_PROT_WR(SMI,
> > + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_
> > VPP1,
> > + MT8188_SMI_COMMON_CLAMP_EN_SET,
> > + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> > + MT8188_SMI_COMMON_CLAMP_EN_STA),
> > + },
> > .reset_smi = {
> > SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
> > MT8188_SMI_LARB10_RESET_ADDR),
> > @@ -585,7 +597,7 @@ static const struct scpsys_domain_data
> > scpsys_domain_data_mt8188[] = {
> > SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
> > MT8188_SMI_LARB15_RESET_ADDR),
> > },
> > - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> > + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
> > MTK_SCPD_CLAMP_PROTECTION,
> > },
> > [MT8188_POWER_DOMAIN_IPE] = {
> > .name = "ipe",
> > @@ -595,11 +607,18 @@ static const struct scpsys_domain_data
> > scpsys_domain_data_mt8188[] = {
> > .pwr_sta2nd_offs = 0x170,
> > .sram_pdn_bits = BIT(8),
> > .sram_pdn_ack_bits = BIT(12),
> > + .bp_cfg = {
> > + BUS_PROT_WR(SMI,
> > + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_
> > VPP1,
> > + MT8188_SMI_COMMON_CLAMP_EN_SET,
> > + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> > + MT8188_SMI_COMMON_CLAMP_EN_STA),
> > + },
> > .reset_smi = {
> > SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
> > MT8188_SMI_LARB12_RESET_ADDR),
> > },
> > - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> > + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
> > MTK_SCPD_CLAMP_PROTECTION,
> > },
> > [MT8188_POWER_DOMAIN_CAM_VCORE] = {
> > .name = "cam_vcore",
> > @@ -676,13 +695,20 @@ static const struct scpsys_domain_data
> > scpsys_domain_data_mt8188[] = {
> > .pwr_sta2nd_offs = 0x170,
> > .sram_pdn_bits = BIT(8),
> > .sram_pdn_ack_bits = BIT(12),
> > + .bp_cfg = {
> > + BUS_PROT_WR(SMI,
> > + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_
> > VPP1,
> > + MT8188_SMI_COMMON_CLAMP_EN_SET,
> > + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> > + MT8188_SMI_COMMON_CLAMP_EN_STA),
> > + },
> > .reset_smi = {
> > SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
> > MT8188_SMI_LARB16A_RESET_ADDR),
> > SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
> > MT8188_SMI_LARB17A_RESET_ADDR),
> > },
> > - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> > + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
> > MTK_SCPD_CLAMP_PROTECTION,
> > },
> > [MT8188_POWER_DOMAIN_CAM_SUBB] = {
> > .name = "cam_subb",
> > @@ -692,13 +718,20 @@ static const struct scpsys_domain_data
> > scpsys_domain_data_mt8188[] = {
> > .pwr_sta2nd_offs = 0x170,
> > .sram_pdn_bits = BIT(8),
> > .sram_pdn_ack_bits = BIT(12),
> > + .bp_cfg = {
> > + BUS_PROT_WR(SMI,
> > + MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUB
> > B_TO_VDO0,
> > + MT8188_SMI_COMMON_CLAMP_EN_SET,
> > + MT8188_SMI_COMMON_CLAMP_EN_CLR,
> > + MT8188_SMI_COMMON_CLAMP_EN_STA),
> > + },
> > .reset_smi = {
> > SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
> > MT8188_SMI_LARB16B_RESET_ADDR),
> > SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
> > MT8188_SMI_LARB17B_RESET_ADDR),
> > },
> > - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
> > + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
> > MTK_SCPD_CLAMP_PROTECTION,
> > },
> > };
> >
> > diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> > b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> > index 9ab6fa105c8c..3c797e136c0e 100644
> > --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> > +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> > @@ -47,9 +47,10 @@ struct scpsys_domain {
> > struct clk_bulk_data *subsys_clks;
> > struct regmap *infracfg_nao;
> > struct regmap *infracfg;
> > - struct regmap *smi;
> > + struct regmap **smi;
> > struct regmap **larb;
> > int num_larb;
> > + int num_smi;
> > struct regulator *supply;
> > };
> >
> > @@ -122,29 +123,19 @@ static int scpsys_sram_disable(struct
> > scpsys_domain *pd)
> > MTK_POLL_TIMEOUT);
> > }
> >
> > -static struct regmap *scpsys_bus_protect_get_regmap(struct
> > scpsys_domain *pd,
> > - const struct
> > scpsys_bus_prot_data *bpd)
> > -{
> > - if (bpd->flags & BUS_PROT_COMPONENT_SMI)
> > - return pd->smi;
> > - else
> > - return pd->infracfg;
> > -}
> > -
> > static struct regmap *scpsys_bus_protect_get_sta_regmap(struct
> > scpsys_domain *pd,
> > const struct
> > scpsys_bus_prot_data *bpd)
> > {
> > if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
> > return pd->infracfg_nao;
> > else
> > - return scpsys_bus_protect_get_regmap(pd, bpd);
> > + return pd->infracfg;
> > }
> >
> > static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
> > - const struct scpsys_bus_prot_data
> > *bpd)
> > + const struct scpsys_bus_prot_data
> > *bpd,
> > + struct regmap *sta_regmap,
> > struct regmap *regmap)
> > {
> > - struct regmap *sta_regmap =
> > scpsys_bus_protect_get_sta_regmap(pd, bpd);
> > - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
> > u32 sta_mask = bpd->bus_prot_sta_mask;
> > u32 expected_ack;
> > u32 val;
> > @@ -165,10 +156,9 @@ static int scpsys_bus_protect_clear(struct
> > scpsys_domain *pd,
> > }
> >
> > static int scpsys_bus_protect_set(struct scpsys_domain *pd,
> > - const struct scpsys_bus_prot_data
> > *bpd)
> > + const struct scpsys_bus_prot_data
> > *bpd,
> > + struct regmap *sta_regmap, struct
> > regmap *regmap)
> > {
> > - struct regmap *sta_regmap =
> > scpsys_bus_protect_get_sta_regmap(pd, bpd);
> > - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
> > u32 sta_mask = bpd->bus_prot_sta_mask;
> > u32 val;
> >
> > @@ -182,19 +172,32 @@ static int scpsys_bus_protect_set(struct
> > scpsys_domain *pd,
> > MTK_POLL_DELAY_US,
> > MTK_POLL_TIMEOUT);
> > }
> >
> > -static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
> > +static int _scpsys_clamp_bus_protection_enable(struct
> > scpsys_domain *pd, bool is_smi)
> > {
> > + int smi_count = 0;
> > +
> > for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
> > const struct scpsys_bus_prot_data *bpd = &pd->data-
> > >bp_cfg[i];
> > + struct regmap *sta_regmap, *regmap;
> > + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
> > int ret;
> >
> > if (!bpd->bus_prot_set_clr_mask)
> > break;
> >
> > + if (is_smi) {
> > + sta_regmap = pd->smi[smi_count];
> > + regmap = pd->smi[smi_count];
> > + smi_count++;
> > + } else {
> > + sta_regmap =
> > scpsys_bus_protect_get_sta_regmap(pd, bpd);
> > + regmap = pd->infracfg;
> > + }
> > +
> > if (bpd->flags & BUS_PROT_INVERTED)
> > - ret = scpsys_bus_protect_clear(pd, bpd);
> > + ret = scpsys_bus_protect_clear(pd, bpd,
> > sta_regmap, regmap);
> > else
> > - ret = scpsys_bus_protect_set(pd, bpd);
> > + ret = scpsys_bus_protect_set(pd, bpd,
> > sta_regmap, regmap);
> > if (ret)
> > return ret;
> > }
> > @@ -202,19 +205,32 @@ static int scpsys_bus_protect_enable(struct
> > scpsys_domain *pd)
> > return 0;
> > }
> >
> > -static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
> > +static int _scpsys_clamp_bus_protection_disable(struct
> > scpsys_domain *pd, bool is_smi)
> > {
> > + int smi_count = pd->num_smi - 1;
> > +
> > for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
> > const struct scpsys_bus_prot_data *bpd = &pd->data-
> > >bp_cfg[i];
> > + struct regmap *sta_regmap, *regmap;
> > + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
> > int ret;
> >
> > if (!bpd->bus_prot_set_clr_mask)
> > continue;
> >
> > + if (is_smi) {
> > + sta_regmap = pd->smi[smi_count];
> > + regmap = pd->smi[smi_count];
> > + smi_count--;
> > + } else {
> > + sta_regmap =
> > scpsys_bus_protect_get_sta_regmap(pd, bpd);
> > + regmap = pd->infracfg;
> > + }
> > +
> > if (bpd->flags & BUS_PROT_INVERTED)
> > - ret = scpsys_bus_protect_set(pd, bpd);
> > + ret = scpsys_bus_protect_set(pd, bpd,
> > sta_regmap, regmap);
> > else
> > - ret = scpsys_bus_protect_clear(pd, bpd);
> > + ret = scpsys_bus_protect_clear(pd, bpd,
> > sta_regmap, regmap);
> > if (ret)
> > return ret;
> > }
> > @@ -222,6 +238,50 @@ static int scpsys_bus_protect_disable(struct
> > scpsys_domain *pd)
> > return 0;
> > }
> >
> > +static int scpsys_clamp_protection(struct scpsys_domain *pd)
> > +{
> > + int ret;
> > +
>
> You can directly call _scpsys_clamp_bus_protection_enable(), no need
> for a helper.
>
> > + ret = _scpsys_clamp_bus_protection_enable(pd, true);
> > + if (ret)
> > + return ret;
> > +
> > + return 0;
> > +}
> > +
> > +static int scpsys_clamp_protection_disable(struct scpsys_domain
> > *pd)
> > +{
> > + int ret;
> > +
> > + ret = _scpsys_clamp_bus_protection_disable(pd, true);
> > + if (ret)
> > + return ret;
> > +
> > + return 0;
> > +}
> > +
> > +static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
>
> Unused function, please remove.

I think this is used in scpsys_power_off function. Do you mean I
should directly call _scpsys_clamp_bus_protection_disable?

>
> > +{
> > + int ret;
> > +
> > + ret = _scpsys_clamp_bus_protection_enable(pd, false);
> > + if (ret)
> > + return ret;
> > +
> > + return 0;
> > +}
> > +
> > +static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
> > +{
>
> Unused function, please remove.

Same here, I think this is used in scpsys_power_on function.

>
> > + int ret;
> > +
> > + ret = _scpsys_clamp_bus_protection_disable(pd, false);
> > + if (ret)
> > + return ret;
> > +
> > + return 0;
> > +}
> > +
> > static int scpsys_regulator_enable(struct regulator *supply)
> > {
> > return supply ? regulator_enable(supply) : 0;
> > @@ -272,6 +332,12 @@ static int scpsys_power_on(struct
> > generic_pm_domain *genpd)
> > bool tmp;
> > int ret;
> >
> > + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> > + ret = scpsys_clamp_protection(pd);
>
> ret = scpsys_clamp_bus_protection_enable(pd, true);
>
> > + if (ret)
> > + return ret;
> > + }
> > +
> > ret = scpsys_regulator_enable(pd->supply);
> > if (ret)
> > return ret;
> > @@ -318,6 +384,12 @@ static int scpsys_power_on(struct
> > generic_pm_domain *genpd)
> > if (ret < 0)
> > goto err_disable_subsys_clks;
> >
> > + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> > + ret = scpsys_clamp_protection_disable(pd);
>
> ret = scpsys_clamp_bus_protection_disable(pd, true);
>
> > + if (ret)
> > + return ret;
> > + }
> > +
> > ret = scpsys_bus_protect_disable(pd);
> > if (ret < 0)
> > goto err_disable_sram;
> > @@ -353,6 +425,12 @@ static int scpsys_power_off(struct
> > generic_pm_domain *genpd)
> > bool tmp;
> > int ret;
> >
> > + if (MTK_SCPD_CAPS(pd, MTK_SCPD_CLAMP_PROTECTION)) {
> > + ret = scpsys_clamp_protection(pd);
>
> ret = scpsys_clamp_bus_protection_enable(pd, true);
>
> > + if (ret)
> > + return ret;
> > + }
> > +
> > ret = scpsys_bus_protect_enable(pd);
> > if (ret < 0)
> > return ret;
>
> Regards,
> Angelo
>
Best Regards,
yu-chang.lee

Subject: Re: [PATCH 2/2] soc: mediatek: pm-domains: support smi clamp protection

Il 26/03/24 03:00, Yu-chang Lee (李禹璋) ha scritto:
> On Mon, 2024-03-25 at 14:05 +0100, AngeloGioacchino Del Regno wrote:
>> Il 25/03/24 13:19, yu-chang.lee ha scritto:
>>> In order to avoid power glitch, this patch use smi clamp
>>> to disable/enable smi common port.
>>>
>>> Signed-off-by: yu-chang.lee <[email protected]>
>>> ---
>>> drivers/pmdomain/mediatek/mt8188-pm-domains.h | 41 ++++-
>>> drivers/pmdomain/mediatek/mtk-pm-domains.c | 147
>>> ++++++++++++++----
>>> drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
>>> 3 files changed, 156 insertions(+), 33 deletions(-)
>>>
>>> diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
>>> b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
>>> index 7bbba4d56a77..39f057dca92c 100644
>>> --- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
>>> +++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
>>> @@ -573,6 +573,18 @@ static const struct scpsys_domain_data
>>> scpsys_domain_data_mt8188[] = {
>>> .pwr_sta2nd_offs = 0x170,
>>> .sram_pdn_bits = BIT(8),
>>> .sram_pdn_ack_bits = BIT(12),
>>> + .bp_cfg = {
>>> + BUS_PROT_WR(SMI,
>>> + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_
>>> VDO0,
>>> + MT8188_SMI_COMMON_CLAMP_EN_SET,
>>> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
>>> + MT8188_SMI_COMMON_CLAMP_EN_STA),
>>> + BUS_PROT_WR(SMI,
>>> + MT8188_SMI_COMMON_SMI_CLAMP_DIP_TO_
>>> VPP1,
>>> + MT8188_SMI_COMMON_CLAMP_EN_SET,
>>> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
>>> + MT8188_SMI_COMMON_CLAMP_EN_STA),
>>> + },
>>> .reset_smi = {
>>> SMI_RESET_WR(MT8188_SMI_LARB10_RESET,
>>> MT8188_SMI_LARB10_RESET_ADDR),
>>> @@ -585,7 +597,7 @@ static const struct scpsys_domain_data
>>> scpsys_domain_data_mt8188[] = {
>>> SMI_RESET_WR(MT8188_SMI_LARB15_RESET,
>>> MT8188_SMI_LARB15_RESET_ADDR),
>>> },
>>> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
>>> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
>>> MTK_SCPD_CLAMP_PROTECTION,
>>> },
>>> [MT8188_POWER_DOMAIN_IPE] = {
>>> .name = "ipe",
>>> @@ -595,11 +607,18 @@ static const struct scpsys_domain_data
>>> scpsys_domain_data_mt8188[] = {
>>> .pwr_sta2nd_offs = 0x170,
>>> .sram_pdn_bits = BIT(8),
>>> .sram_pdn_ack_bits = BIT(12),
>>> + .bp_cfg = {
>>> + BUS_PROT_WR(SMI,
>>> + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_
>>> VPP1,
>>> + MT8188_SMI_COMMON_CLAMP_EN_SET,
>>> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
>>> + MT8188_SMI_COMMON_CLAMP_EN_STA),
>>> + },
>>> .reset_smi = {
>>> SMI_RESET_WR(MT8188_SMI_LARB12_RESET,
>>> MT8188_SMI_LARB12_RESET_ADDR),
>>> },
>>> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
>>> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
>>> MTK_SCPD_CLAMP_PROTECTION,
>>> },
>>> [MT8188_POWER_DOMAIN_CAM_VCORE] = {
>>> .name = "cam_vcore",
>>> @@ -676,13 +695,20 @@ static const struct scpsys_domain_data
>>> scpsys_domain_data_mt8188[] = {
>>> .pwr_sta2nd_offs = 0x170,
>>> .sram_pdn_bits = BIT(8),
>>> .sram_pdn_ack_bits = BIT(12),
>>> + .bp_cfg = {
>>> + BUS_PROT_WR(SMI,
>>> + MT8188_SMI_COMMON_SMI_CLAMP_IPE_TO_
>>> VPP1,
>>> + MT8188_SMI_COMMON_CLAMP_EN_SET,
>>> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
>>> + MT8188_SMI_COMMON_CLAMP_EN_STA),
>>> + },
>>> .reset_smi = {
>>> SMI_RESET_WR(MT8188_SMI_LARB16A_RESET,
>>> MT8188_SMI_LARB16A_RESET_ADDR),
>>> SMI_RESET_WR(MT8188_SMI_LARB17A_RESET,
>>> MT8188_SMI_LARB17A_RESET_ADDR),
>>> },
>>> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
>>> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
>>> MTK_SCPD_CLAMP_PROTECTION,
>>> },
>>> [MT8188_POWER_DOMAIN_CAM_SUBB] = {
>>> .name = "cam_subb",
>>> @@ -692,13 +718,20 @@ static const struct scpsys_domain_data
>>> scpsys_domain_data_mt8188[] = {
>>> .pwr_sta2nd_offs = 0x170,
>>> .sram_pdn_bits = BIT(8),
>>> .sram_pdn_ack_bits = BIT(12),
>>> + .bp_cfg = {
>>> + BUS_PROT_WR(SMI,
>>> + MT8188_SMI_COMMON_SMI_CLAMP_CAM_SUB
>>> B_TO_VDO0,
>>> + MT8188_SMI_COMMON_CLAMP_EN_SET,
>>> + MT8188_SMI_COMMON_CLAMP_EN_CLR,
>>> + MT8188_SMI_COMMON_CLAMP_EN_STA),
>>> + },
>>> .reset_smi = {
>>> SMI_RESET_WR(MT8188_SMI_LARB16B_RESET,
>>> MT8188_SMI_LARB16B_RESET_ADDR),
>>> SMI_RESET_WR(MT8188_SMI_LARB17B_RESET,
>>> MT8188_SMI_LARB17B_RESET_ADDR),
>>> },
>>> - .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
>>> + .caps = MTK_SCPD_KEEP_DEFAULT_OFF |
>>> MTK_SCPD_CLAMP_PROTECTION,
>>> },
>>> };
>>>
>>> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c
>>> b/drivers/pmdomain/mediatek/mtk-pm-domains.c
>>> index 9ab6fa105c8c..3c797e136c0e 100644
>>> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
>>> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
>>> @@ -47,9 +47,10 @@ struct scpsys_domain {
>>> struct clk_bulk_data *subsys_clks;
>>> struct regmap *infracfg_nao;
>>> struct regmap *infracfg;
>>> - struct regmap *smi;
>>> + struct regmap **smi;
>>> struct regmap **larb;
>>> int num_larb;
>>> + int num_smi;
>>> struct regulator *supply;
>>> };
>>>
>>> @@ -122,29 +123,19 @@ static int scpsys_sram_disable(struct
>>> scpsys_domain *pd)
>>> MTK_POLL_TIMEOUT);
>>> }
>>>
>>> -static struct regmap *scpsys_bus_protect_get_regmap(struct
>>> scpsys_domain *pd,
>>> - const struct
>>> scpsys_bus_prot_data *bpd)
>>> -{
>>> - if (bpd->flags & BUS_PROT_COMPONENT_SMI)
>>> - return pd->smi;
>>> - else
>>> - return pd->infracfg;
>>> -}
>>> -
>>> static struct regmap *scpsys_bus_protect_get_sta_regmap(struct
>>> scpsys_domain *pd,
>>> const struct
>>> scpsys_bus_prot_data *bpd)
>>> {
>>> if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
>>> return pd->infracfg_nao;
>>> else
>>> - return scpsys_bus_protect_get_regmap(pd, bpd);
>>> + return pd->infracfg;
>>> }
>>>
>>> static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
>>> - const struct scpsys_bus_prot_data
>>> *bpd)
>>> + const struct scpsys_bus_prot_data
>>> *bpd,
>>> + struct regmap *sta_regmap,
>>> struct regmap *regmap)
>>> {
>>> - struct regmap *sta_regmap =
>>> scpsys_bus_protect_get_sta_regmap(pd, bpd);
>>> - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
>>> u32 sta_mask = bpd->bus_prot_sta_mask;
>>> u32 expected_ack;
>>> u32 val;
>>> @@ -165,10 +156,9 @@ static int scpsys_bus_protect_clear(struct
>>> scpsys_domain *pd,
>>> }
>>>
>>> static int scpsys_bus_protect_set(struct scpsys_domain *pd,
>>> - const struct scpsys_bus_prot_data
>>> *bpd)
>>> + const struct scpsys_bus_prot_data
>>> *bpd,
>>> + struct regmap *sta_regmap, struct
>>> regmap *regmap)
>>> {
>>> - struct regmap *sta_regmap =
>>> scpsys_bus_protect_get_sta_regmap(pd, bpd);
>>> - struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
>>> u32 sta_mask = bpd->bus_prot_sta_mask;
>>> u32 val;
>>>
>>> @@ -182,19 +172,32 @@ static int scpsys_bus_protect_set(struct
>>> scpsys_domain *pd,
>>> MTK_POLL_DELAY_US,
>>> MTK_POLL_TIMEOUT);
>>> }
>>>
>>> -static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
>>> +static int _scpsys_clamp_bus_protection_enable(struct
>>> scpsys_domain *pd, bool is_smi)
>>> {
>>> + int smi_count = 0;
>>> +
>>> for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
>>> const struct scpsys_bus_prot_data *bpd = &pd->data-
>>>> bp_cfg[i];
>>> + struct regmap *sta_regmap, *regmap;
>>> + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
>>> int ret;
>>>
>>> if (!bpd->bus_prot_set_clr_mask)
>>> break;
>>>
>>> + if (is_smi) {
>>> + sta_regmap = pd->smi[smi_count];
>>> + regmap = pd->smi[smi_count];
>>> + smi_count++;
>>> + } else {
>>> + sta_regmap =
>>> scpsys_bus_protect_get_sta_regmap(pd, bpd);
>>> + regmap = pd->infracfg;
>>> + }
>>> +
>>> if (bpd->flags & BUS_PROT_INVERTED)
>>> - ret = scpsys_bus_protect_clear(pd, bpd);
>>> + ret = scpsys_bus_protect_clear(pd, bpd,
>>> sta_regmap, regmap);
>>> else
>>> - ret = scpsys_bus_protect_set(pd, bpd);
>>> + ret = scpsys_bus_protect_set(pd, bpd,
>>> sta_regmap, regmap);
>>> if (ret)
>>> return ret;
>>> }
>>> @@ -202,19 +205,32 @@ static int scpsys_bus_protect_enable(struct
>>> scpsys_domain *pd)
>>> return 0;
>>> }
>>>
>>> -static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
>>> +static int _scpsys_clamp_bus_protection_disable(struct
>>> scpsys_domain *pd, bool is_smi)
>>> {
>>> + int smi_count = pd->num_smi - 1;
>>> +
>>> for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
>>> const struct scpsys_bus_prot_data *bpd = &pd->data-
>>>> bp_cfg[i];
>>> + struct regmap *sta_regmap, *regmap;
>>> + bool is_smi = bpd->flags & BUS_PROT_COMPONENT_SMI;
>>> int ret;
>>>
>>> if (!bpd->bus_prot_set_clr_mask)
>>> continue;
>>>
>>> + if (is_smi) {
>>> + sta_regmap = pd->smi[smi_count];
>>> + regmap = pd->smi[smi_count];
>>> + smi_count--;
>>> + } else {
>>> + sta_regmap =
>>> scpsys_bus_protect_get_sta_regmap(pd, bpd);
>>> + regmap = pd->infracfg;
>>> + }
>>> +
>>> if (bpd->flags & BUS_PROT_INVERTED)
>>> - ret = scpsys_bus_protect_set(pd, bpd);
>>> + ret = scpsys_bus_protect_set(pd, bpd,
>>> sta_regmap, regmap);
>>> else
>>> - ret = scpsys_bus_protect_clear(pd, bpd);
>>> + ret = scpsys_bus_protect_clear(pd, bpd,
>>> sta_regmap, regmap);
>>> if (ret)
>>> return ret;
>>> }
>>> @@ -222,6 +238,50 @@ static int scpsys_bus_protect_disable(struct
>>> scpsys_domain *pd)
>>> return 0;
>>> }
>>>
>>> +static int scpsys_clamp_protection(struct scpsys_domain *pd)
>>> +{
>>> + int ret;
>>> +
>>
>> You can directly call _scpsys_clamp_bus_protection_enable(), no need
>> for a helper.
>>
>>> + ret = _scpsys_clamp_bus_protection_enable(pd, true);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int scpsys_clamp_protection_disable(struct scpsys_domain
>>> *pd)
>>> +{
>>> + int ret;
>>> +
>>> + ret = _scpsys_clamp_bus_protection_disable(pd, true);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
>>
>> Unused function, please remove.
>
> I think this is used in scpsys_power_off function. Do you mean I
> should directly call _scpsys_clamp_bus_protection_disable?
>

Yes, please.

Cheers,
Angelo