summaryrefslogtreecommitdiffstats
path: root/drivers/pmdomain/mediatek
diff options
context:
space:
mode:
authorJinke Han <jinkehan@didiglobal.com>2026-09-08 15:37:42 +0800
committerIngo Molnar <mingo@kernel.org>2026-09-17 09:48:42 +0200
commita5f7a5bb3b7f28ba7e4fa246775b29a0e5537255 (patch)
tree73fef824f9a846cf935869d0dbc5070ef6e2f741 /drivers/pmdomain/mediatek
downloadlinux-stable-a5f7a5bb3b7f28ba7e4fa246775b29a0e5537255.tar.gz
linux-stable-a5f7a5bb3b7f28ba7e4fa246775b29a0e5537255.zip
x86/kprobes: Fix crash when probing CS CALL instructionsgrafted
When using eBPF to probe CS CALL instructions within a function, a crash can be triggered. The eBPF tool probes offset 257 of the __hrtimer_run_queues() function: <__hrtimer_run_queues+249>: nopl 0x0(%rax,%rax,1) <__hrtimer_run_queues+254>: mov %r14,%rdi <__hrtimer_run_queues+257>: cs call <__x86_indirect_thunk_r12> <__hrtimer_run_queues+263>: mov %eax,%r12d <__hrtimer_run_queues+266>: xchg %ax,%ax <__hrtimer_run_queues+268>: mov %r13,%rdi Which triggers this crash: BUG: unable to handle page fault for address: 00000000000f41c9 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page PGD 0 P4D 0 Oops: 0002 [#1] SMP NOPTI CPU: 1 PID: 0 Comm: swapper/1 Kdump: loaded Tainted: P RIP: 0010:__hrtimer_run_queues+0x106/0x230 Note that __hrtimer_run_queues+0x106 is __hrtimer_run_queues+262, which is at the 6th byte of the above CS CALL instruction. Since the CS CALL instruction occupies 6 bytes, the exception occurred in the middle of that call instruction. The root cause is that when using eBPF tools to probe in the middle of a function, a kprobe with INT3 is used as the underlying implementation. During single-step emulation of the original CALL instruction, int3_emulate_call() assumes that the probed CALL instruction is 5 bytes long. However, the actual CS-prefixed CALL instruction occupies 6 bytes, so it constructs an incorrect exception return address. When the CPU returns from the kprobe handler, the next instruction to be executed is at the address of the last byte of that CS CALL instruction. Coincidentally, starting from that address, the CPU fetches and decodes a completely different instruction, which ultimately triggers a kernel crash. Fix the issue by using the actual instruction length obtained from the instruction decoder when constructing the exception return address, rather than relying on the hardcoded CALL_INSN_SIZE macro. [ mingo: Refined the changelog ] Fixes: 6256e668b7af ("x86/kprobes: Use int3 instead of debug trap for single-step") Suggested-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Jinke Han <jinkehan@didiglobal.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Acked-by: Yafang Shao <laoar.shao@gmail.com> Acked-by: Borislav Petkov <bp@alien8.de> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://patch.msgid.link/20260908073742.GA10517@didi-ThinkCentre-M920t-N000
Diffstat (limited to 'drivers/pmdomain/mediatek')
-rw-r--r--drivers/pmdomain/mediatek/Kconfig59
-rw-r--r--drivers/pmdomain/mediatek/Makefile12
-rw-r--r--drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c138
-rw-r--r--drivers/pmdomain/mediatek/mt6735-pm-domains.h96
-rw-r--r--drivers/pmdomain/mediatek/mt6795-pm-domains.h117
-rw-r--r--drivers/pmdomain/mediatek/mt6858-pm-domains.h466
-rw-r--r--drivers/pmdomain/mediatek/mt6893-pm-domains.h585
-rw-r--r--drivers/pmdomain/mediatek/mt8167-pm-domains.h110
-rw-r--r--drivers/pmdomain/mediatek/mt8173-pm-domains.h128
-rw-r--r--drivers/pmdomain/mediatek/mt8183-pm-domains.h303
-rw-r--r--drivers/pmdomain/mediatek/mt8186-pm-domains.h371
-rw-r--r--drivers/pmdomain/mediatek/mt8188-pm-domains.h696
-rw-r--r--drivers/pmdomain/mediatek/mt8189-pm-domains.h485
-rw-r--r--drivers/pmdomain/mediatek/mt8192-pm-domains.h390
-rw-r--r--drivers/pmdomain/mediatek/mt8195-pm-domains.h672
-rw-r--r--drivers/pmdomain/mediatek/mt8196-pm-domains.h652
-rw-r--r--drivers/pmdomain/mediatek/mt8365-pm-domains.h201
-rw-r--r--drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c1084
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c1461
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h221
-rw-r--r--drivers/pmdomain/mediatek/mtk-scpsys.c1154
21 files changed, 9401 insertions, 0 deletions
diff --git a/drivers/pmdomain/mediatek/Kconfig b/drivers/pmdomain/mediatek/Kconfig
new file mode 100644
index 000000000..a2eb704a7
--- /dev/null
+++ b/drivers/pmdomain/mediatek/Kconfig
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menu "MediaTek PM Domains"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+
+config MTK_SCPSYS
+ bool "MediaTek SCPSYS Support"
+ default ARCH_MEDIATEK
+ depends on OF
+ select REGMAP
+ select MTK_INFRACFG
+ select PM_GENERIC_DOMAINS if PM
+ help
+ Say yes here to add support for the MediaTek SCPSYS power domain
+ driver.
+
+config MTK_SCPSYS_PM_DOMAINS
+ bool "MediaTek SCPSYS generic power domain"
+ default ARCH_MEDIATEK
+ depends on PM
+ select PM_GENERIC_DOMAINS
+ select REGMAP
+ help
+ Say y here to enable power domain support.
+ In order to meet high performance and low power requirements, the System
+ Control Processor System (SCPSYS) has several power management related
+ tasks in the system.
+
+config MTK_MFG_PM_DOMAIN
+ bool "MediaTek MFlexGraphics power domain"
+ default ARCH_MEDIATEK
+ depends on PM
+ depends on OF
+ depends on COMMON_CLK
+ select MAILBOX
+ select PM_GENERIC_DOMAINS
+ imply MTK_GPUEB_MBOX
+ help
+ Say y or m here to enable the power domains driver for MediaTek
+ MFlexGraphics. This driver allows for power and frequency control of
+ GPUs on MediaTek SoCs such as the MT8196 or MT6991.
+
+ This driver is required for the Mali GPU to work at all on MT8196 and
+ MT6991.
+
+endmenu
+
+config AIROHA_CPU_PM_DOMAIN
+ tristate "Airoha CPU power domain"
+ default ARCH_AIROHA
+ depends on ARCH_AIROHA || COMPILE_TEST
+ depends on HAVE_ARM_SMCCC
+ depends on PM
+ select PM_GENERIC_DOMAINS
+ help
+ Say y here to enable CPU power domain support for Airoha SoC.
+
+ CPU frequency and power is controlled by ATF with SMC command to
+ set performance states.
diff --git a/drivers/pmdomain/mediatek/Makefile b/drivers/pmdomain/mediatek/Makefile
new file mode 100644
index 000000000..b424f1ed8
--- /dev/null
+++ b/drivers/pmdomain/mediatek/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MTK_MFG_PM_DOMAIN) += mtk-mfg-pmdomain.o
+obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
+obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
+obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN) += airoha-cpu-pmdomain.o
+
+ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
+# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
+# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
+# hooks are inserted via the -pg switch.
+CFLAGS_REMOVE_airoha-cpu-pmdomain.o += $(CC_FLAGS_FTRACE)
+endif
diff --git a/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
new file mode 100644
index 000000000..5efd7a38f
--- /dev/null
+++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+#define AIROHA_SIP_AVS_HANDLE 0x82000301
+#define AIROHA_AVS_OP_BASE 0xddddddd0
+#define AIROHA_AVS_OP_MASK GENMASK(1, 0)
+#define AIROHA_AVS_OP_FREQ_DYN_ADJ (AIROHA_AVS_OP_BASE | \
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
+#define AIROHA_AVS_OP_GET_FREQ (AIROHA_AVS_OP_BASE | \
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
+
+struct airoha_cpu_pmdomain_priv {
+ struct clk_hw hw;
+ struct generic_pm_domain pd;
+};
+
+static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
+ 0, 0, 0, 0, 0, 0, &res);
+
+ /* SMCCC returns freq in MHz */
+ return (int)(res.a0 * 1000 * 1000);
+}
+
+/* Airoha CPU clk SMCC is always enabled */
+static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
+{
+ return true;
+}
+
+static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
+ .recalc_rate = airoha_cpu_pmdomain_clk_get,
+ .is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
+ .determine_rate = clk_determine_rate_noop,
+};
+
+static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
+ unsigned int state)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
+ 0, state, 0, 0, 0, 0, &res);
+
+ /* SMC signal correct apply by unsetting BIT 0 */
+ return res.a0 & BIT(0) ? -EINVAL : 0;
+}
+
+static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
+{
+ struct airoha_cpu_pmdomain_priv *priv;
+ struct device *dev = &pdev->dev;
+ const struct clk_init_data init = {
+ .name = "cpu",
+ .ops = &airoha_cpu_pmdomain_clk_ops,
+ /* Clock with no set_rate, can't cache */
+ .flags = CLK_GET_RATE_NOCACHE,
+ };
+ struct generic_pm_domain *pd;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ /* Init and register a get-only clk for Cpufreq */
+ priv->hw.init = &init;
+ ret = devm_clk_hw_register(dev, &priv->hw);
+ if (ret)
+ return ret;
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &priv->hw);
+ if (ret)
+ return ret;
+
+ /* Init and register a PD for CPU */
+ pd = &priv->pd;
+ pd->name = "cpu_pd";
+ pd->flags = GENPD_FLAG_ALWAYS_ON;
+ pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
+
+ ret = pm_genpd_init(pd, NULL, false);
+ if (ret)
+ return ret;
+
+ ret = of_genpd_add_provider_simple(dev->of_node, pd);
+ if (ret)
+ goto err_add_provider;
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+err_add_provider:
+ pm_genpd_remove(pd);
+
+ return ret;
+}
+
+static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
+{
+ struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
+
+ of_genpd_del_provider(pdev->dev.of_node);
+ pm_genpd_remove(&priv->pd);
+}
+
+static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
+ { .compatible = "airoha,en7581-cpufreq" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
+
+static struct platform_driver airoha_cpu_pmdomain_driver = {
+ .probe = airoha_cpu_pmdomain_probe,
+ .remove = airoha_cpu_pmdomain_remove,
+ .driver = {
+ .name = "airoha-cpu-pmdomain",
+ .of_match_table = airoha_cpu_pmdomain_of_match,
+ },
+};
+module_platform_driver(airoha_cpu_pmdomain_driver);
+
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/mediatek/mt6735-pm-domains.h b/drivers/pmdomain/mediatek/mt6735-pm-domains.h
new file mode 100644
index 000000000..71896be68
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt6735-pm-domains.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT6735_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT6735_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt6735-power-controller.h>
+
+/*
+ * MT6735 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt6735[] = {
+ [MT6735_POWER_DOMAIN_MD1] = {
+ .name = "md1",
+ .sta_mask = PWR_STATUS_MD1,
+ .ctl_offs = SPM_MD1_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT6735_TOP_AXI_PROT_EN_MD1),
+ },
+ },
+ [MT6735_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = SPM_CONN_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT6735_TOP_AXI_PROT_EN_CONN),
+ },
+ },
+ [MT6735_POWER_DOMAIN_DIS] = {
+ .name = "dis",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0),
+ },
+ },
+ [MT6735_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S),
+ },
+ },
+ [MT6735_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT6735_POWER_DOMAIN_VDE] = {
+ .name = "vde",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6735_POWER_DOMAIN_VEN] = {
+ .name = "ven",
+ .sta_mask = BIT(8),
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+};
+
+static const struct scpsys_soc_data mt6735_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt6735,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6735),
+};
+
+#endif /* __SOC_MEDIATEK_MT6735_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt6795-pm-domains.h b/drivers/pmdomain/mediatek/mt6795-pm-domains.h
new file mode 100644
index 000000000..dc8e9f887
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt6795-pm-domains.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt6795-power.h>
+
+/*
+ * MT6795 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt6795[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
+ [MT6795_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6795_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT6795_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT6795_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
+ MT8173_TOP_AXI_PROT_EN_MM_M1),
+ },
+ },
+ [MT6795_POWER_DOMAIN_MJC] = {
+ .name = "mjc",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x298,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT6795_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT6795_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = PWR_STATUS_MFG_ASYNC,
+ .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = 0,
+ },
+ [MT6795_POWER_DOMAIN_MFG_2D] = {
+ .name = "mfg_2d",
+ .sta_mask = PWR_STATUS_MFG_2D,
+ .ctl_offs = SPM_MFG_2D_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT6795_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(13, 8),
+ .sram_pdn_ack_bits = GENMASK(21, 16),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
+ MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+ MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+ MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
+ },
+ },
+};
+
+static const struct scpsys_soc_data mt6795_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt6795,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt6795,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt6795),
+};
+
+#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt6858-pm-domains.h b/drivers/pmdomain/mediatek/mt6858-pm-domains.h
new file mode 100644
index 000000000..177b2e86a
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt6858-pm-domains.h
@@ -0,0 +1,466 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * KY Liu <ky.liu@mediatek.com>
+ * Copyright (c) 2026 Jolla Mobile Ltd
+ * Nikolai Burov <nikolai.burov@jolla.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT6858_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT6858_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt6858-power.h>
+
+/* TOP_AXI registers */
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET 0x0c14
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR 0x0c18
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY 0x0c1c
+
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_DIS0 (BIT(0) | BIT(1) | BIT(18))
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_ISP_IPE BIT(2)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_ISP_IMG1 BIT(3)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_VEN0 BIT(12)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_VDE0 BIT(20)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CAM_MAIN (BIT(30) | BIT(31))
+
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET 0x0c24
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR 0x0c28
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY 0x0c2c
+
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_ISP_IMG1 BIT(7)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_ISP_IPE BIT(8)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CAM_MAIN (BIT(9) | BIT(10))
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_VEN0 BIT(12)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_VDE0 BIT(13)
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_MM_INFRA (GENMASK(3, 1) | BIT(6))
+#define MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_MM_INFRA_2ND (BIT(0) | BIT(5) | GENMASK(15, 7))
+
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_SET 0x0c44
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_CLR 0x0c48
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_RDY 0x0c4c
+
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_CONN BIT(8)
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_MM_INFRA BIT(16)
+
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_SET 0x0c54
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_CLR 0x0c58
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_RDY 0x0c5c
+
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_MM_INFRA BIT(11)
+#define MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_CONN BIT(12)
+
+#define MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_SET 0x0c64
+#define MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_CLR 0x0c68
+#define MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_RDY 0x0c6c
+
+#define MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_MM_INFRA (BIT(20) | BIT(21))
+
+#define MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_SET 0x0c84
+#define MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_CLR 0x0c88
+#define MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_RDY 0x0c8c
+
+#define MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_AUDIO BIT(6)
+#define MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_SSUSB BIT(7)
+
+#define MT6858_TOP_AXI_PROT_EN_MCU_STA_0_SET 0x0c94
+#define MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CLR 0x0c98
+#define MT6858_TOP_AXI_PROT_EN_MCU_STA_0_RDY 0x0c9c
+
+#define MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CONN BIT(1)
+#define MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CONN_2ND BIT(0)
+
+/* {IMG,IPE,CAM}_SUBx registers */
+#define MT6858_SUBx_PROT_EN_SET 0x03c4
+#define MT6858_SUBx_PROT_EN_CLR 0x03c8
+#define MT6858_SUBx_PROT_EN_STA 0x03cc
+
+#define MT6858_IMG_SUB0_PROT_EN_SMI_ISP_IMG1 (BIT(0) | BIT(1))
+
+#define MT6858_IPE_SUB0_PROT_EN_SMI_ISP_IPE (BIT(0) | BIT(1))
+
+#define MT6858_CAM_SUB0_PROT_EN_SMI_CAM_MAIN BIT(0)
+#define MT6858_CAM_SUB0_PROT_EN_SMI_CAM_SUBB BIT(1)
+
+#define MT6858_CAM_SUB1_PROT_EN_SMI_CAM_MAIN BIT(0)
+#define MT6858_CAM_SUB1_PROT_EN_SMI_CAM_SUBA BIT(1)
+
+/* VLP_AXI registers */
+#define MT6858_VLP_AXI_PROT_EN_SET 0x0214
+#define MT6858_VLP_AXI_PROT_EN_CLR 0x0218
+#define MT6858_VLP_AXI_PROT_EN_STA 0x021c
+
+#define MT6858_VLP_AXI_PROT_EN_MM_PROC BIT(8)
+#define MT6858_VLP_AXI_PROT_EN_MM_PROC_2ND (BIT(9) | BIT(10))
+
+/* PWR_CON registers */
+#define MT6858_PWR_ACK BIT(30)
+#define MT6858_PWR_ACK_2ND BIT(31)
+
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt6858[] = {
+ BUS_PROT_BLOCK_INFRA,
+ BUS_PROT_BLOCK_IMG_SUB0,
+ BUS_PROT_BLOCK_CAM_SUB1,
+ BUS_PROT_BLOCK_CAM_SUB0,
+ BUS_PROT_BLOCK_IPE_SUB0,
+ BUS_PROT_BLOCK_VLP,
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt6858[] = {
+ [MT6858_POWER_DOMAIN_MD] = {
+ .name = "md",
+ /*
+ * Note: the PWR_ACK_2ND bit is not used for the modem domain.
+ * Skip it and fall back to checking the 1st bit twice.
+ */
+ .sta_mask = MT6858_PWR_ACK,
+ .ctl_offs = 0xe00,
+ .pwr_sta_offs = 0xe00,
+ .pwr_sta2nd_offs = 0xe00,
+ .ext_buck_iso_offs = 0xf20,
+ .ext_buck_iso_mask = GENMASK(1, 0),
+ .caps = MTK_SCPD_MODEM_SECURE_PWRSEQ | MTK_SCPD_EXT_BUCK_ISO |
+ MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe04,
+ .pwr_sta_offs = 0xe04,
+ .pwr_sta2nd_offs = 0xe04,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CONN,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_CONN,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CONN_2ND,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MCU_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_CONN,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe18,
+ .pwr_sta_offs = 0xe18,
+ .pwr_sta2nd_offs = 0xe18,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_AUDIO,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_RDY),
+ },
+ },
+ [MT6858_POWER_DOMAIN_ISP_IMG1] = {
+ .name = "isp-img1",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe28,
+ .pwr_sta_offs = 0xe28,
+ .pwr_sta2nd_offs = 0xe28,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_ISP_IMG1,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_ISP_IMG1,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(IMG_SUB0,
+ MT6858_IMG_SUB0_PROT_EN_SMI_ISP_IMG1,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_ISP_IMG2] = {
+ .name = "isp-img2",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe2c,
+ .pwr_sta_offs = 0xe2c,
+ .pwr_sta2nd_offs = 0xe2c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_ISP_IPE] = {
+ .name = "isp-ipe",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe30,
+ .pwr_sta_offs = 0xe30,
+ .pwr_sta2nd_offs = 0xe30,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_ISP_IPE,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_ISP_IPE,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(IPE_SUB0,
+ MT6858_IPE_SUB0_PROT_EN_SMI_ISP_IPE,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_VDE0] = {
+ .name = "vde0",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe34,
+ .pwr_sta_offs = 0xe34,
+ .pwr_sta2nd_offs = 0xe34,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_VDE0,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_VDE0,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ },
+ [MT6858_POWER_DOMAIN_VEN0] = {
+ .name = "ven0",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe3c,
+ .pwr_sta_offs = 0xe3c,
+ .pwr_sta2nd_offs = 0xe3c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_VEN0,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_VEN0,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ },
+ [MT6858_POWER_DOMAIN_CAM_MAIN] = {
+ .name = "cam-main",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe44,
+ .pwr_sta_offs = 0xe44,
+ .pwr_sta2nd_offs = 0xe44,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CAM_MAIN,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CAM_MAIN,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(CAM_SUB0,
+ MT6858_CAM_SUB0_PROT_EN_SMI_CAM_MAIN,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ BUS_PROT_WR_IGN(CAM_SUB1,
+ MT6858_CAM_SUB1_PROT_EN_SMI_CAM_MAIN,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_CAM_SUBA] = {
+ .name = "cam-suba",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe4c,
+ .pwr_sta_offs = 0xe4c,
+ .pwr_sta2nd_offs = 0xe4c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(CAM_SUB1,
+ MT6858_CAM_SUB1_PROT_EN_SMI_CAM_SUBA,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_CAM_SUBB] = {
+ .name = "cam-subb",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe50,
+ .pwr_sta_offs = 0xe50,
+ .pwr_sta2nd_offs = 0xe50,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(CAM_SUB0,
+ MT6858_CAM_SUB0_PROT_EN_SMI_CAM_SUBB,
+ MT6858_SUBx_PROT_EN_SET,
+ MT6858_SUBx_PROT_EN_CLR,
+ MT6858_SUBx_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_DIS0] = {
+ .name = "dis0",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe6c,
+ .pwr_sta_offs = 0xe6c,
+ .pwr_sta2nd_offs = 0xe6c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_DIS0,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_0_RDY),
+ },
+ },
+ [MT6858_POWER_DOMAIN_MM_INFRA] = {
+ .name = "mm-infra",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe74,
+ .pwr_sta_offs = 0xe74,
+ .pwr_sta2nd_offs = 0xe74,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_MM_INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_MM_INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_MM_INFRA_2ND,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_SET,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_CLR,
+ MT6858_TOP_AXI_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_MM_INFRA,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_INFRASYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_MM_INFRA,
+ MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_EMISYS_STA_0_RDY),
+ },
+ },
+ [MT6858_POWER_DOMAIN_MM_PROC_DORMANT] = {
+ .name = "mm-proc-dormant",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe78,
+ .pwr_sta_offs = 0xe78,
+ .pwr_sta2nd_offs = 0xe78,
+ .sram_pdn_bits = BIT(9),
+ .sram_pdn_ack_bits = BIT(13),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(VLP,
+ MT6858_VLP_AXI_PROT_EN_MM_PROC,
+ MT6858_VLP_AXI_PROT_EN_SET,
+ MT6858_VLP_AXI_PROT_EN_CLR,
+ MT6858_VLP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(VLP,
+ MT6858_VLP_AXI_PROT_EN_MM_PROC_2ND,
+ MT6858_VLP_AXI_PROT_EN_SET,
+ MT6858_VLP_AXI_PROT_EN_CLR,
+ MT6858_VLP_AXI_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_SRAM_PDN_INVERTED,
+ },
+ [MT6858_POWER_DOMAIN_CSI_RX] = {
+ .name = "csi-rx",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xe98,
+ .pwr_sta_offs = 0xe98,
+ .pwr_sta2nd_offs = 0xe98,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6858_POWER_DOMAIN_SSUSB] = {
+ .name = "ssusb",
+ .sta_mask = MT6858_PWR_ACK,
+ .sta2nd_mask = MT6858_PWR_ACK_2ND,
+ .ctl_offs = 0xea4,
+ .pwr_sta_offs = 0xea4,
+ .pwr_sta2nd_offs = 0xea4,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_SSUSB,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_SET,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_CLR,
+ MT6858_TOP_AXI_PROT_EN_PERISYS_STA_0_RDY),
+ },
+ },
+};
+
+static const struct scpsys_soc_data mt6858_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt6858,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6858),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt6858,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt6858),
+ .type = SCPSYS_MTCMOS_TYPE_DIRECT_CTL,
+};
+
+#endif /* __SOC_MEDIATEK_MT6858_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt6893-pm-domains.h b/drivers/pmdomain/mediatek/mt6893-pm-domains.h
new file mode 100644
index 000000000..c9e2aa511
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt6893-pm-domains.h
@@ -0,0 +1,585 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Collabora Ltd
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#ifndef __PMDOMAIN_MEDIATEK_MT6893_PM_DOMAINS_H
+#define __PMDOMAIN_MEDIATEK_MT6893_PM_DOMAINS_H
+
+#include <linux/soc/mediatek/infracfg.h>
+#include <dt-bindings/power/mediatek,mt6893-power.h>
+#include "mtk-pm-domains.h"
+
+#define MT6893_TOP_AXI_PROT_EN_MCU_STA1 0x2e4
+#define MT6893_TOP_AXI_PROT_EN_MCU_SET 0x2c4
+#define MT6893_TOP_AXI_PROT_EN_MCU_CLR 0x2c8
+#define MT6893_TOP_AXI_PROT_EN_VDNR_1_SET 0xba4
+#define MT6893_TOP_AXI_PROT_EN_VDNR_1_CLR 0xba8
+#define MT6893_TOP_AXI_PROT_EN_VDNR_1_STA1 0xbb0
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET 0xbb8
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR 0xbbc
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1 0xbc4
+
+#define MT6893_TOP_AXI_PROT_EN_1_MFG1_STEP1 GENMASK(21, 19)
+#define MT6893_TOP_AXI_PROT_EN_2_MFG1_STEP2 GENMASK(6, 5)
+#define MT6893_TOP_AXI_PROT_EN_MFG1_STEP3 GENMASK(22, 21)
+#define MT6893_TOP_AXI_PROT_EN_2_MFG1_STEP4 BIT(7)
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP5 GENMASK(19, 17)
+#define MT6893_TOP_AXI_PROT_EN_MM_VDEC0_STEP1 BIT(24)
+#define MT6893_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2 BIT(25)
+#define MT6893_TOP_AXI_PROT_EN_MM_VDEC1_STEP1 BIT(6)
+#define MT6893_TOP_AXI_PROT_EN_MM_VDEC1_STEP2 BIT(7)
+#define MT6893_TOP_AXI_PROT_EN_MM_VENC0_STEP1 BIT(26)
+#define MT6893_TOP_AXI_PROT_EN_MM_2_VENC0_STEP2 BIT(0)
+#define MT6893_TOP_AXI_PROT_EN_MM_VENC0_STEP3 BIT(27)
+#define MT6893_TOP_AXI_PROT_EN_MM_2_VENC0_STEP4 BIT(1)
+#define MT6893_TOP_AXI_PROT_EN_MM_VENC1_STEP1 GENMASK(30, 28)
+#define MT6893_TOP_AXI_PROT_EN_MM_VENC1_STEP2 GENMASK(31, 29)
+#define MT6893_TOP_AXI_PROT_EN_MDP_STEP1 BIT(10)
+#define MT6893_TOP_AXI_PROT_EN_MM_MDP_STEP2 (BIT(2) | BIT(4) | BIT(6) | \
+ BIT(8) | BIT(18) | BIT(22) | \
+ BIT(28) | BIT(30))
+#define MT6893_TOP_AXI_PROT_EN_MM_2_MDP_STEP3 (BIT(0) | BIT(2) | BIT(4) | \
+ BIT(6) | BIT(8))
+#define MT6893_TOP_AXI_PROT_EN_MDP_STEP4 BIT(23)
+#define MT6893_TOP_AXI_PROT_EN_MM_MDP_STEP5 (BIT(3) | BIT(5) | BIT(7) | \
+ BIT(9) | BIT(19) | BIT(23) | \
+ BIT(29) | BIT(31))
+#define MT6893_TOP_AXI_PROT_EN_MM_2_MDP_STEP6 (BIT(1) | BIT(7) | BIT(9) | BIT(11))
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MDP_STEP7 BIT(20)
+#define MT6893_TOP_AXI_PROT_EN_MM_DISP_STEP1 (BIT(0) | BIT(6) | BIT(8) | \
+ BIT(10) | BIT(12) | BIT(14) | \
+ BIT(16) | BIT(20) | BIT(24) | \
+ BIT(26))
+#define MT6893_TOP_AXI_PROT_EN_DISP_STEP2 BIT(6)
+#define MT6893_TOP_AXI_PROT_EN_MM_DISP_STEP3 (BIT(1) | BIT(7) | BIT(9) | \
+ BIT(15) | BIT(17) | BIT(21) | \
+ BIT(25) | BIT(27))
+#define MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_DISP_STEP4 BIT(21)
+#define MT6893_TOP_AXI_PROT_EN_2_ADSP BIT(3)
+#define MT6893_TOP_AXI_PROT_EN_2_CAM_STEP1 BIT(1)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_STEP2 (BIT(0) | BIT(2) | BIT(4))
+#define MT6893_TOP_AXI_PROT_EN_1_CAM_STEP3 BIT(22)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_STEP4 (BIT(1) | BIT(3) | BIT(5))
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWA_STEP1 BIT(18)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWA_STEP2 BIT(19)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWB_STEP1 BIT(20)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWB_STEP2 BIT(21)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWC_STEP1 BIT(22)
+#define MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWC_STEP2 BIT(23)
+
+/*
+ * MT6893 Power Domain (MTCMOS) support
+ *
+ * The register layout for this IP is very similar to MT8192 so where possible
+ * the same definitions are reused to avoid duplication.
+ * Where the bus protection bits are also the same, the entire set is reused.
+ */
+static const struct scpsys_domain_data scpsys_domain_data_mt6893[] = {
+ [MT6893_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x304,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_CONN,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_CONN_2ND,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_1_CONN,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x308,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT6893_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x30c,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_1_MFG1_STEP1,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_2_MFG1_STEP2,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MFG1_STEP3,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_2_MFG1_STEP4,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP5,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT6893_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x310,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x314,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MFG4] = {
+ .name = "mfg4",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x318,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MFG5] = {
+ .name = "mfg5",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x31c,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MFG6] = {
+ .name = "mfg6",
+ .sta_mask = BIT(8),
+ .ctl_offs = 0x320,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x330,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_ISP,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_ISP2] = {
+ .name = "isp2",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x334,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_ISP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_IPE] = {
+ .name = "ipe",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x338,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_IPE,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_VDEC0] = {
+ .name = "vdec0",
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x33c,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VDEC0_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_VDEC1] = {
+ .name = "vdec1",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x340,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VDEC1_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VDEC1_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_VENC0] = {
+ .name = "venc0",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x344,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VENC0_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_2_VENC0_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VENC0_STEP3,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_2_VENC0_STEP4,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_VENC1] = {
+ .name = "venc1",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x348,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VENC1_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_VENC1_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT6893_POWER_DOMAIN_MDP] = {
+ .name = "mdp",
+ .sta_mask = BIT(19),
+ .ctl_offs = 0x34c,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MDP_STEP1,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_MDP_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_2_MDP_STEP3,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MDP_STEP4,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_MDP_STEP5,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_2_MDP_STEP6,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MDP_STEP7,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_DISP] = {
+ .name = "disp",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x350,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_DISP_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_DISP_STEP2,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_DISP_STEP3,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_DISP_STEP4,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT6893_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0x354,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_2_AUDIO,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_ADSP] = {
+ .name = "audio",
+ .sta_mask = BIT(22),
+ .ctl_offs = 0x358,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(9),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_2_ADSP,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x35c,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_2_CAM_STEP1,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_1_CAM_STEP3,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_STEP4,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_CAM_RAWA] = {
+ .name = "cam_rawa",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x360,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWA_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWA_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_CAM_RAWB] = {
+ .name = "cam_rawb",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x364,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWB_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWB_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_CAM_RAWC] = {
+ .name = "cam_rawc",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x368,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWC_STEP1,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT6893_TOP_AXI_PROT_EN_MM_CAM_RAWC_STEP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT6893_POWER_DOMAIN_DP_TX] = {
+ .name = "dp_tx",
+ .sta_mask = BIT(27),
+ .ctl_offs = 0x3ac,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+};
+
+static const struct scpsys_soc_data mt6893_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt6893,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6893),
+};
+
+#endif /* __PMDOMAIN_MEDIATEK_MT6893_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8167-pm-domains.h b/drivers/pmdomain/mediatek/mt8167-pm-domains.h
new file mode 100644
index 000000000..f6ee48a71
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8167-pm-domains.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8167-power.h>
+
+#define MT8167_PWR_STATUS_MFG_2D BIT(24)
+#define MT8167_PWR_STATUS_MFG_ASYNC BIT(25)
+
+/*
+ * MT8167 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8167[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
+ [MT8167_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI |
+ MT8167_TOP_AXI_PROT_EN_MCU_MM),
+ },
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8167_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8167_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8167_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC,
+ .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG |
+ MT8167_TOP_AXI_PROT_EN_MFG_EMI),
+ },
+ },
+ [MT8167_POWER_DOMAIN_MFG_2D] = {
+ .name = "mfg_2d",
+ .sta_mask = MT8167_PWR_STATUS_MFG_2D,
+ .ctl_offs = SPM_MFG_2D_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8167_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8167_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = SPM_CONN_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = 0,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI |
+ MT8167_TOP_AXI_PROT_EN_CONN_MCU |
+ MT8167_TOP_AXI_PROT_EN_MCU_CONN),
+ },
+ },
+};
+
+static const struct scpsys_soc_data mt8167_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8167,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8167,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8167),
+};
+
+#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */
+
diff --git a/drivers/pmdomain/mediatek/mt8173-pm-domains.h b/drivers/pmdomain/mediatek/mt8173-pm-domains.h
new file mode 100644
index 000000000..561a644b5
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8173-pm-domains.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8173-power.h>
+
+/*
+ * MT8173 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8173[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
+ [MT8173_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8173_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8173_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT8173_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
+ MT8173_TOP_AXI_PROT_EN_MM_M1),
+ },
+ },
+ [MT8173_POWER_DOMAIN_VENC_LT] = {
+ .name = "venc_lt",
+ .sta_mask = PWR_STATUS_VENC_LT,
+ .ctl_offs = SPM_VEN2_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8173_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8173_POWER_DOMAIN_USB] = {
+ .name = "usb",
+ .sta_mask = PWR_STATUS_USB,
+ .ctl_offs = SPM_USB_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = PWR_STATUS_MFG_ASYNC,
+ .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = 0,
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8173_POWER_DOMAIN_MFG_2D] = {
+ .name = "mfg_2d",
+ .sta_mask = PWR_STATUS_MFG_2D,
+ .ctl_offs = SPM_MFG_2D_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ },
+ [MT8173_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = GENMASK(13, 8),
+ .sram_pdn_ack_bits = GENMASK(21, 16),
+ .bp_cfg = {
+ BUS_PROT_INFRA_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
+ MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+ MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+ MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
+ },
+ },
+};
+
+static const struct scpsys_soc_data mt8173_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8173,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8173,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8173),
+};
+
+#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8183-pm-domains.h b/drivers/pmdomain/mediatek/mt8183-pm-domains.h
new file mode 100644
index 000000000..5e33b8628
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8183-pm-domains.h
@@ -0,0 +1,303 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8183-power.h>
+
+/*
+ * MT8183 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8183[] = {
+ BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
+ [MT8183_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = 0x0314,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ },
+ [MT8183_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = 0x032c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_CONN,
+ MT8183_TOP_AXI_PROT_EN_SET,
+ MT8183_TOP_AXI_PROT_EN_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1),
+ },
+ },
+ [MT8183_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = PWR_STATUS_MFG_ASYNC,
+ .ctl_offs = 0x0334,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .caps = MTK_SCPD_DOMAIN_SUPPLY | MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8183_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = 0x0338,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_DOMAIN_SUPPLY | MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8183_POWER_DOMAIN_MFG_CORE0] = {
+ .name = "mfg_core0",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x034c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8183_POWER_DOMAIN_MFG_CORE1] = {
+ .name = "mfg_core1",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x0310,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8183_POWER_DOMAIN_MFG_2D] = {
+ .name = "mfg_2d",
+ .sta_mask = PWR_STATUS_MFG_2D,
+ .ctl_offs = 0x0348,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_1_MFG,
+ MT8183_TOP_AXI_PROT_EN_1_SET,
+ MT8183_TOP_AXI_PROT_EN_1_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1_1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MFG,
+ MT8183_TOP_AXI_PROT_EN_SET,
+ MT8183_TOP_AXI_PROT_EN_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1),
+ },
+ },
+ [MT8183_POWER_DOMAIN_DISP] = {
+ .name = "disp",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = 0x030c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_1_DISP,
+ MT8183_TOP_AXI_PROT_EN_1_SET,
+ MT8183_TOP_AXI_PROT_EN_1_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1_1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_DISP,
+ MT8183_TOP_AXI_PROT_EN_SET,
+ MT8183_TOP_AXI_PROT_EN_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_DISP,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x0344,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(9, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_CAM,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_CAM,
+ MT8183_TOP_AXI_PROT_EN_SET,
+ MT8183_TOP_AXI_PROT_EN_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_CAM,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = 0x0308,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(9, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_ISP,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_ISP,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x0300,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_VDEC,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = 0x0304,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_VENC,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_VPU_TOP] = {
+ .name = "vpu_top",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x0324,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_VPU_TOP,
+ MT8183_TOP_AXI_PROT_EN_SET,
+ MT8183_TOP_AXI_PROT_EN_CLR,
+ MT8183_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND,
+ MT8183_TOP_AXI_PROT_EN_MM_SET,
+ MT8183_TOP_AXI_PROT_EN_MM_CLR,
+ MT8183_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(SMI,
+ MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP,
+ MT8183_SMI_COMMON_CLAMP_EN_SET,
+ MT8183_SMI_COMMON_CLAMP_EN_CLR,
+ MT8183_SMI_COMMON_CLAMP_EN),
+ },
+ },
+ [MT8183_POWER_DOMAIN_VPU_CORE0] = {
+ .name = "vpu_core0",
+ .sta_mask = BIT(27),
+ .ctl_offs = 0x33c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0,
+ MT8183_TOP_AXI_PROT_EN_MCU_SET,
+ MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+ MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND,
+ MT8183_TOP_AXI_PROT_EN_MCU_SET,
+ MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+ MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+ },
+ .caps = MTK_SCPD_SRAM_ISO,
+ },
+ [MT8183_POWER_DOMAIN_VPU_CORE1] = {
+ .name = "vpu_core1",
+ .sta_mask = BIT(28),
+ .ctl_offs = 0x0340,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1,
+ MT8183_TOP_AXI_PROT_EN_MCU_SET,
+ MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+ MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND,
+ MT8183_TOP_AXI_PROT_EN_MCU_SET,
+ MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+ MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+ },
+ .caps = MTK_SCPD_SRAM_ISO,
+ },
+};
+
+static const struct scpsys_soc_data mt8183_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8183,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8183,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8183),
+};
+
+#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8186-pm-domains.h b/drivers/pmdomain/mediatek/mt8186-pm-domains.h
new file mode 100644
index 000000000..00b9861af
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8186-pm-domains.h
@@ -0,0 +1,371 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8186-power.h>
+
+/*
+ * MT8186 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8186[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
+ [MT8186_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x308,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8186_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x30c,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_MFG1_STEP2,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_MFG1_STEP3,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8186_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x310,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x314,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_SSUSB] = {
+ .name = "ssusb",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x9F0,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8186_POWER_DOMAIN_SSUSB_P1] = {
+ .name = "ssusb_p1",
+ .sta_mask = BIT(19),
+ .ctl_offs = 0x9F4,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8186_POWER_DOMAIN_DIS] = {
+ .name = "dis",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0x354,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_DIS_STEP2,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ },
+ },
+ [MT8186_POWER_DOMAIN_IMG] = {
+ .name = "img",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x334,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_IMG2] = {
+ .name = "img2",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x338,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_IPE] = {
+ .name = "ipe",
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x33C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x35C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_CAM_RAWA] = {
+ .name = "cam_rawa",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x360,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_CAM_RAWB] = {
+ .name = "cam_rawb",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x364,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x348,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x340,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_WPE] = {
+ .name = "wpe",
+ .sta_mask = BIT(0),
+ .ctl_offs = 0x3F8,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1,
+ MT8186_TOP_AXI_PROT_EN_2_SET,
+ MT8186_TOP_AXI_PROT_EN_2_CLR,
+ MT8186_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2,
+ MT8186_TOP_AXI_PROT_EN_2_SET,
+ MT8186_TOP_AXI_PROT_EN_2_CLR,
+ MT8186_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_CONN_ON] = {
+ .name = "conn_on",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x304,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1,
+ MT8186_TOP_AXI_PROT_EN_1_SET,
+ MT8186_TOP_AXI_PROT_EN_1_CLR,
+ MT8186_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4,
+ MT8186_TOP_AXI_PROT_EN_SET,
+ MT8186_TOP_AXI_PROT_EN_CLR,
+ MT8186_TOP_AXI_PROT_EN_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8186_POWER_DOMAIN_CSIRX_TOP] = {
+ .name = "csirx_top",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x318,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8186_POWER_DOMAIN_ADSP_AO] = {
+ .name = "adsp_ao",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x9FC,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ },
+ [MT8186_POWER_DOMAIN_ADSP_INFRA] = {
+ .name = "adsp_infra",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x9F8,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ },
+ [MT8186_POWER_DOMAIN_ADSP_TOP] = {
+ .name = "adsp_top",
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x3E4,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1,
+ MT8186_TOP_AXI_PROT_EN_3_SET,
+ MT8186_TOP_AXI_PROT_EN_3_CLR,
+ MT8186_TOP_AXI_PROT_EN_3_STA),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2,
+ MT8186_TOP_AXI_PROT_EN_3_SET,
+ MT8186_TOP_AXI_PROT_EN_3_CLR,
+ MT8186_TOP_AXI_PROT_EN_3_STA),
+ },
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+static const struct scpsys_soc_data mt8186_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8186,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8186,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8186),
+};
+
+#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
new file mode 100644
index 000000000..3a989e83e
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
@@ -0,0 +1,696 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Garmin Chang <garmin.chang@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt8188-power.h>
+
+/*
+ * MT8188 power domain support
+ */
+
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8188[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
+ [MT8188_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x300,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8188_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x304,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MFG1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_1_SET,
+ MT8188_TOP_AXI_PROT_EN_1_CLR,
+ MT8188_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MFG1_STEP5,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8188_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x308,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x30C,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_MFG4] = {
+ .name = "mfg4",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x310,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = {
+ .name = "pextp_mac_p0",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x324,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = {
+ .name = "pextp_phy_top",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x328,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_CSIRX_TOP] = {
+ .name = "pextp_csirx_top",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x3C4,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_ETHER] = {
+ .name = "ether",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x338,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8188_POWER_DOMAIN_HDMI_TX] = {
+ .name = "hdmi_tx",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x37C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8188_POWER_DOMAIN_ADSP_AO] = {
+ .name = "adsp_ao",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x35C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .ext_buck_iso_offs = 0x3EC,
+ .ext_buck_iso_mask = BIT(10),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON | MTK_SCPD_EXT_BUCK_ISO,
+ },
+ [MT8188_POWER_DOMAIN_ADSP_INFRA] = {
+ .name = "adsp_infra",
+ .sta_mask = BIT(9),
+ .ctl_offs = 0x358,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ALWAYS_ON,
+ },
+ [MT8188_POWER_DOMAIN_ADSP] = {
+ .name = "adsp",
+ .sta_mask = BIT(8),
+ .ctl_offs = 0x354,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8188_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x34C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8188_POWER_DOMAIN_AUDIO_ASRC] = {
+ .name = "audio_asrc",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x350,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_VPPSYS0] = {
+ .name = "vppsys0",
+ .sta_mask = BIT(11),
+ .ctl_offs = 0x360,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDOSYS0] = {
+ .name = "vdosys0",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x368,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_SET,
+ MT8188_TOP_AXI_PROT_EN_CLR,
+ MT8188_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_VDOSYS1] = {
+ .name = "vdosys1",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x36C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_DP_TX] = {
+ .name = "dp_tx",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x374,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_EDP_TX] = {
+ .name = "edp_tx",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x378,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+ MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_VPPSYS1] = {
+ .name = "vppsys1",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x364,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ },
+ [MT8188_POWER_DOMAIN_WPE] = {
+ .name = "wpe",
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x370,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_VDEC0] = {
+ .name = "vdec0",
+ .sta_mask = BIT(19),
+ .ctl_offs = 0x380,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_VDEC1] = {
+ .name = "vdec1",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x384,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = BIT(22),
+ .ctl_offs = 0x38C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_IMG_VCORE] = {
+ .name = "vcore",
+ .sta_mask = BIT(28),
+ .ctl_offs = 0x3A4,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .ext_buck_iso_offs = 0x3EC,
+ .ext_buck_iso_mask = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY |
+ MTK_SCPD_EXT_BUCK_ISO,
+ },
+ [MT8188_POWER_DOMAIN_IMG_MAIN] = {
+ .name = "img_main",
+ .sta_mask = BIT(29),
+ .ctl_offs = 0x3A8,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_DIP] = {
+ .name = "dip",
+ .sta_mask = BIT(30),
+ .ctl_offs = 0x3AC,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_IPE] = {
+ .name = "ipe",
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x3B0,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_CAM_VCORE] = {
+ .name = "cam_vcore",
+ .sta_mask = BIT(27),
+ .ctl_offs = 0x3A0,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .ext_buck_iso_offs = 0x3EC,
+ .ext_buck_iso_mask = BIT(11),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3,
+ MT8188_TOP_AXI_PROT_EN_1_SET,
+ MT8188_TOP_AXI_PROT_EN_1_CLR,
+ MT8188_TOP_AXI_PROT_EN_1_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4,
+ MT8188_TOP_AXI_PROT_EN_MM_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY |
+ MTK_SCPD_EXT_BUCK_ISO,
+ },
+ [MT8188_POWER_DOMAIN_CAM_MAIN] = {
+ .name = "cam_main",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x394,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3,
+ MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+ BUS_PROT_WR(INFRA,
+ MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4,
+ MT8188_TOP_AXI_PROT_EN_2_SET,
+ MT8188_TOP_AXI_PROT_EN_2_CLR,
+ MT8188_TOP_AXI_PROT_EN_2_STA),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_CAM_SUBA] = {
+ .name = "cam_suba",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x398,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8188_POWER_DOMAIN_CAM_SUBB] = {
+ .name = "cam_subb",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x39C,
+ .pwr_sta_offs = 0x16C,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+};
+
+static const struct scpsys_soc_data mt8188_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8188,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8188,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8188),
+};
+
+#endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8189-pm-domains.h b/drivers/pmdomain/mediatek/mt8189-pm-domains.h
new file mode 100644
index 000000000..c28b9460c
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8189-pm-domains.h
@@ -0,0 +1,485 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Qiqi Wang <qiqi.wang@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8189_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8189_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt8189-power.h>
+
+/*
+ * MT8189 power domain support
+ */
+
+#define MT8189_SPM_PWR_STATUS 0x0f40
+#define MT8189_SPM_PWR_STATUS_2ND 0x0f44
+#define MT8189_SPM_PWR_STATUS_MSB 0x0f48
+#define MT8189_SPM_PWR_STATUS_MSB_2ND 0x0f4c
+#define MT8189_SPM_XPU_PWR_STATUS 0x0f50
+#define MT8189_SPM_XPU_PWR_STATUS_2ND 0x0f54
+
+#define MT8189_PROT_EN_EMICFG_GALS_SLP_SET 0x0084
+#define MT8189_PROT_EN_EMICFG_GALS_SLP_CLR 0x0088
+#define MT8189_PROT_EN_EMICFG_GALS_SLP_RDY 0x008c
+#define MT8189_PROT_EN_MMSYS_STA_0_SET 0x0c14
+#define MT8189_PROT_EN_MMSYS_STA_0_CLR 0x0c18
+#define MT8189_PROT_EN_MMSYS_STA_0_RDY 0x0c1c
+#define MT8189_PROT_EN_MMSYS_STA_1_SET 0x0c24
+#define MT8189_PROT_EN_MMSYS_STA_1_CLR 0x0c28
+#define MT8189_PROT_EN_MMSYS_STA_1_RDY 0x0c2c
+#define MT8189_PROT_EN_INFRASYS_STA_0_SET 0x0c44
+#define MT8189_PROT_EN_INFRASYS_STA_0_CLR 0x0c48
+#define MT8189_PROT_EN_INFRASYS_STA_0_RDY 0x0c4c
+#define MT8189_PROT_EN_INFRASYS_STA_1_SET 0x0c54
+#define MT8189_PROT_EN_INFRASYS_STA_1_CLR 0x0c58
+#define MT8189_PROT_EN_INFRASYS_STA_1_RDY 0x0c5c
+#define MT8189_PROT_EN_PERISYS_STA_0_SET 0x0c84
+#define MT8189_PROT_EN_PERISYS_STA_0_CLR 0x0c88
+#define MT8189_PROT_EN_PERISYS_STA_0_RDY 0x0c8c
+#define MT8189_PROT_EN_MCU_STA_0_SET 0x0c94
+#define MT8189_PROT_EN_MCU_STA_0_CLR 0x0c98
+#define MT8189_PROT_EN_MCU_STA_0_RDY 0x0c9c
+#define MT8189_PROT_EN_MD_STA_0_SET 0x0ca4
+#define MT8189_PROT_EN_MD_STA_0_CLR 0x0ca8
+#define MT8189_PROT_EN_MD_STA_0_RDY 0x0cac
+
+#define MT8189_PROT_EN_EMISYS_STA_0_MM_INFRA (GENMASK(21, 20))
+#define MT8189_PROT_EN_INFRASYS_STA_0_CONN (BIT(8))
+#define MT8189_PROT_EN_INFRASYS_STA_1_CONN (BIT(12))
+#define MT8189_PROT_EN_INFRASYS_STA_0_MM_INFRA (BIT(16))
+#define MT8189_PROT_EN_INFRASYS_STA_1_MM_INFRA (BIT(11))
+#define MT8189_PROT_EN_INFRASYS_STA_1_MFG1 (BIT(20))
+#define MT8189_PROT_EN_MCU_STA_0_CONN (BIT(1))
+#define MT8189_PROT_EN_MCU_STA_0_CONN_2ND (BIT(0))
+#define MT8189_PROT_EN_MD_STA_0_MFG1 (BIT(0) | BIT(2))
+#define MT8189_PROT_EN_MD_STA_0_MFG1_2ND (BIT(4))
+#define MT8189_PROT_EN_MM_INFRA_IGN (BIT(1))
+#define MT8189_PROT_EN_MM_INFRA_2_IGN (BIT(0))
+#define MT8189_PROT_EN_MMSYS_STA_0_CAM_MAIN (GENMASK(31, 30))
+#define MT8189_PROT_EN_MMSYS_STA_1_CAM_MAIN (GENMASK(10, 9))
+#define MT8189_PROT_EN_MMSYS_STA_0_DISP (GENMASK(1, 0))
+#define MT8189_PROT_EN_MMSYS_STA_0_ISP_IMG1 (BIT(3))
+#define MT8189_PROT_EN_MMSYS_STA_1_ISP_IMG1 (BIT(7))
+#define MT8189_PROT_EN_MMSYS_STA_0_ISP_IPE (BIT(2))
+#define MT8189_PROT_EN_MMSYS_STA_1_ISP_IPE (BIT(8))
+#define MT8189_PROT_EN_MMSYS_STA_0_MDP0 (BIT(18))
+#define MT8189_PROT_EN_MMSYS_STA_1_MM_INFRA (GENMASK(3, 2))
+#define MT8189_PROT_EN_MMSYS_STA_1_MM_INFRA_2ND (GENMASK(15, 7))
+#define MT8189_PROT_EN_MMSYS_STA_0_VDE0 (BIT(20))
+#define MT8189_PROT_EN_MMSYS_STA_1_VDE0 (BIT(13))
+#define MT8189_PROT_EN_MMSYS_STA_0_VEN0 (BIT(12))
+#define MT8189_PROT_EN_MMSYS_STA_1_VEN0 (BIT(12))
+#define MT8189_PROT_EN_PERISYS_STA_0_AUDIO (BIT(6))
+#define MT8189_PROT_EN_PERISYS_STA_0_SSUSB (BIT(7))
+#define MT8189_PROT_EN_EMICFG_GALS_SLP_MFG1 (GENMASK(5, 4))
+
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8189[] = {
+ BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8189[] = {
+ [MT8189_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0xe04,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MCU_STA_0_CONN,
+ MT8189_PROT_EN_MCU_STA_0_SET,
+ MT8189_PROT_EN_MCU_STA_0_CLR,
+ MT8189_PROT_EN_MCU_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_INFRASYS_STA_1_CONN,
+ MT8189_PROT_EN_INFRASYS_STA_1_SET,
+ MT8189_PROT_EN_INFRASYS_STA_1_CLR,
+ MT8189_PROT_EN_INFRASYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MCU_STA_0_CONN_2ND,
+ MT8189_PROT_EN_MCU_STA_0_SET,
+ MT8189_PROT_EN_MCU_STA_0_CLR,
+ MT8189_PROT_EN_MCU_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_INFRASYS_STA_0_CONN,
+ MT8189_PROT_EN_INFRASYS_STA_0_SET,
+ MT8189_PROT_EN_INFRASYS_STA_0_CLR,
+ MT8189_PROT_EN_INFRASYS_STA_0_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0xe18,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_PERISYS_STA_0_AUDIO,
+ MT8189_PROT_EN_PERISYS_STA_0_SET,
+ MT8189_PROT_EN_PERISYS_STA_0_CLR,
+ MT8189_PROT_EN_PERISYS_STA_0_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_ADSP_TOP_DORMANT] = {
+ .name = "adsp-top-dormant",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0xe1c,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(9),
+ .sram_pdn_ack_bits = BIT(13),
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_SRAM_PDN_INVERTED |
+ MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_ADSP_INFRA] = {
+ .name = "adsp-infra",
+ .sta_mask = BIT(8),
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .ctl_offs = 0xe20,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_ADSP_AO] = {
+ .name = "adsp-ao",
+ .sta_mask = BIT(9),
+ .ctl_offs = 0xe24,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ },
+ [MT8189_POWER_DOMAIN_ISP_IMG1] = {
+ .name = "isp-img1",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0xe28,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_ISP_IMG1,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_ISP_IMG1,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_ISP_IMG2] = {
+ .name = "isp-img2",
+ .sta_mask = BIT(11),
+ .ctl_offs = 0xe2c,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_ISP_IPE] = {
+ .name = "isp-ipe",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0xe30,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_ISP_IPE,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_ISP_IPE,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_VDE0] = {
+ .name = "vde0",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0xe38,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_VDE0,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_VDE0,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_VEN0] = {
+ .name = "ven0",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0xe40,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_VEN0,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_VEN0,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_CAM_MAIN] = {
+ .name = "cam-main",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0xe48,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_CAM_MAIN,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_CAM_MAIN,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_CAM_SUBA] = {
+ .name = "cam-suba",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0xe50,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_CAM_SUBB] = {
+ .name = "cam-subb",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0xe54,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_MDP0] = {
+ .name = "mdp0",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0xe68,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_MDP0,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_DISP] = {
+ .name = "disp",
+ .sta_mask = BIT(28),
+ .ctl_offs = 0xe70,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_0_DISP,
+ MT8189_PROT_EN_MMSYS_STA_0_SET,
+ MT8189_PROT_EN_MMSYS_STA_0_CLR,
+ MT8189_PROT_EN_MMSYS_STA_0_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_MM_INFRA] = {
+ .name = "mm-infra",
+ .sta_mask = BIT(30),
+ .ctl_offs = 0xe78,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_MM_INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MMSYS_STA_1_MM_INFRA_2ND,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN_SUBCLK(INFRA,
+ MT8189_PROT_EN_MM_INFRA_IGN,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ BUS_PROT_WR_IGN_SUBCLK(INFRA,
+ MT8189_PROT_EN_MM_INFRA_2_IGN,
+ MT8189_PROT_EN_MMSYS_STA_1_SET,
+ MT8189_PROT_EN_MMSYS_STA_1_CLR,
+ MT8189_PROT_EN_MMSYS_STA_1_RDY),
+ },
+ },
+ [MT8189_POWER_DOMAIN_DP_TX] = {
+ .name = "dp-tx",
+ .sta_mask = BIT(0),
+ .ctl_offs = 0xe80,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8189_POWER_DOMAIN_CSI_RX] = {
+ .name = "csi-rx",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0xe9c,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8189_POWER_DOMAIN_SSUSB] = {
+ .name = "ssusb",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0xea8,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_PERISYS_STA_0_SSUSB,
+ MT8189_PROT_EN_PERISYS_STA_0_SET,
+ MT8189_PROT_EN_PERISYS_STA_0_CLR,
+ MT8189_PROT_EN_PERISYS_STA_0_RDY),
+ },
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8189_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0xeb4,
+ .pwr_sta_offs = MT8189_SPM_XPU_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_XPU_PWR_STATUS_2ND,
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8189_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0xeb8,
+ .pwr_sta_offs = MT8189_SPM_XPU_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_XPU_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_INFRASYS_STA_1_MFG1,
+ MT8189_PROT_EN_INFRASYS_STA_1_SET,
+ MT8189_PROT_EN_INFRASYS_STA_1_CLR,
+ MT8189_PROT_EN_INFRASYS_STA_1_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MD_STA_0_MFG1,
+ MT8189_PROT_EN_MD_STA_0_SET,
+ MT8189_PROT_EN_MD_STA_0_CLR,
+ MT8189_PROT_EN_MD_STA_0_RDY),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8189_PROT_EN_MD_STA_0_MFG1_2ND,
+ MT8189_PROT_EN_MD_STA_0_SET,
+ MT8189_PROT_EN_MD_STA_0_CLR,
+ MT8189_PROT_EN_MD_STA_0_RDY),
+ BUS_PROT_WR_IGN(SMI,
+ MT8189_PROT_EN_EMICFG_GALS_SLP_MFG1,
+ MT8189_PROT_EN_EMICFG_GALS_SLP_SET,
+ MT8189_PROT_EN_EMICFG_GALS_SLP_CLR,
+ MT8189_PROT_EN_EMICFG_GALS_SLP_RDY),
+ },
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8189_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0xebc,
+ .pwr_sta_offs = MT8189_SPM_XPU_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_XPU_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8189_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0xec0,
+ .pwr_sta_offs = MT8189_SPM_XPU_PWR_STATUS,
+ .pwr_sta2nd_offs = MT8189_SPM_XPU_PWR_STATUS_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ },
+ [MT8189_POWER_DOMAIN_EDP_TX_DORMANT] = {
+ .name = "edp-tx-dormant",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0xf70,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ .sram_pdn_bits = BIT(9),
+ .sram_pdn_ack_bits = 0,
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_SRAM_PDN_INVERTED,
+ },
+ [MT8189_POWER_DOMAIN_PCIE] = {
+ .name = "pcie",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0xf74,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8189_POWER_DOMAIN_PCIE_PHY] = {
+ .name = "pcie-phy",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0xf78,
+ .pwr_sta_offs = MT8189_SPM_PWR_STATUS_MSB,
+ .pwr_sta2nd_offs = MT8189_SPM_PWR_STATUS_MSB_2ND,
+ },
+};
+
+static const struct scpsys_soc_data mt8189_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8189,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8189),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8189,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8189),
+};
+
+#endif /* __SOC_MEDIATEK_MT8189_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8192-pm-domains.h b/drivers/pmdomain/mediatek/mt8192-pm-domains.h
new file mode 100644
index 000000000..5d62fac5f
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8192-pm-domains.h
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8192-power.h>
+
+/*
+ * MT8192 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8192[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
+ [MT8192_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0x0354,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_2_AUDIO,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = 0x0304,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_CONN,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_CONN_2ND,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_1_CONN,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8192_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x0308,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8192_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x030c,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_1_MFG1,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_2_MFG1,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MFG1,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ },
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8192_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x0310,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x0314,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_MFG4] = {
+ .name = "mfg4",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x0318,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_MFG5] = {
+ .name = "mfg5",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x031c,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_MFG6] = {
+ .name = "mfg6",
+ .sta_mask = BIT(8),
+ .ctl_offs = 0x0320,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_DISP] = {
+ .name = "disp",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x0350,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_DISP,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR_IGN(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_DISP,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_DISP,
+ MT8192_TOP_AXI_PROT_EN_SET,
+ MT8192_TOP_AXI_PROT_EN_CLR,
+ MT8192_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_IPE] = {
+ .name = "ipe",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x0338,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_IPE,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x0330,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_ISP,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_ISP2] = {
+ .name = "isp2",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x0334,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_ISP2,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_MDP] = {
+ .name = "mdp",
+ .sta_mask = BIT(19),
+ .ctl_offs = 0x034c,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_MDP,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x0344,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_VENC,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x033c,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_VDEC,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_VDEC2] = {
+ .name = "vdec2",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x0340,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x035c,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_2_CAM,
+ MT8192_TOP_AXI_PROT_EN_2_SET,
+ MT8192_TOP_AXI_PROT_EN_2_CLR,
+ MT8192_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_CAM,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_1_CAM,
+ MT8192_TOP_AXI_PROT_EN_1_SET,
+ MT8192_TOP_AXI_PROT_EN_1_CLR,
+ MT8192_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND,
+ MT8192_TOP_AXI_PROT_EN_MM_SET,
+ MT8192_TOP_AXI_PROT_EN_MM_CLR,
+ MT8192_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8192_TOP_AXI_PROT_EN_VDNR_CAM,
+ MT8192_TOP_AXI_PROT_EN_VDNR_SET,
+ MT8192_TOP_AXI_PROT_EN_VDNR_CLR,
+ MT8192_TOP_AXI_PROT_EN_VDNR_STA1),
+ },
+ },
+ [MT8192_POWER_DOMAIN_CAM_RAWA] = {
+ .name = "cam_rawa",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x0360,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_CAM_RAWB] = {
+ .name = "cam_rawb",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x0364,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT8192_POWER_DOMAIN_CAM_RAWC] = {
+ .name = "cam_rawc",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x0368,
+ .pwr_sta_offs = 0x016c,
+ .pwr_sta2nd_offs = 0x0170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+};
+
+static const struct scpsys_soc_data mt8192_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8192,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8192,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8192),
+};
+
+#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8195-pm-domains.h b/drivers/pmdomain/mediatek/mt8195-pm-domains.h
new file mode 100644
index 000000000..1d3ca195a
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8195-pm-domains.h
@@ -0,0 +1,672 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8195-power.h>
+
+/*
+ * MT8195 power domain support
+ */
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8195[] = {
+ BUS_PROT_BLOCK_INFRA
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
+ [MT8195_POWER_DOMAIN_PCIE_MAC_P0] = {
+ .name = "pcie_mac_p0",
+ .sta_mask = BIT(11),
+ .ctl_offs = 0x328,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0,
+ MT8195_TOP_AXI_PROT_EN_VDNR_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_PCIE_MAC_P1] = {
+ .name = "pcie_mac_p1",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x32C,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1,
+ MT8195_TOP_AXI_PROT_EN_VDNR_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_PCIE_PHY] = {
+ .name = "pcie_phy",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x330,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY] = {
+ .name = "ssusb_pcie_phy",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x334,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_ALWAYS_ON,
+ },
+ [MT8195_POWER_DOMAIN_CSI_RX_TOP] = {
+ .name = "csi_rx_top",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x3C4,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_ETHER] = {
+ .name = "ether",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x344,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8195_POWER_DOMAIN_ADSP] = {
+ .name = "adsp",
+ .sta_mask = BIT(10),
+ .ctl_offs = 0x360,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_2_ADSP,
+ MT8195_TOP_AXI_PROT_EN_2_SET,
+ MT8195_TOP_AXI_PROT_EN_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_2_STA1),
+ },
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8195_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(8),
+ .ctl_offs = 0x358,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_2_AUDIO,
+ MT8195_TOP_AXI_PROT_EN_2_SET,
+ MT8195_TOP_AXI_PROT_EN_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8195_POWER_DOMAIN_MFG0] = {
+ .name = "mfg0",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x300,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8195_POWER_DOMAIN_MFG1] = {
+ .name = "mfg1",
+ .sta_mask = BIT(2),
+ .ctl_offs = 0x304,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MFG1,
+ MT8195_TOP_AXI_PROT_EN_SET,
+ MT8195_TOP_AXI_PROT_EN_CLR,
+ MT8195_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_2_MFG1,
+ MT8195_TOP_AXI_PROT_EN_2_SET,
+ MT8195_TOP_AXI_PROT_EN_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_1_MFG1,
+ MT8195_TOP_AXI_PROT_EN_1_SET,
+ MT8195_TOP_AXI_PROT_EN_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND,
+ MT8195_TOP_AXI_PROT_EN_2_SET,
+ MT8195_TOP_AXI_PROT_EN_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MFG1_2ND,
+ MT8195_TOP_AXI_PROT_EN_SET,
+ MT8195_TOP_AXI_PROT_EN_CLR,
+ MT8195_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+ },
+ [MT8195_POWER_DOMAIN_MFG2] = {
+ .name = "mfg2",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x308,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_MFG3] = {
+ .name = "mfg3",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x30C,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_MFG4] = {
+ .name = "mfg4",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x310,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_MFG5] = {
+ .name = "mfg5",
+ .sta_mask = BIT(6),
+ .ctl_offs = 0x314,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_MFG6] = {
+ .name = "mfg6",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x318,
+ .pwr_sta_offs = 0x174,
+ .pwr_sta2nd_offs = 0x178,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_VPPSYS0] = {
+ .name = "vppsys0",
+ .sta_mask = BIT(11),
+ .ctl_offs = 0x364,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VPPSYS0,
+ MT8195_TOP_AXI_PROT_EN_SET,
+ MT8195_TOP_AXI_PROT_EN_CLR,
+ MT8195_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND,
+ MT8195_TOP_AXI_PROT_EN_SET,
+ MT8195_TOP_AXI_PROT_EN_CLR,
+ MT8195_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_VDOSYS0] = {
+ .name = "vdosys0",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x36C,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDOSYS0,
+ MT8195_TOP_AXI_PROT_EN_SET,
+ MT8195_TOP_AXI_PROT_EN_CLR,
+ MT8195_TOP_AXI_PROT_EN_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+ MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_VPPSYS1] = {
+ .name = "vppsys1",
+ .sta_mask = BIT(12),
+ .ctl_offs = 0x368,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_VDOSYS1] = {
+ .name = "vdosys1",
+ .sta_mask = BIT(14),
+ .ctl_offs = 0x370,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_DP_TX] = {
+ .name = "dp_tx",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x378,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_EPD_TX] = {
+ .name = "epd_tx",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x37C,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_HDMI_TX] = {
+ .name = "hdmi_tx",
+ .sta_mask = BIT(18),
+ .ctl_offs = 0x380,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8195_POWER_DOMAIN_WPESYS] = {
+ .name = "wpesys",
+ .sta_mask = BIT(15),
+ .ctl_offs = 0x374,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_WPESYS,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ },
+ [MT8195_POWER_DOMAIN_VDEC0] = {
+ .name = "vdec0",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x388,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDEC0,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_VDEC1] = {
+ .name = "vdec1",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0x38C,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDEC1,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_VDEC2] = {
+ .name = "vdec2",
+ .sta_mask = BIT(22),
+ .ctl_offs = 0x390,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x394,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VENC,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VENC,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_VENC_CORE1] = {
+ .name = "venc_core1",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x398,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_IMG] = {
+ .name = "img",
+ .sta_mask = BIT(29),
+ .ctl_offs = 0x3AC,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_IMG,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_DIP] = {
+ .name = "dip",
+ .sta_mask = BIT(30),
+ .ctl_offs = 0x3B0,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_IPE] = {
+ .name = "ipe",
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x3B4,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_IPE,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_IPE,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x39C,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_2_CAM,
+ MT8195_TOP_AXI_PROT_EN_2_SET,
+ MT8195_TOP_AXI_PROT_EN_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_2_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_CAM,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_1_CAM,
+ MT8195_TOP_AXI_PROT_EN_1_SET,
+ MT8195_TOP_AXI_PROT_EN_1_CLR,
+ MT8195_TOP_AXI_PROT_EN_1_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND,
+ MT8195_TOP_AXI_PROT_EN_MM_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_STA1),
+ BUS_PROT_WR(INFRA,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CAM,
+ MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+ MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+ MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_CAM_RAWA] = {
+ .name = "cam_rawa",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x3A0,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_CAM_RAWB] = {
+ .name = "cam_rawb",
+ .sta_mask = BIT(27),
+ .ctl_offs = 0x3A4,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8195_POWER_DOMAIN_CAM_MRAW] = {
+ .name = "cam_mraw",
+ .sta_mask = BIT(28),
+ .ctl_offs = 0x3A8,
+ .pwr_sta_offs = 0x16c,
+ .pwr_sta2nd_offs = 0x170,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+};
+
+static const struct scpsys_soc_data mt8195_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8195,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8195,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8195),
+};
+
+#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8196-pm-domains.h b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
new file mode 100644
index 000000000..d704c9fa9
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
@@ -0,0 +1,652 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Collabora Ltd
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8196_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8196_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt8196-power.h>
+
+/*
+ * MT8196 and MT6991 power domain support
+ */
+
+/* INFRA TOP_AXI registers */
+#define MT8196_TOP_AXI_PROT_EN_SET 0x4
+#define MT8196_TOP_AXI_PROT_EN_CLR 0x8
+#define MT8196_TOP_AXI_PROT_EN_STA 0xc
+ #define MT8196_TOP_AXI_PROT_EN_SLEEP0_MD BIT(29)
+
+#define MT8196_TOP_AXI_PROT_EN_1_SET 0x24
+#define MT8196_TOP_AXI_PROT_EN_1_CLR 0x28
+#define MT8196_TOP_AXI_PROT_EN_1_STA 0x2c
+ #define MT8196_TOP_AXI_PROT_EN_1_SLEEP1_MD BIT(0)
+
+/* SPM BUS_PROTECT registers */
+#define MT8196_SPM_BUS_PROTECT_CON_SET 0xdc
+#define MT8196_SPM_BUS_PROTECT_CON_CLR 0xe0
+#define MT8196_SPM_BUS_PROTECT_RDY 0x208
+ #define MT8196_SPM_PROT_EN_BUS_CONN BIT(1)
+ #define MT8196_SPM_PROT_EN_BUS_SSUSB_DP_PHY_P0 BIT(6)
+ #define MT8196_SPM_PROT_EN_BUS_SSUSB_P0 BIT(7)
+ #define MT8196_SPM_PROT_EN_BUS_SSUSB_P1 BIT(8)
+ #define MT8196_SPM_PROT_EN_BUS_SSUSB_P23 BIT(9)
+ #define MT8196_SPM_PROT_EN_BUS_SSUSB_PHY_P2 BIT(10)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC0 BIT(13)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC1 BIT(14)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_MAC2 BIT(15)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY0 BIT(16)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY1 BIT(17)
+ #define MT8196_SPM_PROT_EN_BUS_PEXTP_PHY2 BIT(18)
+ #define MT8196_SPM_PROT_EN_BUS_AUDIO BIT(19)
+ #define MT8196_SPM_PROT_EN_BUS_ADSP_TOP BIT(21)
+ #define MT8196_SPM_PROT_EN_BUS_ADSP_INFRA BIT(22)
+ #define MT8196_SPM_PROT_EN_BUS_ADSP_AO BIT(23)
+ #define MT8196_SPM_PROT_EN_BUS_MM_PROC BIT(24)
+
+/* PWR_CON registers */
+#define MT8196_PWR_ACK BIT(30)
+#define MT8196_PWR_ACK_2ND BIT(31)
+
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8196[] = {
+ BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SPM
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8196[] = {
+ [MT8196_POWER_DOMAIN_MD] = {
+ .name = "md",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe00,
+ .pwr_sta_offs = 0xe00,
+ .pwr_sta2nd_offs = 0xe00,
+ .ext_buck_iso_offs = 0xefc,
+ .ext_buck_iso_mask = GENMASK(1, 0),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(INFRA, MT8196_TOP_AXI_PROT_EN_SLEEP0_MD,
+ MT8196_TOP_AXI_PROT_EN_SET,
+ MT8196_TOP_AXI_PROT_EN_CLR,
+ MT8196_TOP_AXI_PROT_EN_STA),
+ BUS_PROT_WR_IGN(INFRA, MT8196_TOP_AXI_PROT_EN_1_SLEEP1_MD,
+ MT8196_TOP_AXI_PROT_EN_1_SET,
+ MT8196_TOP_AXI_PROT_EN_1_CLR,
+ MT8196_TOP_AXI_PROT_EN_1_STA),
+ },
+ .caps = MTK_SCPD_MODEM_PWRSEQ | MTK_SCPD_EXT_BUCK_ISO |
+ MTK_SCPD_SKIP_RESET_B | MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8196_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe04,
+ .pwr_sta_offs = 0xe04,
+ .pwr_sta2nd_offs = 0xe04,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_CONN,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_SSUSB_DP_PHY_P0] = {
+ .name = "ssusb-dp-phy-p0",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe18,
+ .pwr_sta_offs = 0xe18,
+ .pwr_sta2nd_offs = 0xe18,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_SSUSB_DP_PHY_P0,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_SSUSB_P0] = {
+ .name = "ssusb-p0",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe1c,
+ .pwr_sta_offs = 0xe1c,
+ .pwr_sta2nd_offs = 0xe1c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_SSUSB_P0,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_SSUSB_P1] = {
+ .name = "ssusb-p1",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe20,
+ .pwr_sta_offs = 0xe20,
+ .pwr_sta2nd_offs = 0xe20,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_SSUSB_P1,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_SSUSB_P23] = {
+ .name = "ssusb-p23",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe24,
+ .pwr_sta_offs = 0xe24,
+ .pwr_sta2nd_offs = 0xe24,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_SSUSB_P23,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_SSUSB_PHY_P2] = {
+ .name = "ssusb-phy-p2",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe28,
+ .pwr_sta_offs = 0xe28,
+ .pwr_sta2nd_offs = 0xe28,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_SSUSB_PHY_P2,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_MAC0] = {
+ .name = "pextp-mac0",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe34,
+ .pwr_sta_offs = 0xe34,
+ .pwr_sta2nd_offs = 0xe34,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC0,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_MAC1] = {
+ .name = "pextp-mac1",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe38,
+ .pwr_sta_offs = 0xe38,
+ .pwr_sta2nd_offs = 0xe38,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC1,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_MAC2] = {
+ .name = "pextp-mac2",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe3c,
+ .pwr_sta_offs = 0xe3c,
+ .pwr_sta2nd_offs = 0xe3c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_MAC2,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_PHY0] = {
+ .name = "pextp-phy0",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe40,
+ .pwr_sta_offs = 0xe40,
+ .pwr_sta2nd_offs = 0xe40,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY0,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_PHY1] = {
+ .name = "pextp-phy1",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe44,
+ .pwr_sta_offs = 0xe44,
+ .pwr_sta2nd_offs = 0xe44,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY1,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_PEXTP_PHY2] = {
+ .name = "pextp-phy2",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe48,
+ .pwr_sta_offs = 0xe48,
+ .pwr_sta2nd_offs = 0xe48,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_PEXTP_PHY2,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_PCIE_PHY,
+ },
+ [MT8196_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe4c,
+ .pwr_sta_offs = 0xe4c,
+ .pwr_sta2nd_offs = 0xe4c,
+ .sram_pdn_bits = BIT(8),
+ .sram_pdn_ack_bits = BIT(12),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_AUDIO,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_ADSP_TOP_DORMANT] = {
+ .name = "adsp-top-dormant",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe54,
+ .pwr_sta_offs = 0xe54,
+ .pwr_sta2nd_offs = 0xe54,
+ /* Note: This is not managing powerdown (pdn), but sleep instead (slp) */
+ .sram_pdn_bits = BIT(9),
+ .sram_pdn_ack_bits = BIT(13),
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_ADSP_TOP,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_SRAM_PDN_INVERTED,
+ },
+ [MT8196_POWER_DOMAIN_ADSP_INFRA] = {
+ .name = "adsp-infra",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe58,
+ .pwr_sta_offs = 0xe58,
+ .pwr_sta2nd_offs = 0xe58,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_ADSP_INFRA,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+ [MT8196_POWER_DOMAIN_ADSP_AO] = {
+ .name = "adsp-ao",
+ .sta_mask = MT8196_PWR_ACK,
+ .sta2nd_mask = MT8196_PWR_ACK_2ND,
+ .ctl_offs = 0xe5c,
+ .pwr_sta_offs = 0xe5c,
+ .pwr_sta2nd_offs = 0xe5c,
+ .bp_cfg = {
+ BUS_PROT_WR_IGN(SPM, MT8196_SPM_PROT_EN_BUS_ADSP_AO,
+ MT8196_SPM_BUS_PROTECT_CON_SET,
+ MT8196_SPM_BUS_PROTECT_CON_CLR,
+ MT8196_SPM_BUS_PROTECT_RDY),
+ },
+ .caps = MTK_SCPD_ALWAYS_ON,
+ .rtff_type = SCPSYS_RTFF_TYPE_GENERIC,
+ },
+};
+
+static const struct scpsys_hwv_domain_data scpsys_hwv_domain_data_mt8196[] = {
+ [MT8196_POWER_DOMAIN_MM_PROC_DORMANT] = {
+ .name = "mm-proc-dormant",
+ .set = 0x0218,
+ .clr = 0x021c,
+ .done = 0x141c,
+ .en = 0x1410,
+ .set_sta = 0x146c,
+ .clr_sta = 0x1470,
+ .setclr_bit = 0,
+ .caps = MTK_SCPD_ALWAYS_ON,
+ },
+ [MT8196_POWER_DOMAIN_SSR] = {
+ .name = "ssrsys",
+ .set = 0x0218,
+ .clr = 0x021c,
+ .done = 0x141c,
+ .en = 0x1410,
+ .set_sta = 0x146c,
+ .clr_sta = 0x1470,
+ .setclr_bit = 1,
+ },
+};
+
+static const struct scpsys_hwv_domain_data hfrpsys_hwv_domain_data_mt8196[] = {
+ [MT8196_POWER_DOMAIN_VDE0] = {
+ .name = "vde0",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 7,
+ },
+ [MT8196_POWER_DOMAIN_VDE1] = {
+ .name = "vde1",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 8,
+ },
+ [MT8196_POWER_DOMAIN_VDE_VCORE0] = {
+ .name = "vde-vcore0",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 9,
+ },
+ [MT8196_POWER_DOMAIN_VEN0] = {
+ .name = "ven0",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 10,
+ },
+ [MT8196_POWER_DOMAIN_VEN1] = {
+ .name = "ven1",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 11,
+ },
+ [MT8196_POWER_DOMAIN_VEN2] = {
+ .name = "ven2",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 12,
+ },
+ [MT8196_POWER_DOMAIN_DISP_VCORE] = {
+ .name = "disp-vcore",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 24,
+ },
+ [MT8196_POWER_DOMAIN_DIS0_DORMANT] = {
+ .name = "dis0-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 25,
+ },
+ [MT8196_POWER_DOMAIN_DIS1_DORMANT] = {
+ .name = "dis1-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 26,
+ },
+ [MT8196_POWER_DOMAIN_OVL0_DORMANT] = {
+ .name = "ovl0-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 27,
+ },
+ [MT8196_POWER_DOMAIN_OVL1_DORMANT] = {
+ .name = "ovl1-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 28,
+ },
+ [MT8196_POWER_DOMAIN_DISP_EDPTX_DORMANT] = {
+ .name = "disp-edptx-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 29,
+ },
+ [MT8196_POWER_DOMAIN_DISP_DPTX_DORMANT] = {
+ .name = "disp-dptx-dormant",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 30,
+ },
+ [MT8196_POWER_DOMAIN_MML0_SHUTDOWN] = {
+ .name = "mml0-shutdown",
+ .set = 0x0218,
+ .clr = 0x021C,
+ .done = 0x141C,
+ .en = 0x1410,
+ .set_sta = 0x146C,
+ .clr_sta = 0x1470,
+ .setclr_bit = 31,
+ },
+ [MT8196_POWER_DOMAIN_MML1_SHUTDOWN] = {
+ .name = "mml1-shutdown",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 0,
+ },
+ [MT8196_POWER_DOMAIN_MM_INFRA0] = {
+ .name = "mm-infra0",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 1,
+ },
+ [MT8196_POWER_DOMAIN_MM_INFRA1] = {
+ .name = "mm-infra1",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 2,
+ },
+ [MT8196_POWER_DOMAIN_MM_INFRA_AO] = {
+ .name = "mm-infra-ao",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 3,
+ },
+ [MT8196_POWER_DOMAIN_CSI_BS_RX] = {
+ .name = "csi-bs-rx",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 5,
+ },
+ [MT8196_POWER_DOMAIN_CSI_LS_RX] = {
+ .name = "csi-ls-rx",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 6,
+ },
+ [MT8196_POWER_DOMAIN_DSI_PHY0] = {
+ .name = "dsi-phy0",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 7,
+ },
+ [MT8196_POWER_DOMAIN_DSI_PHY1] = {
+ .name = "dsi-phy1",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 8,
+ },
+ [MT8196_POWER_DOMAIN_DSI_PHY2] = {
+ .name = "dsi-phy2",
+ .set = 0x0220,
+ .clr = 0x0224,
+ .done = 0x142C,
+ .en = 0x1420,
+ .set_sta = 0x1474,
+ .clr_sta = 0x1478,
+ .setclr_bit = 9,
+ },
+};
+
+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),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8196,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8196),
+ .type = SCPSYS_MTCMOS_TYPE_DIRECT_CTL,
+};
+
+static const struct scpsys_soc_data mt8196_scpsys_hwv_data = {
+ .hwv_domains_data = scpsys_hwv_domain_data_mt8196,
+ .num_hwv_domains = ARRAY_SIZE(scpsys_hwv_domain_data_mt8196),
+ .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),
+ .type = SCPSYS_MTCMOS_TYPE_HW_VOTER,
+};
+
+#endif /* __SOC_MEDIATEK_MT8196_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8365-pm-domains.h b/drivers/pmdomain/mediatek/mt8365-pm-domains.h
new file mode 100644
index 000000000..33265ab8c
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8365-pm-domains.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8365_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8365_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt8365-power.h>
+
+/*
+ * MT8365 power domain support
+ */
+
+#define MT8365_BUS_PROT_INFRA_WR_TOPAXI(_mask) \
+ BUS_PROT_WR(INFRA, _mask, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_SET, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_CLR, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_STA1)
+
+#define MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(_mask) \
+ BUS_PROT_WR(INFRA, _mask, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_SET, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_CLR, \
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_STA1)
+
+#define MT8365_BUS_PROT_SMI_WR_CLAMP_EN_PORT(port) \
+ BUS_PROT_WR(SMI, BIT(port), \
+ MT8365_SMI_COMMON_CLAMP_EN_SET, \
+ MT8365_SMI_COMMON_CLAMP_EN_CLR, \
+ MT8365_SMI_COMMON_CLAMP_EN)
+
+#define MT8365_BUS_PROT_WAY_EN(_set_mask, _set, _sta_mask, _sta) \
+ _BUS_PROT_STA(INFRA, INFRA_NAO, _set_mask, _set, _set, \
+ _sta_mask, _sta, \
+ BUS_PROT_INVERTED | BUS_PROT_REG_UPDATE)
+
+static enum scpsys_bus_prot_block scpsys_bus_prot_blocks_mt8365[] = {
+ BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_INFRA_NAO, BUS_PROT_BLOCK_SMI
+};
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = {
+ [MT8365_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = 0x30c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_MM2INFRA_AXI_GALS_MST_0 |
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_MM2INFRA_AXI_GALS_MST_1),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(
+ MT8365_INFRA_TOPAXI_PROTECTEN_MM_M0 |
+ MT8365_INFRA_TOPAXI_PROTECTEN_MDMCU_M1 |
+ MT8365_INFRA_TOPAXI_PROTECTEN_MM2INFRA_AXI_GALS_SLV_0 |
+ MT8365_INFRA_TOPAXI_PROTECTEN_MM2INFRA_AXI_GALS_SLV_1),
+ MT8365_BUS_PROT_WAY_EN(
+ MT8365_INFRA_TOPAXI_SI0_WAY_EN_MMAPB_S,
+ MT8365_INFRA_TOPAXI_SI0_CTL,
+ MT8365_INFRA_NAO_TOPAXI_SI0_CTRL_UPDATED,
+ MT8365_INFRA_NAO_TOPAXI_SI0_STA),
+ MT8365_BUS_PROT_WAY_EN(
+ MT8365_INFRA_TOPAXI_SI2_WAY_EN_PERI_M1,
+ MT8365_INFRA_TOPAXI_SI2_CTL,
+ MT8365_INFRA_NAO_TOPAXI_SI2_CTRL_UPDATED,
+ MT8365_INFRA_NAO_TOPAXI_SI2_STA),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(
+ MT8365_INFRA_TOPAXI_PROTECTEN_MMAPB_S),
+ },
+ .caps = MTK_SCPD_STRICT_BUS_PROTECTION | MTK_SCPD_HAS_INFRA_NAO,
+ },
+ [MT8365_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = 0x0304,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_SMI_WR_CLAMP_EN_PORT(1),
+ },
+ },
+ [MT8365_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = 0x0314,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(12, 8),
+ .sram_pdn_ack_bits = GENMASK(17, 13),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_PWRDNREQ_MP1_L2C_AFIFO |
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_AUDIO_BUS_AUDIO_M),
+ },
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8365_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = 0x032c,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(
+ MT8365_INFRA_TOPAXI_PROTECTEN_AP2CONN_AHB),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_CONN2INFRA_AXI_GALS_MST),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(
+ MT8365_INFRA_TOPAXI_PROTECTEN_CONN2INFRA_AHB),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_INFRA2CONN_AHB_GALS_SLV),
+ },
+ .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_KEEP_DEFAULT_OFF,
+ },
+ [MT8365_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = 0x0338,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(9, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(BIT(25)),
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI(
+ MT8365_INFRA_TOPAXI_PROTECTEN_MFG_M0 |
+ MT8365_INFRA_TOPAXI_PROTECTEN_INFRA2MFG),
+ },
+ },
+ [MT8365_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x0344,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(9, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_CAM2MM_AXI_GALS_MST),
+ MT8365_BUS_PROT_SMI_WR_CLAMP_EN_PORT(2),
+ },
+ },
+ [MT8365_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = BIT(31),
+ .ctl_offs = 0x0370,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_SMI_WR_CLAMP_EN_PORT(3),
+ },
+ },
+ [MT8365_POWER_DOMAIN_APU] = {
+ .name = "apu",
+ .sta_mask = BIT(16),
+ .ctl_offs = 0x0378,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(14, 8),
+ .sram_pdn_ack_bits = GENMASK(21, 15),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_APU2AP |
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_APU_CBIP_GALS_MST),
+ MT8365_BUS_PROT_SMI_WR_CLAMP_EN_PORT(4),
+ },
+ },
+ [MT8365_POWER_DOMAIN_DSP] = {
+ .name = "dsp",
+ .sta_mask = BIT(17),
+ .ctl_offs = 0x037C,
+ .pwr_sta_offs = 0x0180,
+ .pwr_sta2nd_offs = 0x0184,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .bp_cfg = {
+ MT8365_BUS_PROT_INFRA_WR_TOPAXI_1(
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_PWRDNREQ_INFRA_GALS_ADB |
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_AUDIO_BUS_DSP_M |
+ MT8365_INFRA_TOPAXI_PROTECTEN_1_AUDIO_BUS_DSP_S),
+ },
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+static const struct scpsys_soc_data mt8365_scpsys_data = {
+ .domains_data = scpsys_domain_data_mt8365,
+ .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8365),
+ .bus_prot_blocks = scpsys_bus_prot_blocks_mt8365,
+ .num_bus_prot_blocks = ARRAY_SIZE(scpsys_bus_prot_blocks_mt8365),
+};
+
+#endif /* __SOC_MEDIATEK_MT8365_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c b/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c
new file mode 100644
index 000000000..1417ffc22
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c
@@ -0,0 +1,1084 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for MediaTek MFlexGraphics Devices
+ *
+ * Copyright (C) 2025, Collabora Ltd.
+ */
+
+#include <linux/completion.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/container_of.h>
+#include <linux/iopoll.h>
+#include <linux/nvmem-provider.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_opp.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#define GPR_LP_STATE 0x0028
+#define EB_ON_SUSPEND 0x0
+#define EB_ON_RESUME 0x1
+#define GPR_IPI_MAGIC 0x34
+
+#define RPC_PWR_CON 0x0504
+#define PWR_ACK_M GENMASK(31, 30)
+#define RPC_DUMMY_REG_2 0x0658
+#define RPC_GHPM_CFG0_CON 0x0800
+#define GHPM_ENABLE_M BIT(0)
+#define GHPM_ON_SEQ_M BIT(2)
+#define RPC_GHPM_RO0_CON 0x09A4
+#define GHPM_STATE_M GENMASK(7, 0)
+#define GHPM_PWR_STATE_M BIT(16)
+
+#define GF_REG_MAGIC 0x0000
+#define GF_REG_GPU_OPP_IDX 0x0004
+#define GF_REG_STK_OPP_IDX 0x0008
+#define GF_REG_GPU_OPP_NUM 0x000c
+#define GF_REG_STK_OPP_NUM 0x0010
+#define GF_REG_GPU_OPP_SNUM 0x0014
+#define GF_REG_STK_OPP_SNUM 0x0018
+#define GF_REG_POWER_COUNT 0x001c
+#define GF_REG_BUCK_COUNT 0x0020
+#define GF_REG_MTCMOS_COUNT 0x0024
+#define GF_REG_CG_COUNT 0x0028 /* CG = Clock Gate? */
+#define GF_REG_ACTIVE_COUNT 0x002C
+#define GF_REG_TEMP_RAW 0x0030
+#define GF_REG_TEMP_NORM_GPU 0x0034
+#define GF_REG_TEMP_HIGH_GPU 0x0038
+#define GF_REG_TEMP_NORM_STK 0x003C
+#define GF_REG_TEMP_HIGH_STK 0x0040
+#define GF_REG_FREQ_CUR_GPU 0x0044
+#define GF_REG_FREQ_CUR_STK 0x0048
+#define GF_REG_FREQ_OUT_GPU 0x004C /* Guess: actual achieved freq */
+#define GF_REG_FREQ_OUT_STK 0x0050 /* Guess: actual achieved freq */
+#define GF_REG_FREQ_METER_GPU 0x0054 /* Seems unused, always 0 */
+#define GF_REG_FREQ_METER_STK 0x0058 /* Seems unused, always 0 */
+#define GF_REG_VOLT_CUR_GPU 0x005C /* in tens of microvolts */
+#define GF_REG_VOLT_CUR_STK 0x0060 /* in tens of microvolts */
+#define GF_REG_VOLT_CUR_GPU_SRAM 0x0064
+#define GF_REG_VOLT_CUR_STK_SRAM 0x0068
+#define GF_REG_VOLT_CUR_GPU_REG 0x006C /* Seems unused, always 0 */
+#define GF_REG_VOLT_CUR_STK_REG 0x0070 /* Seems unused, always 0 */
+#define GF_REG_VOLT_CUR_GPU_REG_SRAM 0x0074
+#define GF_REG_VOLT_CUR_STK_REG_SRAM 0x0078
+#define GF_REG_PWR_CUR_GPU 0x007C /* in milliwatts */
+#define GF_REG_PWR_CUR_STK 0x0080 /* in milliwatts */
+#define GF_REG_PWR_MAX_GPU 0x0084 /* in milliwatts */
+#define GF_REG_PWR_MAX_STK 0x0088 /* in milliwatts */
+#define GF_REG_PWR_MIN_GPU 0x008C /* in milliwatts */
+#define GF_REG_PWR_MIN_STK 0x0090 /* in milliwatts */
+#define GF_REG_LEAKAGE_RT_GPU 0x0094 /* Unknown */
+#define GF_REG_LEAKAGE_RT_STK 0x0098 /* Unknown */
+#define GF_REG_LEAKAGE_RT_SRAM 0x009C /* Unknown */
+#define GF_REG_LEAKAGE_HT_GPU 0x00A0 /* Unknown */
+#define GF_REG_LEAKAGE_HT_STK 0x00A4 /* Unknown */
+#define GF_REG_LEAKAGE_HT_SRAM 0x00A8 /* Unknown */
+#define GF_REG_VOLT_DAC_LOW_GPU 0x00AC /* Seems unused, always 0 */
+#define GF_REG_VOLT_DAC_LOW_STK 0x00B0 /* Seems unused, always 0 */
+#define GF_REG_OPP_CUR_CEIL 0x00B4
+#define GF_REG_OPP_CUR_FLOOR 0x00B8
+#define GF_REG_OPP_CUR_LIMITER_CEIL 0x00BC
+#define GF_REG_OPP_CUR_LIMITER_FLOOR 0x00C0
+#define GF_REG_OPP_PRIORITY_CEIL 0x00C4
+#define GF_REG_OPP_PRIORITY_FLOOR 0x00C8
+#define GF_REG_PWR_CTL 0x00CC
+#define GF_REG_ACTIVE_SLEEP_CTL 0x00D0
+#define GF_REG_DVFS_STATE 0x00D4
+#define GF_REG_SHADER_PRESENT 0x00D8
+#define GF_REG_ASENSOR_ENABLE 0x00DC
+#define GF_REG_AGING_LOAD 0x00E0
+#define GF_REG_AGING_MARGIN 0x00E4
+#define GF_REG_AVS_ENABLE 0x00E8
+#define GF_REG_AVS_MARGIN 0x00EC
+#define GF_REG_CHIP_TYPE 0x00F0
+#define GF_REG_SB_VERSION 0x00F4
+#define GF_REG_PTP_VERSION 0x00F8
+#define GF_REG_DBG_VERSION 0x00FC
+#define GF_REG_KDBG_VERSION 0x0100
+#define GF_REG_GPM1_MODE 0x0104
+#define GF_REG_GPM3_MODE 0x0108
+#define GF_REG_DFD_MODE 0x010C
+#define GF_REG_DUAL_BUCK 0x0110
+#define GF_REG_SEGMENT_ID 0x0114
+#define GF_REG_POWER_TIME_H 0x0118
+#define GF_REG_POWER_TIME_L 0x011C
+#define GF_REG_PWR_STATUS 0x0120
+#define GF_REG_STRESS_TEST 0x0124
+#define GF_REG_TEST_MODE 0x0128
+#define GF_REG_IPS_MODE 0x012C
+#define GF_REG_TEMP_COMP_MODE 0x0130
+#define GF_REG_HT_TEMP_COMP_MODE 0x0134
+#define GF_REG_PWR_TRACKER_MODE 0x0138
+#define GF_REG_OPP_TABLE_GPU 0x0314
+#define GF_REG_OPP_TABLE_STK 0x09A4
+#define GF_REG_OPP_TABLE_GPU_S 0x1034
+#define GF_REG_OPP_TABLE_STK_S 0x16c4
+#define GF_REG_LIMIT_TABLE 0x1d54
+#define GF_REG_GPM3_TABLE 0x223C
+
+#define MFG_MT8196_E2_ID 0x101
+#define GPUEB_SLEEP_MAGIC 0x55667788UL
+#define GPUEB_MEM_MAGIC 0xBABADADAUL
+
+#define GPUEB_TIMEOUT_US 10000UL
+#define GPUEB_POLL_US 50
+
+#define MAX_OPP_NUM 70
+
+#define GPUEB_MBOX_MAX_RX_SIZE 32 /* in bytes */
+
+/*
+ * This enum is part of the ABI of the GPUEB firmware. Don't change the
+ * numbering, as you would wreak havoc.
+ */
+enum mtk_mfg_ipi_cmd {
+ CMD_INIT_SHARED_MEM = 0,
+ CMD_GET_FREQ_BY_IDX = 1,
+ CMD_GET_POWER_BY_IDX = 2,
+ CMD_GET_OPPIDX_BY_FREQ = 3,
+ CMD_GET_LEAKAGE_POWER = 4,
+ CMD_SET_LIMIT = 5,
+ CMD_POWER_CONTROL = 6,
+ CMD_ACTIVE_SLEEP_CONTROL = 7,
+ CMD_COMMIT = 8,
+ CMD_DUAL_COMMIT = 9,
+ CMD_PDCA_CONFIG = 10,
+ CMD_UPDATE_DEBUG_OPP_INFO = 11,
+ CMD_SWITCH_LIMIT = 12,
+ CMD_FIX_TARGET_OPPIDX = 13,
+ CMD_FIX_DUAL_TARGET_OPPIDX = 14,
+ CMD_FIX_CUSTOM_FREQ_VOLT = 15,
+ CMD_FIX_DUAL_CUSTOM_FREQ_VOLT = 16,
+ CMD_SET_MFGSYS_CONFIG = 17,
+ CMD_MSSV_COMMIT = 18,
+ CMD_NUM = 19,
+};
+
+/*
+ * This struct is part of the ABI of the GPUEB firmware. Changing it, or
+ * reordering fields in it, will break things, so don't do it. Thank you.
+ */
+struct __packed mtk_mfg_ipi_msg {
+ __le32 magic;
+ __le32 cmd;
+ __le32 target;
+ /*
+ * Downstream relies on the compiler to implicitly add the following
+ * padding, as it declares the struct as non-packed.
+ */
+ __le32 reserved;
+ union {
+ s32 __bitwise oppidx;
+ s32 __bitwise return_value;
+ __le32 freq;
+ __le32 volt;
+ __le32 power;
+ __le32 power_state;
+ __le32 mode;
+ __le32 value;
+ struct {
+ __le64 base;
+ __le32 size;
+ } shared_mem;
+ struct {
+ __le32 freq;
+ __le32 volt;
+ } custom;
+ struct {
+ __le32 limiter;
+ s32 __bitwise ceiling_info;
+ s32 __bitwise floor_info;
+ } set_limit;
+ struct {
+ __le32 target;
+ __le32 val;
+ } mfg_cfg;
+ struct {
+ __le32 target;
+ __le32 val;
+ } mssv;
+ struct {
+ s32 __bitwise gpu_oppidx;
+ s32 __bitwise stack_oppidx;
+ } dual_commit;
+ struct {
+ __le32 fgpu;
+ __le32 vgpu;
+ __le32 fstack;
+ __le32 vstack;
+ } dual_custom;
+ } u;
+};
+
+struct __packed mtk_mfg_ipi_sleep_msg {
+ __le32 event;
+ __le32 state;
+ __le32 magic;
+};
+
+/**
+ * struct mtk_mfg_opp_entry - OPP table entry from firmware
+ * @freq_khz: The operating point's frequency in kilohertz
+ * @voltage_core: The operating point's core voltage in tens of microvolts
+ * @voltage_sram: The operating point's SRAM voltage in tens of microvolts
+ * @posdiv: exponent of base 2 for PLL frequency divisor used for this OPP
+ * @voltage_margin: Number of tens of microvolts the voltage can be undershot
+ * @power_mw: estimate of power usage at this operating point, in milliwatts
+ *
+ * This struct is part of the ABI with the EB firmware. Do not change it.
+ */
+struct mtk_mfg_opp_entry {
+ __le32 freq_khz;
+ __le32 voltage_core;
+ __le32 voltage_sram;
+ __le32 posdiv;
+ __le32 voltage_margin;
+ __le32 power_mw;
+} __packed;
+
+struct mtk_mfg_mbox {
+ struct mbox_client cl;
+ struct completion rx_done;
+ struct mtk_mfg *mfg;
+ struct mbox_chan *ch;
+ void *rx_data;
+};
+
+struct mtk_mfg {
+ struct generic_pm_domain pd;
+ struct platform_device *pdev;
+ struct clk *clk_eb;
+ struct clk_bulk_data *gpu_clks;
+ struct clk_hw clk_core_hw;
+ struct clk_hw clk_stack_hw;
+ struct regulator_bulk_data *gpu_regs;
+ void __iomem *rpc;
+ void __iomem *gpr;
+ void __iomem *shared_mem;
+ phys_addr_t shared_mem_phys;
+ unsigned int shared_mem_size;
+ u16 ghpm_en_reg;
+ u32 ipi_magic;
+ unsigned short num_gpu_opps;
+ unsigned short num_stack_opps;
+ struct dev_pm_opp_data *gpu_opps;
+ struct dev_pm_opp_data *stack_opps;
+ struct mtk_mfg_mbox *gf_mbox;
+ struct mtk_mfg_mbox *slp_mbox;
+ const struct mtk_mfg_variant *variant;
+};
+
+struct mtk_mfg_variant {
+ const char *const *clk_names;
+ unsigned int num_clks;
+ const char *const *regulator_names;
+ unsigned int num_regulators;
+ /** @turbo_below: opp indices below this value are considered turbo */
+ unsigned int turbo_below;
+ int (*init)(struct mtk_mfg *mfg);
+};
+
+static inline struct mtk_mfg *mtk_mfg_from_genpd(struct generic_pm_domain *pd)
+{
+ return container_of(pd, struct mtk_mfg, pd);
+}
+
+static inline void mtk_mfg_update_reg_bits(void __iomem *addr, u32 mask, u32 val)
+{
+ writel((readl(addr) & ~mask) | (val & mask), addr);
+}
+
+static inline bool mtk_mfg_is_powered_on(struct mtk_mfg *mfg)
+{
+ return (readl(mfg->rpc + RPC_PWR_CON) & PWR_ACK_M) == PWR_ACK_M;
+}
+
+static unsigned long mtk_mfg_recalc_rate_gpu(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtk_mfg *mfg = container_of(hw, struct mtk_mfg, clk_core_hw);
+
+ return readl(mfg->shared_mem + GF_REG_FREQ_OUT_GPU) * HZ_PER_KHZ;
+}
+
+static unsigned long mtk_mfg_recalc_rate_stack(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtk_mfg *mfg = container_of(hw, struct mtk_mfg, clk_stack_hw);
+
+ return readl(mfg->shared_mem + GF_REG_FREQ_OUT_STK) * HZ_PER_KHZ;
+}
+
+static const struct clk_ops mtk_mfg_clk_gpu_ops = {
+ .recalc_rate = mtk_mfg_recalc_rate_gpu,
+ .determine_rate = clk_determine_rate_noop,
+};
+
+static const struct clk_ops mtk_mfg_clk_stack_ops = {
+ .recalc_rate = mtk_mfg_recalc_rate_stack,
+ .determine_rate = clk_determine_rate_noop,
+};
+
+static const struct clk_init_data mtk_mfg_clk_gpu_init = {
+ .name = "gpu-core",
+ .ops = &mtk_mfg_clk_gpu_ops,
+ .flags = CLK_GET_RATE_NOCACHE,
+};
+
+static const struct clk_init_data mtk_mfg_clk_stack_init = {
+ .name = "gpu-stack",
+ .ops = &mtk_mfg_clk_stack_ops,
+ .flags = CLK_GET_RATE_NOCACHE,
+};
+
+static int mtk_mfg_eb_on(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ u32 val;
+ int ret;
+
+ /*
+ * If MFG is already on from e.g. the bootloader, skip doing the
+ * power-on sequence, as it wouldn't work without powering it off first.
+ */
+ if (mtk_mfg_is_powered_on(mfg))
+ return 0;
+
+ ret = readl_poll_timeout(mfg->rpc + RPC_GHPM_RO0_CON, val,
+ !(val & (GHPM_PWR_STATE_M | GHPM_STATE_M)),
+ GPUEB_POLL_US, GPUEB_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "timed out waiting for EB to power on\n");
+ return ret;
+ }
+
+ mtk_mfg_update_reg_bits(mfg->rpc + mfg->ghpm_en_reg, GHPM_ENABLE_M,
+ GHPM_ENABLE_M);
+
+ mtk_mfg_update_reg_bits(mfg->rpc + RPC_GHPM_CFG0_CON, GHPM_ON_SEQ_M, 0);
+ mtk_mfg_update_reg_bits(mfg->rpc + RPC_GHPM_CFG0_CON, GHPM_ON_SEQ_M,
+ GHPM_ON_SEQ_M);
+
+ mtk_mfg_update_reg_bits(mfg->rpc + mfg->ghpm_en_reg, GHPM_ENABLE_M, 0);
+
+
+ ret = readl_poll_timeout(mfg->rpc + RPC_PWR_CON, val,
+ (val & PWR_ACK_M) == PWR_ACK_M,
+ GPUEB_POLL_US, GPUEB_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "timed out waiting for EB power ack, val = 0x%X\n",
+ val);
+ return ret;
+ }
+
+ ret = readl_poll_timeout(mfg->gpr + GPR_LP_STATE, val,
+ (val == EB_ON_RESUME),
+ GPUEB_POLL_US, GPUEB_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "timed out waiting for EB to resume, status = 0x%X\n", val);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_mfg_eb_off(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct mtk_mfg_ipi_sleep_msg msg = {
+ .event = 0,
+ .state = 0,
+ .magic = GPUEB_SLEEP_MAGIC
+ };
+ u32 val;
+ int ret;
+
+ ret = mbox_send_message(mfg->slp_mbox->ch, &msg);
+ if (ret < 0) {
+ dev_err(dev, "Cannot send sleep command: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = readl_poll_timeout(mfg->rpc + RPC_PWR_CON, val,
+ !(val & PWR_ACK_M), GPUEB_POLL_US,
+ GPUEB_TIMEOUT_US);
+
+ if (ret) {
+ dev_err(dev, "Timed out waiting for EB to power off, val=0x%08X\n", val);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * mtk_mfg_send_ipi - synchronously send an IPI message on the gpufreq channel
+ * @mfg: pointer to this driver instance's private &struct mtk_mfg
+ * @msg: pointer to a message to send; will have magic filled and response assigned
+ *
+ * Send an IPI message on the gpufreq channel, and wait for a response. Once a
+ * response is received, assign a pointer to the response buffer (valid until
+ * next response is received) to @msg.
+ *
+ * Returns 0 on success, negative errno on failure.
+ */
+static int mtk_mfg_send_ipi(struct mtk_mfg *mfg, struct mtk_mfg_ipi_msg *msg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ unsigned long wait;
+ int ret;
+
+ msg->magic = mfg->ipi_magic;
+
+ ret = mbox_send_message(mfg->gf_mbox->ch, msg);
+ if (ret < 0) {
+ dev_err(dev, "Cannot send GPUFreq IPI command: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ wait = wait_for_completion_timeout(&mfg->gf_mbox->rx_done, msecs_to_jiffies(500));
+ if (!wait)
+ return -ETIMEDOUT;
+
+ msg = mfg->gf_mbox->rx_data;
+
+ if (msg->u.return_value < 0) {
+ dev_err(dev, "IPI return: %d\n", msg->u.return_value);
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+static int mtk_mfg_init_shared_mem(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct mtk_mfg_ipi_msg msg = {};
+ int ret;
+
+ dev_dbg(dev, "clearing GPUEB shared memory, 0x%X bytes\n", mfg->shared_mem_size);
+ memset_io(mfg->shared_mem, 0, mfg->shared_mem_size);
+
+ msg.cmd = CMD_INIT_SHARED_MEM;
+ msg.u.shared_mem.base = mfg->shared_mem_phys;
+ msg.u.shared_mem.size = mfg->shared_mem_size;
+
+ ret = mtk_mfg_send_ipi(mfg, &msg);
+ if (ret)
+ return ret;
+
+ if (readl(mfg->shared_mem + GF_REG_MAGIC) != GPUEB_MEM_MAGIC) {
+ dev_err(dev, "EB did not initialise shared memory correctly\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mtk_mfg_power_control(struct mtk_mfg *mfg, bool enabled)
+{
+ struct mtk_mfg_ipi_msg msg = {};
+
+ msg.cmd = CMD_POWER_CONTROL;
+ msg.u.power_state = enabled ? 1 : 0;
+
+ return mtk_mfg_send_ipi(mfg, &msg);
+}
+
+static int mtk_mfg_set_oppidx(struct mtk_mfg *mfg, unsigned int opp_idx)
+{
+ struct mtk_mfg_ipi_msg msg = {};
+ int ret;
+
+ if (opp_idx >= mfg->num_gpu_opps)
+ return -EINVAL;
+
+ msg.cmd = CMD_FIX_DUAL_TARGET_OPPIDX;
+ msg.u.dual_commit.gpu_oppidx = opp_idx;
+ msg.u.dual_commit.stack_oppidx = opp_idx;
+
+ ret = mtk_mfg_send_ipi(mfg, &msg);
+ if (ret) {
+ dev_err(&mfg->pdev->dev, "Failed to set OPP %u: %pe\n",
+ opp_idx, ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_mfg_read_opp_tables(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct mtk_mfg_opp_entry e = {};
+ unsigned int i;
+
+ mfg->num_gpu_opps = readl(mfg->shared_mem + GF_REG_GPU_OPP_NUM);
+ mfg->num_stack_opps = readl(mfg->shared_mem + GF_REG_STK_OPP_NUM);
+
+ if (mfg->num_gpu_opps > MAX_OPP_NUM || mfg->num_gpu_opps == 0) {
+ dev_err(dev, "GPU OPP count (%u) out of range %u >= count > 0\n",
+ mfg->num_gpu_opps, MAX_OPP_NUM);
+ return -EINVAL;
+ }
+
+ if (mfg->num_stack_opps && mfg->num_stack_opps > MAX_OPP_NUM) {
+ dev_err(dev, "Stack OPP count (%u) out of range %u >= count >= 0\n",
+ mfg->num_stack_opps, MAX_OPP_NUM);
+ return -EINVAL;
+ }
+
+ mfg->gpu_opps = devm_kcalloc(dev, mfg->num_gpu_opps,
+ sizeof(struct dev_pm_opp_data), GFP_KERNEL);
+ if (!mfg->gpu_opps)
+ return -ENOMEM;
+
+ if (mfg->num_stack_opps) {
+ mfg->stack_opps = devm_kcalloc(dev, mfg->num_stack_opps,
+ sizeof(struct dev_pm_opp_data), GFP_KERNEL);
+ if (!mfg->stack_opps)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < mfg->num_gpu_opps; i++) {
+ memcpy_fromio(&e, mfg->shared_mem + GF_REG_OPP_TABLE_GPU + i * sizeof(e),
+ sizeof(e));
+ if (mem_is_zero(&e, sizeof(e))) {
+ dev_err(dev, "ran into an empty GPU OPP at index %u\n",
+ i);
+ return -EINVAL;
+ }
+ mfg->gpu_opps[i].freq = e.freq_khz * HZ_PER_KHZ;
+ mfg->gpu_opps[i].u_volt = e.voltage_core * 10;
+ mfg->gpu_opps[i].level = i;
+ if (i < mfg->variant->turbo_below)
+ mfg->gpu_opps[i].turbo = true;
+ }
+
+ for (i = 0; i < mfg->num_stack_opps; i++) {
+ memcpy_fromio(&e, mfg->shared_mem + GF_REG_OPP_TABLE_STK + i * sizeof(e),
+ sizeof(e));
+ if (mem_is_zero(&e, sizeof(e))) {
+ dev_err(dev, "ran into an empty Stack OPP at index %u\n",
+ i);
+ return -EINVAL;
+ }
+ mfg->stack_opps[i].freq = e.freq_khz * HZ_PER_KHZ;
+ mfg->stack_opps[i].u_volt = e.voltage_core * 10;
+ mfg->stack_opps[i].level = i;
+ if (i < mfg->variant->turbo_below)
+ mfg->stack_opps[i].turbo = true;
+ }
+
+ return 0;
+}
+
+static const char *const mtk_mfg_mt8196_clk_names[] = {
+ "core",
+ "stack0",
+ "stack1",
+};
+
+static const char *const mtk_mfg_mt8196_regulators[] = {
+ "core",
+ "stack",
+ "sram",
+};
+
+static int mtk_mfg_mt8196_init(struct mtk_mfg *mfg)
+{
+ void __iomem *e2_base;
+
+ e2_base = devm_platform_ioremap_resource_byname(mfg->pdev, "hw-revision");
+ if (IS_ERR(e2_base))
+ return dev_err_probe(&mfg->pdev->dev, PTR_ERR(e2_base),
+ "Couldn't get hw-revision register\n");
+
+ clk_prepare_enable(mfg->clk_eb);
+
+ if (readl(e2_base) == MFG_MT8196_E2_ID)
+ mfg->ghpm_en_reg = RPC_DUMMY_REG_2;
+ else
+ mfg->ghpm_en_reg = RPC_GHPM_CFG0_CON;
+
+ clk_disable_unprepare(mfg->clk_eb);
+
+ return 0;
+}
+
+static const struct mtk_mfg_variant mtk_mfg_mt8196_variant = {
+ .clk_names = mtk_mfg_mt8196_clk_names,
+ .num_clks = ARRAY_SIZE(mtk_mfg_mt8196_clk_names),
+ .regulator_names = mtk_mfg_mt8196_regulators,
+ .num_regulators = ARRAY_SIZE(mtk_mfg_mt8196_regulators),
+ .turbo_below = 7,
+ .init = mtk_mfg_mt8196_init,
+};
+
+static void mtk_mfg_mbox_rx_callback(struct mbox_client *cl, void *mssg)
+{
+ struct mtk_mfg_mbox *mb = container_of(cl, struct mtk_mfg_mbox, cl);
+
+ if (mb->rx_data)
+ mb->rx_data = memcpy(mb->rx_data, mssg, GPUEB_MBOX_MAX_RX_SIZE);
+ complete(&mb->rx_done);
+}
+
+static int mtk_mfg_attach_dev(struct generic_pm_domain *pd, struct device *dev)
+{
+ struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
+ struct dev_pm_opp_data *so = mfg->stack_opps;
+ struct dev_pm_opp_data *go = mfg->gpu_opps;
+ struct dev_pm_opp_data *prev_o = NULL;
+ struct dev_pm_opp_data *o;
+ int i, ret;
+
+ for (i = mfg->num_gpu_opps - 1; i >= 0; i--) {
+ /*
+ * Adding the lower of the two OPPs avoids gaps of indices in
+ * situations where the GPU OPPs are duplicated a couple of
+ * times when only the Stack OPP is being lowered at that index.
+ */
+ if (i >= mfg->num_stack_opps || go[i].freq < so[i].freq)
+ o = &go[i];
+ else
+ o = &so[i];
+
+ /*
+ * Skip indices where both GPU and Stack OPPs are equal. Nominally,
+ * OPP core shouldn't care about dupes, but not doing so will cause
+ * dev_pm_opp_find_freq_ceil_indexed to -ERANGE later down the line.
+ */
+ if (prev_o && prev_o->freq == o->freq)
+ continue;
+
+ ret = dev_pm_opp_add_dynamic(dev, o);
+ if (ret) {
+ dev_err(dev, "Failed to add OPP level %u from PD %s: %pe\n",
+ o->level, pd->name, ERR_PTR(ret));
+ dev_pm_opp_remove_all_dynamic(dev);
+ return ret;
+ }
+ prev_o = o;
+ }
+
+ return 0;
+}
+
+static void mtk_mfg_detach_dev(struct generic_pm_domain *pd, struct device *dev)
+{
+ dev_pm_opp_remove_all_dynamic(dev);
+}
+
+static int mtk_mfg_set_performance(struct generic_pm_domain *pd,
+ unsigned int state)
+{
+ struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
+
+ /*
+ * pmdomain core intentionally sets a performance state before turning
+ * a domain on, and after turning it off. For the GPUEB however, it's
+ * only possible to act on performance requests when the GPUEB is
+ * powered on. To do this, return cleanly without taking action, and
+ * defer setting what pmdomain core set in mtk_mfg_power_on.
+ */
+ if (mfg->pd.status != GENPD_STATE_ON)
+ return 0;
+
+ return mtk_mfg_set_oppidx(mfg, state);
+}
+
+static int mtk_mfg_power_on(struct generic_pm_domain *pd)
+{
+ struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
+ int ret;
+
+ ret = regulator_bulk_enable(mfg->variant->num_regulators,
+ mfg->gpu_regs);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(mfg->clk_eb);
+ if (ret)
+ goto err_disable_regulators;
+
+ ret = clk_bulk_prepare_enable(mfg->variant->num_clks, mfg->gpu_clks);
+ if (ret)
+ goto err_disable_eb_clk;
+
+ ret = mtk_mfg_eb_on(mfg);
+ if (ret)
+ goto err_disable_clks;
+
+ mfg->ipi_magic = readl(mfg->gpr + GPR_IPI_MAGIC);
+
+ ret = mtk_mfg_power_control(mfg, true);
+ if (ret)
+ goto err_eb_off;
+
+ /* Don't try to set a OPP in probe before OPPs have been read from EB */
+ if (mfg->gpu_opps) {
+ /* The aforementioned deferred setting of pmdomain's state */
+ ret = mtk_mfg_set_oppidx(mfg, pd->performance_state);
+ if (ret)
+ dev_warn(&mfg->pdev->dev, "Failed to set oppidx in %s\n", __func__);
+ }
+
+ return 0;
+
+err_eb_off:
+ mtk_mfg_eb_off(mfg);
+err_disable_clks:
+ clk_bulk_disable_unprepare(mfg->variant->num_clks, mfg->gpu_clks);
+err_disable_eb_clk:
+ clk_disable_unprepare(mfg->clk_eb);
+err_disable_regulators:
+ regulator_bulk_disable(mfg->variant->num_regulators, mfg->gpu_regs);
+
+ return ret;
+}
+
+static int mtk_mfg_power_off(struct generic_pm_domain *pd)
+{
+ struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
+ struct device *dev = &mfg->pdev->dev;
+ int ret;
+
+ ret = mtk_mfg_power_control(mfg, false);
+ if (ret) {
+ dev_err(dev, "power_control failed: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = mtk_mfg_eb_off(mfg);
+ if (ret) {
+ dev_err(dev, "eb_off failed: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ clk_bulk_disable_unprepare(mfg->variant->num_clks, mfg->gpu_clks);
+ clk_disable_unprepare(mfg->clk_eb);
+ ret = regulator_bulk_disable(mfg->variant->num_regulators, mfg->gpu_regs);
+ if (ret) {
+ dev_err(dev, "Disabling regulators failed: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_mfg_init_mbox(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct mtk_mfg_mbox *gf;
+ struct mtk_mfg_mbox *slp;
+
+ gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
+ if (!gf)
+ return -ENOMEM;
+
+ gf->rx_data = devm_kzalloc(dev, GPUEB_MBOX_MAX_RX_SIZE, GFP_KERNEL);
+ if (!gf->rx_data)
+ return -ENOMEM;
+
+ gf->mfg = mfg;
+ init_completion(&gf->rx_done);
+ gf->cl.dev = dev;
+ gf->cl.rx_callback = mtk_mfg_mbox_rx_callback;
+ gf->cl.tx_tout = GPUEB_TIMEOUT_US / USEC_PER_MSEC;
+ gf->ch = mbox_request_channel_byname(&gf->cl, "gpufreq");
+ if (IS_ERR(gf->ch))
+ return PTR_ERR(gf->ch);
+
+ mfg->gf_mbox = gf;
+
+ slp = devm_kzalloc(dev, sizeof(*slp), GFP_KERNEL);
+ if (!slp)
+ return -ENOMEM;
+
+ slp->mfg = mfg;
+ init_completion(&slp->rx_done);
+ slp->cl.dev = dev;
+ slp->cl.tx_tout = GPUEB_TIMEOUT_US / USEC_PER_MSEC;
+ slp->cl.tx_block = true;
+ slp->ch = mbox_request_channel_byname(&slp->cl, "sleep");
+ if (IS_ERR(slp->ch)) {
+ mbox_free_channel(gf->ch);
+ return PTR_ERR(slp->ch);
+ }
+
+ mfg->slp_mbox = slp;
+
+ return 0;
+}
+
+static int mtk_mfg_init_clk_provider(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct clk_hw_onecell_data *clk_data;
+ int ret;
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, 2), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = 2;
+
+ mfg->clk_core_hw.init = &mtk_mfg_clk_gpu_init;
+ mfg->clk_stack_hw.init = &mtk_mfg_clk_stack_init;
+
+ ret = devm_clk_hw_register(dev, &mfg->clk_core_hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't register GPU core clock\n");
+
+ ret = devm_clk_hw_register(dev, &mfg->clk_stack_hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't register GPU stack clock\n");
+
+ clk_data->hws[0] = &mfg->clk_core_hw;
+ clk_data->hws[1] = &mfg->clk_stack_hw;
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't register clock provider\n");
+
+ return 0;
+}
+
+static int mtk_mfg_read_nvmem(void *priv, unsigned int offset, void *val, size_t bytes)
+{
+ struct mtk_mfg *mfg = priv;
+ u32 *buf = val;
+
+ if (bytes != 4)
+ return -EINVAL;
+
+ if (!mfg->shared_mem)
+ return -ENODEV;
+
+ if (offset + bytes >= mfg->shared_mem_size)
+ return -EINVAL;
+
+ *buf = readl(mfg->shared_mem + offset);
+
+ return 0;
+}
+
+static int mtk_mfg_init_nvmem_provider(struct mtk_mfg *mfg)
+{
+ struct device *dev = &mfg->pdev->dev;
+ struct nvmem_cell_info cell = {};
+ struct nvmem_config config = {};
+ struct nvmem_device *nvdev;
+ int ret;
+
+ config.reg_read = mtk_mfg_read_nvmem;
+ config.dev = dev;
+ config.read_only = true;
+ config.priv = mfg;
+ config.size = 4;
+ config.word_size = 4;
+
+ nvdev = devm_nvmem_register(dev, &config);
+ if (IS_ERR(nvdev))
+ return dev_err_probe(dev, PTR_ERR(nvdev), "Couldn't register nvmem provider\n");
+
+ cell.name = "shader-present";
+ cell.offset = GF_REG_SHADER_PRESENT;
+ cell.bytes = 4;
+ cell.np = of_get_child_by_name(dev->of_node, cell.name);
+
+ ret = nvmem_add_one_cell(nvdev, &cell);
+ if (ret) {
+ of_node_put(cell.np);
+ return dev_err_probe(dev, ret, "Couldn't add cell %s\n", cell.name);
+ }
+
+ /* cell.np purposefully not put as nvmem_add_one_cell does not increase refcount */
+
+ return 0;
+}
+
+static int mtk_mfg_probe(struct platform_device *pdev)
+{
+ struct mtk_mfg *mfg;
+ struct device *dev = &pdev->dev;
+ const struct mtk_mfg_variant *data = of_device_get_match_data(dev);
+ struct resource res;
+ int ret, i;
+
+ mfg = devm_kzalloc(dev, sizeof(*mfg), GFP_KERNEL);
+ if (!mfg)
+ return -ENOMEM;
+
+ mfg->pdev = pdev;
+ mfg->variant = data;
+
+ dev_set_drvdata(dev, mfg);
+
+ mfg->gpr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mfg->gpr))
+ return dev_err_probe(dev, PTR_ERR(mfg->gpr),
+ "Couldn't retrieve GPR MMIO registers\n");
+
+ mfg->rpc = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(mfg->rpc))
+ return dev_err_probe(dev, PTR_ERR(mfg->rpc),
+ "Couldn't retrieve RPC MMIO registers\n");
+
+ mfg->clk_eb = devm_clk_get(dev, "eb");
+ if (IS_ERR(mfg->clk_eb))
+ return dev_err_probe(dev, PTR_ERR(mfg->clk_eb),
+ "Couldn't get 'eb' clock\n");
+
+ mfg->gpu_clks = devm_kcalloc(dev, data->num_clks, sizeof(*mfg->gpu_clks),
+ GFP_KERNEL);
+ if (!mfg->gpu_clks)
+ return -ENOMEM;
+
+ for (i = 0; i < data->num_clks; i++)
+ mfg->gpu_clks[i].id = data->clk_names[i];
+
+ ret = devm_clk_bulk_get(dev, data->num_clks, mfg->gpu_clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't get GPU clocks\n");
+
+ mfg->gpu_regs = devm_kcalloc(dev, data->num_regulators,
+ sizeof(*mfg->gpu_regs), GFP_KERNEL);
+ if (!mfg->gpu_regs)
+ return -ENOMEM;
+
+ for (i = 0; i < data->num_regulators; i++)
+ mfg->gpu_regs[i].supply = data->regulator_names[i];
+
+ ret = devm_regulator_bulk_get(dev, data->num_regulators, mfg->gpu_regs);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't get GPU regulators\n");
+
+ ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't get GPUEB shared memory\n");
+
+ mfg->shared_mem = devm_ioremap(dev, res.start, resource_size(&res));
+ if (!mfg->shared_mem)
+ return dev_err_probe(dev, -ENOMEM, "Can't ioremap GPUEB shared memory\n");
+ mfg->shared_mem_size = resource_size(&res);
+ mfg->shared_mem_phys = res.start;
+
+ if (data->init) {
+ ret = data->init(mfg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Variant init failed\n");
+ }
+
+ mfg->pd.name = dev_name(dev);
+ mfg->pd.attach_dev = mtk_mfg_attach_dev;
+ mfg->pd.detach_dev = mtk_mfg_detach_dev;
+ mfg->pd.power_off = mtk_mfg_power_off;
+ mfg->pd.power_on = mtk_mfg_power_on;
+ mfg->pd.set_performance_state = mtk_mfg_set_performance;
+ mfg->pd.flags = GENPD_FLAG_OPP_TABLE_FW;
+
+ ret = pm_genpd_init(&mfg->pd, NULL, false);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to initialise power domain\n");
+
+ ret = mtk_mfg_init_mbox(mfg);
+ if (ret) {
+ dev_err_probe(dev, ret, "Couldn't initialise mailbox\n");
+ goto err_remove_genpd;
+ }
+
+ ret = mtk_mfg_power_on(&mfg->pd);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to power on MFG\n");
+ goto err_free_mbox;
+ }
+
+ ret = mtk_mfg_init_shared_mem(mfg);
+ if (ret) {
+ dev_err_probe(dev, ret, "Couldn't initialize EB shared memory\n");
+ goto err_power_off;
+ }
+
+ ret = mtk_mfg_read_opp_tables(mfg);
+ if (ret) {
+ dev_err_probe(dev, ret, "Error reading OPP tables from EB\n");
+ goto err_power_off;
+ }
+
+ ret = mtk_mfg_init_clk_provider(mfg);
+ if (ret)
+ goto err_power_off;
+
+ ret = mtk_mfg_init_nvmem_provider(mfg);
+ if (ret)
+ goto err_power_off;
+
+ ret = of_genpd_add_provider_simple(dev->of_node, &mfg->pd);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to add pmdomain provider\n");
+ goto err_power_off;
+ }
+
+ return 0;
+
+err_power_off:
+ mtk_mfg_power_off(&mfg->pd);
+err_free_mbox:
+ mbox_free_channel(mfg->slp_mbox->ch);
+ mfg->slp_mbox->ch = NULL;
+ mbox_free_channel(mfg->gf_mbox->ch);
+ mfg->gf_mbox->ch = NULL;
+err_remove_genpd:
+ pm_genpd_remove(&mfg->pd);
+
+ return ret;
+}
+
+static const struct of_device_id mtk_mfg_of_match[] = {
+ { .compatible = "mediatek,mt8196-gpufreq", .data = &mtk_mfg_mt8196_variant },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mtk_mfg_of_match);
+
+static void mtk_mfg_remove(struct platform_device *pdev)
+{
+ struct mtk_mfg *mfg = dev_get_drvdata(&pdev->dev);
+
+ if (mtk_mfg_is_powered_on(mfg))
+ mtk_mfg_power_off(&mfg->pd);
+
+ of_genpd_del_provider(pdev->dev.of_node);
+ pm_genpd_remove(&mfg->pd);
+
+ mbox_free_channel(mfg->gf_mbox->ch);
+ mfg->gf_mbox->ch = NULL;
+
+ mbox_free_channel(mfg->slp_mbox->ch);
+ mfg->slp_mbox->ch = NULL;
+}
+
+static struct platform_driver mtk_mfg_driver = {
+ .driver = {
+ .name = "mtk-mfg-pmdomain",
+ .of_match_table = mtk_mfg_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = mtk_mfg_probe,
+ .remove = mtk_mfg_remove,
+};
+module_platform_driver(mtk_mfg_driver);
+
+MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli@collabora.com>");
+MODULE_DESCRIPTION("MediaTek MFlexGraphics Power Domain Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
new file mode 100644
index 000000000..f0fa79e01
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -0,0 +1,1461 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 Collabora Ltd.
+ */
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#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"
+#include "mt6858-pm-domains.h"
+#include "mt6893-pm-domains.h"
+#include "mt8167-pm-domains.h"
+#include "mt8173-pm-domains.h"
+#include "mt8183-pm-domains.h"
+#include "mt8186-pm-domains.h"
+#include "mt8188-pm-domains.h"
+#include "mt8189-pm-domains.h"
+#include "mt8192-pm-domains.h"
+#include "mt8195-pm-domains.h"
+#include "mt8196-pm-domains.h"
+#include "mt8365-pm-domains.h"
+
+#define MTK_POLL_DELAY_US 10
+#define MTK_POLL_TIMEOUT USEC_PER_SEC
+
+#define MTK_HWV_POLL_DELAY_US 5
+#define MTK_HWV_POLL_TIMEOUT (300 * USEC_PER_MSEC)
+
+#define MTK_HWV_PREPARE_DELAY_US 1
+#define MTK_HWV_PREPARE_TIMEOUT (3 * USEC_PER_MSEC)
+
+#define PWR_RST_B_BIT BIT(0)
+#define PWR_ISO_BIT BIT(1)
+#define PWR_ON_BIT BIT(2)
+#define PWR_ON_2ND_BIT BIT(3)
+#define PWR_CLK_DIS_BIT BIT(4)
+#define PWR_SRAM_CLKISO_BIT BIT(5)
+#define PWR_SRAM_ISOINT_B_BIT BIT(6)
+
+#define PWR_RTFF_SAVE BIT(24)
+#define PWR_RTFF_NRESTORE BIT(25)
+#define PWR_RTFF_CLK_DIS BIT(26)
+#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)
+
+/* Secure MTCMOS commands for modem subsystem */
+#define MTK_MD_MTCMOS_ENABLE 18
+#define MTK_MD_MTCMOS_DISABLE 19
+
+struct scpsys_domain {
+ struct generic_pm_domain genpd;
+ const struct scpsys_domain_data *data;
+ const struct scpsys_hwv_domain_data *hwv_data;
+ struct scpsys *scpsys;
+ int num_clks;
+ struct clk_bulk_data *clks;
+ int num_subsys_clks;
+ struct clk_bulk_data *subsys_clks;
+ struct regulator *supply;
+};
+
+struct scpsys {
+ struct device *dev;
+ struct regmap *base;
+ const struct scpsys_soc_data *soc_data;
+ u8 bus_prot_index[BUS_PROT_BLOCK_COUNT];
+ struct regmap **bus_prot;
+ struct genpd_onecell_data pd_data;
+ struct generic_pm_domain *domains[];
+};
+
+#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
+
+static bool scpsys_domain_is_on(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ u32 mask = pd->data->sta_mask;
+ u32 status, status2, mask2;
+
+ mask2 = pd->data->sta2nd_mask ? pd->data->sta2nd_mask : mask;
+
+ regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
+ status &= mask;
+
+ regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
+ status2 &= mask2;
+
+ /* A domain is on when both status bits are set. */
+ return status && status2;
+}
+
+static bool scpsys_hwv_domain_is_disable_done(struct scpsys_domain *pd)
+{
+ const struct scpsys_hwv_domain_data *hwv = pd->hwv_data;
+ u32 regs[2] = { hwv->done, hwv->clr_sta };
+ u32 val[2];
+ u32 mask = BIT(hwv->setclr_bit);
+
+ regmap_multi_reg_read(pd->scpsys->base, regs, val, 2);
+
+ /* Disable is done when the bit is set in DONE, cleared in CLR_STA */
+ return (val[0] & mask) && !(val[1] & mask);
+}
+
+static bool scpsys_hwv_domain_is_enable_done(struct scpsys_domain *pd)
+{
+ const struct scpsys_hwv_domain_data *hwv = pd->hwv_data;
+ u32 regs[3] = { hwv->done, hwv->en, hwv->set_sta };
+ u32 val[3];
+ u32 mask = BIT(hwv->setclr_bit);
+
+ regmap_multi_reg_read(pd->scpsys->base, regs, val, 3);
+
+ /* Enable is done when the bit is set in DONE and EN, cleared in SET_STA */
+ 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;
+ struct scpsys *scpsys = pd->scpsys;
+ unsigned int tmp;
+ int ret;
+
+ 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) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
+ udelay(1);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
+ }
+
+ return 0;
+}
+
+static int scpsys_sram_disable(struct scpsys_domain *pd)
+{
+ u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
+ struct scpsys *scpsys = pd->scpsys;
+ unsigned int tmp;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
+ udelay(1);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
+ }
+
+ 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) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
+ const struct scpsys_bus_prot_data *bpd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ unsigned short block_idx = scpsys->bus_prot_index[bpd->bus_prot_block];
+
+ return scpsys->bus_prot[block_idx];
+}
+
+static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
+ const struct scpsys_bus_prot_data *bpd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ int block_idx = scpsys->bus_prot_index[bpd->bus_prot_sta_block];
+
+ return scpsys->bus_prot[block_idx];
+}
+
+static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
+ const struct scpsys_bus_prot_data *bpd)
+{
+ struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
+ struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
+ u32 sta_mask = bpd->bus_prot_sta_mask;
+ u32 expected_ack;
+ u32 val;
+
+ expected_ack = (bpd->bus_prot_sta_block == BUS_PROT_BLOCK_INFRA_NAO ? sta_mask : 0);
+
+ if (bpd->flags & BUS_PROT_REG_UPDATE)
+ regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
+ else
+ regmap_write(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
+
+ if (bpd->flags & BUS_PROT_IGNORE_CLR_ACK)
+ return 0;
+
+ return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
+ val, (val & sta_mask) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static int scpsys_bus_protect_set(struct scpsys_domain *pd,
+ const struct scpsys_bus_prot_data *bpd)
+{
+ struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
+ struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
+ u32 sta_mask = bpd->bus_prot_sta_mask;
+ u32 val;
+
+ if (bpd->flags & BUS_PROT_REG_UPDATE)
+ regmap_set_bits(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
+ else
+ regmap_write(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
+
+ return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
+ val, (val & sta_mask) == sta_mask,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static int scpsys_bus_protect_enable(struct scpsys_domain *pd, u8 flags)
+{
+ for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
+ const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
+ int ret;
+
+ if (!bpd->bus_prot_set_clr_mask)
+ break;
+
+ if ((bpd->flags & BUS_PROT_IGNORE_SUBCLK) !=
+ (flags & BUS_PROT_IGNORE_SUBCLK))
+ continue;
+
+ if (bpd->flags & BUS_PROT_INVERTED)
+ ret = scpsys_bus_protect_clear(pd, bpd);
+ else
+ ret = scpsys_bus_protect_set(pd, bpd);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scpsys_bus_protect_disable(struct scpsys_domain *pd, u8 flags)
+{
+ for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
+ const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
+ int ret;
+
+ if (!bpd->bus_prot_set_clr_mask)
+ continue;
+
+ if ((bpd->flags & BUS_PROT_IGNORE_SUBCLK) !=
+ (flags & BUS_PROT_IGNORE_SUBCLK))
+ continue;
+
+ if (bpd->flags & BUS_PROT_INVERTED)
+ ret = scpsys_bus_protect_set(pd, bpd);
+ else
+ ret = scpsys_bus_protect_clear(pd, bpd);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scpsys_regulator_enable(struct regulator *supply)
+{
+ return supply ? regulator_enable(supply) : 0;
+}
+
+static int scpsys_regulator_disable(struct regulator *supply)
+{
+ return supply ? regulator_disable(supply) : 0;
+}
+
+static int scpsys_hwv_power_on(struct generic_pm_domain *genpd)
+{
+ struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+ const struct scpsys_hwv_domain_data *hwv = pd->hwv_data;
+ struct scpsys *scpsys = pd->scpsys;
+ 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)
+ goto err_infra;
+
+ ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+ if (ret)
+ goto err_reg;
+
+ /* For HWV the subsys clocks refer to the HWV low power subsystem */
+ ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
+ if (ret)
+ goto err_disable_clks;
+
+ /* Make sure the HW Voter is idle and able to accept commands */
+ ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->done, val,
+ val & BIT(hwv->setclr_bit),
+ MTK_HWV_POLL_DELAY_US,
+ MTK_HWV_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(scpsys->dev, "Failed to power on: HW Voter busy.\n");
+ goto err_disable_subsys_clks;
+ }
+
+ /*
+ * Instruct the HWV to power on the MTCMOS (power domain): after that,
+ * the same bit will be unset immediately by the hardware.
+ */
+ regmap_write(scpsys->base, hwv->set, BIT(hwv->setclr_bit));
+
+ /*
+ * Wait until the HWV sets the bit again, signalling that its internal
+ * state machine was started and it now processing the vote command.
+ */
+ ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->set, val,
+ val & BIT(hwv->setclr_bit),
+ MTK_HWV_PREPARE_DELAY_US,
+ MTK_HWV_PREPARE_TIMEOUT);
+ if (ret) {
+ dev_err(scpsys->dev, "Failed to power on: HW Voter not starting.\n");
+ goto err_disable_subsys_clks;
+ }
+
+ /* Wait for ACK, signalling that the MTCMOS was enabled */
+ ret = readx_poll_timeout_atomic(scpsys_hwv_domain_is_enable_done, pd, val, val,
+ MTK_HWV_POLL_DELAY_US, MTK_HWV_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(scpsys->dev, "Failed to power on: HW Voter ACK timeout.\n");
+ goto err_disable_subsys_clks;
+ }
+
+ /* 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_subsys_clks, pd->subsys_clks);
+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;
+};
+
+static int scpsys_hwv_power_off_internal(struct scpsys_domain *pd)
+{
+ const struct scpsys_hwv_domain_data *hwv = pd->hwv_data;
+ struct scpsys *scpsys = pd->scpsys;
+ 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)
+ 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,
+ val & BIT(hwv->setclr_bit),
+ MTK_HWV_POLL_DELAY_US,
+ MTK_HWV_POLL_TIMEOUT);
+ if (ret)
+ goto err_disable_subsys_clks;
+
+
+ /*
+ * Instruct the HWV to power off the MTCMOS (power domain): differently
+ * from poweron, the bit will be kept set.
+ */
+ regmap_write(scpsys->base, hwv->clr, BIT(hwv->setclr_bit));
+
+ /*
+ * Wait until the HWV clears the bit, signalling that its internal
+ * state machine was started and it now processing the clear command.
+ */
+ ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->clr, val,
+ !(val & BIT(hwv->setclr_bit)),
+ MTK_HWV_PREPARE_DELAY_US,
+ MTK_HWV_PREPARE_TIMEOUT);
+ if (ret)
+ goto err_disable_subsys_clks;
+
+ /* Poweroff needs 100us for the HW to stabilize */
+ udelay(100);
+
+ /* Wait for ACK, signalling that the MTCMOS was disabled */
+ ret = readx_poll_timeout_atomic(scpsys_hwv_domain_is_disable_done, pd, val, val,
+ MTK_HWV_POLL_DELAY_US, MTK_HWV_POLL_TIMEOUT);
+ if (ret)
+ goto err_disable_subsys_clks;
+
+ clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+
+ 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;
+};
+
+static int scpsys_hwv_power_off(struct generic_pm_domain *genpd)
+{
+ struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+
+ return scpsys_hwv_power_off_internal(pd);
+}
+
+static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ bool do_rtff_nrestore, tmp;
+ int ret;
+
+ /* subsys power on */
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
+
+ /* wait until PWR_ACK = 1 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+ /*
+ * RTFF HW state may be modified by secure world or remote processors.
+ *
+ * With the only exception of STOR_UFS, which always needs save/restore,
+ * check if this power domain's RTFF is already on before trying to do
+ * the NRESTORE procedure, otherwise the system will lock up.
+ */
+ switch (pd->data->rtff_type) {
+ case SCPSYS_RTFF_TYPE_GENERIC:
+ case SCPSYS_RTFF_TYPE_PCIE_PHY:
+ {
+ u32 ctl_status;
+
+ regmap_read(scpsys->base, pd->data->ctl_offs, &ctl_status);
+ do_rtff_nrestore = ctl_status & PWR_RTFF_SAVE_FLAG;
+ break;
+ }
+ case SCPSYS_RTFF_TYPE_STOR_UFS:
+ /* STOR_UFS always needs NRESTORE */
+ do_rtff_nrestore = true;
+ break;
+ default:
+ do_rtff_nrestore = false;
+ break;
+ }
+
+ /* Return early if RTFF NRESTORE shall not be done */
+ if (!do_rtff_nrestore)
+ return 0;
+
+ switch (pd->data->rtff_type) {
+ case SCPSYS_RTFF_TYPE_GENERIC:
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+ break;
+ case SCPSYS_RTFF_TYPE_PCIE_PHY:
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+ break;
+ case SCPSYS_RTFF_TYPE_STOR_UFS:
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+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:
+ case SCPSYS_RTFF_TYPE_PCIE_PHY:
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
+ break;
+ case SCPSYS_RTFF_TYPE_STOR_UFS:
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
+ break;
+ default:
+ break;
+ }
+
+ /* subsys power off */
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
+
+ /* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
+ if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
+ udelay(1);
+
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+ 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)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ bool tmp;
+ int ret;
+
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SKIP_RESET_B))
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
+
+ /* wait until PWR_ACK = 1 */
+ 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_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 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);
+ struct scpsys *scpsys = pd->scpsys;
+ int ret;
+
+ ret = scpsys_regulator_enable(pd->supply);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+ if (ret)
+ goto err_reg;
+
+ if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
+ 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_SECURE_PWRSEQ))
+ ret = scpsys_modem_sec_power_on(true);
+ else 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);
+
+ if (ret)
+ goto err_pwr_ack;
+
+ /*
+ * In MT8189 mminfra power domain, the bus protect policy separates
+ * into two parts, one is set before subsys clocks enabled, and another
+ * need to enable after subsys clocks enable.
+ */
+ ret = scpsys_bus_protect_disable(pd, BUS_PROT_IGNORE_SUBCLK);
+ if (ret < 0)
+ goto err_pwr_ack;
+
+ /*
+ * In few Mediatek platforms(e.g. MT6779), the bus protect policy is
+ * stricter, which leads to bus protect release must be prior to bus
+ * access.
+ */
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
+ ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
+ pd->subsys_clks);
+ if (ret)
+ goto err_pwr_ack;
+ }
+
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ) &&
+ !MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE_PWRSEQ)) {
+ ret = scpsys_sram_enable(pd);
+ if (ret < 0)
+ goto err_disable_subsys_clks;
+ }
+
+ ret = scpsys_bus_protect_disable(pd, 0);
+ if (ret < 0)
+ goto err_disable_sram;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
+ ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
+ pd->subsys_clks);
+ if (ret)
+ goto err_enable_bus_protect;
+ }
+
+ return 0;
+
+err_enable_bus_protect:
+ scpsys_bus_protect_enable(pd, 0);
+err_disable_sram:
+ if (!MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ) &&
+ !MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE_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,
+ pd->subsys_clks);
+err_pwr_ack:
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+err_reg:
+ scpsys_regulator_disable(pd->supply);
+ return ret;
+}
+
+static int scpsys_power_off_internal(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ int ret;
+
+ ret = scpsys_bus_protect_enable(pd, 0);
+ if (ret < 0)
+ return ret;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE_PWRSEQ)) {
+ ret = scpsys_modem_sec_power_on(false);
+ if (ret)
+ return ret;
+ } else 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,
+ pd->data->ext_buck_iso_mask);
+
+ clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+
+ ret = scpsys_bus_protect_enable(pd, BUS_PROT_IGNORE_SUBCLK);
+ if (ret < 0)
+ return ret;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
+ ret = scpsys_modem_pwrseq_off(pd);
+ else if (MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
+ ret = scpsys_simple_pwrseq_off(pd);
+ else if (!MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_SECURE_PWRSEQ))
+ ret = scpsys_ctl_pwrseq_off(pd);
+
+ if (ret < 0) {
+ /* Re-enable clocks so that next power off doesn't break the refcount */
+ int r = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
+
+ if (r)
+ dev_warn(scpsys->dev, "Could not re-enable clocks: %d\n", r);
+
+ return ret;
+ }
+
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+
+ scpsys_regulator_disable(pd->supply);
+
+ return 0;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+ struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+
+ return scpsys_power_off_internal(pd);
+}
+
+static struct
+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;
+ struct scpsys_domain *pd;
+ struct property *prop;
+ const char *clk_name;
+ int i, ret, num_clks;
+ struct clk *clk;
+ int clk_ind = 0;
+ u32 id;
+
+ ret = of_property_read_u32(node, "reg", &id);
+ if (ret) {
+ dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
+ node, ret);
+ return ERR_PTR(-EINVAL);
+ }
+
+ switch (scpsys->soc_data->type) {
+ case SCPSYS_MTCMOS_TYPE_DIRECT_CTL:
+ if (id >= scpsys->soc_data->num_domains) {
+ dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ domain_data = &scpsys->soc_data->domains_data[id];
+ hwv_domain_data = NULL;
+
+ if (domain_data->sta_mask == 0) {
+ dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ break;
+ case SCPSYS_MTCMOS_TYPE_HW_VOTER:
+ if (id >= scpsys->soc_data->num_hwv_domains) {
+ dev_err(scpsys->dev, "%pOF: invalid HWV domain id %d\n", node, id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ domain_data = NULL;
+ hwv_domain_data = &scpsys->soc_data->hwv_domains_data[id];
+
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return ERR_PTR(-ENOMEM);
+
+ pd->data = domain_data;
+ pd->hwv_data = hwv_domain_data;
+ pd->scpsys = scpsys;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
+ pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
+ if (IS_ERR(pd->supply))
+ return dev_err_cast_probe(scpsys->dev, pd->supply,
+ "%pOF: failed to get power supply.\n",
+ node);
+ }
+
+ num_clks = of_clk_get_parent_count(node);
+ if (num_clks > 0) {
+ /* Calculate number of subsys_clks */
+ of_property_for_each_string(node, "clock-names", prop, clk_name) {
+ char *subsys;
+
+ subsys = strchr(clk_name, '-');
+ if (subsys)
+ pd->num_subsys_clks++;
+ else
+ pd->num_clks++;
+ }
+
+ pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
+ if (!pd->clks)
+ return ERR_PTR(-ENOMEM);
+
+ pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
+ sizeof(*pd->subsys_clks), GFP_KERNEL);
+ if (!pd->subsys_clks)
+ return ERR_PTR(-ENOMEM);
+
+ }
+
+ for (i = 0; i < pd->num_clks; i++) {
+ clk = of_clk_get(node, i);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err_probe(scpsys->dev, ret,
+ "%pOF: failed to get clk at index %d\n", node, i);
+ goto err_put_clocks;
+ }
+
+ pd->clks[clk_ind++].clk = clk;
+ }
+
+ for (i = 0; i < pd->num_subsys_clks; i++) {
+ clk = of_clk_get(node, i + clk_ind);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err_probe(scpsys->dev, ret,
+ "%pOF: failed to get clk at index %d\n", node,
+ i + clk_ind);
+ goto err_put_subsys_clocks;
+ }
+
+ pd->subsys_clks[i].clk = clk;
+ }
+
+ if (scpsys->domains[id]) {
+ ret = -EINVAL;
+ dev_err(scpsys->dev,
+ "power domain with id %d already exists, check your device-tree\n", id);
+ goto err_put_subsys_clocks;
+ }
+
+ if (pd->data && pd->data->name)
+ pd->genpd.name = pd->data->name;
+ else if (pd->hwv_data && pd->hwv_data->name)
+ pd->genpd.name = pd->hwv_data->name;
+ else
+ pd->genpd.name = node->name;
+
+ if (scpsys->soc_data->type == SCPSYS_MTCMOS_TYPE_DIRECT_CTL) {
+ pd->genpd.power_off = scpsys_power_off;
+ pd->genpd.power_on = scpsys_power_on;
+ } else {
+ pd->genpd.power_off = scpsys_hwv_power_off;
+ pd->genpd.power_on = scpsys_hwv_power_on;
+
+ /* HW-Voter code can be invoked in atomic context */
+ pd->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
+ }
+
+ /*
+ * Initially turn on all domains to make the domains usable
+ * with !CONFIG_PM and to get the hardware in sync with the
+ * software. The unused domains will be switched off during
+ * late_init time.
+ */
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
+ bool domain_is_on;
+
+ if (scpsys->soc_data->type == SCPSYS_MTCMOS_TYPE_HW_VOTER)
+ domain_is_on = scpsys_hwv_domain_is_enable_done(pd);
+ else
+ domain_is_on = scpsys_domain_is_on(pd);
+
+ if (domain_is_on)
+ dev_warn(scpsys->dev,
+ "%pOF: A default off power domain has been ON\n", node);
+ } else {
+ ret = pd->genpd.power_on(&pd->genpd);
+ if (ret < 0) {
+ dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
+ goto err_put_subsys_clocks;
+ }
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
+ pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+ }
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
+ pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
+ pm_genpd_init(&pd->genpd, NULL, true);
+ 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];
+
+err_put_subsys_clocks:
+ clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+err_put_clocks:
+ clk_bulk_put(pd->num_clks, pd->clks);
+ return ERR_PTR(ret);
+}
+
+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;
+ int ret;
+
+ for_each_child_of_node(parent, child) {
+ u32 id;
+
+ ret = of_property_read_u32(parent, "reg", &id);
+ if (ret) {
+ dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
+ goto err_put_node;
+ }
+
+ if (!scpsys->pd_data.domains[id]) {
+ ret = -EINVAL;
+ dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
+ goto err_put_node;
+ }
+
+ parent_pd = scpsys->pd_data.domains[id];
+
+ 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",
+ child);
+ goto err_put_node;
+ }
+
+ /* recursive call to add all subdomains */
+ ret = scpsys_add_subdomain(scpsys, child, domains_idx, num_domains);
+ if (ret)
+ goto err_put_node;
+
+ ret = pm_genpd_add_subdomain(parent_pd, child_pd);
+ if (ret) {
+ dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
+ child_pd->name, parent_pd->name);
+ goto err_put_node;
+ } else {
+ dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
+ child_pd->name);
+ }
+ }
+
+ return 0;
+
+err_put_node:
+ of_node_put(child);
+ return ret;
+}
+
+static void scpsys_remove_one_domain(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+ int ret;
+
+ /*
+ * We're in the error cleanup already, so we only complain,
+ * but won't emit another error on top of the original one.
+ */
+ ret = pm_genpd_remove(&pd->genpd);
+ if (ret < 0)
+ dev_err(pd->scpsys->dev,
+ "failed to remove domain '%s' : %d - state may be inconsistent\n",
+ pd->genpd.name, ret);
+
+ if (scpsys->soc_data->type == SCPSYS_MTCMOS_TYPE_HW_VOTER) {
+ if (scpsys_hwv_domain_is_enable_done(pd))
+ scpsys_hwv_power_off_internal(pd);
+ } else {
+ if (scpsys_domain_is_on(pd) || MTK_SCPD_CAPS(pd, MTK_SCPD_SIMPLE_PWRSEQ))
+ scpsys_power_off_internal(pd);
+ }
+
+ clk_bulk_put(pd->num_clks, pd->clks);
+ clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+}
+
+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 = 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);
+ }
+ }
+}
+
+static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)
+{
+ const u8 bp_blocks[3] = {
+ BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI, BUS_PROT_BLOCK_INFRA_NAO
+ };
+ struct device_node *np = dev->of_node;
+ struct device_node *node, *smi_np;
+ int num_regmaps = 0, i, j;
+ struct regmap *regmap[3];
+ int ret = 0;
+
+ /*
+ * Legacy code retrieves a maximum of three bus protection handles:
+ * some may be optional, or may not be, so the array of bp blocks
+ * that is normally passed in as platform data must be dynamically
+ * built in this case.
+ *
+ * Here, try to retrieve all of the regmaps that the legacy code
+ * supported and then count the number of the ones that are present,
+ * this makes it then possible to allocate the array of bus_prot
+ * regmaps and convert all to the new style handling.
+ */
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg");
+ if (node) {
+ regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
+ num_regmaps++;
+ if (IS_ERR(regmap[0])) {
+ ret = dev_err_probe(dev, PTR_ERR(regmap[0]),
+ "%pOF: failed to get infracfg regmap\n",
+ node);
+ of_node_put(node);
+ return ret;
+ }
+ of_node_put(node);
+ } else {
+ regmap[0] = NULL;
+ }
+
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,smi");
+ if (node) {
+ smi_np = of_parse_phandle(node, "mediatek,smi", 0);
+ if (!smi_np) {
+ of_node_put(node);
+ return -ENODEV;
+ }
+
+ regmap[1] = device_node_to_regmap(smi_np);
+ num_regmaps++;
+ of_node_put(smi_np);
+ if (IS_ERR(regmap[1])) {
+ ret = dev_err_probe(dev, PTR_ERR(regmap[1]),
+ "%pOF: failed to get SMI regmap\n",
+ node);
+ of_node_put(node);
+ return ret;
+ }
+ of_node_put(node);
+ } else {
+ regmap[1] = NULL;
+ }
+
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg-nao");
+ if (node) {
+ regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
+ num_regmaps++;
+ if (IS_ERR(regmap[2])) {
+ ret = dev_err_probe(dev, PTR_ERR(regmap[2]),
+ "%pOF: failed to get infracfg regmap\n",
+ node);
+ of_node_put(node);
+ return ret;
+ }
+ of_node_put(node);
+ } else {
+ 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)
+ return -ENOMEM;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(bp_blocks); i++) {
+ enum scpsys_bus_prot_block bp_type;
+
+ if (!regmap[i])
+ continue;
+
+ bp_type = bp_blocks[i];
+ scpsys->bus_prot_index[bp_type] = j;
+ scpsys->bus_prot[j] = regmap[i];
+
+ j++;
+ }
+
+ return 0;
+}
+
+static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys)
+{
+ const struct scpsys_soc_data *soc = scpsys->soc_data;
+ struct device_node *np = dev->of_node;
+ int i, num_handles;
+
+ num_handles = of_count_phandle_with_args(np, "access-controllers", NULL);
+ if (num_handles < 0 || num_handles != soc->num_bus_prot_blocks)
+ return dev_err_probe(dev, -EINVAL,
+ "Cannot get access controllers: expected %u, got %d\n",
+ soc->num_bus_prot_blocks, num_handles);
+
+ scpsys->bus_prot = devm_kmalloc_array(dev, soc->num_bus_prot_blocks,
+ sizeof(*scpsys->bus_prot), GFP_KERNEL);
+ if (!scpsys->bus_prot)
+ return -ENOMEM;
+
+ for (i = 0; i < soc->num_bus_prot_blocks; i++) {
+ enum scpsys_bus_prot_block bp_type;
+ struct device_node *node;
+
+ node = of_parse_phandle(np, "access-controllers", i);
+ if (!node)
+ return -EINVAL;
+
+ /*
+ * Index the bus protection regmaps so that we don't have to
+ * find the right one by type with a loop at every execution
+ * of power sequence(s).
+ */
+ bp_type = soc->bus_prot_blocks[i];
+ scpsys->bus_prot_index[bp_type] = i;
+
+ scpsys->bus_prot[i] = device_node_to_regmap(node);
+ of_node_put(node);
+ if (IS_ERR_OR_NULL(scpsys->bus_prot[i]))
+ return dev_err_probe(dev, scpsys->bus_prot[i] ?
+ PTR_ERR(scpsys->bus_prot[i]) : -ENXIO,
+ "Cannot get regmap for access controller %d\n", i);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id scpsys_of_match[] = {
+ {
+ .compatible = "mediatek,mt6735-power-controller",
+ .data = &mt6735_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt6795-power-controller",
+ .data = &mt6795_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt6858-power-controller",
+ .data = &mt6858_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt6893-power-controller",
+ .data = &mt6893_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8167-power-controller",
+ .data = &mt8167_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8173-power-controller",
+ .data = &mt8173_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8183-power-controller",
+ .data = &mt8183_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8186-power-controller",
+ .data = &mt8186_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8188-power-controller",
+ .data = &mt8188_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8189-power-controller",
+ .data = &mt8189_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8192-power-controller",
+ .data = &mt8192_scpsys_data,
+ },
+ {
+ .compatible = "mediatek,mt8195-power-controller",
+ .data = &mt8195_scpsys_data,
+ },
+ {
+ .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,
+ },
+ {
+ .compatible = "mediatek,mt8196-hwv-scp-power-controller",
+ .data = &mt8196_scpsys_hwv_data,
+ },
+ {
+ .compatible = "mediatek,mt8365-power-controller",
+ .data = &mt8365_scpsys_data,
+ },
+ { }
+};
+
+static int scpsys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct scpsys_soc_data *soc;
+ 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) {
+ dev_err(&pdev->dev, "no power controller data\n");
+ return -EINVAL;
+ }
+
+ num_domains = soc->num_domains + soc->num_hwv_domains;
+
+ scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, num_domains), GFP_KERNEL);
+ 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;
+
+ scpsys->pd_data.domains = scpsys->domains;
+ scpsys->pd_data.num_domains = num_domains;
+
+ parent = dev->parent;
+ if (!parent) {
+ dev_err(dev, "no parent for syscon devices\n");
+ return -ENODEV;
+ }
+
+ scpsys->base = syscon_node_to_regmap(parent->of_node);
+ if (IS_ERR(scpsys->base)) {
+ dev_err(dev, "no regmap available\n");
+ return PTR_ERR(scpsys->base);
+ }
+
+ if (of_find_property(np, "access-controllers", NULL))
+ ret = scpsys_get_bus_protection(dev, scpsys);
+ else
+ ret = scpsys_get_bus_protection_legacy(dev, scpsys);
+
+ if (ret)
+ return ret;
+
+ ret = -ENODEV;
+ for_each_available_child_of_node_scoped(np, node) {
+ struct generic_pm_domain *domain;
+
+ 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,
+ added_pds_idx, &num_added_pds);
+ if (ret)
+ goto err_cleanup_domains;
+ }
+
+ if (ret) {
+ dev_dbg(dev, "no power domains present\n");
+ return ret;
+ }
+
+ ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
+ if (ret) {
+ dev_err(dev, "failed to add provider: %d\n", ret);
+ goto err_cleanup_domains;
+ }
+
+ devm_kfree(dev, added_pds_idx);
+ return 0;
+
+err_cleanup_domains:
+ scpsys_domain_cleanup(scpsys, added_pds_idx, num_added_pds);
+ return ret;
+}
+
+static struct platform_driver scpsys_pm_domain_driver = {
+ .probe = scpsys_probe,
+ .driver = {
+ .name = "mtk-power-controller",
+ .suppress_bind_attrs = true,
+ .of_match_table = scpsys_of_match,
+ },
+};
+builtin_platform_driver(scpsys_pm_domain_driver);
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
new file mode 100644
index 000000000..45da83e9d
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+
+#define MTK_SCPD_ACTIVE_WAKEUP BIT(0)
+#define MTK_SCPD_FWAIT_SRAM BIT(1)
+#define MTK_SCPD_SRAM_ISO BIT(2)
+#define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3)
+#define MTK_SCPD_DOMAIN_SUPPLY BIT(4)
+/* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */
+#define MTK_SCPD_ALWAYS_ON BIT(5)
+#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_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_MODEM_SECURE_PWRSEQ BIT(14)
+#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data ? \
+ (_scpd)->data->caps & (_x) : \
+ (_scpd)->hwv_data->caps & (_x))
+
+#define SPM_VDE_PWR_CON 0x0210
+#define SPM_MFG_PWR_CON 0x0214
+#define SPM_VEN_PWR_CON 0x0230
+#define SPM_ISP_PWR_CON 0x0238
+#define SPM_DIS_PWR_CON 0x023c
+#define SPM_CONN_PWR_CON 0x0280
+#define SPM_MD1_PWR_CON 0x0284
+#define SPM_VEN2_PWR_CON 0x0298
+#define SPM_AUDIO_PWR_CON 0x029c
+#define SPM_MFG_2D_PWR_CON 0x02c0
+#define SPM_MFG_ASYNC_PWR_CON 0x02c4
+#define SPM_USB_PWR_CON 0x02cc
+
+#define SPM_PWR_STATUS 0x060c
+#define SPM_PWR_STATUS_2ND 0x0610
+
+#define PWR_STATUS_MD1 BIT(0)
+#define PWR_STATUS_CONN BIT(1)
+#define PWR_STATUS_DISP BIT(3)
+#define PWR_STATUS_MFG BIT(4)
+#define PWR_STATUS_ISP BIT(5)
+#define PWR_STATUS_VDEC BIT(7)
+#define PWR_STATUS_VENC_LT BIT(20)
+#define PWR_STATUS_VENC BIT(21)
+#define PWR_STATUS_MFG_2D BIT(22)
+#define PWR_STATUS_MFG_ASYNC BIT(23)
+#define PWR_STATUS_AUDIO BIT(24)
+#define PWR_STATUS_USB BIT(25)
+
+#define SPM_MAX_BUS_PROT_DATA 7
+
+enum scpsys_bus_prot_flags {
+ BUS_PROT_REG_UPDATE = BIT(1),
+ BUS_PROT_IGNORE_CLR_ACK = BIT(2),
+ BUS_PROT_INVERTED = BIT(3),
+ BUS_PROT_IGNORE_SUBCLK = BIT(4),
+};
+
+enum scpsys_bus_prot_block {
+ BUS_PROT_BLOCK_INFRA,
+ BUS_PROT_BLOCK_INFRA_NAO,
+ BUS_PROT_BLOCK_SMI,
+ BUS_PROT_BLOCK_SPM,
+ BUS_PROT_BLOCK_IMG_SUB0,
+ BUS_PROT_BLOCK_CAM_SUB1,
+ BUS_PROT_BLOCK_CAM_SUB0,
+ BUS_PROT_BLOCK_IPE_SUB0,
+ BUS_PROT_BLOCK_VLP,
+ BUS_PROT_BLOCK_COUNT,
+};
+
+#define _BUS_PROT_STA(_hwip, _sta_hwip, _set_clr_mask, _set, _clr, \
+ _sta_mask, _sta, _flags) \
+ { \
+ .bus_prot_block = BUS_PROT_BLOCK_##_hwip, \
+ .bus_prot_sta_block = BUS_PROT_BLOCK_##_sta_hwip, \
+ .bus_prot_set_clr_mask = (_set_clr_mask), \
+ .bus_prot_set = _set, \
+ .bus_prot_clr = _clr, \
+ .bus_prot_sta_mask = (_sta_mask), \
+ .bus_prot_sta = _sta, \
+ .flags = _flags \
+ }
+
+#define _BUS_PROT(_hwip, _set_clr_mask, _set, _clr, _sta_mask, \
+ _sta, _flags) \
+ _BUS_PROT_STA(_hwip, _hwip, _set_clr_mask, _set, _clr, \
+ _sta_mask, _sta, _flags)
+
+#define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \
+ _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, 0)
+
+#define BUS_PROT_WR_IGN(_hwip, _mask, _set, _clr, _sta) \
+ _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
+ BUS_PROT_IGNORE_CLR_ACK)
+
+#define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \
+ _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
+ BUS_PROT_REG_UPDATE)
+
+#define BUS_PROT_WR_IGN_SUBCLK(_hwip, _mask, _set, _clr, _sta) \
+ _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
+ BUS_PROT_IGNORE_CLR_ACK | BUS_PROT_IGNORE_SUBCLK)
+
+#define BUS_PROT_INFRA_UPDATE_TOPAXI(_mask) \
+ BUS_PROT_UPDATE(INFRA, _mask, \
+ INFRA_TOPAXI_PROTECTEN, \
+ INFRA_TOPAXI_PROTECTEN, \
+ INFRA_TOPAXI_PROTECTSTA1)
+
+struct scpsys_bus_prot_data {
+ u8 bus_prot_block;
+ u8 bus_prot_sta_block;
+ u32 bus_prot_set_clr_mask;
+ u32 bus_prot_set;
+ u32 bus_prot_clr;
+ u32 bus_prot_sta_mask;
+ u32 bus_prot_sta;
+ u8 flags;
+};
+
+/**
+ * enum scpsys_rtff_type - Type of RTFF Hardware for power domain
+ * @SCPSYS_RTFF_NONE: RTFF HW not present or domain not RTFF managed
+ * @SCPSYS_RTFF_TYPE_GENERIC: Non-CPU, peripheral-generic RTFF HW
+ * @SCPSYS_RTFF_TYPE_PCIE_PHY: PCI-Express PHY specific RTFF HW
+ * @SCPSYS_RTFF_TYPE_STOR_UFS: Storage (UFS) specific RTFF HW
+ * @SCPSYS_RTFF_TYPE_MAX: Number of supported RTFF HW Types
+ */
+enum scpsys_rtff_type {
+ SCPSYS_RTFF_NONE = 0,
+ SCPSYS_RTFF_TYPE_GENERIC,
+ SCPSYS_RTFF_TYPE_PCIE_PHY,
+ SCPSYS_RTFF_TYPE_STOR_UFS,
+ SCPSYS_RTFF_TYPE_MAX
+};
+
+/**
+ * enum scpsys_mtcmos_type - Type of power domain controller
+ * @SCPSYS_MTCMOS_TYPE_DIRECT_CTL: Power domains are controlled with direct access
+ * @SCPSYS_MTCMOS_TYPE_HW_VOTER: Hardware-assisted voted power domain control
+ * @SCPSYS_MTCMOS_TYPE_MAX: Number of supported power domain types
+ */
+enum scpsys_mtcmos_type {
+ SCPSYS_MTCMOS_TYPE_DIRECT_CTL = 0,
+ SCPSYS_MTCMOS_TYPE_HW_VOTER,
+ SCPSYS_MTCMOS_TYPE_MAX
+};
+
+/**
+ * struct scpsys_domain_data - scp domain data for power on/off flow
+ * @name: The name of the power domain.
+ * @sta_mask: The mask for power on/off status bit.
+ * @sta2nd_mask: The mask for second power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @ext_buck_iso_offs: The offset for external buck isolation
+ * @ext_buck_iso_mask: The mask for external buck isolation
+ * @caps: The flag for active wake-up action.
+ * @rtff_type: The power domain RTFF HW type
+ * @bp_cfg: bus protection configuration for any subsystem
+ */
+struct scpsys_domain_data {
+ const char *name;
+ u32 sta_mask;
+ u32 sta2nd_mask;
+ int ctl_offs;
+ u32 sram_pdn_bits;
+ u32 sram_pdn_ack_bits;
+ int ext_buck_iso_offs;
+ u32 ext_buck_iso_mask;
+ u16 caps;
+ enum scpsys_rtff_type rtff_type;
+ const struct scpsys_bus_prot_data bp_cfg[SPM_MAX_BUS_PROT_DATA];
+ int pwr_sta_offs;
+ int pwr_sta2nd_offs;
+};
+
+/**
+ * struct scpsys_hwv_domain_data - Hardware Voter power domain data
+ * @name: Name of the power domain
+ * @set: Offset of the HWV SET register
+ * @clr: Offset of the HWV CLEAR register
+ * @done: Offset of the HWV DONE register
+ * @en: Offset of the HWV ENABLE register
+ * @set_sta: Offset of the HWV SET STATUS register
+ * @clr_sta: Offset of the HWV CLEAR STATUS register
+ * @setclr_bit: The SET/CLR bit to enable/disable the power domain
+ * @sta_bit: The SET/CLR STA bit to check for on/off ACK
+ * @caps: The flag for active wake-up action
+ */
+struct scpsys_hwv_domain_data {
+ const char *name;
+ u16 set;
+ u16 clr;
+ u16 done;
+ u16 en;
+ u16 set_sta;
+ u16 clr_sta;
+ u8 setclr_bit;
+ u8 sta_bit;
+ u16 caps;
+};
+
+struct scpsys_soc_data {
+ const struct scpsys_domain_data *domains_data;
+ int num_domains;
+ const struct scpsys_hwv_domain_data *hwv_domains_data;
+ int num_hwv_domains;
+ enum scpsys_bus_prot_block *bus_prot_blocks;
+ int num_bus_prot_blocks;
+ enum scpsys_mtcmos_type type;
+};
+
+#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
new file mode 100644
index 000000000..efc8f276f
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-scpsys.c
@@ -0,0 +1,1154 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
+ */
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regulator/consumer.h>
+#include <linux/soc/mediatek/infracfg.h>
+
+#include <dt-bindings/power/mt2701-power.h>
+#include <dt-bindings/power/mt2712-power.h>
+#include <dt-bindings/power/mt6797-power.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/power/mt7623a-power.h>
+#include <dt-bindings/power/mt8173-power.h>
+
+#define MTK_POLL_DELAY_US 10
+#define MTK_POLL_TIMEOUT USEC_PER_SEC
+
+#define MTK_SCPD_ACTIVE_WAKEUP BIT(0)
+#define MTK_SCPD_FWAIT_SRAM BIT(1)
+#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
+
+#define SPM_VDE_PWR_CON 0x0210
+#define SPM_MFG_PWR_CON 0x0214
+#define SPM_VEN_PWR_CON 0x0230
+#define SPM_ISP_PWR_CON 0x0238
+#define SPM_DIS_PWR_CON 0x023c
+#define SPM_CONN_PWR_CON 0x0280
+#define SPM_VEN2_PWR_CON 0x0298
+#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */
+#define SPM_BDP_PWR_CON 0x029c /* MT2701 */
+#define SPM_ETH_PWR_CON 0x02a0
+#define SPM_HIF_PWR_CON 0x02a4
+#define SPM_IFR_MSC_PWR_CON 0x02a8
+#define SPM_MFG_2D_PWR_CON 0x02c0
+#define SPM_MFG_ASYNC_PWR_CON 0x02c4
+#define SPM_USB_PWR_CON 0x02cc
+#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */
+#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */
+#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */
+#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */
+#define SPM_WB_PWR_CON 0x02ec /* MT7622 */
+
+#define SPM_PWR_STATUS 0x060c
+#define SPM_PWR_STATUS_2ND 0x0610
+
+#define PWR_RST_B_BIT BIT(0)
+#define PWR_ISO_BIT BIT(1)
+#define PWR_ON_BIT BIT(2)
+#define PWR_ON_2ND_BIT BIT(3)
+#define PWR_CLK_DIS_BIT BIT(4)
+
+#define PWR_STATUS_CONN BIT(1)
+#define PWR_STATUS_DISP BIT(3)
+#define PWR_STATUS_MFG BIT(4)
+#define PWR_STATUS_ISP BIT(5)
+#define PWR_STATUS_VDEC BIT(7)
+#define PWR_STATUS_BDP BIT(14)
+#define PWR_STATUS_ETH BIT(15)
+#define PWR_STATUS_HIF BIT(16)
+#define PWR_STATUS_IFR_MSC BIT(17)
+#define PWR_STATUS_USB2 BIT(19) /* MT2712 */
+#define PWR_STATUS_VENC_LT BIT(20)
+#define PWR_STATUS_VENC BIT(21)
+#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */
+#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */
+#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */
+#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */
+#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */
+#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */
+#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */
+#define PWR_STATUS_WB BIT(27) /* MT7622 */
+
+enum clk_id {
+ CLK_NONE,
+ CLK_MM,
+ CLK_MFG,
+ CLK_VENC,
+ CLK_VENC_LT,
+ CLK_ETHIF,
+ CLK_VDEC,
+ CLK_HIFSEL,
+ CLK_JPGDEC,
+ CLK_AUDIO,
+ CLK_MAX,
+};
+
+static const char * const clk_names[] = {
+ NULL,
+ "mm",
+ "mfg",
+ "venc",
+ "venc_lt",
+ "ethif",
+ "vdec",
+ "hif_sel",
+ "jpgdec",
+ "audio",
+ NULL,
+};
+
+#define MAX_CLKS 3
+
+/**
+ * struct scp_domain_data - scp domain data for power on/off flow
+ * @name: The domain name.
+ * @sta_mask: The mask for power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @bus_prot_mask: The mask for single step bus protection.
+ * @clk_id: The basic clocks required by this power domain.
+ * @caps: The flag for active wake-up action.
+ */
+struct scp_domain_data {
+ const char *name;
+ u32 sta_mask;
+ int ctl_offs;
+ u32 sram_pdn_bits;
+ u32 sram_pdn_ack_bits;
+ u32 bus_prot_mask;
+ enum clk_id clk_id[MAX_CLKS];
+ u8 caps;
+};
+
+struct scp;
+
+struct scp_domain {
+ struct generic_pm_domain genpd;
+ struct scp *scp;
+ struct clk *clk[MAX_CLKS];
+ const struct scp_domain_data *data;
+ struct regulator *supply;
+};
+
+struct scp_ctrl_reg {
+ int pwr_sta_offs;
+ int pwr_sta2nd_offs;
+};
+
+struct scp {
+ struct scp_domain *domains;
+ struct genpd_onecell_data pd_data;
+ struct device *dev;
+ void __iomem *base;
+ struct regmap *infracfg;
+ struct scp_ctrl_reg ctrl_reg;
+ bool bus_prot_reg_update;
+};
+
+struct scp_subdomain {
+ int origin;
+ int subdomain;
+};
+
+struct scp_soc_data {
+ const struct scp_domain_data *domains;
+ int num_domains;
+ const struct scp_subdomain *subdomains;
+ int num_subdomains;
+ const struct scp_ctrl_reg regs;
+ bool bus_prot_reg_update;
+};
+
+static int scpsys_domain_is_on(struct scp_domain *scpd)
+{
+ struct scp *scp = scpd->scp;
+
+ u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
+ scpd->data->sta_mask;
+ u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
+ scpd->data->sta_mask;
+
+ /*
+ * A domain is on when both status bits are set. If only one is set
+ * return an error. This happens while powering up a domain
+ */
+
+ if (status && status2)
+ return true;
+ if (!status && !status2)
+ return false;
+
+ return -EINVAL;
+}
+
+static int scpsys_regulator_enable(struct scp_domain *scpd)
+{
+ if (!scpd->supply)
+ return 0;
+
+ return regulator_enable(scpd->supply);
+}
+
+static int scpsys_regulator_disable(struct scp_domain *scpd)
+{
+ if (!scpd->supply)
+ return 0;
+
+ return regulator_disable(scpd->supply);
+}
+
+static void scpsys_clk_disable(struct clk *clk[], int max_num)
+{
+ int i;
+
+ for (i = max_num - 1; i >= 0; i--)
+ clk_disable_unprepare(clk[i]);
+}
+
+static int scpsys_clk_enable(struct clk *clk[], int max_num)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < max_num && clk[i]; i++) {
+ ret = clk_prepare_enable(clk[i]);
+ if (ret) {
+ scpsys_clk_disable(clk, i);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+ u32 val;
+ u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+ int tmp;
+
+ val = readl(ctl_addr);
+ val &= ~scpd->data->sram_pdn_bits;
+ writel(val, ctl_addr);
+
+ /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
+ if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
+ /*
+ * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
+ * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
+ * is applied here.
+ */
+ usleep_range(12000, 12100);
+ } else {
+ /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+ int ret = readl_poll_timeout(ctl_addr, tmp,
+ (tmp & pdn_ack) == 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+ u32 val;
+ u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+ int tmp;
+
+ val = readl(ctl_addr);
+ val |= scpd->data->sram_pdn_bits;
+ writel(val, ctl_addr);
+
+ /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+ return readl_poll_timeout(ctl_addr, tmp,
+ (tmp & pdn_ack) == pdn_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static int scpsys_bus_protect_enable(struct scp_domain *scpd)
+{
+ struct scp *scp = scpd->scp;
+
+ if (!scpd->data->bus_prot_mask)
+ return 0;
+
+ return mtk_infracfg_set_bus_protection(scp->infracfg,
+ scpd->data->bus_prot_mask,
+ scp->bus_prot_reg_update);
+}
+
+static int scpsys_bus_protect_disable(struct scp_domain *scpd)
+{
+ struct scp *scp = scpd->scp;
+
+ if (!scpd->data->bus_prot_mask)
+ return 0;
+
+ return mtk_infracfg_clear_bus_protection(scp->infracfg,
+ scpd->data->bus_prot_mask,
+ scp->bus_prot_reg_update);
+}
+
+static int scpsys_power_on(struct generic_pm_domain *genpd)
+{
+ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+ struct scp *scp = scpd->scp;
+ void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
+ u32 val;
+ int ret, tmp;
+
+ ret = scpsys_regulator_enable(scpd);
+ if (ret < 0)
+ return ret;
+
+ ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
+ if (ret)
+ goto err_clk;
+
+ /* subsys power on */
+ val = readl(ctl_addr);
+ val |= PWR_ON_BIT;
+ writel(val, ctl_addr);
+ val |= PWR_ON_2ND_BIT;
+ writel(val, ctl_addr);
+
+ /* wait until PWR_ACK = 1 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ goto err_pwr_ack;
+
+ val &= ~PWR_CLK_DIS_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_ISO_BIT;
+ writel(val, ctl_addr);
+
+ val |= PWR_RST_B_BIT;
+ writel(val, ctl_addr);
+
+ ret = scpsys_sram_enable(scpd, ctl_addr);
+ if (ret < 0)
+ goto err_pwr_ack;
+
+ ret = scpsys_bus_protect_disable(scpd);
+ if (ret < 0)
+ goto err_pwr_ack;
+
+ return 0;
+
+err_pwr_ack:
+ scpsys_clk_disable(scpd->clk, MAX_CLKS);
+err_clk:
+ scpsys_regulator_disable(scpd);
+
+ dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
+
+ return ret;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+ struct scp *scp = scpd->scp;
+ void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
+ u32 val;
+ int ret, tmp;
+
+ ret = scpsys_bus_protect_enable(scpd);
+ if (ret < 0)
+ goto out;
+
+ ret = scpsys_sram_disable(scpd, ctl_addr);
+ if (ret < 0)
+ goto out;
+
+ /* subsys power off */
+ val = readl(ctl_addr);
+ val |= PWR_ISO_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_RST_B_BIT;
+ writel(val, ctl_addr);
+
+ val |= PWR_CLK_DIS_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_ON_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_ON_2ND_BIT;
+ writel(val, ctl_addr);
+
+ /* wait until PWR_ACK = 0 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ goto out;
+
+ scpsys_clk_disable(scpd->clk, MAX_CLKS);
+
+ ret = scpsys_regulator_disable(scpd);
+ if (ret < 0)
+ goto out;
+
+ return 0;
+
+out:
+ dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
+
+ return ret;
+}
+
+static void init_clks(struct platform_device *pdev, struct clk **clk)
+{
+ int i;
+
+ for (i = CLK_NONE + 1; i < CLK_MAX; i++)
+ clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
+}
+
+static struct scp *init_scp(struct platform_device *pdev,
+ const struct scp_domain_data *scp_domain_data, int num,
+ const struct scp_ctrl_reg *scp_ctrl_reg,
+ bool bus_prot_reg_update)
+{
+ struct genpd_onecell_data *pd_data;
+ int i, j;
+ struct scp *scp;
+ struct clk *clk[CLK_MAX];
+
+ scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
+ if (!scp)
+ return ERR_PTR(-ENOMEM);
+
+ scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
+ scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
+
+ scp->bus_prot_reg_update = bus_prot_reg_update;
+
+ scp->dev = &pdev->dev;
+
+ scp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(scp->base))
+ return ERR_CAST(scp->base);
+
+ scp->domains = devm_kcalloc(&pdev->dev,
+ num, sizeof(*scp->domains), GFP_KERNEL);
+ if (!scp->domains)
+ return ERR_PTR(-ENOMEM);
+
+ pd_data = &scp->pd_data;
+
+ pd_data->domains = devm_kcalloc(&pdev->dev,
+ num, sizeof(*pd_data->domains), GFP_KERNEL);
+ if (!pd_data->domains)
+ return ERR_PTR(-ENOMEM);
+
+ scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "infracfg");
+ if (IS_ERR(scp->infracfg)) {
+ dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
+ PTR_ERR(scp->infracfg));
+ return ERR_CAST(scp->infracfg);
+ }
+
+ for (i = 0; i < num; i++) {
+ struct scp_domain *scpd = &scp->domains[i];
+ const struct scp_domain_data *data = &scp_domain_data[i];
+
+ scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
+ if (IS_ERR(scpd->supply)) {
+ if (PTR_ERR(scpd->supply) == -ENODEV)
+ scpd->supply = NULL;
+ else
+ return ERR_CAST(scpd->supply);
+ }
+ }
+
+ pd_data->num_domains = num;
+
+ init_clks(pdev, clk);
+
+ for (i = 0; i < num; i++) {
+ struct scp_domain *scpd = &scp->domains[i];
+ struct generic_pm_domain *genpd = &scpd->genpd;
+ const struct scp_domain_data *data = &scp_domain_data[i];
+
+ pd_data->domains[i] = genpd;
+ scpd->scp = scp;
+
+ scpd->data = data;
+
+ for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
+ struct clk *c = clk[data->clk_id[j]];
+
+ if (IS_ERR(c)) {
+ dev_err(&pdev->dev, "%s: clk unavailable\n",
+ data->name);
+ return ERR_CAST(c);
+ }
+
+ scpd->clk[j] = c;
+ }
+
+ genpd->name = data->name;
+ genpd->power_off = scpsys_power_off;
+ genpd->power_on = scpsys_power_on;
+ if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
+ genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+ }
+
+ return scp;
+}
+
+static void mtk_register_power_domains(struct platform_device *pdev,
+ struct scp *scp, int num)
+{
+ struct genpd_onecell_data *pd_data;
+ int i, ret;
+
+ for (i = 0; i < num; i++) {
+ struct scp_domain *scpd = &scp->domains[i];
+ struct generic_pm_domain *genpd = &scpd->genpd;
+ bool on;
+
+ /*
+ * Initially turn on all domains to make the domains usable
+ * with !CONFIG_PM and to get the hardware in sync with the
+ * software. The unused domains will be switched off during
+ * late_init time.
+ */
+ on = !WARN_ON(genpd->power_on(genpd) < 0);
+
+ pm_genpd_init(genpd, NULL, !on);
+ }
+
+ /*
+ * We are not allowed to fail here since there is no way to unregister
+ * a power domain. Once registered above we have to keep the domains
+ * valid.
+ */
+
+ pd_data = &scp->pd_data;
+
+ ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
+}
+
+/*
+ * MT2701 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt2701[] = {
+ [MT2701_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = SPM_CONN_PWR_CON,
+ .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
+ MT2701_TOP_AXI_PROT_EN_CONN_S,
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_DISP] = {
+ .name = "disp",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .clk_id = {CLK_MM},
+ .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MFG},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_MM},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_BDP] = {
+ .name = "bdp",
+ .sta_mask = PWR_STATUS_BDP,
+ .ctl_offs = SPM_BDP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_ETH] = {
+ .name = "eth",
+ .sta_mask = PWR_STATUS_ETH,
+ .ctl_offs = SPM_ETH_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_ETHIF},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_HIF] = {
+ .name = "hif",
+ .sta_mask = PWR_STATUS_HIF,
+ .ctl_offs = SPM_HIF_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_ETHIF},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2701_POWER_DOMAIN_IFR_MSC] = {
+ .name = "ifr_msc",
+ .sta_mask = PWR_STATUS_IFR_MSC,
+ .ctl_offs = SPM_IFR_MSC_PWR_CON,
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+/*
+ * MT2712 power domain support
+ */
+static const struct scp_domain_data scp_domain_data_mt2712[] = {
+ [MT2712_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM, CLK_VDEC},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_MM},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_AUDIO},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_USB] = {
+ .name = "usb",
+ .sta_mask = PWR_STATUS_USB,
+ .ctl_offs = SPM_USB_PWR_CON,
+ .sram_pdn_bits = GENMASK(10, 8),
+ .sram_pdn_ack_bits = GENMASK(14, 12),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_USB2] = {
+ .name = "usb2",
+ .sta_mask = PWR_STATUS_USB2,
+ .ctl_offs = SPM_USB2_PWR_CON,
+ .sram_pdn_bits = GENMASK(10, 8),
+ .sram_pdn_ack_bits = GENMASK(14, 12),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(16, 16),
+ .clk_id = {CLK_MFG},
+ .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_MFG_SC1] = {
+ .name = "mfg_sc1",
+ .sta_mask = BIT(22),
+ .ctl_offs = 0x02c0,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(16, 16),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_MFG_SC2] = {
+ .name = "mfg_sc2",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x02c4,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(16, 16),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT2712_POWER_DOMAIN_MFG_SC3] = {
+ .name = "mfg_sc3",
+ .sta_mask = BIT(30),
+ .ctl_offs = 0x01f8,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(16, 16),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+static const struct scp_subdomain scp_subdomain_mt2712[] = {
+ {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC},
+ {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC},
+ {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP},
+ {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1},
+ {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2},
+ {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3},
+};
+
+/*
+ * MT6797 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt6797[] = {
+ [MT6797_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x300,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_VDEC},
+ },
+ [MT6797_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = BIT(21),
+ .ctl_offs = 0x304,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ },
+ [MT6797_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x308,
+ .sram_pdn_bits = GENMASK(9, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_NONE},
+ },
+ [MT6797_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x30C,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ .bus_prot_mask = (BIT(1) | BIT(2)),
+ },
+ [MT6797_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = BIT(24),
+ .ctl_offs = 0x314,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ },
+ [MT6797_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = BIT(13),
+ .ctl_offs = 0x334,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .clk_id = {CLK_MFG},
+ },
+ [MT6797_POWER_DOMAIN_MJC] = {
+ .name = "mjc",
+ .sta_mask = BIT(20),
+ .ctl_offs = 0x310,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_NONE},
+ },
+};
+
+#define SPM_PWR_STATUS_MT6797 0x0180
+#define SPM_PWR_STATUS_2ND_MT6797 0x0184
+
+static const struct scp_subdomain scp_subdomain_mt6797[] = {
+ {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
+ {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
+ {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
+ {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
+};
+
+/*
+ * MT7622 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt7622[] = {
+ [MT7622_POWER_DOMAIN_ETHSYS] = {
+ .name = "ethsys",
+ .sta_mask = PWR_STATUS_ETHSYS,
+ .ctl_offs = SPM_ETHSYS_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7622_POWER_DOMAIN_HIF0] = {
+ .name = "hif0",
+ .sta_mask = PWR_STATUS_HIF0,
+ .ctl_offs = SPM_HIF0_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_HIFSEL},
+ .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7622_POWER_DOMAIN_HIF1] = {
+ .name = "hif1",
+ .sta_mask = PWR_STATUS_HIF1,
+ .ctl_offs = SPM_HIF1_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_HIFSEL},
+ .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7622_POWER_DOMAIN_WB] = {
+ .name = "wb",
+ .sta_mask = PWR_STATUS_WB,
+ .ctl_offs = SPM_WB_PWR_CON,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ .clk_id = {CLK_NONE},
+ .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
+ },
+ [MT7622_POWER_DOMAIN_AUDIO] = {
+ .name = "audsys",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+/*
+ * MT7623A power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt7623a[] = {
+ [MT7623A_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = PWR_STATUS_CONN,
+ .ctl_offs = SPM_CONN_PWR_CON,
+ .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
+ MT2701_TOP_AXI_PROT_EN_CONN_S,
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7623A_POWER_DOMAIN_ETH] = {
+ .name = "eth",
+ .sta_mask = PWR_STATUS_ETH,
+ .ctl_offs = SPM_ETH_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_ETHIF},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7623A_POWER_DOMAIN_HIF] = {
+ .name = "hif",
+ .sta_mask = PWR_STATUS_HIF,
+ .ctl_offs = SPM_HIF_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_ETHIF},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT7623A_POWER_DOMAIN_IFR_MSC] = {
+ .name = "ifr_msc",
+ .sta_mask = PWR_STATUS_IFR_MSC,
+ .ctl_offs = SPM_IFR_MSC_PWR_CON,
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+};
+
+/*
+ * MT8173 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt8173[] = {
+ [MT8173_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ },
+ [MT8173_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_MM, CLK_VENC},
+ },
+ [MT8173_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_MM},
+ },
+ [MT8173_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
+ MT8173_TOP_AXI_PROT_EN_MM_M1,
+ },
+ [MT8173_POWER_DOMAIN_VENC_LT] = {
+ .name = "venc_lt",
+ .sta_mask = PWR_STATUS_VENC_LT,
+ .ctl_offs = SPM_VEN2_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_MM, CLK_VENC_LT},
+ },
+ [MT8173_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ },
+ [MT8173_POWER_DOMAIN_USB] = {
+ .name = "usb",
+ .sta_mask = PWR_STATUS_USB,
+ .ctl_offs = SPM_USB_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_NONE},
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
+ },
+ [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = PWR_STATUS_MFG_ASYNC,
+ .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = 0,
+ .clk_id = {CLK_MFG},
+ },
+ [MT8173_POWER_DOMAIN_MFG_2D] = {
+ .name = "mfg_2d",
+ .sta_mask = PWR_STATUS_MFG_2D,
+ .ctl_offs = SPM_MFG_2D_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_NONE},
+ },
+ [MT8173_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .sram_pdn_bits = GENMASK(13, 8),
+ .sram_pdn_ack_bits = GENMASK(21, 16),
+ .clk_id = {CLK_NONE},
+ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
+ MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+ MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+ MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
+ },
+};
+
+static const struct scp_subdomain scp_subdomain_mt8173[] = {
+ {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
+ {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
+};
+
+static const struct scp_soc_data mt2701_data = {
+ .domains = scp_domain_data_mt2701,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt2712_data = {
+ .domains = scp_domain_data_mt2712,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
+ .subdomains = scp_subdomain_mt2712,
+ .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = false,
+};
+
+static const struct scp_soc_data mt6797_data = {
+ .domains = scp_domain_data_mt6797,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
+ .subdomains = scp_subdomain_mt6797,
+ .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
+ },
+ .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt7622_data = {
+ .domains = scp_domain_data_mt7622,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt7623a_data = {
+ .domains = scp_domain_data_mt7623a,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt8173_data = {
+ .domains = scp_domain_data_mt8173,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
+ .subdomains = scp_subdomain_mt8173,
+ .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = true,
+};
+
+/*
+ * scpsys driver init
+ */
+
+static const struct of_device_id of_scpsys_match_tbl[] = {
+ {
+ .compatible = "mediatek,mt2701-scpsys",
+ .data = &mt2701_data,
+ }, {
+ .compatible = "mediatek,mt2712-scpsys",
+ .data = &mt2712_data,
+ }, {
+ .compatible = "mediatek,mt6797-scpsys",
+ .data = &mt6797_data,
+ }, {
+ .compatible = "mediatek,mt7622-scpsys",
+ .data = &mt7622_data,
+ }, {
+ .compatible = "mediatek,mt7623a-scpsys",
+ .data = &mt7623a_data,
+ }, {
+ .compatible = "mediatek,mt8173-scpsys",
+ .data = &mt8173_data,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int scpsys_probe(struct platform_device *pdev)
+{
+ const struct scp_subdomain *sd;
+ const struct scp_soc_data *soc;
+ struct scp *scp;
+ struct genpd_onecell_data *pd_data;
+ int i, ret;
+
+ soc = of_device_get_match_data(&pdev->dev);
+
+ scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
+ soc->bus_prot_reg_update);
+ if (IS_ERR(scp))
+ return PTR_ERR(scp);
+
+ mtk_register_power_domains(pdev, scp, soc->num_domains);
+
+ pd_data = &scp->pd_data;
+
+ for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
+ ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
+ pd_data->domains[sd->subdomain]);
+ if (ret && IS_ENABLED(CONFIG_PM))
+ dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
+ ret);
+ }
+
+ return 0;
+}
+
+static struct platform_driver scpsys_drv = {
+ .probe = scpsys_probe,
+ .driver = {
+ .name = "mtk-scpsys",
+ .suppress_bind_attrs = true,
+ .of_match_table = of_scpsys_match_tbl,
+ },
+};
+builtin_platform_driver(scpsys_drv);