[PATCH v1 03/13] pmdomain: mediatek: Handle SoCs with inverted SRAM power-down bits

From: AngeloGioacchino Del Regno
Date: Mon Jun 23 2025 - 08:11:44 EST


Some SoCs, and even some subsystems in the same SoC, may have the
logic for SRAM power-down inverted, as in, setting the bit means
"power down" and unsetting means "power up": this is because some
hardware subsystems use this as a power-lock indication and some
use this as a power down one (for example, usually, the modem ss
has it inverted!).

In preparation for adding support for power domains with inverted
SRAM_PDN bits, add a new MTK_SCPD_SRAM_PDN_INVERTED flag and check
for it in scpsys_sram_enable() and scpsys_sram_disable().

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@xxxxxxxxxxxxx>
---
drivers/pmdomain/mediatek/mtk-pm-domains.c | 27 ++++++++++++++++------
drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index 8c1b5a4851a1..2a430e7cd353 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -79,16 +79,23 @@ static bool scpsys_domain_is_on(struct scpsys_domain *pd)

static int scpsys_sram_enable(struct scpsys_domain *pd)
{
- u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+ u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
int ret;

- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = pdn_ack;
+ } else {
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = 0;
+ }

/* Either wait until SRAM_PDN_ACK all 1 or 0 */
ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
- (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ (tmp & pdn_ack) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;

@@ -103,7 +110,7 @@ static int scpsys_sram_enable(struct scpsys_domain *pd)

static int scpsys_sram_disable(struct scpsys_domain *pd)
{
- u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+ u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;

@@ -113,12 +120,18 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
}

- regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = 0;
+ } else {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = pdn_ack;
+ }

/* Either wait until SRAM_PDN_ACK all 1 or 0 */
return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
- (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
- MTK_POLL_TIMEOUT);
+ (tmp & pdn_ack) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
}

static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
index 2a71989bc2b4..f7f0a5fb383b 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_SRAM_PDN_INVERTED BIT(9)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))

#define SPM_VDE_PWR_CON 0x0210
--
2.49.0