diff options
| -rw-r--r-- | drivers/pmdomain/mediatek/mtk-pm-domains.c | 40 | ||||
| -rw-r--r-- | drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 |
2 files changed, 39 insertions, 2 deletions
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c index 36767f740f57..f400b0c6b5fd 100644 --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c @@ -15,6 +15,7 @@ #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/soc/mediatek/infracfg.h> +#include <linux/soc/mediatek/mtk_sip_svc.h> #include "mt6735-pm-domains.h" #include "mt6795-pm-domains.h" @@ -51,6 +52,8 @@ #define PWR_RTFF_SAVE_FLAG BIT(27) #define PWR_RTFF_UFS_CLK_DIS BIT(28) +#define MTK_SIP_KERNEL_HWCCF_CONTROL MTK_SIP_SMC_CMD(0x540) + struct scpsys_domain { struct generic_pm_domain genpd; const struct scpsys_domain_data *data; @@ -116,6 +119,15 @@ static bool scpsys_hwv_domain_is_enable_done(struct scpsys_domain *pd) return (val[0] & mask) && (val[1] & mask) && !(val[2] & mask); } +static int scpsys_sec_infra_power_on(bool on) +{ + struct arm_smccc_res res; + unsigned long cmd = on ? 1 : 0; + + arm_smccc_smc(MTK_SIP_KERNEL_HWCCF_CONTROL, cmd, 0, 0, 0, 0, 0, 0, &res); + return res.a0; +} + static int scpsys_sram_enable(struct scpsys_domain *pd) { u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits; @@ -291,9 +303,15 @@ static int scpsys_hwv_power_on(struct generic_pm_domain *genpd) u32 val; int ret; + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) { + ret = scpsys_sec_infra_power_on(true); + if (ret) + return ret; + } + ret = scpsys_regulator_enable(pd->supply); if (ret) - return ret; + goto err_infra; ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); if (ret) @@ -344,6 +362,9 @@ static int scpsys_hwv_power_on(struct generic_pm_domain *genpd) /* It's done! Disable the HWV low power subsystem clocks */ clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) + scpsys_sec_infra_power_on(false); + return 0; err_disable_subsys_clks: @@ -352,6 +373,9 @@ err_disable_clks: clk_bulk_disable_unprepare(pd->num_clks, pd->clks); err_reg: scpsys_regulator_disable(pd->supply); +err_infra: + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) + scpsys_sec_infra_power_on(false); return ret; }; @@ -363,9 +387,15 @@ static int scpsys_hwv_power_off(struct generic_pm_domain *genpd) u32 val; int ret; + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) { + ret = scpsys_sec_infra_power_on(true); + if (ret) + return ret; + } + ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks); if (ret) - return ret; + goto err_infra; /* Make sure the HW Voter is idle and able to accept commands */ ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->done, val, @@ -407,10 +437,16 @@ static int scpsys_hwv_power_off(struct generic_pm_domain *genpd) scpsys_regulator_disable(pd->supply); + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) + scpsys_sec_infra_power_on(false); + return 0; err_disable_subsys_clks: clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); +err_infra: + if (MTK_SCPD_CAPS(pd, MTK_SCPD_INFRA_PWR_CTL)) + scpsys_sec_infra_power_on(false); return ret; }; diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h index df4bf013709b..36adcfca80c6 100644 --- a/drivers/pmdomain/mediatek/mtk-pm-domains.h +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h @@ -16,6 +16,7 @@ #define MTK_SCPD_SRAM_PDN_INVERTED BIT(9) #define MTK_SCPD_MODEM_PWRSEQ BIT(10) #define MTK_SCPD_SKIP_RESET_B BIT(11) +#define MTK_SCPD_INFRA_PWR_CTL BIT(12) #define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data ? \ (_scpd)->data->caps & (_x) : \ (_scpd)->hwv_data->caps & (_x)) |
