#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"
#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;
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;
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)
/* 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:
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;
};
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,
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;
};