Re: [PATCH 2/3] pmdomain: mediatek: Add support for secure modem power domain control

From: Matthias Brugger

Date: Tue Jul 14 2026 - 11:29:56 EST




On 14/07/2026 15:43, Nikolai Burov via B4 Relay wrote:
From: Nikolai Burov <nikolai.burov@xxxxxxxxx>

On recent MediaTek SoCs such as MT6858, the kernel is required to use
a secure monitor call (SMC) to enable or disable the modem power domain.
The power domain control register can be read, but firmware prevents it
from being modified directly. Other parts of the power sequence, such as
setting the ext_buck_iso register, still need to be performed on the
kernel side.

In preparation for modem support, add a flag to enable this new power
sequence for SoCs that need it.

Signed-off-by: Nikolai Burov <nikolai.burov@xxxxxxxxx>
---
drivers/pmdomain/mediatek/mtk-pm-domains.c | 54 +++++++++++++++++++++++++++---
drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
include/linux/soc/mediatek/mtk_sip_svc.h | 3 ++
3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index e1cfd4223473..56437b32b252 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -57,6 +57,12 @@
#define MTK_SIP_KERNEL_HWCCF_CONTROL MTK_SIP_SMC_CMD(0x540)
+/* Power domain commands for MTK_SIP_KERNEL_CCCI_CONTROL */
+enum {
+ MTK_MD_MTCMOS_ENABLE = 18,
+ MTK_MD_MTCMOS_DISABLE = 19,
+};
+
struct scpsys_domain {
struct generic_pm_domain genpd;
const struct scpsys_domain_data *data;
@@ -615,6 +621,34 @@ static void scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
}
+static bool scpsys_modem_sec_poll(unsigned long cmd)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(MTK_SIP_KERNEL_CCCI_CONTROL, cmd, 1, 0, 0, 0, 0, 0, &res);
+
+ return res.a0 == 0;
+}
+
+static int scpsys_modem_sec_power_on(bool on)
+{
+ struct arm_smccc_res res;
+ unsigned long cmd = on ? MTK_MD_MTCMOS_ENABLE : MTK_MD_MTCMOS_DISABLE;
+ bool tmp;
+ int ret;
+
+ arm_smccc_smc(MTK_SIP_KERNEL_CCCI_CONTROL, cmd, 0, 0, 0, 0, 0, 0, &res);
+ if (res.a0 == 0)
+ return 0;
+
+ ret = readx_poll_timeout(scpsys_modem_sec_poll, cmd, tmp, tmp,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ 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);
@@ -633,7 +667,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
pd->data->ext_buck_iso_mask);
- if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE))
+ ret = scpsys_modem_sec_power_on(true);
+ else if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
ret = scpsys_modem_pwrseq_on(pd);

So we can have either cap MTK_SCPD_MODEM_SECURE or MTK_SCPD_MODEM_PWRSEQ but...

[...]

@@ -719,10 +761,12 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
if (ret < 0)
return ret;
- if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
- scpsys_modem_pwrseq_off(pd);
- else
- scpsys_ctl_pwrseq_off(pd);
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE)) {
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))

... here it seems that a power domain could have both caps set. I suppose this second case does not exist, but code should treat just one of the two cases (mutual exclusive or not mutual exclusive).

Regards,
Matthias