summaryrefslogtreecommitdiff
path: root/drivers/pmdomain
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pmdomain')
-rw-r--r--drivers/pmdomain/Kconfig1
-rw-r--r--drivers/pmdomain/Makefile1
-rw-r--r--drivers/pmdomain/amlogic/meson-secure-pwrc.c95
-rw-r--r--drivers/pmdomain/apple/pmgr-pwrstate.c1
-rw-r--r--drivers/pmdomain/imx/gpc.c1
-rw-r--r--drivers/pmdomain/imx/imx93-blk-ctrl.c23
-rw-r--r--drivers/pmdomain/marvell/Kconfig18
-rw-r--r--drivers/pmdomain/marvell/Makefile3
-rw-r--r--drivers/pmdomain/marvell/pxa1908-power-controller.c274
-rw-r--r--drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c8
-rw-r--r--drivers/pmdomain/mediatek/mt6795-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8167-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8173-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8183-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8186-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8188-pm-domains.h6
-rw-r--r--drivers/pmdomain/mediatek/mt8192-pm-domains.h5
-rw-r--r--drivers/pmdomain/mediatek/mt8195-pm-domains.h6
-rw-r--r--drivers/pmdomain/mediatek/mt8365-pm-domains.h14
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c399
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h74
-rw-r--r--drivers/pmdomain/qcom/rpmpd.c112
-rw-r--r--drivers/pmdomain/rockchip/Kconfig1
-rw-r--r--drivers/pmdomain/thead/th1520-pm-domains.c16
-rw-r--r--drivers/pmdomain/ti/ti_sci_pm_domains.c24
25 files changed, 956 insertions, 151 deletions
diff --git a/drivers/pmdomain/Kconfig b/drivers/pmdomain/Kconfig
index 91f04ace35d4..23076ae90e66 100644
--- a/drivers/pmdomain/Kconfig
+++ b/drivers/pmdomain/Kconfig
@@ -7,6 +7,7 @@ source "drivers/pmdomain/apple/Kconfig"
source "drivers/pmdomain/arm/Kconfig"
source "drivers/pmdomain/bcm/Kconfig"
source "drivers/pmdomain/imx/Kconfig"
+source "drivers/pmdomain/marvell/Kconfig"
source "drivers/pmdomain/mediatek/Kconfig"
source "drivers/pmdomain/qcom/Kconfig"
source "drivers/pmdomain/renesas/Kconfig"
diff --git a/drivers/pmdomain/Makefile b/drivers/pmdomain/Makefile
index 7030f44a49df..ebc802f13eb9 100644
--- a/drivers/pmdomain/Makefile
+++ b/drivers/pmdomain/Makefile
@@ -5,6 +5,7 @@ obj-y += apple/
obj-y += arm/
obj-y += bcm/
obj-y += imx/
+obj-y += marvell/
obj-y += mediatek/
obj-y += qcom/
obj-y += renesas/
diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
index e8bda60078c4..1d2f371d2d7f 100644
--- a/drivers/pmdomain/amlogic/meson-secure-pwrc.c
+++ b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
@@ -16,6 +16,9 @@
#include <dt-bindings/power/amlogic,t7-pwrc.h>
#include <dt-bindings/power/amlogic,a4-pwrc.h>
#include <dt-bindings/power/amlogic,a5-pwrc.h>
+#include <dt-bindings/power/amlogic,s6-pwrc.h>
+#include <dt-bindings/power/amlogic,s7-pwrc.h>
+#include <dt-bindings/power/amlogic,s7d-pwrc.h>
#include <linux/arm-smccc.h>
#include <linux/firmware/meson/meson_sm.h>
#include <linux/module.h>
@@ -201,6 +204,71 @@ static const struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
SEC_PD(S4_AUDIO, 0),
};
+static const struct meson_secure_pwrc_domain_desc s6_pwrc_domains[] = {
+ SEC_PD(S6_DSPA, 0),
+ SEC_PD(S6_DOS_HEVC, 0),
+ SEC_PD(S6_DOS_VDEC, 0),
+ SEC_PD(S6_VPU_HDMI, 0),
+ SEC_PD(S6_U2DRD, 0),
+ SEC_PD(S6_U3DRD, 0),
+ SEC_PD(S6_SD_EMMC_C, 0),
+ SEC_PD(S6_GE2D, 0),
+ SEC_PD(S6_AMFC, 0),
+ SEC_PD(S6_VC9000E, 0),
+ SEC_PD(S6_DEWARP, 0),
+ SEC_PD(S6_VICP, 0),
+ SEC_PD(S6_SD_EMMC_A, 0),
+ SEC_PD(S6_SD_EMMC_B, 0),
+ /* ETH is for ethernet online wakeup, and should be always on */
+ SEC_PD(S6_ETH, GENPD_FLAG_ALWAYS_ON),
+ SEC_PD(S6_PCIE, 0),
+ SEC_PD(S6_NNA_4T, 0),
+ SEC_PD(S6_AUDIO, 0),
+ SEC_PD(S6_AUCPU, 0),
+ SEC_PD(S6_ADAPT, 0),
+};
+
+static const struct meson_secure_pwrc_domain_desc s7_pwrc_domains[] = {
+ SEC_PD(S7_DOS_HEVC, 0),
+ SEC_PD(S7_DOS_VDEC, 0),
+ SEC_PD(S7_VPU_HDMI, 0),
+ SEC_PD(S7_USB_COMB, 0),
+ SEC_PD(S7_SD_EMMC_C, 0),
+ SEC_PD(S7_GE2D, 0),
+ SEC_PD(S7_SD_EMMC_A, 0),
+ SEC_PD(S7_SD_EMMC_B, 0),
+ /* ETH is for ethernet online wakeup, and should be always on */
+ SEC_PD(S7_ETH, GENPD_FLAG_ALWAYS_ON),
+ SEC_PD(S7_AUCPU, 0),
+ SEC_PD(S7_AUDIO, 0),
+};
+
+static const struct meson_secure_pwrc_domain_desc s7d_pwrc_domains[] = {
+ SEC_PD(S7D_DOS_HCODEC, 0),
+ SEC_PD(S7D_DOS_HEVC, 0),
+ SEC_PD(S7D_DOS_VDEC, 0),
+ SEC_PD(S7D_VPU_HDMI, 0),
+ SEC_PD(S7D_USB_U2DRD, 0),
+ SEC_PD(S7D_USB_U2H, 0),
+ SEC_PD(S7D_SSD_EMMC_C, 0),
+ SEC_PD(S7D_GE2D, 0),
+ SEC_PD(S7D_AMFC, 0),
+ SEC_PD(S7D_EMMC_A, 0),
+ SEC_PD(S7D_EMMC_B, 0),
+ /* ETH is for ethernet online wakeup, and should be always on */
+ SEC_PD(S7D_ETH, GENPD_FLAG_ALWAYS_ON),
+ SEC_PD(S7D_AUCPU, 0),
+ SEC_PD(S7D_AUDIO, 0),
+ /* SRAMA is used as ATF runtime memory, and should be always on */
+ SEC_PD(S7D_SRAMA, GENPD_FLAG_ALWAYS_ON),
+ /* DMC0 is for DDR PHY ana/dig and DMC, and should be always on */
+ SEC_PD(S7D_DMC0, GENPD_FLAG_ALWAYS_ON),
+ /* DMC1 is for DDR PHY ana/dig and DMC, and should be always on */
+ SEC_PD(S7D_DMC1, GENPD_FLAG_ALWAYS_ON),
+ /* DDR should be always on */
+ SEC_PD(S7D_DDR, GENPD_FLAG_ALWAYS_ON),
+};
+
static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
SEC_PD(T7_DSPA, 0),
SEC_PD(T7_DSPB, 0),
@@ -367,6 +435,21 @@ static const struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = {
.count = ARRAY_SIZE(s4_pwrc_domains),
};
+static const struct meson_secure_pwrc_domain_data amlogic_secure_s6_pwrc_data = {
+ .domains = s6_pwrc_domains,
+ .count = ARRAY_SIZE(s6_pwrc_domains),
+};
+
+static const struct meson_secure_pwrc_domain_data amlogic_secure_s7_pwrc_data = {
+ .domains = s7_pwrc_domains,
+ .count = ARRAY_SIZE(s7_pwrc_domains),
+};
+
+static const struct meson_secure_pwrc_domain_data amlogic_secure_s7d_pwrc_data = {
+ .domains = s7d_pwrc_domains,
+ .count = ARRAY_SIZE(s7d_pwrc_domains),
+};
+
static const struct meson_secure_pwrc_domain_data amlogic_secure_t7_pwrc_data = {
.domains = t7_pwrc_domains,
.count = ARRAY_SIZE(t7_pwrc_domains),
@@ -394,6 +477,18 @@ static const struct of_device_id meson_secure_pwrc_match_table[] = {
.data = &meson_secure_s4_pwrc_data,
},
{
+ .compatible = "amlogic,s6-pwrc",
+ .data = &amlogic_secure_s6_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,s7-pwrc",
+ .data = &amlogic_secure_s7_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,s7d-pwrc",
+ .data = &amlogic_secure_s7d_pwrc_data,
+ },
+ {
.compatible = "amlogic,t7-pwrc",
.data = &amlogic_secure_t7_pwrc_data,
},
diff --git a/drivers/pmdomain/apple/pmgr-pwrstate.c b/drivers/pmdomain/apple/pmgr-pwrstate.c
index 9467235110f4..82c33cf727a8 100644
--- a/drivers/pmdomain/apple/pmgr-pwrstate.c
+++ b/drivers/pmdomain/apple/pmgr-pwrstate.c
@@ -306,6 +306,7 @@ err_remove:
}
static const struct of_device_id apple_pmgr_ps_of_match[] = {
+ { .compatible = "apple,t8103-pmgr-pwrstate" },
{ .compatible = "apple,pmgr-pwrstate" },
{}
};
diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
index f18c7e6e75dd..33991f3c6b55 100644
--- a/drivers/pmdomain/imx/gpc.c
+++ b/drivers/pmdomain/imx/gpc.c
@@ -343,7 +343,6 @@ static const struct regmap_config imx_gpc_regmap_config = {
.rd_table = &access_table,
.wr_table = &access_table,
.max_register = 0x2ac,
- .fast_io = true,
};
static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
diff --git a/drivers/pmdomain/imx/imx93-blk-ctrl.c b/drivers/pmdomain/imx/imx93-blk-ctrl.c
index 0e2ba8ec55d7..e094fe5a42bf 100644
--- a/drivers/pmdomain/imx/imx93-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx93-blk-ctrl.c
@@ -86,6 +86,7 @@ struct imx93_blk_ctrl_domain {
struct imx93_blk_ctrl_data {
const struct imx93_blk_ctrl_domain_data *domains;
+ u32 skip_mask;
int num_domains;
const char * const *clk_names;
int num_clks;
@@ -250,6 +251,8 @@ static int imx93_blk_ctrl_probe(struct platform_device *pdev)
int j;
domain->data = data;
+ if (bc_data->skip_mask & BIT(i))
+ continue;
for (j = 0; j < data->num_clks; j++)
domain->clks[j].id = data->clk_names[j];
@@ -418,16 +421,32 @@ static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
.n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
};
+static const char * const media_blk_clk_names[] = {
+ "axi", "apb", "nic"
+};
+
+static const struct imx93_blk_ctrl_data imx91_media_blk_ctl_dev_data = {
+ .domains = imx93_media_blk_ctl_domain_data,
+ .skip_mask = BIT(IMX93_MEDIABLK_PD_MIPI_DSI) | BIT(IMX93_MEDIABLK_PD_PXP),
+ .num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
+ .clk_names = media_blk_clk_names,
+ .num_clks = ARRAY_SIZE(media_blk_clk_names),
+ .reg_access_table = &imx93_media_blk_ctl_access_table,
+};
+
static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
.domains = imx93_media_blk_ctl_domain_data,
.num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
- .clk_names = (const char *[]){ "axi", "apb", "nic", },
- .num_clks = 3,
+ .clk_names = media_blk_clk_names,
+ .num_clks = ARRAY_SIZE(media_blk_clk_names),
.reg_access_table = &imx93_media_blk_ctl_access_table,
};
static const struct of_device_id imx93_blk_ctrl_of_match[] = {
{
+ .compatible = "fsl,imx91-media-blk-ctrl",
+ .data = &imx91_media_blk_ctl_dev_data
+ }, {
.compatible = "fsl,imx93-media-blk-ctrl",
.data = &imx93_media_blk_ctl_dev_data
}, {
diff --git a/drivers/pmdomain/marvell/Kconfig b/drivers/pmdomain/marvell/Kconfig
new file mode 100644
index 000000000000..6c4084c82667
--- /dev/null
+++ b/drivers/pmdomain/marvell/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menu "Marvell PM Domains"
+ depends on ARCH_MMP || COMPILE_TEST
+
+config PXA1908_PM_DOMAINS
+ tristate "Marvell PXA1908 power domains"
+ depends on OF
+ depends on PM
+ default y if ARCH_MMP && ARM64
+ select AUXILIARY_BUS
+ select MFD_SYSCON
+ select PM_GENERIC_DOMAINS
+ select PM_GENERIC_DOMAINS_OF
+ help
+ Say Y here to enable support for Marvell PXA1908's power domanis.
+
+endmenu
diff --git a/drivers/pmdomain/marvell/Makefile b/drivers/pmdomain/marvell/Makefile
new file mode 100644
index 000000000000..22c25013f6c8
--- /dev/null
+++ b/drivers/pmdomain/marvell/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_PXA1908_PM_DOMAINS) += pxa1908-power-controller.o
diff --git a/drivers/pmdomain/marvell/pxa1908-power-controller.c b/drivers/pmdomain/marvell/pxa1908-power-controller.c
new file mode 100644
index 000000000000..ff5e6e82d3f8
--- /dev/null
+++ b/drivers/pmdomain/marvell/pxa1908-power-controller.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2025 Duje Mihanović <duje@dujemihanovic.xyz>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/container_of.h>
+#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/power/marvell,pxa1908-power.h>
+
+/* VPU, GPU, ISP */
+#define APMU_PWR_CTRL_REG 0xd8
+#define APMU_PWR_BLK_TMR_REG 0xdc
+#define APMU_PWR_STATUS_REG 0xf0
+
+/* DSI */
+#define APMU_DEBUG 0x88
+#define DSI_PHY_DVM_MASK BIT(31)
+
+#define POWER_ON_LATENCY_US 300
+#define POWER_OFF_LATENCY_US 20
+#define POWER_POLL_TIMEOUT_US (25 * USEC_PER_MSEC)
+#define POWER_POLL_SLEEP_US 6
+
+#define NR_DOMAINS 5
+
+#define to_pxa1908_pd(_genpd) container_of(_genpd, struct pxa1908_pd, genpd)
+
+struct pxa1908_pd_ctrl {
+ struct generic_pm_domain *domains[NR_DOMAINS];
+ struct genpd_onecell_data onecell_data;
+ struct regmap *base;
+ struct device *dev;
+};
+
+struct pxa1908_pd_data {
+ u32 reg_clk_res_ctrl;
+ u32 pwr_state;
+ u32 hw_mode;
+ bool keep_on;
+ int id;
+};
+
+struct pxa1908_pd {
+ const struct pxa1908_pd_data data;
+ struct pxa1908_pd_ctrl *ctrl;
+ struct generic_pm_domain genpd;
+ bool initialized;
+};
+
+static inline bool pxa1908_pd_is_on(struct pxa1908_pd *pd)
+{
+ struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
+
+ return pd->data.id != PXA1908_POWER_DOMAIN_DSI
+ ? regmap_test_bits(ctrl->base, APMU_PWR_STATUS_REG, pd->data.pwr_state)
+ : regmap_test_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
+}
+
+static int pxa1908_pd_power_on(struct generic_pm_domain *genpd)
+{
+ struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
+ const struct pxa1908_pd_data *data = &pd->data;
+ struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
+ unsigned int status;
+ int ret = 0;
+
+ regmap_set_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
+ if (data->id != PXA1908_POWER_DOMAIN_ISP)
+ regmap_write(ctrl->base, APMU_PWR_BLK_TMR_REG, 0x20001fff);
+ regmap_set_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);
+
+ ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
+ status & data->pwr_state, POWER_POLL_SLEEP_US,
+ POWER_ON_LATENCY_US + POWER_POLL_TIMEOUT_US);
+ if (ret == -ETIMEDOUT)
+ dev_err(ctrl->dev, "timed out powering on domain '%s'\n", pd->genpd.name);
+
+ return ret;
+}
+
+static int pxa1908_pd_power_off(struct generic_pm_domain *genpd)
+{
+ struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
+ const struct pxa1908_pd_data *data = &pd->data;
+ struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
+ unsigned int status;
+ int ret;
+
+ regmap_clear_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);
+
+ ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
+ !(status & data->pwr_state), POWER_POLL_SLEEP_US,
+ POWER_OFF_LATENCY_US + POWER_POLL_TIMEOUT_US);
+ if (ret == -ETIMEDOUT) {
+ dev_err(ctrl->dev, "timed out powering off domain '%s'\n", pd->genpd.name);
+ return ret;
+ }
+
+ return regmap_clear_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
+}
+
+static inline int pxa1908_dsi_power_on(struct generic_pm_domain *genpd)
+{
+ struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
+ struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
+
+ return regmap_set_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
+}
+
+static inline int pxa1908_dsi_power_off(struct generic_pm_domain *genpd)
+{
+ struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
+ struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
+
+ return regmap_clear_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
+}
+
+#define DOMAIN(_id, _name, ctrl, mode, state) \
+ [_id] = { \
+ .data = { \
+ .reg_clk_res_ctrl = ctrl, \
+ .hw_mode = BIT(mode), \
+ .pwr_state = BIT(state), \
+ .id = _id, \
+ }, \
+ .genpd = { \
+ .name = _name, \
+ .power_on = pxa1908_pd_power_on, \
+ .power_off = pxa1908_pd_power_off, \
+ }, \
+ }
+
+static struct pxa1908_pd domains[NR_DOMAINS] = {
+ DOMAIN(PXA1908_POWER_DOMAIN_VPU, "vpu", 0xa4, 19, 2),
+ DOMAIN(PXA1908_POWER_DOMAIN_GPU, "gpu", 0xcc, 11, 0),
+ DOMAIN(PXA1908_POWER_DOMAIN_GPU2D, "gpu2d", 0xf4, 11, 6),
+ DOMAIN(PXA1908_POWER_DOMAIN_ISP, "isp", 0x38, 15, 4),
+ [PXA1908_POWER_DOMAIN_DSI] = {
+ .genpd = {
+ .name = "dsi",
+ .power_on = pxa1908_dsi_power_on,
+ .power_off = pxa1908_dsi_power_off,
+ /*
+ * TODO: There is no DSI driver written yet and until then we probably
+ * don't want to power off the DSI PHY ever.
+ */
+ .flags = GENPD_FLAG_ALWAYS_ON,
+ },
+ .data = {
+ /* See above. */
+ .keep_on = true,
+ },
+ },
+};
+
+static void pxa1908_pd_remove(struct auxiliary_device *auxdev)
+{
+ struct pxa1908_pd *pd;
+ int ret;
+
+ for (int i = NR_DOMAINS - 1; i >= 0; i--) {
+ pd = &domains[i];
+
+ if (!pd->initialized)
+ continue;
+
+ if (pxa1908_pd_is_on(pd) && !pd->data.keep_on)
+ pxa1908_pd_power_off(&pd->genpd);
+
+ ret = pm_genpd_remove(&pd->genpd);
+ if (ret)
+ dev_err(&auxdev->dev, "failed to remove domain '%s': %d\n",
+ pd->genpd.name, ret);
+ }
+}
+
+static int
+pxa1908_pd_init(struct pxa1908_pd_ctrl *ctrl, int id, struct device *dev)
+{
+ struct pxa1908_pd *pd = &domains[id];
+ int ret;
+
+ ctrl->domains[id] = &pd->genpd;
+
+ pd->ctrl = ctrl;
+
+ /* Make sure the state of the hardware is synced with the domain table above. */
+ if (pd->data.keep_on) {
+ ret = pd->genpd.power_on(&pd->genpd);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on domain '%s'\n",
+ pd->genpd.name);
+ } else {
+ if (pxa1908_pd_is_on(pd)) {
+ dev_warn(dev,
+ "domain '%s' is on despite being default off; powering off\n",
+ pd->genpd.name);
+
+ ret = pd->genpd.power_off(&pd->genpd);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to power off domain '%s'\n",
+ pd->genpd.name);
+ }
+ }
+
+ ret = pm_genpd_init(&pd->genpd, NULL, !pd->data.keep_on);
+ if (ret)
+ return dev_err_probe(dev, ret, "domain '%s' failed to initialize\n",
+ pd->genpd.name);
+
+ pd->initialized = true;
+
+ return 0;
+}
+
+static int
+pxa1908_pd_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *aux_id)
+{
+ struct pxa1908_pd_ctrl *ctrl;
+ struct device *dev = &auxdev->dev;
+ int ret;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ auxiliary_set_drvdata(auxdev, ctrl);
+
+ ctrl->base = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(ctrl->base))
+ return dev_err_probe(dev, PTR_ERR(ctrl->base), "no regmap available\n");
+
+ ctrl->dev = dev;
+ ctrl->onecell_data.domains = ctrl->domains;
+ ctrl->onecell_data.num_domains = NR_DOMAINS;
+
+ for (int i = 0; i < NR_DOMAINS; i++) {
+ ret = pxa1908_pd_init(ctrl, i, dev);
+ if (ret)
+ goto err;
+ }
+
+ return of_genpd_add_provider_onecell(dev->parent->of_node, &ctrl->onecell_data);
+
+err:
+ pxa1908_pd_remove(auxdev);
+ return ret;
+}
+
+static const struct auxiliary_device_id pxa1908_pd_id[] = {
+ { .name = "clk_pxa1908_apmu.power" },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, pxa1908_pd_id);
+
+static struct auxiliary_driver pxa1908_pd_driver = {
+ .probe = pxa1908_pd_probe,
+ .remove = pxa1908_pd_remove,
+ .id_table = pxa1908_pd_id,
+};
+module_auxiliary_driver(pxa1908_pd_driver);
+
+MODULE_AUTHOR("Duje Mihanović <duje@dujemihanovic.xyz>");
+MODULE_DESCRIPTION("Marvell PXA1908 power domain driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
index 0fd88d2f9ac2..3b1d202f89dc 100644
--- a/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
+++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
@@ -21,10 +21,10 @@ struct airoha_cpu_pmdomain_priv {
struct generic_pm_domain pd;
};
-static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int airoha_cpu_pmdomain_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return rate;
+ return 0;
}
static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
@@ -48,7 +48,7 @@ static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
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,
- .round_rate = airoha_cpu_pmdomain_clk_round,
+ .determine_rate = airoha_cpu_pmdomain_clk_determine_rate,
};
static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
diff --git a/drivers/pmdomain/mediatek/mt6795-pm-domains.h b/drivers/pmdomain/mediatek/mt6795-pm-domains.h
index a3f7785b04bd..dc8e9f8877ad 100644
--- a/drivers/pmdomain/mediatek/mt6795-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt6795-pm-domains.h
@@ -9,6 +9,9 @@
/*
* 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] = {
@@ -107,6 +110,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
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/mt8167-pm-domains.h b/drivers/pmdomain/mediatek/mt8167-pm-domains.h
index 8a0e898b79ab..f6ee48a711a1 100644
--- a/drivers/pmdomain/mediatek/mt8167-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8167-pm-domains.h
@@ -12,6 +12,9 @@
/*
* 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] = {
@@ -99,6 +102,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
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
index 7be0f47f5214..561a644b5d1c 100644
--- a/drivers/pmdomain/mediatek/mt8173-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8173-pm-domains.h
@@ -9,6 +9,9 @@
/*
* 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] = {
@@ -118,6 +121,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
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
index c4c1b63d85b1..3742782a2702 100644
--- a/drivers/pmdomain/mediatek/mt8183-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8183-pm-domains.h
@@ -9,6 +9,9 @@
/*
* 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] = {
@@ -290,6 +293,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
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
index cbac715c38fa..00b9861af7c9 100644
--- a/drivers/pmdomain/mediatek/mt8186-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8186-pm-domains.h
@@ -13,6 +13,9 @@
/*
* 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] = {
@@ -361,6 +364,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
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
index 007235be9efe..3a989e83e9b7 100644
--- a/drivers/pmdomain/mediatek/mt8188-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
@@ -14,6 +14,10 @@
* 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",
@@ -685,6 +689,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
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/mt8192-pm-domains.h b/drivers/pmdomain/mediatek/mt8192-pm-domains.h
index 6f139eed3769..5d62fac5f682 100644
--- a/drivers/pmdomain/mediatek/mt8192-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8192-pm-domains.h
@@ -9,6 +9,9 @@
/*
* 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] = {
@@ -380,6 +383,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
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
index 59aa031ae632..1d3ca195ac75 100644
--- a/drivers/pmdomain/mediatek/mt8195-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8195-pm-domains.h
@@ -13,6 +13,9 @@
/*
* 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] = {
@@ -123,6 +126,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
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",
@@ -661,6 +665,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
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/mt8365-pm-domains.h b/drivers/pmdomain/mediatek/mt8365-pm-domains.h
index 3d83d49eaa7c..33265ab8ce76 100644
--- a/drivers/pmdomain/mediatek/mt8365-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mt8365-pm-domains.h
@@ -29,11 +29,13 @@
MT8365_SMI_COMMON_CLAMP_EN)
#define MT8365_BUS_PROT_WAY_EN(_set_mask, _set, _sta_mask, _sta) \
- _BUS_PROT(_set_mask, _set, _set, _sta_mask, _sta, \
- BUS_PROT_COMPONENT_INFRA | \
- BUS_PROT_STA_COMPONENT_INFRA_NAO | \
- BUS_PROT_INVERTED | \
- BUS_PROT_REG_UPDATE)
+ _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] = {
@@ -192,6 +194,8 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = {
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-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index a58ed7e2d9a4..0ebe7379b94e 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -39,6 +39,12 @@
#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)
+
struct scpsys_domain {
struct generic_pm_domain genpd;
const struct scpsys_domain_data *data;
@@ -47,9 +53,6 @@ struct scpsys_domain {
struct clk_bulk_data *clks;
int num_subsys_clks;
struct clk_bulk_data *subsys_clks;
- struct regmap *infracfg_nao;
- struct regmap *infracfg;
- struct regmap *smi;
struct regulator *supply;
};
@@ -57,6 +60,8 @@ 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[];
};
@@ -80,16 +85,23 @@ static bool scpsys_domain_is_on(struct scpsys_domain *pd)
static int scpsys_sram_enable(struct scpsys_domain *pd)
{
- u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+ u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
int ret;
- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = pdn_ack;
+ } else {
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = 0;
+ }
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
- (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ (tmp & pdn_ack) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;
@@ -104,7 +116,7 @@ static int scpsys_sram_enable(struct scpsys_domain *pd)
static int scpsys_sram_disable(struct scpsys_domain *pd)
{
- u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+ u32 expected_ack, pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
@@ -114,30 +126,36 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
}
- regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_PDN_INVERTED)) {
+ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = 0;
+ } else {
+ regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+ expected_ack = pdn_ack;
+ }
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
- (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
- MTK_POLL_TIMEOUT);
+ (tmp & pdn_ack) == expected_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
}
static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
const struct scpsys_bus_prot_data *bpd)
{
- if (bpd->flags & BUS_PROT_COMPONENT_SMI)
- return pd->smi;
- else
- return pd->infracfg;
+ 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)
{
- if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
- return pd->infracfg_nao;
- else
- return scpsys_bus_protect_get_regmap(pd, 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,
@@ -149,7 +167,7 @@ static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
u32 expected_ack;
u32 val;
- expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0);
+ 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);
@@ -232,11 +250,161 @@ static int scpsys_regulator_disable(struct regulator *supply)
return supply ? regulator_disable(supply) : 0;
}
+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;
- bool tmp;
int ret;
ret = scpsys_regulator_enable(pd->supply);
@@ -251,20 +419,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
pd->data->ext_buck_iso_mask);
- /* 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);
+ if (MTK_SCPD_CAPS(pd, MTK_SCPD_MODEM_PWRSEQ))
+ ret = scpsys_modem_pwrseq_on(pd);
+ else
+ ret = scpsys_ctl_pwrseq_on(pd);
- /* 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)
+ if (ret)
goto err_pwr_ack;
- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
- regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
-
/*
* In few Mediatek platforms(e.g. MT6779), the bus protect policy is
* stricter, which leads to bus protect release must be prior to bus
@@ -330,12 +492,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
- /* subsys power off */
- regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
- 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);
+ 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,
@@ -355,7 +515,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
{
const struct scpsys_domain_data *domain_data;
struct scpsys_domain *pd;
- struct device_node *smi_node;
struct property *prop;
const char *clk_name;
int i, ret, num_clks;
@@ -396,32 +555,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
node);
}
- pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
- if (IS_ERR(pd->infracfg))
- return dev_err_cast_probe(scpsys->dev, pd->infracfg,
- "%pOF: failed to get infracfg regmap\n",
- node);
-
- smi_node = of_parse_phandle(node, "mediatek,smi", 0);
- if (smi_node) {
- pd->smi = device_node_to_regmap(smi_node);
- of_node_put(smi_node);
- if (IS_ERR(pd->smi))
- return dev_err_cast_probe(scpsys->dev, pd->smi,
- "%pOF: failed to get SMI regmap\n",
- node);
- }
-
- if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
- pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
- if (IS_ERR(pd->infracfg_nao))
- return dev_err_cast_probe(scpsys->dev, pd->infracfg_nao,
- "%pOF: failed to get infracfg-nao regmap\n",
- node);
- } else {
- pd->infracfg_nao = NULL;
- }
-
num_clks = of_clk_get_parent_count(node);
if (num_clks > 0) {
/* Calculate number of subsys_clks */
@@ -615,6 +748,136 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
}
}
+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];
+
+ /*
+ * 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.
+ */
+ 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;
+ }
+
+ 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;
+ }
+
+ 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++;
+ of_node_put(node);
+ if (IS_ERR(regmap[2]))
+ return dev_err_probe(dev, PTR_ERR(regmap[2]),
+ "%pOF: failed to get infracfg regmap\n",
+ 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",
@@ -701,6 +964,14 @@ static int scpsys_probe(struct platform_device *pdev)
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(np, node) {
struct generic_pm_domain *domain;
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
index 7085fa2976e9..b2e3dee03831 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.h
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h
@@ -13,6 +13,9 @@
#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_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
#define SPM_VDE_PWR_CON 0x0210
@@ -50,30 +53,43 @@ 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_COMPONENT_INFRA = BIT(4),
- BUS_PROT_COMPONENT_SMI = BIT(5),
- BUS_PROT_STA_COMPONENT_INFRA_NAO = BIT(6),
};
-#define _BUS_PROT(_set_clr_mask, _set, _clr, _sta_mask, _sta, _flags) { \
- .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 \
+enum scpsys_bus_prot_block {
+ BUS_PROT_BLOCK_INFRA,
+ BUS_PROT_BLOCK_INFRA_NAO,
+ BUS_PROT_BLOCK_SMI,
+ 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_WR(_hwip, _mask, _set, _clr, _sta) \
- _BUS_PROT(_mask, _set, _clr, _mask, _sta, BUS_PROT_COMPONENT_##_hwip)
+#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_IGN(_hwip, _mask, _set, _clr, _sta) \
- _BUS_PROT(_mask, _set, _clr, _mask, _sta, \
- BUS_PROT_COMPONENT_##_hwip | BUS_PROT_IGNORE_CLR_ACK)
+#define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \
+ _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, 0)
-#define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \
- _BUS_PROT(_mask, _set, _clr, _mask, _sta, \
- BUS_PROT_COMPONENT_##_hwip | BUS_PROT_REG_UPDATE)
+#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_INFRA_UPDATE_TOPAXI(_mask) \
BUS_PROT_UPDATE(INFRA, _mask, \
@@ -82,6 +98,8 @@ enum scpsys_bus_prot_flags {
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;
@@ -91,6 +109,22 @@ struct scpsys_bus_prot_data {
};
/**
+ * 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
+};
+
+/**
* 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.
@@ -100,6 +134,7 @@ struct scpsys_bus_prot_data {
* @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 {
@@ -111,6 +146,7 @@ struct scpsys_domain_data {
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;
@@ -119,6 +155,8 @@ struct scpsys_domain_data {
struct scpsys_soc_data {
const struct scpsys_domain_data *domains_data;
int num_domains;
+ enum scpsys_bus_prot_block *bus_prot_blocks;
+ int num_bus_prot_blocks;
};
#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
index 833c46944600..f8580ec0f737 100644
--- a/drivers/pmdomain/qcom/rpmpd.c
+++ b/drivers/pmdomain/qcom/rpmpd.c
@@ -631,12 +631,12 @@ static struct rpmpd ssc_mx_rwsm0_vfl = {
};
static struct rpmpd *mdm9607_rpmpds[] = {
- [MDM9607_VDDCX] = &cx_s3a_lvl,
- [MDM9607_VDDCX_AO] = &cx_s3a_lvl_ao,
- [MDM9607_VDDCX_VFL] = &cx_s3a_vfl,
- [MDM9607_VDDMX] = &mx_l12a_lvl,
- [MDM9607_VDDMX_AO] = &mx_l12a_lvl_ao,
- [MDM9607_VDDMX_VFL] = &mx_l12a_vfl,
+ [RPMPD_VDDCX] = &cx_s3a_lvl,
+ [RPMPD_VDDCX_AO] = &cx_s3a_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_s3a_vfl,
+ [RPMPD_VDDMX] = &mx_l12a_lvl,
+ [RPMPD_VDDMX_AO] = &mx_l12a_lvl_ao,
+ [RPMPD_VDDMX_VFL] = &mx_l12a_vfl,
};
static const struct rpmpd_desc mdm9607_desc = {
@@ -646,9 +646,9 @@ static const struct rpmpd_desc mdm9607_desc = {
};
static struct rpmpd *msm8226_rpmpds[] = {
- [MSM8226_VDDCX] = &cx_s1a_corner,
- [MSM8226_VDDCX_AO] = &cx_s1a_corner_ao,
- [MSM8226_VDDCX_VFC] = &cx_s1a_vfc,
+ [RPMPD_VDDCX] = &cx_s1a_corner,
+ [RPMPD_VDDCX_AO] = &cx_s1a_corner_ao,
+ [RPMPD_VDDCX_VFC] = &cx_s1a_vfc,
};
static const struct rpmpd_desc msm8226_desc = {
@@ -675,11 +675,11 @@ static const struct rpmpd_desc msm8939_desc = {
};
static struct rpmpd *msm8916_rpmpds[] = {
- [MSM8916_VDDCX] = &cx_s1a_corner,
- [MSM8916_VDDCX_AO] = &cx_s1a_corner_ao,
- [MSM8916_VDDCX_VFC] = &cx_s1a_vfc,
- [MSM8916_VDDMX] = &mx_l3a_corner,
- [MSM8916_VDDMX_AO] = &mx_l3a_corner_ao,
+ [RPMPD_VDDCX] = &cx_s1a_corner,
+ [RPMPD_VDDCX_AO] = &cx_s1a_corner_ao,
+ [RPMPD_VDDCX_VFC] = &cx_s1a_vfc,
+ [RPMPD_VDDMX] = &mx_l3a_corner,
+ [RPMPD_VDDMX_AO] = &mx_l3a_corner_ao,
};
static const struct rpmpd_desc msm8916_desc = {
@@ -689,11 +689,11 @@ static const struct rpmpd_desc msm8916_desc = {
};
static struct rpmpd *msm8917_rpmpds[] = {
- [MSM8917_VDDCX] = &cx_s2a_lvl,
- [MSM8917_VDDCX_AO] = &cx_s2a_lvl_ao,
- [MSM8917_VDDCX_VFL] = &cx_s2a_vfl,
- [MSM8917_VDDMX] = &mx_l3a_lvl,
- [MSM8917_VDDMX_AO] = &mx_l3a_lvl_ao,
+ [RPMPD_VDDCX] = &cx_s2a_lvl,
+ [RPMPD_VDDCX_AO] = &cx_s2a_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_s2a_vfl,
+ [RPMPD_VDDMX] = &mx_l3a_lvl,
+ [RPMPD_VDDMX_AO] = &mx_l3a_lvl_ao,
};
static const struct rpmpd_desc msm8917_desc = {
@@ -747,12 +747,12 @@ static const struct rpmpd_desc msm8974pro_pma8084_desc = {
};
static struct rpmpd *msm8976_rpmpds[] = {
- [MSM8976_VDDCX] = &cx_s2a_lvl,
- [MSM8976_VDDCX_AO] = &cx_s2a_lvl_ao,
- [MSM8976_VDDCX_VFL] = &cx_rwsc2_vfl,
- [MSM8976_VDDMX] = &mx_s6a_lvl,
- [MSM8976_VDDMX_AO] = &mx_s6a_lvl_ao,
- [MSM8976_VDDMX_VFL] = &mx_rwsm6_vfl,
+ [RPMPD_VDDCX] = &cx_s2a_lvl,
+ [RPMPD_VDDCX_AO] = &cx_s2a_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_rwsc2_vfl,
+ [RPMPD_VDDMX] = &mx_s6a_lvl,
+ [RPMPD_VDDMX_AO] = &mx_s6a_lvl_ao,
+ [RPMPD_VDDMX_VFL] = &mx_rwsm6_vfl,
};
static const struct rpmpd_desc msm8976_desc = {
@@ -796,16 +796,16 @@ static const struct rpmpd_desc msm8996_desc = {
};
static struct rpmpd *msm8998_rpmpds[] = {
- [MSM8998_VDDCX] = &cx_rwcx0_lvl,
- [MSM8998_VDDCX_AO] = &cx_rwcx0_lvl_ao,
- [MSM8998_VDDCX_VFL] = &cx_rwcx0_vfl,
- [MSM8998_VDDMX] = &mx_rwmx0_lvl,
- [MSM8998_VDDMX_AO] = &mx_rwmx0_lvl_ao,
- [MSM8998_VDDMX_VFL] = &mx_rwmx0_vfl,
- [MSM8998_SSCCX] = &ssc_cx_rwsc0_lvl,
- [MSM8998_SSCCX_VFL] = &ssc_cx_rwsc0_vfl,
- [MSM8998_SSCMX] = &ssc_mx_rwsm0_lvl,
- [MSM8998_SSCMX_VFL] = &ssc_mx_rwsm0_vfl,
+ [RPMPD_VDDCX] = &cx_rwcx0_lvl,
+ [RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
+ [RPMPD_VDDMX] = &mx_rwmx0_lvl,
+ [RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
+ [RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
+ [RPMPD_SSCCX] = &ssc_cx_rwsc0_lvl,
+ [RPMPD_SSCCX_VFL] = &ssc_cx_rwsc0_vfl,
+ [RPMPD_SSCMX] = &ssc_mx_rwsm0_lvl,
+ [RPMPD_SSCMX_VFL] = &ssc_mx_rwsm0_vfl,
};
static const struct rpmpd_desc msm8998_desc = {
@@ -831,11 +831,11 @@ static const struct rpmpd_desc qcs404_desc = {
};
static struct rpmpd *qm215_rpmpds[] = {
- [QM215_VDDCX] = &cx_s1a_lvl,
- [QM215_VDDCX_AO] = &cx_s1a_lvl_ao,
- [QM215_VDDCX_VFL] = &cx_s1a_vfl,
- [QM215_VDDMX] = &mx_l2a_lvl,
- [QM215_VDDMX_AO] = &mx_l2a_lvl_ao,
+ [RPMPD_VDDCX] = &cx_s1a_lvl,
+ [RPMPD_VDDCX_AO] = &cx_s1a_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_s1a_vfl,
+ [RPMPD_VDDMX] = &mx_l2a_lvl,
+ [RPMPD_VDDMX_AO] = &mx_l2a_lvl_ao,
};
static const struct rpmpd_desc qm215_desc = {
@@ -845,16 +845,16 @@ static const struct rpmpd_desc qm215_desc = {
};
static struct rpmpd *sdm660_rpmpds[] = {
- [SDM660_VDDCX] = &cx_rwcx0_lvl,
- [SDM660_VDDCX_AO] = &cx_rwcx0_lvl_ao,
- [SDM660_VDDCX_VFL] = &cx_rwcx0_vfl,
- [SDM660_VDDMX] = &mx_rwmx0_lvl,
- [SDM660_VDDMX_AO] = &mx_rwmx0_lvl_ao,
- [SDM660_VDDMX_VFL] = &mx_rwmx0_vfl,
- [SDM660_SSCCX] = &ssc_cx_rwlc0_lvl,
- [SDM660_SSCCX_VFL] = &ssc_cx_rwlc0_vfl,
- [SDM660_SSCMX] = &ssc_mx_rwlm0_lvl,
- [SDM660_SSCMX_VFL] = &ssc_mx_rwlm0_vfl,
+ [RPMPD_VDDCX] = &cx_rwcx0_lvl,
+ [RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
+ [RPMPD_VDDMX] = &mx_rwmx0_lvl,
+ [RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
+ [RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
+ [RPMPD_SSCCX] = &ssc_cx_rwlc0_lvl,
+ [RPMPD_SSCCX_VFL] = &ssc_cx_rwlc0_vfl,
+ [RPMPD_SSCMX] = &ssc_mx_rwlm0_lvl,
+ [RPMPD_SSCMX_VFL] = &ssc_mx_rwlm0_vfl,
};
static const struct rpmpd_desc sdm660_desc = {
@@ -881,12 +881,12 @@ static const struct rpmpd_desc sm6115_desc = {
};
static struct rpmpd *sm6125_rpmpds[] = {
- [SM6125_VDDCX] = &cx_rwcx0_lvl,
- [SM6125_VDDCX_AO] = &cx_rwcx0_lvl_ao,
- [SM6125_VDDCX_VFL] = &cx_rwcx0_vfl,
- [SM6125_VDDMX] = &mx_rwmx0_lvl,
- [SM6125_VDDMX_AO] = &mx_rwmx0_lvl_ao,
- [SM6125_VDDMX_VFL] = &mx_rwmx0_vfl,
+ [RPMPD_VDDCX] = &cx_rwcx0_lvl,
+ [RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao,
+ [RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl,
+ [RPMPD_VDDMX] = &mx_rwmx0_lvl,
+ [RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao,
+ [RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl,
};
static const struct rpmpd_desc sm6125_desc = {
diff --git a/drivers/pmdomain/rockchip/Kconfig b/drivers/pmdomain/rockchip/Kconfig
index 218d43186e5b..17f2e6fe86b6 100644
--- a/drivers/pmdomain/rockchip/Kconfig
+++ b/drivers/pmdomain/rockchip/Kconfig
@@ -3,6 +3,7 @@ if ARCH_ROCKCHIP || COMPILE_TEST
config ROCKCHIP_PM_DOMAINS
bool "Rockchip generic power domain"
+ default ARCH_ROCKCHIP
depends on PM
depends on HAVE_ARM_SMCCC_DISCOVERY
depends on REGULATOR
diff --git a/drivers/pmdomain/thead/th1520-pm-domains.c b/drivers/pmdomain/thead/th1520-pm-domains.c
index 9040b698e7f7..d7cb9633c7c8 100644
--- a/drivers/pmdomain/thead/th1520-pm-domains.c
+++ b/drivers/pmdomain/thead/th1520-pm-domains.c
@@ -173,6 +173,18 @@ static int th1520_pd_pwrseq_gpu_init(struct device *dev)
adev);
}
+static int th1520_pd_reboot_init(struct device *dev,
+ struct th1520_aon_chan *aon_chan)
+{
+ struct auxiliary_device *adev;
+
+ adev = devm_auxiliary_device_create(dev, "reboot", aon_chan);
+ if (!adev)
+ return -ENODEV;
+
+ return 0;
+}
+
static int th1520_pd_probe(struct platform_device *pdev)
{
struct generic_pm_domain **domains;
@@ -235,6 +247,10 @@ static int th1520_pd_probe(struct platform_device *pdev)
if (ret)
goto err_clean_provider;
+ ret = th1520_pd_reboot_init(dev, aon_chan);
+ if (ret)
+ goto err_clean_provider;
+
return 0;
err_clean_provider:
diff --git a/drivers/pmdomain/ti/ti_sci_pm_domains.c b/drivers/pmdomain/ti/ti_sci_pm_domains.c
index 82df7e44250b..e5d1934f78d9 100644
--- a/drivers/pmdomain/ti/ti_sci_pm_domains.c
+++ b/drivers/pmdomain/ti/ti_sci_pm_domains.c
@@ -200,6 +200,23 @@ static bool ti_sci_pm_idx_exists(struct ti_sci_genpd_provider *pd_provider, u32
return false;
}
+static bool ti_sci_pm_pd_is_on(struct ti_sci_genpd_provider *pd_provider,
+ int pd_idx)
+{
+ bool is_on;
+ int ret;
+
+ if (!pd_provider->ti_sci->ops.dev_ops.is_on)
+ return false;
+
+ ret = pd_provider->ti_sci->ops.dev_ops.is_on(pd_provider->ti_sci,
+ pd_idx, NULL, &is_on);
+ if (ret)
+ return false;
+
+ return is_on;
+}
+
static int ti_sci_pm_domain_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -231,6 +248,8 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
index, &args)) {
if (args.args_count >= 1 && args.np == dev->of_node) {
+ bool is_on;
+
of_node_put(args.np);
if (args.args[0] > max_id) {
max_id = args.args[0];
@@ -264,7 +283,10 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
pd_provider->ti_sci->ops.pm_ops.set_latency_constraint)
pd->pd.domain.ops.suspend = ti_sci_pd_suspend;
- pm_genpd_init(&pd->pd, NULL, true);
+ is_on = ti_sci_pm_pd_is_on(pd_provider,
+ pd->idx);
+
+ pm_genpd_init(&pd->pd, NULL, !is_on);
list_add(&pd->node, &pd_provider->pd_list);
} else {