summaryrefslogtreecommitdiffstats
path: root/drivers/pmdomain/mediatek
diff options
context:
space:
mode:
authorBreno Leitao <leitao@debian.org>2026-08-05 07:52:36 -0700
committerTejun Heo <tj@kernel.org>2026-08-10 11:47:20 -1000
commita5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656 (patch)
tree39f5b258386e1127d253d293194e9a2991bf3c34 /drivers/pmdomain/mediatek
downloadlinux-stable-a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656.tar.gz
linux-stable-a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656.zip
workqueue: skip the node_nr_active update for non-unbound workqueuesgrafted
apply_wqattrs_commit() updates node_nr_active->max unconditionally. wq->node_nr_active[] is only allocated for unbound workqueues, so guard the call before per-cpu workqueues start using this path. No functional change: only unbound workqueues reach apply_wqattrs_*() today. Signed-off-by: Breno Leitao <leitao@debian.org> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/pmdomain/mediatek')
-rw-r--r--drivers/pmdomain/mediatek/Kconfig58
-rw-r--r--drivers/pmdomain/mediatek/Makefile12
-rw-r--r--drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c144
-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/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.h300
-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.h625
-rw-r--r--drivers/pmdomain/mediatek/mt8365-pm-domains.h201
-rw-r--r--drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c1103
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c1298
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h214
-rw-r--r--drivers/pmdomain/mediatek/mtk-scpsys.c1154
20 files changed, 8759 insertions, 0 deletions
diff --git a/drivers/pmdomain/mediatek/Kconfig b/drivers/pmdomain/mediatek/Kconfig
new file mode 100644
index 000000000..8923e6516
--- /dev/null
+++ b/drivers/pmdomain/mediatek/Kconfig
@@ -0,0 +1,58 @@
+# 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.
+
+config AIROHA_CPU_PM_DOMAIN
+ tristate "Airoha CPU power domain"
+ default ARCH_AIROHA
+ 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.
+
+endmenu
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..3b1d202f8
--- /dev/null
+++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
@@ -0,0 +1,144 @@
+// 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 int airoha_cpu_pmdomain_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return 0;
+}
+
+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 = airoha_cpu_pmdomain_clk_determine_rate,
+};
+
+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/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..3742782a2
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8183-pm-domains.h
@@ -0,0 +1,300 @@
+/* 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,
+ },
+ [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,
+ },
+ [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),
+ },
+ [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),
+ },
+ [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),
+ .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..2e4b28720
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mt8196-pm-domains.h
@@ -0,0 +1,625 @@
+/* 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_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_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..53bdab66c
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c
@@ -0,0 +1,1103 @@
+// 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 int mtk_mfg_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ /*
+ * The determine_rate callback needs to be implemented to avoid returning
+ * the current clock frequency, rather than something even remotely
+ * close to the frequency that was asked for.
+ *
+ * Instead of writing considerable amounts of possibly slow code just to
+ * somehow figure out which of the three PLLs to round for, or even to
+ * do a search through one of two OPP tables in order to find the closest
+ * OPP of a frequency, just return the rate as-is. This avoids devfreq
+ * "rounding" a request for the lowest frequency to the possibly very
+ * high current frequency, breaking the powersave governor in the process.
+ */
+
+ return 0;
+}
+
+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 = mtk_mfg_determine_rate,
+};
+
+static const struct clk_ops mtk_mfg_clk_stack_ops = {
+ .recalc_rate = mtk_mfg_recalc_rate_stack,
+ .determine_rate = mtk_mfg_determine_rate,
+};
+
+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;
+ 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..e1cfd4223
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -0,0 +1,1298 @@
+// 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 "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)
+
+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(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 = 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_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;
+
+ if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
+
+ 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);
+
+ /* 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(5);
+
+ 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 void scpsys_ctl_pwrseq_off(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+
+ 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);
+}
+
+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 void scpsys_modem_pwrseq_off(struct scpsys_domain *pd)
+{
+ struct scpsys *scpsys = pd->scpsys;
+
+ 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);
+}
+
+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_PWRSEQ))
+ ret = scpsys_modem_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;
+ }
+
+ 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:
+ 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(struct generic_pm_domain *genpd)
+{
+ struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+ struct scpsys *scpsys = pd->scpsys;
+ bool tmp;
+ int ret;
+
+ ret = scpsys_bus_protect_enable(pd, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = scpsys_sram_disable(pd);
+ if (ret < 0)
+ return ret;
+
+ if (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))
+ scpsys_modem_pwrseq_off(pd);
+ else
+ scpsys_ctl_pwrseq_off(pd);
+
+ /* wait until PWR_ACK = 0 */
+ ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+
+ scpsys_regulator_disable(pd->supply);
+
+ return 0;
+}
+
+static struct
+generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
+{
+ 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)) {
+ if (scpsys_domain_is_on(pd))
+ 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);
+
+ 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)
+{
+ 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);
+ 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);
+ 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)
+{
+ 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_domain_is_on(pd))
+ scpsys_power_off(&pd->genpd);
+
+ 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)
+{
+ struct generic_pm_domain *genpd;
+ struct scpsys_domain *pd;
+ int i;
+
+ for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
+ genpd = scpsys->pd_data.domains[i];
+ 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");
+ of_node_put(node);
+ num_regmaps++;
+ if (IS_ERR(regmap[0]))
+ return dev_err_probe(dev, PTR_ERR(regmap[0]),
+ "%pOF: failed to get infracfg regmap\n",
+ 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);
+ of_node_put(node);
+ if (!smi_np)
+ return -ENODEV;
+
+ regmap[1] = device_node_to_regmap(smi_np);
+ num_regmaps++;
+ of_node_put(smi_np);
+ if (IS_ERR(regmap[1]))
+ return dev_err_probe(dev, PTR_ERR(regmap[1]),
+ "%pOF: failed to get SMI regmap\n",
+ 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;
+ }
+
+ 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,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-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;
+
+ 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;
+
+ 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);
+ if (IS_ERR(domain)) {
+ ret = PTR_ERR(domain);
+ goto err_cleanup_domains;
+ }
+
+ ret = scpsys_add_subdomain(scpsys, node);
+ 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;
+ }
+
+ return 0;
+
+err_cleanup_domains:
+ scpsys_domain_cleanup(scpsys);
+ 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..a5dca24cb
--- /dev/null
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -0,0 +1,214 @@
+/* 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_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_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);