summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c40
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h1
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))