* [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct
@ 2026-07-01 12:19 AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP AngeloGioacchino Del Regno
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
To: ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
nfraprado, irving-ch.lin, macpaul.lin, aford173, mbrugger,
devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-mediatek, justin.yeh, kernel
This series adds support for the DirectCTL HFRPSYS power domains found
on the MT8196 SoC (the ones without HW Voter support) and also adds a
fix to respect the power domain relationships during error cleanup,
which avoids HW lockups in case probe deferrals in the specific case
of "almost fully probed" power domains (where most of them probed and
got set up but a probe deferral happened almost at the end), behavior
seen on the MT8189 SoC during bringup (but honestly I have no idea how
are the current ones working fine without this fix...!).
This was tested on MT8173, MT8186, MT8188, MT8189, MT8192, MT8195 and
also on MT8196, over months of development, both manually and over CI,
with no regressions detected.
AngeloGioacchino Del Regno (4):
dt-bindings: power: mediatek: Add support for MT8196 direct HFRP
pmdomain: mediatek: Respect PD relationships during error cleanup
pmdomain: mediatek: Add support for Direct CTL simple power sequence
pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains
.../power/mediatek,power-controller.yaml | 1 +
drivers/pmdomain/mediatek/mt8196-pm-domains.h | 27 ++++
drivers/pmdomain/mediatek/mtk-pm-domains.c | 134 ++++++++++++++----
drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
.../dt-bindings/power/mediatek,mt8196-power.h | 4 +
5 files changed, 141 insertions(+), 26 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP
2026-07-01 12:19 [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct AngeloGioacchino Del Regno
@ 2026-07-01 12:19 ` AngeloGioacchino Del Regno
2026-07-06 15:06 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup AngeloGioacchino Del Regno
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
To: ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
nfraprado, irving-ch.lin, macpaul.lin, aford173, mbrugger,
devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-mediatek, justin.yeh, kernel
Add support for the HFRPSYS direct control power domains in the
MT8196 SoC, controlling power for the DisplayPort and for the
Embedded DisplayPort Transmitter IPs.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../devicetree/bindings/power/mediatek,power-controller.yaml | 1 +
include/dt-bindings/power/mediatek,mt8196-power.h | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
index 07f046277f8a..070c6e5666dc 100644
--- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
+++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
@@ -34,6 +34,7 @@ properties:
- mediatek,mt8189-power-controller
- mediatek,mt8192-power-controller
- mediatek,mt8195-power-controller
+ - mediatek,mt8196-hfrp-power-controller
- mediatek,mt8196-hwv-hfrp-power-controller
- mediatek,mt8196-hwv-scp-power-controller
- mediatek,mt8196-power-controller
diff --git a/include/dt-bindings/power/mediatek,mt8196-power.h b/include/dt-bindings/power/mediatek,mt8196-power.h
index 0f622a93c807..085790bf8124 100644
--- a/include/dt-bindings/power/mediatek,mt8196-power.h
+++ b/include/dt-bindings/power/mediatek,mt8196-power.h
@@ -30,6 +30,10 @@
#define MT8196_POWER_DOMAIN_MM_PROC_DORMANT 0
#define MT8196_POWER_DOMAIN_SSR 1
+/* HFRPSYS Multimedia Power Control (MMPC) - Direct Control */
+#define MT8196_POWER_DOMAIN_EDPTX 0
+#define MT8196_POWER_DOMAIN_DPTX 1
+
/* HFRPSYS MultiMedia Power Control (MMPC) - HW Voter */
#define MT8196_POWER_DOMAIN_VDE0 0
#define MT8196_POWER_DOMAIN_VDE1 1
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup
2026-07-01 12:19 [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP AngeloGioacchino Del Regno
@ 2026-07-01 12:19 ` AngeloGioacchino Del Regno
2026-07-06 15:09 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains AngeloGioacchino Del Regno
3 siblings, 1 reply; 9+ messages in thread
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
To: ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
nfraprado, irving-ch.lin, macpaul.lin, aford173, mbrugger,
devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-mediatek, justin.yeh, kernel
In case any probe error occurs (usually, a probe deferral) the
power domains shall be cleaned up while respecting their child
to parent relationship, or the system may freeze.
In order to do that without any memory footprint impacts after
the fact, allocate a temporary array in the probe function and
use it to store the indices of the added power domains in the
correct order.
This will be used in the error cleanup path and will be freed
at the end regardless of the probe status as, when the probing
succeeds, the genpd API takes care of unregistering all PDs in
the correct order anyway.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pmdomain/mediatek/mtk-pm-domains.c | 43 +++++++++++++++++-----
1 file changed, 33 insertions(+), 10 deletions(-)
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index e1cfd4223473..db543d4b1813 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -738,7 +738,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
}
static struct
-generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
+generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node,
+ u8 *domains_idx, u8 *num_domains)
{
const struct scpsys_domain_data *domain_data;
const struct scpsys_hwv_domain_data *hwv_domain_data;
@@ -906,6 +907,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
else
pm_genpd_init(&pd->genpd, NULL, false);
+ domains_idx[(*num_domains)++] = (u8) id;
scpsys->domains[id] = &pd->genpd;
return scpsys->pd_data.domains[id];
@@ -917,7 +919,8 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
return ERR_PTR(ret);
}
-static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
+static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent,
+ u8 *domains_idx, u8 *num_domains)
{
struct generic_pm_domain *child_pd, *parent_pd;
struct device_node *child;
@@ -940,7 +943,7 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
parent_pd = scpsys->pd_data.domains[id];
- child_pd = scpsys_add_one_domain(scpsys, child);
+ child_pd = scpsys_add_one_domain(scpsys, child, domains_idx, num_domains);
if (IS_ERR(child_pd)) {
ret = PTR_ERR(child_pd);
dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
@@ -949,7 +952,7 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
}
/* recursive call to add all subdomains */
- ret = scpsys_add_subdomain(scpsys, child);
+ ret = scpsys_add_subdomain(scpsys, child, domains_idx, num_domains);
if (ret)
goto err_put_node;
@@ -991,14 +994,16 @@ static void scpsys_remove_one_domain(struct scpsys_domain *pd)
clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
}
-static void scpsys_domain_cleanup(struct scpsys *scpsys)
+static void scpsys_domain_cleanup(struct scpsys *scpsys, u8 *domains_idx, u8 num_probed)
{
struct generic_pm_domain *genpd;
struct scpsys_domain *pd;
int i;
- for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
- genpd = scpsys->pd_data.domains[i];
+ for (i = num_probed - 1; i >= 0; i--) {
+ u8 pd_idx = domains_idx[i];
+
+ genpd = scpsys->pd_data.domains[pd_idx];
if (genpd) {
pd = to_scpsys_domain(genpd);
scpsys_remove_one_domain(pd);
@@ -1215,6 +1220,8 @@ static int scpsys_probe(struct platform_device *pdev)
struct device *parent;
struct scpsys *scpsys;
int num_domains, ret;
+ u8 num_added_pds = 0;
+ u8 *added_pds_idx;
soc = of_device_get_match_data(&pdev->dev);
if (!soc) {
@@ -1228,6 +1235,19 @@ static int scpsys_probe(struct platform_device *pdev)
if (!scpsys)
return -ENOMEM;
+ /*
+ * Temporarily store the IDs of the power domains that are added as in
+ * case of a probe deferral this can be used to correctly cleanup all
+ * of what was added before.
+ *
+ * Note that this array is used only in the probe function and must be
+ * freed at the end, regardless of whether all of the power domains were
+ * probed successfully or any failure happened.
+ */
+ added_pds_idx = devm_kmalloc_array(dev, num_domains, sizeof(*added_pds_idx), GFP_KERNEL);
+ if (!added_pds_idx)
+ return -ENOMEM;
+
scpsys->dev = dev;
scpsys->soc_data = soc;
@@ -1258,13 +1278,15 @@ static int scpsys_probe(struct platform_device *pdev)
for_each_available_child_of_node_scoped(np, node) {
struct generic_pm_domain *domain;
- domain = scpsys_add_one_domain(scpsys, node);
+ domain = scpsys_add_one_domain(scpsys, node,
+ added_pds_idx, &num_added_pds);
if (IS_ERR(domain)) {
ret = PTR_ERR(domain);
goto err_cleanup_domains;
}
- ret = scpsys_add_subdomain(scpsys, node);
+ ret = scpsys_add_subdomain(scpsys, node,
+ added_pds_idx, &num_added_pds);
if (ret)
goto err_cleanup_domains;
}
@@ -1280,10 +1302,11 @@ static int scpsys_probe(struct platform_device *pdev)
goto err_cleanup_domains;
}
+ devm_kfree(dev, added_pds_idx);
return 0;
err_cleanup_domains:
- scpsys_domain_cleanup(scpsys);
+ scpsys_domain_cleanup(scpsys, added_pds_idx, num_added_pds);
return ret;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence
2026-07-01 12:19 [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup AngeloGioacchino Del Regno
@ 2026-07-01 12:19 ` AngeloGioacchino Del Regno
2026-07-06 15:20 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains AngeloGioacchino Del Regno
3 siblings, 1 reply; 9+ messages in thread
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
To: ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
nfraprado, irving-ch.lin, macpaul.lin, aford173, mbrugger,
devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-mediatek, justin.yeh, kernel
Some new SoCs like MT8196, MT6991, and others, have got one
additional power controller (usually in the HFRP Multimedia
block) which needs a simplified power on/off sequence while
using Direct Control strategy.
Domains using the "simple power sequence" are not backed by
the RTFF hardware, have no Bus Protection mechanism, lacks
the ISO, PWR_ON, PWR_ON_2ND bits, and therefore get enabled
automatically after getting out of reset.
This simple power sequence is then a subset of the full one
as only needs the enablement of the specific power domain's
clock input and reset (where, again, after getting out of
reset, the ISO and PWR_ON bits are automatically internally
getting flipped) to enable or disable (power on or off).
Moreover, the simple power sequence power domains guarantee
that they always get enabled/disabled after executing the
relevant power sequence (on/off) so, differently from the
others, there is also no need to poll for a PWR_ACK.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pmdomain/mediatek/mtk-pm-domains.c | 87 ++++++++++++++++++----
drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
2 files changed, 72 insertions(+), 16 deletions(-)
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index db543d4b1813..5276adea1d04 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -549,9 +549,11 @@ static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
return 0;
}
-static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
+static int scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
+ bool tmp;
+ int ret;
switch (pd->data->rtff_type) {
case SCPSYS_RTFF_TYPE_GENERIC:
@@ -583,6 +585,41 @@ static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
+
+ /* wait until PWR_ACK = 0 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int scpsys_simple_pwrseq_on(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+
+ /* Enable subsys clock input and trigger power domain reset state */
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+ /* Wait for the hardware to stabilize */
+ udelay(1);
+
+ /* Get out of reset: set power on */
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+ return 0;
+}
+
+static int scpsys_simple_pwrseq_off(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+
+ return 0;
}
static int scpsys_modem_pwrseq_on(struct scpsys_domain *pd)
@@ -605,14 +642,24 @@ static int scpsys_modem_pwrseq_on(struct scpsys_domain *pd)
return 0;
}
-static void scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
+static int scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
+ bool tmp;
+ int ret;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SKIP_RESET_B))
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+ /* wait until PWR_ACK = 0 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, pd, 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)
@@ -635,6 +682,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
ret = scpsys_modem_pwrseq_on(pd);
+ else if (MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
+ ret = scpsys_simple_pwrseq_on(pd);
else
ret = scpsys_ctl_pwrseq_on(pd);
@@ -662,9 +711,11 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
goto err_pwr_ack;
}
- ret = scpsys_sram_enable(pd);
- if (ret < 0)
- goto err_disable_subsys_clks;
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ)) {
+ ret = scpsys_sram_enable(pd);
+ if (ret < 0)
+ goto err_disable_subsys_clks;
+ }
ret = scpsys_bus_protect_disable(pd, 0);
if (ret < 0)
@@ -682,7 +733,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
err_enable_bus_protect:
scpsys_bus_protect_enable(pd, 0);
err_disable_sram:
- scpsys_sram_disable(pd);
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
+ scpsys_sram_disable(pd);
err_disable_subsys_clks:
if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION))
clk_bulk_disable_unprepare(pd->num_subsys_clks,
@@ -698,16 +750,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
{
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
struct scpsys *scpsys = pd->scpsys;
- bool tmp;
int ret;
ret = scpsys_bus_protect_enable(pd, 0);
if (ret < 0)
return ret;
- ret = scpsys_sram_disable(pd);
- if (ret < 0)
- return ret;
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ)) {
+ ret = scpsys_sram_disable(pd);
+ if (ret < 0)
+ return ret;
+ }
if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
@@ -721,15 +774,11 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
scpsys_modem_pwrseq_off(pd);
+ else if (MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
+ ret = scpsys_simple_pwrseq_off(pd);
else
scpsys_ctl_pwrseq_off(pd);
- /* wait until PWR_ACK = 0 */
- ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
- MTK_POLL_TIMEOUT);
- if (ret < 0)
- return ret;
-
clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
scpsys_regulator_disable(pd->supply);
@@ -1083,6 +1132,12 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
regmap[2] = NULL;
}
+ /* If no access controllers are needed, don't allocate and don't fail */
+ if (num_regmaps == 0) {
+ scpsys->bus_prot = NULL;
+ return 0;
+ }
+
scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps,
sizeof(*scpsys->bus_prot), GFP_KERNEL);
if (!scpsys->bus_prot)
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
index a5dca24cbc2f..092403de66fa 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -17,6 +17,7 @@
#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_SIMPLE_PWRSEQ BIT(13)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data ? \
(_scpd)->data->caps & (_x) : \
(_scpd)->hwv_data->caps & (_x))
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains
2026-07-01 12:19 [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct AngeloGioacchino Del Regno
` (2 preceding siblings ...)
2026-07-01 12:19 ` [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence AngeloGioacchino Del Regno
@ 2026-07-01 12:19 ` AngeloGioacchino Del Regno
2026-07-06 15:21 ` Matthias Brugger
3 siblings, 1 reply; 9+ messages in thread
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
To: ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
nfraprado, irving-ch.lin, macpaul.lin, aford173, mbrugger,
devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-mediatek, justin.yeh, kernel
Add support for the power domains provided by the HFRPSYS Power
Controller of the MT8196 SoC.
Those control power to the eDP and DP Transmitter IPs.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pmdomain/mediatek/mt8196-pm-domains.h | 27 +++++++++++++++++++
drivers/pmdomain/mediatek/mtk-pm-domains.c | 4 +++
2 files changed, 31 insertions(+)
diff --git a/drivers/pmdomain/mediatek/mt8196-pm-domains.h b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
index 2e4b28720659..d704c9fa9337 100644
--- a/drivers/pmdomain/mediatek/mt8196-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
@@ -602,6 +602,27 @@ static const struct scpsys_hwv_domain_data hfrpsys_hwv_domain_data_mt8196[] = {
},
};
+static const struct scpsys_domain_data hfrpsys_domain_data_mt8196[] = {
+ [MT8196_POWER_DOMAIN_EDPTX] = {
+ .name = "edp-tx",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0x74,
+ .pwr_sta_offs = 0x74,
+ .pwr_sta2nd_offs = 0x74,
+ .caps = MTK_SCPD_SIMPLE_PWRSEQ,
+ },
+ [MT8196_POWER_DOMAIN_DPTX] = {
+ .name = "dp-tx",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0x78,
+ .pwr_sta_offs = 0x78,
+ .pwr_sta2nd_offs = 0x78,
+ .caps = MTK_SCPD_SIMPLE_PWRSEQ,
+ },
+};
+
static const struct scpsys_soc_data mt8196_scpsys_data = {
.domains_data = scpsys_domain_data_mt8196,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8196),
@@ -616,6 +637,12 @@ static const struct scpsys_soc_data mt8196_scpsys_hwv_data = {
.type = SCPSYS_MTCMOS_TYPE_HW_VOTER,
};
+static const struct scpsys_soc_data mt8196_hfrpsys_data = {
+ .domains_data = hfrpsys_domain_data_mt8196,
+ .num_domains = ARRAY_SIZE(hfrpsys_domain_data_mt8196),
+ .type = SCPSYS_MTCMOS_TYPE_DIRECT_CTL,
+};
+
static const struct scpsys_soc_data mt8196_hfrpsys_hwv_data = {
.hwv_domains_data = hfrpsys_hwv_domain_data_mt8196,
.num_hwv_domains = ARRAY_SIZE(hfrpsys_hwv_domain_data_mt8196),
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index 5276adea1d04..f69cf69ba0f6 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -1252,6 +1252,10 @@ static const struct of_device_id scpsys_of_match[] = {
.compatible = "mediatek,mt8196-power-controller",
.data = &mt8196_scpsys_data,
},
+ {
+ .compatible = "mediatek,mt8196-hfrp-power-controller",
+ .data = &mt8196_hfrpsys_data,
+ },
{
.compatible = "mediatek,mt8196-hwv-hfrp-power-controller",
.data = &mt8196_hfrpsys_hwv_data,
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP
2026-07-01 12:19 ` [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP AngeloGioacchino Del Regno
@ 2026-07-06 15:06 ` Matthias Brugger
0 siblings, 0 replies; 9+ messages in thread
From: Matthias Brugger @ 2026-07-06 15:06 UTC (permalink / raw)
To: AngeloGioacchino Del Regno, ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, nfraprado, irving-ch.lin,
macpaul.lin, aford173, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-mediatek, justin.yeh, kernel
On 01/07/2026 14:19, AngeloGioacchino Del Regno wrote:
> Add support for the HFRPSYS direct control power domains in the
> MT8196 SoC, controlling power for the DisplayPort and for the
> Embedded DisplayPort Transmitter IPs.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> .../devicetree/bindings/power/mediatek,power-controller.yaml | 1 +
> include/dt-bindings/power/mediatek,mt8196-power.h | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
> index 07f046277f8a..070c6e5666dc 100644
> --- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
> +++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
> @@ -34,6 +34,7 @@ properties:
> - mediatek,mt8189-power-controller
> - mediatek,mt8192-power-controller
> - mediatek,mt8195-power-controller
> + - mediatek,mt8196-hfrp-power-controller
> - mediatek,mt8196-hwv-hfrp-power-controller
> - mediatek,mt8196-hwv-scp-power-controller
> - mediatek,mt8196-power-controller
> diff --git a/include/dt-bindings/power/mediatek,mt8196-power.h b/include/dt-bindings/power/mediatek,mt8196-power.h
> index 0f622a93c807..085790bf8124 100644
> --- a/include/dt-bindings/power/mediatek,mt8196-power.h
> +++ b/include/dt-bindings/power/mediatek,mt8196-power.h
> @@ -30,6 +30,10 @@
> #define MT8196_POWER_DOMAIN_MM_PROC_DORMANT 0
> #define MT8196_POWER_DOMAIN_SSR 1
>
> +/* HFRPSYS Multimedia Power Control (MMPC) - Direct Control */
> +#define MT8196_POWER_DOMAIN_EDPTX 0
> +#define MT8196_POWER_DOMAIN_DPTX 1
> +
> /* HFRPSYS MultiMedia Power Control (MMPC) - HW Voter */
> #define MT8196_POWER_DOMAIN_VDE0 0
> #define MT8196_POWER_DOMAIN_VDE1 1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup
2026-07-01 12:19 ` [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup AngeloGioacchino Del Regno
@ 2026-07-06 15:09 ` Matthias Brugger
0 siblings, 0 replies; 9+ messages in thread
From: Matthias Brugger @ 2026-07-06 15:09 UTC (permalink / raw)
To: AngeloGioacchino Del Regno, ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, nfraprado, irving-ch.lin,
macpaul.lin, aford173, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-mediatek, justin.yeh, kernel
On 01/07/2026 14:19, AngeloGioacchino Del Regno wrote:
> In case any probe error occurs (usually, a probe deferral) the
> power domains shall be cleaned up while respecting their child
> to parent relationship, or the system may freeze.
>
> In order to do that without any memory footprint impacts after
> the fact, allocate a temporary array in the probe function and
> use it to store the indices of the added power domains in the
> correct order.
>
> This will be used in the error cleanup path and will be freed
> at the end regardless of the probe status as, when the probing
> succeeds, the genpd API takes care of unregistering all PDs in
> the correct order anyway.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 43 +++++++++++++++++-----
> 1 file changed, 33 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> index e1cfd4223473..db543d4b1813 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> @@ -738,7 +738,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> }
>
> static struct
> -generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
> +generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node,
> + u8 *domains_idx, u8 *num_domains)
> {
> const struct scpsys_domain_data *domain_data;
> const struct scpsys_hwv_domain_data *hwv_domain_data;
> @@ -906,6 +907,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
> else
> pm_genpd_init(&pd->genpd, NULL, false);
>
> + domains_idx[(*num_domains)++] = (u8) id;
> scpsys->domains[id] = &pd->genpd;
>
> return scpsys->pd_data.domains[id];
> @@ -917,7 +919,8 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
> return ERR_PTR(ret);
> }
>
> -static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
> +static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent,
> + u8 *domains_idx, u8 *num_domains)
> {
> struct generic_pm_domain *child_pd, *parent_pd;
> struct device_node *child;
> @@ -940,7 +943,7 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
>
> parent_pd = scpsys->pd_data.domains[id];
>
> - child_pd = scpsys_add_one_domain(scpsys, child);
> + child_pd = scpsys_add_one_domain(scpsys, child, domains_idx, num_domains);
> if (IS_ERR(child_pd)) {
> ret = PTR_ERR(child_pd);
> dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
> @@ -949,7 +952,7 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren
> }
>
> /* recursive call to add all subdomains */
> - ret = scpsys_add_subdomain(scpsys, child);
> + ret = scpsys_add_subdomain(scpsys, child, domains_idx, num_domains);
> if (ret)
> goto err_put_node;
>
> @@ -991,14 +994,16 @@ static void scpsys_remove_one_domain(struct scpsys_domain *pd)
> clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
> }
>
> -static void scpsys_domain_cleanup(struct scpsys *scpsys)
> +static void scpsys_domain_cleanup(struct scpsys *scpsys, u8 *domains_idx, u8 num_probed)
> {
> struct generic_pm_domain *genpd;
> struct scpsys_domain *pd;
> int i;
>
> - for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
> - genpd = scpsys->pd_data.domains[i];
> + for (i = num_probed - 1; i >= 0; i--) {
> + u8 pd_idx = domains_idx[i];
> +
> + genpd = scpsys->pd_data.domains[pd_idx];
> if (genpd) {
> pd = to_scpsys_domain(genpd);
> scpsys_remove_one_domain(pd);
> @@ -1215,6 +1220,8 @@ static int scpsys_probe(struct platform_device *pdev)
> struct device *parent;
> struct scpsys *scpsys;
> int num_domains, ret;
> + u8 num_added_pds = 0;
> + u8 *added_pds_idx;
>
> soc = of_device_get_match_data(&pdev->dev);
> if (!soc) {
> @@ -1228,6 +1235,19 @@ static int scpsys_probe(struct platform_device *pdev)
> if (!scpsys)
> return -ENOMEM;
>
> + /*
> + * Temporarily store the IDs of the power domains that are added as in
> + * case of a probe deferral this can be used to correctly cleanup all
> + * of what was added before.
> + *
> + * Note that this array is used only in the probe function and must be
> + * freed at the end, regardless of whether all of the power domains were
> + * probed successfully or any failure happened.
> + */
> + added_pds_idx = devm_kmalloc_array(dev, num_domains, sizeof(*added_pds_idx), GFP_KERNEL);
> + if (!added_pds_idx)
> + return -ENOMEM;
> +
> scpsys->dev = dev;
> scpsys->soc_data = soc;
>
> @@ -1258,13 +1278,15 @@ static int scpsys_probe(struct platform_device *pdev)
> for_each_available_child_of_node_scoped(np, node) {
> struct generic_pm_domain *domain;
>
> - domain = scpsys_add_one_domain(scpsys, node);
> + domain = scpsys_add_one_domain(scpsys, node,
> + added_pds_idx, &num_added_pds);
> if (IS_ERR(domain)) {
> ret = PTR_ERR(domain);
> goto err_cleanup_domains;
> }
>
> - ret = scpsys_add_subdomain(scpsys, node);
> + ret = scpsys_add_subdomain(scpsys, node,
> + added_pds_idx, &num_added_pds);
> if (ret)
> goto err_cleanup_domains;
> }
> @@ -1280,10 +1302,11 @@ static int scpsys_probe(struct platform_device *pdev)
> goto err_cleanup_domains;
> }
>
> + devm_kfree(dev, added_pds_idx);
> return 0;
>
> err_cleanup_domains:
> - scpsys_domain_cleanup(scpsys);
> + scpsys_domain_cleanup(scpsys, added_pds_idx, num_added_pds);
> return ret;
> }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence
2026-07-01 12:19 ` [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence AngeloGioacchino Del Regno
@ 2026-07-06 15:20 ` Matthias Brugger
0 siblings, 0 replies; 9+ messages in thread
From: Matthias Brugger @ 2026-07-06 15:20 UTC (permalink / raw)
To: AngeloGioacchino Del Regno, ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, nfraprado, irving-ch.lin,
macpaul.lin, aford173, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-mediatek, justin.yeh, kernel
On 01/07/2026 14:19, AngeloGioacchino Del Regno wrote:
> Some new SoCs like MT8196, MT6991, and others, have got one
> additional power controller (usually in the HFRP Multimedia
> block) which needs a simplified power on/off sequence while
> using Direct Control strategy.
>
> Domains using the "simple power sequence" are not backed by
> the RTFF hardware, have no Bus Protection mechanism, lacks
> the ISO, PWR_ON, PWR_ON_2ND bits, and therefore get enabled
> automatically after getting out of reset.
>
> This simple power sequence is then a subset of the full one
> as only needs the enablement of the specific power domain's
> clock input and reset (where, again, after getting out of
> reset, the ISO and PWR_ON bits are automatically internally
> getting flipped) to enable or disable (power on or off).
>
> Moreover, the simple power sequence power domains guarantee
> that they always get enabled/disabled after executing the
> relevant power sequence (on/off) so, differently from the
> others, there is also no need to poll for a PWR_ACK.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 87 ++++++++++++++++++----
> drivers/pmdomain/mediatek/mtk-pm-domains.h | 1 +
> 2 files changed, 72 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> index db543d4b1813..5276adea1d04 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> @@ -549,9 +549,11 @@ static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
> return 0;
> }
>
> -static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
> +static int scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
> {
> struct scpsys *scpsys = pd->scpsys;
> + bool tmp;
> + int ret;
>
> switch (pd->data->rtff_type) {
> case SCPSYS_RTFF_TYPE_GENERIC:
> @@ -583,6 +585,41 @@ static void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
> regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
> regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
> regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
> +
> + /* wait until PWR_ACK = 0 */
> + ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
> + MTK_POLL_TIMEOUT);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int scpsys_simple_pwrseq_on(struct scpsys_domain *pd)
> +{
> + struct scpsys *scpsys = pd->scpsys;
> +
> + /* Enable subsys clock input and trigger power domain reset state */
> + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
> + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
> +
> + /* Wait for the hardware to stabilize */
> + udelay(1);
> +
> + /* Get out of reset: set power on */
> + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
> +
> + return 0;
> +}
> +
> +static int scpsys_simple_pwrseq_off(struct scpsys_domain *pd)
> +{
> + struct scpsys *scpsys = pd->scpsys;
> +
> + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
> + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
> +
> + return 0;
> }
>
> static int scpsys_modem_pwrseq_on(struct scpsys_domain *pd)
> @@ -605,14 +642,24 @@ static int scpsys_modem_pwrseq_on(struct scpsys_domain *pd)
> return 0;
> }
>
> -static void scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
> +static int scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
> {
> struct scpsys *scpsys = pd->scpsys;
> + bool tmp;
> + int ret;
>
> regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
>
> if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SKIP_RESET_B))
> regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
> +
> + /* wait until PWR_ACK = 0 */
> + ret = readx_poll_timeout(scpsys_domain_is_on, pd, 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)
> @@ -635,6 +682,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>
> if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
> ret = scpsys_modem_pwrseq_on(pd);
> + else if (MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
> + ret = scpsys_simple_pwrseq_on(pd);
> else
> ret = scpsys_ctl_pwrseq_on(pd);
>
> @@ -662,9 +711,11 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> goto err_pwr_ack;
> }
>
> - ret = scpsys_sram_enable(pd);
> - if (ret < 0)
> - goto err_disable_subsys_clks;
> + if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ)) {
> + ret = scpsys_sram_enable(pd);
> + if (ret < 0)
> + goto err_disable_subsys_clks;
> + }
>
> ret = scpsys_bus_protect_disable(pd, 0);
> if (ret < 0)
> @@ -682,7 +733,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> err_enable_bus_protect:
> scpsys_bus_protect_enable(pd, 0);
> err_disable_sram:
> - scpsys_sram_disable(pd);
> + if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
> + scpsys_sram_disable(pd);
> err_disable_subsys_clks:
> if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION))
> clk_bulk_disable_unprepare(pd->num_subsys_clks,
> @@ -698,16 +750,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> {
> struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
> struct scpsys *scpsys = pd->scpsys;
> - bool tmp;
> int ret;
>
> ret = scpsys_bus_protect_enable(pd, 0);
> if (ret < 0)
> return ret;
>
> - ret = scpsys_sram_disable(pd);
> - if (ret < 0)
> - return ret;
> + if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ)) {
> + ret = scpsys_sram_disable(pd);
> + if (ret < 0)
> + return ret;
> + }
>
> if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
> regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
> @@ -721,15 +774,11 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>
> if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
> scpsys_modem_pwrseq_off(pd);
> + else if (MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
> + ret = scpsys_simple_pwrseq_off(pd);
> else
> scpsys_ctl_pwrseq_off(pd);
>
> - /* wait until PWR_ACK = 0 */
> - ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
> - MTK_POLL_TIMEOUT);
> - if (ret < 0)
> - return ret;
> -
> clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
>
> scpsys_regulator_disable(pd->supply);
> @@ -1083,6 +1132,12 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
> regmap[2] = NULL;
> }
>
> + /* If no access controllers are needed, don't allocate and don't fail */
> + if (num_regmaps == 0) {
> + scpsys->bus_prot = NULL;
> + return 0;
> + }
> +
> scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps,
> sizeof(*scpsys->bus_prot), GFP_KERNEL);
> if (!scpsys->bus_prot)
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
> index a5dca24cbc2f..092403de66fa 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.h
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
> @@ -17,6 +17,7 @@
> #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_SIMPLE_PWRSEQ BIT(13)
> #define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data ? \
> (_scpd)->data->caps & (_x) : \
> (_scpd)->hwv_data->caps & (_x))
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains
2026-07-01 12:19 ` [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains AngeloGioacchino Del Regno
@ 2026-07-06 15:21 ` Matthias Brugger
0 siblings, 0 replies; 9+ messages in thread
From: Matthias Brugger @ 2026-07-06 15:21 UTC (permalink / raw)
To: AngeloGioacchino Del Regno, ulfh
Cc: robh, krzk+dt, conor+dt, matthias.bgg, nfraprado, irving-ch.lin,
macpaul.lin, aford173, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-mediatek, justin.yeh, kernel
On 01/07/2026 14:19, AngeloGioacchino Del Regno wrote:
> Add support for the power domains provided by the HFRPSYS Power
> Controller of the MT8196 SoC.
> Those control power to the eDP and DP Transmitter IPs.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> drivers/pmdomain/mediatek/mt8196-pm-domains.h | 27 +++++++++++++++++++
> drivers/pmdomain/mediatek/mtk-pm-domains.c | 4 +++
> 2 files changed, 31 insertions(+)
>
> diff --git a/drivers/pmdomain/mediatek/mt8196-pm-domains.h b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
> index 2e4b28720659..d704c9fa9337 100644
> --- a/drivers/pmdomain/mediatek/mt8196-pm-domains.h
> +++ b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
> @@ -602,6 +602,27 @@ static const struct scpsys_hwv_domain_data hfrpsys_hwv_domain_data_mt8196[] = {
> },
> };
>
> +static const struct scpsys_domain_data hfrpsys_domain_data_mt8196[] = {
> + [MT8196_POWER_DOMAIN_EDPTX] = {
> + .name = "edp-tx",
> + .sta_mask = MT8196_PWR_ACK,
> + .sta2nd_mask = MT8196_PWR_ACK_2ND,
> + .ctl_offs = 0x74,
> + .pwr_sta_offs = 0x74,
> + .pwr_sta2nd_offs = 0x74,
> + .caps = MTK_SCPD_SIMPLE_PWRSEQ,
> + },
> + [MT8196_POWER_DOMAIN_DPTX] = {
> + .name = "dp-tx",
> + .sta_mask = MT8196_PWR_ACK,
> + .sta2nd_mask = MT8196_PWR_ACK_2ND,
> + .ctl_offs = 0x78,
> + .pwr_sta_offs = 0x78,
> + .pwr_sta2nd_offs = 0x78,
> + .caps = MTK_SCPD_SIMPLE_PWRSEQ,
> + },
> +};
> +
> static const struct scpsys_soc_data mt8196_scpsys_data = {
> .domains_data = scpsys_domain_data_mt8196,
> .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8196),
> @@ -616,6 +637,12 @@ static const struct scpsys_soc_data mt8196_scpsys_hwv_data = {
> .type = SCPSYS_MTCMOS_TYPE_HW_VOTER,
> };
>
> +static const struct scpsys_soc_data mt8196_hfrpsys_data = {
> + .domains_data = hfrpsys_domain_data_mt8196,
> + .num_domains = ARRAY_SIZE(hfrpsys_domain_data_mt8196),
> + .type = SCPSYS_MTCMOS_TYPE_DIRECT_CTL,
> +};
> +
> static const struct scpsys_soc_data mt8196_hfrpsys_hwv_data = {
> .hwv_domains_data = hfrpsys_hwv_domain_data_mt8196,
> .num_hwv_domains = ARRAY_SIZE(hfrpsys_hwv_domain_data_mt8196),
> diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> index 5276adea1d04..f69cf69ba0f6 100644
> --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
> +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
> @@ -1252,6 +1252,10 @@ static const struct of_device_id scpsys_of_match[] = {
> .compatible = "mediatek,mt8196-power-controller",
> .data = &mt8196_scpsys_data,
> },
> + {
> + .compatible = "mediatek,mt8196-hfrp-power-controller",
> + .data = &mt8196_hfrpsys_data,
> + },
> {
> .compatible = "mediatek,mt8196-hwv-hfrp-power-controller",
> .data = &mt8196_hfrpsys_hwv_data,
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-06 15:21 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 12:19 [PATCH 0/4] pmdomains: Fixes and add support for HFRP Direct AngeloGioacchino Del Regno
2026-07-01 12:19 ` [PATCH 1/4] dt-bindings: power: mediatek: Add support for MT8196 direct HFRP AngeloGioacchino Del Regno
2026-07-06 15:06 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 2/4] pmdomain: mediatek: Respect PD relationships during error cleanup AngeloGioacchino Del Regno
2026-07-06 15:09 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 3/4] pmdomain: mediatek: Add support for Direct CTL simple power sequence AngeloGioacchino Del Regno
2026-07-06 15:20 ` Matthias Brugger
2026-07-01 12:19 ` [PATCH 4/4] pmdomain: mediatek: Add support for MT8196 HFRP DirectCTL domains AngeloGioacchino Del Regno
2026-07-06 15:21 ` Matthias Brugger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox