soc: imx: Move power-domain drivers to the genpd dir
authorUlf Hansson <ulf.hansson@linaro.org>
Wed, 5 Jul 2023 12:17:29 +0000 (14:17 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 11 Jul 2023 13:30:09 +0000 (15:30 +0200)
To simplify with maintenance let's move the imx power-domain drivers to the
new genpd directory. Going forward, patches are intended to be managed
through a separate git tree, according to MAINTAINERS.

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: <kernel@pengutronix.de>
Cc: <linux-imx@nxp.com>
Reviewed-by: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
14 files changed:
drivers/genpd/imx/Makefile [new file with mode: 0644]
drivers/genpd/imx/gpc.c [new file with mode: 0644]
drivers/genpd/imx/gpcv2.c [new file with mode: 0644]
drivers/genpd/imx/imx8m-blk-ctrl.c [new file with mode: 0644]
drivers/genpd/imx/imx8mp-blk-ctrl.c [new file with mode: 0644]
drivers/genpd/imx/imx93-blk-ctrl.c [new file with mode: 0644]
drivers/genpd/imx/imx93-pd.c [new file with mode: 0644]
drivers/soc/imx/Makefile
drivers/soc/imx/gpc.c [deleted file]
drivers/soc/imx/gpcv2.c [deleted file]
drivers/soc/imx/imx8m-blk-ctrl.c [deleted file]
drivers/soc/imx/imx8mp-blk-ctrl.c [deleted file]
drivers/soc/imx/imx93-blk-ctrl.c [deleted file]
drivers/soc/imx/imx93-pd.c [deleted file]

diff --git a/drivers/genpd/imx/Makefile b/drivers/genpd/imx/Makefile
new file mode 100644 (file)
index 0000000..5f01271
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
+obj-$(CONFIG_SOC_IMX9) += imx93-pd.o
+obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
diff --git a/drivers/genpd/imx/gpc.c b/drivers/genpd/imx/gpc.c
new file mode 100644 (file)
index 0000000..90a8b2c
--- /dev/null
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define GPC_CNTR               0x000
+
+#define GPC_PGC_CTRL_OFFS      0x0
+#define GPC_PGC_PUPSCR_OFFS    0x4
+#define GPC_PGC_PDNSCR_OFFS    0x8
+#define GPC_PGC_SW2ISO_SHIFT   0x8
+#define GPC_PGC_SW_SHIFT       0x0
+
+#define GPC_PGC_PCI_PDN                0x200
+#define GPC_PGC_PCI_SR         0x20c
+
+#define GPC_PGC_GPU_PDN                0x260
+#define GPC_PGC_GPU_PUPSCR     0x264
+#define GPC_PGC_GPU_PDNSCR     0x268
+#define GPC_PGC_GPU_SR         0x26c
+
+#define GPC_PGC_DISP_PDN       0x240
+#define GPC_PGC_DISP_SR                0x24c
+
+#define GPU_VPU_PUP_REQ                BIT(1)
+#define GPU_VPU_PDN_REQ                BIT(0)
+
+#define GPC_CLK_MAX            7
+
+#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
+
+struct imx_pm_domain {
+       struct generic_pm_domain base;
+       struct regmap *regmap;
+       struct regulator *supply;
+       struct clk *clk[GPC_CLK_MAX];
+       int num_clks;
+       unsigned int reg_offs;
+       signed char cntr_pdn_bit;
+       unsigned int ipg_rate_mhz;
+};
+
+static inline struct imx_pm_domain *
+to_imx_pm_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pm_domain, base);
+}
+
+static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int iso, iso2sw;
+       u32 val;
+
+       /* Read ISO and ISO2SW power down delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
+       iso = val & 0x3f;
+       iso2sw = (val >> 8) & 0x3f;
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power down domain */
+       val = BIT(pd->cntr_pdn_bit);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
+
+       if (pd->supply)
+               regulator_disable(pd->supply);
+
+       return 0;
+}
+
+static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int i, ret;
+       u32 val, req;
+
+       if (pd->supply) {
+               ret = regulator_enable(pd->supply);
+               if (ret) {
+                       pr_err("%s: failed to enable regulator: %d\n",
+                              __func__, ret);
+                       return ret;
+               }
+       }
+
+       /* Enable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_prepare_enable(pd->clk[i]);
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power up domain */
+       req = BIT(pd->cntr_pdn_bit + 1);
+       regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
+
+       /* Wait for the PGC to handle the request */
+       ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
+                                      1, 50);
+       if (ret)
+               pr_err("powerup request on domain %s timed out\n", genpd->name);
+
+       /* Wait for reset to propagate through peripherals */
+       usleep_range(5, 10);
+
+       /* Disable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_disable_unprepare(pd->clk[i]);
+
+       return 0;
+}
+
+static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
+{
+       int i, ret;
+
+       for (i = 0; ; i++) {
+               struct clk *clk = of_clk_get(dev->of_node, i);
+               if (IS_ERR(clk))
+                       break;
+               if (i >= GPC_CLK_MAX) {
+                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
+                       ret = -EINVAL;
+                       goto clk_err;
+               }
+               domain->clk[i] = clk;
+       }
+       domain->num_clks = i;
+
+       return 0;
+
+clk_err:
+       while (i--)
+               clk_put(domain->clk[i]);
+
+       return ret;
+}
+
+static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
+{
+       int i;
+
+       for (i = domain->num_clks - 1; i >= 0; i--)
+               clk_put(domain->clk[i]);
+}
+
+static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
+{
+       /* try to get the domain supply regulator */
+       domain->supply = devm_regulator_get_optional(dev, "power");
+       if (IS_ERR(domain->supply)) {
+               if (PTR_ERR(domain->supply) == -ENODEV)
+                       domain->supply = NULL;
+               else
+                       return PTR_ERR(domain->supply);
+       }
+
+       /* try to get all clocks needed for reset propagation */
+       return imx_pgc_get_clocks(dev, domain);
+}
+
+static int imx_pgc_power_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       /* if this PD is associated with a DT node try to parse it */
+       if (dev->of_node) {
+               ret = imx_pgc_parse_dt(dev, domain);
+               if (ret)
+                       return ret;
+       }
+
+       /* initially power on the domain */
+       if (domain->base.power_on)
+               domain->base.power_on(&domain->base);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               pm_genpd_init(&domain->base, NULL, false);
+               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
+
+       return 0;
+
+genpd_err:
+       pm_genpd_remove(&domain->base);
+       imx_pgc_put_clocks(domain);
+
+       return ret;
+}
+
+static int imx_pgc_power_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               of_genpd_del_provider(pdev->dev.of_node);
+               pm_genpd_remove(&domain->base);
+               imx_pgc_put_clocks(domain);
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id imx_pgc_power_domain_id[] = {
+       { "imx-pgc-power-domain"},
+       { },
+};
+
+static struct platform_driver imx_pgc_power_domain_driver = {
+       .driver = {
+               .name = "imx-pgc-pd",
+       },
+       .probe = imx_pgc_power_domain_probe,
+       .remove = imx_pgc_power_domain_remove,
+       .id_table = imx_pgc_power_domain_id,
+};
+builtin_platform_driver(imx_pgc_power_domain_driver)
+
+#define GPC_PGC_DOMAIN_ARM     0
+#define GPC_PGC_DOMAIN_PU      1
+#define GPC_PGC_DOMAIN_DISPLAY 2
+#define GPC_PGC_DOMAIN_PCI     3
+
+static struct genpd_power_state imx6_pm_domain_pu_state = {
+       .power_off_latency_ns = 25000,
+       .power_on_latency_ns = 2000000,
+};
+
+static struct imx_pm_domain imx_gpc_domains[] = {
+       [GPC_PGC_DOMAIN_ARM] = {
+               .base = {
+                       .name = "ARM",
+                       .flags = GENPD_FLAG_ALWAYS_ON,
+               },
+       },
+       [GPC_PGC_DOMAIN_PU] = {
+               .base = {
+                       .name = "PU",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+                       .states = &imx6_pm_domain_pu_state,
+                       .state_count = 1,
+               },
+               .reg_offs = 0x260,
+               .cntr_pdn_bit = 0,
+       },
+       [GPC_PGC_DOMAIN_DISPLAY] = {
+               .base = {
+                       .name = "DISPLAY",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x240,
+               .cntr_pdn_bit = 4,
+       },
+       [GPC_PGC_DOMAIN_PCI] = {
+               .base = {
+                       .name = "PCI",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x200,
+               .cntr_pdn_bit = 6,
+       },
+};
+
+struct imx_gpc_dt_data {
+       int num_domains;
+       bool err009619_present;
+       bool err006287_present;
+};
+
+static const struct imx_gpc_dt_data imx6q_dt_data = {
+       .num_domains = 2,
+       .err009619_present = false,
+       .err006287_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6qp_dt_data = {
+       .num_domains = 2,
+       .err009619_present = true,
+       .err006287_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6sl_dt_data = {
+       .num_domains = 3,
+       .err009619_present = false,
+       .err006287_present = true,
+};
+
+static const struct imx_gpc_dt_data imx6sx_dt_data = {
+       .num_domains = 4,
+       .err009619_present = false,
+       .err006287_present = false,
+};
+
+static const struct of_device_id imx_gpc_dt_ids[] = {
+       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
+       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
+       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
+       { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data },
+       { }
+};
+
+static const struct regmap_range yes_ranges[] = {
+       regmap_reg_range(GPC_CNTR, GPC_CNTR),
+       regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR),
+       regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR),
+       regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR),
+};
+
+static const struct regmap_access_table access_table = {
+       .yes_ranges     = yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
+};
+
+static const struct regmap_config imx_gpc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .rd_table = &access_table,
+       .wr_table = &access_table,
+       .max_register = 0x2ac,
+       .fast_io = true,
+};
+
+static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
+       &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
+       &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
+};
+
+static struct genpd_onecell_data imx_gpc_onecell_data = {
+       .domains = imx_gpc_onecell_domains,
+       .num_domains = 2,
+};
+
+static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
+                              unsigned int num_domains)
+{
+       struct imx_pm_domain *domain;
+       int i, ret;
+
+       for (i = 0; i < num_domains; i++) {
+               domain = &imx_gpc_domains[i];
+               domain->regmap = regmap;
+               domain->ipg_rate_mhz = 66;
+
+               if (i == 1) {
+                       domain->supply = devm_regulator_get(dev, "pu");
+                       if (IS_ERR(domain->supply))
+                               return PTR_ERR(domain->supply);
+
+                       ret = imx_pgc_get_clocks(dev, domain);
+                       if (ret)
+                               goto clk_err;
+
+                       domain->base.power_on(&domain->base);
+               }
+       }
+
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               ret = of_genpd_add_provider_onecell(dev->of_node,
+                                                   &imx_gpc_onecell_data);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       return 0;
+
+genpd_err:
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_remove(&imx_gpc_domains[i].base);
+       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+clk_err:
+       return ret;
+}
+
+static int imx_gpc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
+       const struct imx_gpc_dt_data *of_id_data = of_id->data;
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
+                                          &imx_gpc_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&pdev->dev, "failed to init regmap: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /*
+        * Disable PU power down by runtime PM if ERR009619 is present.
+        *
+        * The PRE clock will be paused for several cycles when turning on the
+        * PU domain LDO from power down state. If PRE is in use at that time,
+        * the IPU/PRG cannot get the correct display data from the PRE.
+        *
+        * This is not a concern when the whole system enters suspend state, so
+        * it's safe to power down PU in this case.
+        */
+       if (of_id_data->err009619_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
+                               GENPD_FLAG_RPM_ALWAYS_ON;
+
+       /* Keep DISP always on if ERR006287 is present */
+       if (of_id_data->err006287_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
+                               GENPD_FLAG_ALWAYS_ON;
+
+       if (!pgc_node) {
+               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
+                                         of_id_data->num_domains);
+               if (ret)
+                       return ret;
+       } else {
+               struct imx_pm_domain *domain;
+               struct platform_device *pd_pdev;
+               struct device_node *np;
+               struct clk *ipg_clk;
+               unsigned int ipg_rate_mhz;
+               int domain_index;
+
+               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+               if (IS_ERR(ipg_clk))
+                       return PTR_ERR(ipg_clk);
+               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
+
+               for_each_child_of_node(pgc_node, np) {
+                       ret = of_property_read_u32(np, "reg", &domain_index);
+                       if (ret) {
+                               of_node_put(np);
+                               return ret;
+                       }
+                       if (domain_index >= of_id_data->num_domains)
+                               continue;
+
+                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
+                                                       domain_index);
+                       if (!pd_pdev) {
+                               of_node_put(np);
+                               return -ENOMEM;
+                       }
+
+                       ret = platform_device_add_data(pd_pdev,
+                                                      &imx_gpc_domains[domain_index],
+                                                      sizeof(imx_gpc_domains[domain_index]));
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+                       domain = pd_pdev->dev.platform_data;
+                       domain->regmap = regmap;
+                       domain->ipg_rate_mhz = ipg_rate_mhz;
+
+                       pd_pdev->dev.parent = &pdev->dev;
+                       pd_pdev->dev.of_node = np;
+
+                       ret = platform_device_add(pd_pdev);
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int imx_gpc_remove(struct platform_device *pdev)
+{
+       struct device_node *pgc_node;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       /*
+        * If the old DT binding is used the toplevel driver needs to
+        * de-register the power domains
+        */
+       if (!pgc_node) {
+               of_genpd_del_provider(pdev->dev.of_node);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
+               if (ret)
+                       return ret;
+               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpc",
+               .of_match_table = imx_gpc_dt_ids,
+       },
+       .probe = imx_gpc_probe,
+       .remove = imx_gpc_remove,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/genpd/imx/gpcv2.c b/drivers/genpd/imx/gpcv2.c
new file mode 100644 (file)
index 0000000..4b3300b
--- /dev/null
@@ -0,0 +1,1550 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2017 Impinj, Inc
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on the code of analogus driver:
+ *
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+#include <dt-bindings/power/imx7-power.h>
+#include <dt-bindings/power/imx8mq-power.h>
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/power/imx8mp-power.h>
+
+#define GPC_LPCR_A_CORE_BSC                    0x000
+
+#define GPC_PGC_CPU_MAPPING            0x0ec
+#define IMX8MP_GPC_PGC_CPU_MAPPING     0x1cc
+
+#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN                BIT(6)
+#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN                BIT(5)
+#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN                BIT(4)
+#define IMX7_PCIE_PHY_A_CORE_DOMAIN            BIT(3)
+#define IMX7_MIPI_PHY_A_CORE_DOMAIN            BIT(2)
+
+#define IMX8M_PCIE2_A53_DOMAIN                 BIT(15)
+#define IMX8M_MIPI_CSI2_A53_DOMAIN             BIT(14)
+#define IMX8M_MIPI_CSI1_A53_DOMAIN             BIT(13)
+#define IMX8M_DISP_A53_DOMAIN                  BIT(12)
+#define IMX8M_HDMI_A53_DOMAIN                  BIT(11)
+#define IMX8M_VPU_A53_DOMAIN                   BIT(10)
+#define IMX8M_GPU_A53_DOMAIN                   BIT(9)
+#define IMX8M_DDR2_A53_DOMAIN                  BIT(8)
+#define IMX8M_DDR1_A53_DOMAIN                  BIT(7)
+#define IMX8M_OTG2_A53_DOMAIN                  BIT(5)
+#define IMX8M_OTG1_A53_DOMAIN                  BIT(4)
+#define IMX8M_PCIE1_A53_DOMAIN                 BIT(3)
+#define IMX8M_MIPI_A53_DOMAIN                  BIT(2)
+
+#define IMX8MM_VPUH1_A53_DOMAIN                        BIT(15)
+#define IMX8MM_VPUG2_A53_DOMAIN                        BIT(14)
+#define IMX8MM_VPUG1_A53_DOMAIN                        BIT(13)
+#define IMX8MM_DISPMIX_A53_DOMAIN              BIT(12)
+#define IMX8MM_VPUMIX_A53_DOMAIN               BIT(10)
+#define IMX8MM_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MM_GPU_A53_DOMAIN                  (BIT(8) | BIT(11))
+#define IMX8MM_DDR1_A53_DOMAIN                 BIT(7)
+#define IMX8MM_OTG2_A53_DOMAIN                 BIT(5)
+#define IMX8MM_OTG1_A53_DOMAIN                 BIT(4)
+#define IMX8MM_PCIE_A53_DOMAIN                 BIT(3)
+#define IMX8MM_MIPI_A53_DOMAIN                 BIT(2)
+
+#define IMX8MN_DISPMIX_A53_DOMAIN              BIT(12)
+#define IMX8MN_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MN_DDR1_A53_DOMAIN         BIT(7)
+#define IMX8MN_OTG1_A53_DOMAIN         BIT(4)
+#define IMX8MN_MIPI_A53_DOMAIN         BIT(2)
+
+#define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20)
+#define IMX8MP_HSIOMIX_A53_DOMAIN              BIT(19)
+#define IMX8MP_MIPI_PHY2_A53_DOMAIN            BIT(18)
+#define IMX8MP_HDMI_PHY_A53_DOMAIN             BIT(17)
+#define IMX8MP_HDMIMIX_A53_DOMAIN              BIT(16)
+#define IMX8MP_VPU_VC8000E_A53_DOMAIN          BIT(15)
+#define IMX8MP_VPU_G2_A53_DOMAIN               BIT(14)
+#define IMX8MP_VPU_G1_A53_DOMAIN               BIT(13)
+#define IMX8MP_MEDIAMIX_A53_DOMAIN             BIT(12)
+#define IMX8MP_GPU3D_A53_DOMAIN                        BIT(11)
+#define IMX8MP_VPUMIX_A53_DOMAIN               BIT(10)
+#define IMX8MP_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MP_GPU2D_A53_DOMAIN                        BIT(8)
+#define IMX8MP_AUDIOMIX_A53_DOMAIN             BIT(7)
+#define IMX8MP_MLMIX_A53_DOMAIN                        BIT(6)
+#define IMX8MP_USB2_PHY_A53_DOMAIN             BIT(5)
+#define IMX8MP_USB1_PHY_A53_DOMAIN             BIT(4)
+#define IMX8MP_PCIE_PHY_A53_DOMAIN             BIT(3)
+#define IMX8MP_MIPI_PHY1_A53_DOMAIN            BIT(2)
+
+#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ   0x0d8
+#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ   0x0e4
+
+#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ          0x104
+
+#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ           BIT(4)
+#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ           BIT(3)
+#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ           BIT(2)
+#define IMX7_PCIE_PHY_SW_Pxx_REQ               BIT(1)
+#define IMX7_MIPI_PHY_SW_Pxx_REQ               BIT(0)
+
+#define IMX8M_PCIE2_SW_Pxx_REQ                 BIT(13)
+#define IMX8M_MIPI_CSI2_SW_Pxx_REQ             BIT(12)
+#define IMX8M_MIPI_CSI1_SW_Pxx_REQ             BIT(11)
+#define IMX8M_DISP_SW_Pxx_REQ                  BIT(10)
+#define IMX8M_HDMI_SW_Pxx_REQ                  BIT(9)
+#define IMX8M_VPU_SW_Pxx_REQ                   BIT(8)
+#define IMX8M_GPU_SW_Pxx_REQ                   BIT(7)
+#define IMX8M_DDR2_SW_Pxx_REQ                  BIT(6)
+#define IMX8M_DDR1_SW_Pxx_REQ                  BIT(5)
+#define IMX8M_OTG2_SW_Pxx_REQ                  BIT(3)
+#define IMX8M_OTG1_SW_Pxx_REQ                  BIT(2)
+#define IMX8M_PCIE1_SW_Pxx_REQ                 BIT(1)
+#define IMX8M_MIPI_SW_Pxx_REQ                  BIT(0)
+
+#define IMX8MM_VPUH1_SW_Pxx_REQ                        BIT(13)
+#define IMX8MM_VPUG2_SW_Pxx_REQ                        BIT(12)
+#define IMX8MM_VPUG1_SW_Pxx_REQ                        BIT(11)
+#define IMX8MM_DISPMIX_SW_Pxx_REQ              BIT(10)
+#define IMX8MM_VPUMIX_SW_Pxx_REQ               BIT(8)
+#define IMX8MM_GPUMIX_SW_Pxx_REQ               BIT(7)
+#define IMX8MM_GPU_SW_Pxx_REQ                  (BIT(6) | BIT(9))
+#define IMX8MM_DDR1_SW_Pxx_REQ                 BIT(5)
+#define IMX8MM_OTG2_SW_Pxx_REQ                 BIT(3)
+#define IMX8MM_OTG1_SW_Pxx_REQ                 BIT(2)
+#define IMX8MM_PCIE_SW_Pxx_REQ                 BIT(1)
+#define IMX8MM_MIPI_SW_Pxx_REQ                 BIT(0)
+
+#define IMX8MN_DISPMIX_SW_Pxx_REQ              BIT(10)
+#define IMX8MN_GPUMIX_SW_Pxx_REQ               BIT(7)
+#define IMX8MN_DDR1_SW_Pxx_REQ         BIT(5)
+#define IMX8MN_OTG1_SW_Pxx_REQ         BIT(2)
+#define IMX8MN_MIPI_SW_Pxx_REQ         BIT(0)
+
+#define IMX8MP_DDRMIX_Pxx_REQ                  BIT(19)
+#define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ           BIT(18)
+#define IMX8MP_HSIOMIX_Pxx_REQ                 BIT(17)
+#define IMX8MP_MIPI_PHY2_Pxx_REQ               BIT(16)
+#define IMX8MP_HDMI_PHY_Pxx_REQ                        BIT(15)
+#define IMX8MP_HDMIMIX_Pxx_REQ                 BIT(14)
+#define IMX8MP_VPU_VC8K_Pxx_REQ                        BIT(13)
+#define IMX8MP_VPU_G2_Pxx_REQ                  BIT(12)
+#define IMX8MP_VPU_G1_Pxx_REQ                  BIT(11)
+#define IMX8MP_MEDIMIX_Pxx_REQ                 BIT(10)
+#define IMX8MP_GPU_3D_Pxx_REQ                  BIT(9)
+#define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ     BIT(8)
+#define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ         BIT(7)
+#define IMX8MP_GPU_2D_Pxx_REQ                  BIT(6)
+#define IMX8MP_AUDIOMIX_Pxx_REQ                        BIT(5)
+#define IMX8MP_MLMIX_Pxx_REQ                   BIT(4)
+#define IMX8MP_USB2_PHY_Pxx_REQ                        BIT(3)
+#define IMX8MP_USB1_PHY_Pxx_REQ                        BIT(2)
+#define IMX8MP_PCIE_PHY_SW_Pxx_REQ             BIT(1)
+#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ            BIT(0)
+
+#define GPC_M4_PU_PDN_FLG              0x1bc
+
+#define IMX8MP_GPC_PU_PWRHSK           0x190
+#define GPC_PU_PWRHSK                  0x1fc
+
+#define IMX8M_GPU_HSK_PWRDNACKN                        BIT(26)
+#define IMX8M_VPU_HSK_PWRDNACKN                        BIT(25)
+#define IMX8M_DISP_HSK_PWRDNACKN               BIT(24)
+#define IMX8M_GPU_HSK_PWRDNREQN                        BIT(6)
+#define IMX8M_VPU_HSK_PWRDNREQN                        BIT(5)
+#define IMX8M_DISP_HSK_PWRDNREQN               BIT(4)
+
+#define IMX8MM_GPUMIX_HSK_PWRDNACKN            BIT(29)
+#define IMX8MM_GPU_HSK_PWRDNACKN               (BIT(27) | BIT(28))
+#define IMX8MM_VPUMIX_HSK_PWRDNACKN            BIT(26)
+#define IMX8MM_DISPMIX_HSK_PWRDNACKN           BIT(25)
+#define IMX8MM_HSIO_HSK_PWRDNACKN              (BIT(23) | BIT(24))
+#define IMX8MM_GPUMIX_HSK_PWRDNREQN            BIT(11)
+#define IMX8MM_GPU_HSK_PWRDNREQN               (BIT(9) | BIT(10))
+#define IMX8MM_VPUMIX_HSK_PWRDNREQN            BIT(8)
+#define IMX8MM_DISPMIX_HSK_PWRDNREQN           BIT(7)
+#define IMX8MM_HSIO_HSK_PWRDNREQN              (BIT(5) | BIT(6))
+
+#define IMX8MN_GPUMIX_HSK_PWRDNACKN            (BIT(29) | BIT(27))
+#define IMX8MN_DISPMIX_HSK_PWRDNACKN           BIT(25)
+#define IMX8MN_HSIO_HSK_PWRDNACKN              BIT(23)
+#define IMX8MN_GPUMIX_HSK_PWRDNREQN            (BIT(11) | BIT(9))
+#define IMX8MN_DISPMIX_HSK_PWRDNREQN           BIT(7)
+#define IMX8MN_HSIO_HSK_PWRDNREQN              BIT(5)
+
+#define IMX8MP_MEDIAMIX_PWRDNACKN              BIT(30)
+#define IMX8MP_HDMIMIX_PWRDNACKN               BIT(29)
+#define IMX8MP_HSIOMIX_PWRDNACKN               BIT(28)
+#define IMX8MP_VPUMIX_PWRDNACKN                        BIT(26)
+#define IMX8MP_GPUMIX_PWRDNACKN                        BIT(25)
+#define IMX8MP_MLMIX_PWRDNACKN                 (BIT(23) | BIT(24))
+#define IMX8MP_AUDIOMIX_PWRDNACKN              (BIT(20) | BIT(31))
+#define IMX8MP_MEDIAMIX_PWRDNREQN              BIT(14)
+#define IMX8MP_HDMIMIX_PWRDNREQN               BIT(13)
+#define IMX8MP_HSIOMIX_PWRDNREQN               BIT(12)
+#define IMX8MP_VPUMIX_PWRDNREQN                        BIT(10)
+#define IMX8MP_GPUMIX_PWRDNREQN                        BIT(9)
+#define IMX8MP_MLMIX_PWRDNREQN                 (BIT(7) | BIT(8))
+#define IMX8MP_AUDIOMIX_PWRDNREQN              (BIT(4) | BIT(15))
+
+/*
+ * The PGC offset values in Reference Manual
+ * (Rev. 1, 01/2018 and the older ones) GPC chapter's
+ * GPC_PGC memory map are incorrect, below offset
+ * values are from design RTL.
+ */
+#define IMX7_PGC_MIPI                  16
+#define IMX7_PGC_PCIE                  17
+#define IMX7_PGC_USB_HSIC              20
+
+#define IMX8M_PGC_MIPI                 16
+#define IMX8M_PGC_PCIE1                        17
+#define IMX8M_PGC_OTG1                 18
+#define IMX8M_PGC_OTG2                 19
+#define IMX8M_PGC_DDR1                 21
+#define IMX8M_PGC_GPU                  23
+#define IMX8M_PGC_VPU                  24
+#define IMX8M_PGC_DISP                 26
+#define IMX8M_PGC_MIPI_CSI1            27
+#define IMX8M_PGC_MIPI_CSI2            28
+#define IMX8M_PGC_PCIE2                        29
+
+#define IMX8MM_PGC_MIPI                        16
+#define IMX8MM_PGC_PCIE                        17
+#define IMX8MM_PGC_OTG1                        18
+#define IMX8MM_PGC_OTG2                        19
+#define IMX8MM_PGC_DDR1                        21
+#define IMX8MM_PGC_GPU2D               22
+#define IMX8MM_PGC_GPUMIX              23
+#define IMX8MM_PGC_VPUMIX              24
+#define IMX8MM_PGC_GPU3D               25
+#define IMX8MM_PGC_DISPMIX             26
+#define IMX8MM_PGC_VPUG1               27
+#define IMX8MM_PGC_VPUG2               28
+#define IMX8MM_PGC_VPUH1               29
+
+#define IMX8MN_PGC_MIPI                16
+#define IMX8MN_PGC_OTG1                18
+#define IMX8MN_PGC_DDR1                21
+#define IMX8MN_PGC_GPUMIX              23
+#define IMX8MN_PGC_DISPMIX             26
+
+#define IMX8MP_PGC_NOC                 9
+#define IMX8MP_PGC_MIPI1               12
+#define IMX8MP_PGC_PCIE                        13
+#define IMX8MP_PGC_USB1                        14
+#define IMX8MP_PGC_USB2                        15
+#define IMX8MP_PGC_MLMIX               16
+#define IMX8MP_PGC_AUDIOMIX            17
+#define IMX8MP_PGC_GPU2D               18
+#define IMX8MP_PGC_GPUMIX              19
+#define IMX8MP_PGC_VPUMIX              20
+#define IMX8MP_PGC_GPU3D               21
+#define IMX8MP_PGC_MEDIAMIX            22
+#define IMX8MP_PGC_VPU_G1              23
+#define IMX8MP_PGC_VPU_G2              24
+#define IMX8MP_PGC_VPU_VC8000E         25
+#define IMX8MP_PGC_HDMIMIX             26
+#define IMX8MP_PGC_HDMI                        27
+#define IMX8MP_PGC_MIPI2               28
+#define IMX8MP_PGC_HSIOMIX             29
+#define IMX8MP_PGC_MEDIA_ISP_DWP       30
+#define IMX8MP_PGC_DDRMIX              31
+
+#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
+#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
+
+#define GPC_PGC_CTRL_PCR               BIT(0)
+
+struct imx_pgc_regs {
+       u16 map;
+       u16 pup;
+       u16 pdn;
+       u16 hsk;
+};
+
+struct imx_pgc_domain {
+       struct generic_pm_domain genpd;
+       struct regmap *regmap;
+       const struct imx_pgc_regs *regs;
+       struct regulator *regulator;
+       struct reset_control *reset;
+       struct clk_bulk_data *clks;
+       int num_clks;
+
+       unsigned long pgc;
+
+       const struct {
+               u32 pxx;
+               u32 map;
+               u32 hskreq;
+               u32 hskack;
+       } bits;
+
+       const int voltage;
+       const bool keep_clocks;
+       struct device *dev;
+
+       unsigned int pgc_sw_pup_reg;
+       unsigned int pgc_sw_pdn_reg;
+};
+
+struct imx_pgc_domain_data {
+       const struct imx_pgc_domain *domains;
+       size_t domains_num;
+       const struct regmap_access_table *reg_access_table;
+       const struct imx_pgc_regs *pgc_regs;
+};
+
+static inline struct imx_pgc_domain *
+to_imx_pgc_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pgc_domain, genpd);
+}
+
+static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+{
+       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+       u32 reg_val, pgc;
+       int ret;
+
+       ret = pm_runtime_get_sync(domain->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(domain->dev);
+               return ret;
+       }
+
+       if (!IS_ERR(domain->regulator)) {
+               ret = regulator_enable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev,
+                               "failed to enable regulator: %pe\n",
+                               ERR_PTR(ret));
+                       goto out_put_pm;
+               }
+       }
+
+       reset_control_assert(domain->reset);
+
+       /* Enable reset clocks for all devices in the domain */
+       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+       if (ret) {
+               dev_err(domain->dev, "failed to enable reset clocks\n");
+               goto out_regulator_disable;
+       }
+
+       /* delays for reset to propagate */
+       udelay(5);
+
+       if (domain->bits.pxx) {
+               /* request the domain to power up */
+               regmap_update_bits(domain->regmap, domain->regs->pup,
+                                  domain->bits.pxx, domain->bits.pxx);
+               /*
+                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+                * for PUP_REQ/PDN_REQ bit to be cleared
+                */
+               ret = regmap_read_poll_timeout(domain->regmap,
+                                              domain->regs->pup, reg_val,
+                                              !(reg_val & domain->bits.pxx),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to command PGC\n");
+                       goto out_clk_disable;
+               }
+
+               /* disable power control */
+               for_each_set_bit(pgc, &domain->pgc, 32) {
+                       regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+                                         GPC_PGC_CTRL_PCR);
+               }
+       }
+
+       /* delay for reset to propagate */
+       udelay(5);
+
+       reset_control_deassert(domain->reset);
+
+       /* request the ADB400 to power up */
+       if (domain->bits.hskreq) {
+               regmap_update_bits(domain->regmap, domain->regs->hsk,
+                                  domain->bits.hskreq, domain->bits.hskreq);
+
+               /*
+                * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
+                *                                (reg_val & domain->bits.hskack), 0,
+                *                                USEC_PER_MSEC);
+                * Technically we need the commented code to wait handshake. But that needs
+                * the BLK-CTL module BUS clk-en bit being set.
+                *
+                * There is a separate BLK-CTL module and we will have such a driver for it,
+                * that driver will set the BUS clk-en bit and handshake will be triggered
+                * automatically there. Just add a delay and suppose the handshake finish
+                * after that.
+                */
+       }
+
+       /* Disable reset clocks for all devices in the domain */
+       if (!domain->keep_clocks)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return 0;
+
+out_clk_disable:
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+out_regulator_disable:
+       if (!IS_ERR(domain->regulator))
+               regulator_disable(domain->regulator);
+out_put_pm:
+       pm_runtime_put(domain->dev);
+
+       return ret;
+}
+
+static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+{
+       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+       u32 reg_val, pgc;
+       int ret;
+
+       /* Enable reset clocks for all devices in the domain */
+       if (!domain->keep_clocks) {
+               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable reset clocks\n");
+                       return ret;
+               }
+       }
+
+       /* request the ADB400 to power down */
+       if (domain->bits.hskreq) {
+               regmap_clear_bits(domain->regmap, domain->regs->hsk,
+                                 domain->bits.hskreq);
+
+               ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
+                                              reg_val,
+                                              !(reg_val & domain->bits.hskack),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to power down ADB400\n");
+                       goto out_clk_disable;
+               }
+       }
+
+       if (domain->bits.pxx) {
+               /* enable power control */
+               for_each_set_bit(pgc, &domain->pgc, 32) {
+                       regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+                                          GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+               }
+
+               /* request the domain to power down */
+               regmap_update_bits(domain->regmap, domain->regs->pdn,
+                                  domain->bits.pxx, domain->bits.pxx);
+               /*
+                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+                * for PUP_REQ/PDN_REQ bit to be cleared
+                */
+               ret = regmap_read_poll_timeout(domain->regmap,
+                                              domain->regs->pdn, reg_val,
+                                              !(reg_val & domain->bits.pxx),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to command PGC\n");
+                       goto out_clk_disable;
+               }
+       }
+
+       /* Disable reset clocks for all devices in the domain */
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       if (!IS_ERR(domain->regulator)) {
+               ret = regulator_disable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev,
+                               "failed to disable regulator: %pe\n",
+                               ERR_PTR(ret));
+                       return ret;
+               }
+       }
+
+       pm_runtime_put_sync_suspend(domain->dev);
+
+       return 0;
+
+out_clk_disable:
+       if (!domain->keep_clocks)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return ret;
+}
+
+static const struct imx_pgc_domain imx7_pgc_domains[] = {
+       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
+               .genpd = {
+                       .name      = "mipi-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
+                       .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = BIT(IMX7_PGC_MIPI),
+       },
+
+       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name      = "pcie-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
+                       .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = BIT(IMX7_PGC_PCIE),
+       },
+
+       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+               .genpd = {
+                       .name      = "usb-hsic-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
+                       .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1200000,
+               .pgc       = BIT(IMX7_PGC_USB_HSIC),
+       },
+};
+
+static const struct regmap_range imx7_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_M4_PU_PDN_FLG),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
+                                GPC_PGC_SR(IMX7_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
+                                GPC_PGC_SR(IMX7_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
+                                GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
+};
+
+static const struct regmap_access_table imx7_access_table = {
+       .yes_ranges     = imx7_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
+};
+
+static const struct imx_pgc_regs imx7_pgc_regs = {
+       .map = GPC_PGC_CPU_MAPPING,
+       .pup = GPC_PU_PGC_SW_PUP_REQ,
+       .pdn = GPC_PU_PGC_SW_PDN_REQ,
+       .hsk = GPC_PU_PWRHSK,
+};
+
+static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
+       .domains = imx7_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx7_pgc_domains),
+       .reg_access_table = &imx7_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+       [IMX8M_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name      = "mipi",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_A53_DOMAIN,
+               },
+               .pgc       = BIT(IMX8M_PGC_MIPI),
+       },
+
+       [IMX8M_POWER_DOMAIN_PCIE1] = {
+               .genpd = {
+                       .name = "pcie1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
+                       .map = IMX8M_PCIE1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_PCIE1),
+       },
+
+       [IMX8M_POWER_DOMAIN_USB_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_OTG1_SW_Pxx_REQ,
+                       .map = IMX8M_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_OTG1),
+       },
+
+       [IMX8M_POWER_DOMAIN_USB_OTG2] = {
+               .genpd = {
+                       .name = "usb-otg2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_OTG2_SW_Pxx_REQ,
+                       .map = IMX8M_OTG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_OTG2),
+       },
+
+       [IMX8M_POWER_DOMAIN_DDR1] = {
+               .genpd = {
+                       .name = "ddr1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_DDR1_SW_Pxx_REQ,
+                       .map = IMX8M_DDR2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_DDR1),
+       },
+
+       [IMX8M_POWER_DOMAIN_GPU] = {
+               .genpd = {
+                       .name = "gpu",
+               },
+               .bits  = {
+                       .pxx = IMX8M_GPU_SW_Pxx_REQ,
+                       .map = IMX8M_GPU_A53_DOMAIN,
+                       .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
+                       .hskack = IMX8M_GPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_GPU),
+       },
+
+       [IMX8M_POWER_DOMAIN_VPU] = {
+               .genpd = {
+                       .name = "vpu",
+               },
+               .bits  = {
+                       .pxx = IMX8M_VPU_SW_Pxx_REQ,
+                       .map = IMX8M_VPU_A53_DOMAIN,
+                       .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
+                       .hskack = IMX8M_VPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_VPU),
+               .keep_clocks = true,
+       },
+
+       [IMX8M_POWER_DOMAIN_DISP] = {
+               .genpd = {
+                       .name = "disp",
+               },
+               .bits  = {
+                       .pxx = IMX8M_DISP_SW_Pxx_REQ,
+                       .map = IMX8M_DISP_A53_DOMAIN,
+                       .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
+                       .hskack = IMX8M_DISP_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_DISP),
+       },
+
+       [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
+               .genpd = {
+                       .name = "mipi-csi1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_MIPI_CSI1),
+       },
+
+       [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
+               .genpd = {
+                       .name = "mipi-csi2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_MIPI_CSI2),
+       },
+
+       [IMX8M_POWER_DOMAIN_PCIE2] = {
+               .genpd = {
+                       .name = "pcie2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
+                       .map = IMX8M_PCIE2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_PCIE2),
+       },
+};
+
+static const struct regmap_range imx8m_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_PU_PWRHSK),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
+                                GPC_PGC_SR(IMX8M_PGC_PCIE1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
+                                GPC_PGC_SR(IMX8M_PGC_OTG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
+                                GPC_PGC_SR(IMX8M_PGC_OTG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
+                                GPC_PGC_SR(IMX8M_PGC_DDR1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
+                                GPC_PGC_SR(IMX8M_PGC_GPU)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
+                                GPC_PGC_SR(IMX8M_PGC_VPU)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
+                                GPC_PGC_SR(IMX8M_PGC_DISP)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
+                                GPC_PGC_SR(IMX8M_PGC_PCIE2)),
+};
+
+static const struct regmap_access_table imx8m_access_table = {
+       .yes_ranges     = imx8m_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8m_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
+       .domains = imx8m_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
+       .reg_access_table = &imx8m_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+       [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits  = {
+                       .pxx = 0, /* no power sequence control */
+                       .map = 0, /* no power sequence control */
+                       .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
+               },
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_PCIE] = {
+               .genpd = {
+                       .name = "pcie",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
+                       .map = IMX8MM_PCIE_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_PCIE),
+       },
+
+       [IMX8MM_POWER_DOMAIN_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
+                       .map = IMX8MM_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_OTG1),
+       },
+
+       [IMX8MM_POWER_DOMAIN_OTG2] = {
+               .genpd = {
+                       .name = "usb-otg2",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
+                       .map = IMX8MM_OTG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_OTG2),
+       },
+
+       [IMX8MM_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_GPU] = {
+               .genpd = {
+                       .name = "gpu",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_GPU_SW_Pxx_REQ,
+                       .map = IMX8MM_GPU_A53_DOMAIN,
+                       .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUMIX] = {
+               .genpd = {
+                       .name = "vpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUG1] = {
+               .genpd = {
+                       .name = "vpu-g1",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUG1),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUG2] = {
+               .genpd = {
+                       .name = "vpu-g2",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUG2),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUH1] = {
+               .genpd = {
+                       .name = "vpu-h1",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUH1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUH1),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_DISPMIX] = {
+               .genpd = {
+                       .name = "dispmix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_DISPMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_DISPMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name = "mipi",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
+                       .map = IMX8MM_MIPI_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_MIPI),
+       },
+};
+
+static const struct regmap_range imx8mm_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_PU_PWRHSK),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
+                                GPC_PGC_SR(IMX8MM_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
+                                GPC_PGC_SR(IMX8MM_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
+                                GPC_PGC_SR(IMX8MM_PGC_OTG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
+                                GPC_PGC_SR(IMX8MM_PGC_OTG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
+                                GPC_PGC_SR(IMX8MM_PGC_DDR1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
+                                GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
+                                GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
+};
+
+static const struct regmap_access_table imx8mm_access_table = {
+       .yes_ranges     = imx8mm_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mm_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
+       .domains = imx8mm_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
+       .reg_access_table = &imx8mm_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
+       [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = {
+               .genpd = {
+                       .name = "mipi-phy1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ,
+                       .map = IMX8MP_MIPI_PHY1_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MIPI1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name = "pcie-phy1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
+                       .map = IMX8MP_PCIE_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_PCIE),
+       },
+
+       [IMX8MP_POWER_DOMAIN_USB1_PHY] = {
+               .genpd = {
+                       .name = "usb-otg1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_USB1_PHY_Pxx_REQ,
+                       .map = IMX8MP_USB1_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_USB1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_USB2_PHY] = {
+               .genpd = {
+                       .name = "usb-otg2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_USB2_PHY_Pxx_REQ,
+                       .map = IMX8MP_USB2_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_USB2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MLMIX] = {
+               .genpd = {
+                       .name = "mlmix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MLMIX_Pxx_REQ,
+                       .map = IMX8MP_MLMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_MLMIX_PWRDNREQN,
+                       .hskack = IMX8MP_MLMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MLMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_AUDIOMIX] = {
+               .genpd = {
+                       .name = "audiomix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_AUDIOMIX_Pxx_REQ,
+                       .map = IMX8MP_AUDIOMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN,
+                       .hskack = IMX8MP_AUDIOMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_AUDIOMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPU2D] = {
+               .genpd = {
+                       .name = "gpu2d",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_2D_Pxx_REQ,
+                       .map = IMX8MP_GPU2D_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPU2D),
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ,
+                       .map = IMX8MP_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_GPUMIX_PWRDNREQN,
+                       .hskack = IMX8MP_GPUMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPUMIX] = {
+               .genpd = {
+                       .name = "vpumix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ,
+                       .map = IMX8MP_VPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_VPUMIX_PWRDNREQN,
+                       .hskack = IMX8MP_VPUMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPU3D] = {
+               .genpd = {
+                       .name = "gpu3d",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_3D_Pxx_REQ,
+                       .map = IMX8MP_GPU3D_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPU3D),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
+               .genpd = {
+                       .name = "mediamix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MEDIMIX_Pxx_REQ,
+                       .map = IMX8MP_MEDIAMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
+                       .hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MEDIAMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_G1] = {
+               .genpd = {
+                       .name = "vpu-g1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_G1_Pxx_REQ,
+                       .map = IMX8MP_VPU_G1_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_G1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_G2] = {
+               .genpd = {
+                       .name = "vpu-g2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_G2_Pxx_REQ,
+                       .map = IMX8MP_VPU_G2_A53_DOMAIN
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_G2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = {
+               .genpd = {
+                       .name = "vpu-h1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_VC8K_Pxx_REQ,
+                       .map = IMX8MP_VPU_VC8000E_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_VC8000E),
+       },
+
+       [IMX8MP_POWER_DOMAIN_HDMIMIX] = {
+               .genpd = {
+                       .name = "hdmimix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HDMIMIX_Pxx_REQ,
+                       .map = IMX8MP_HDMIMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_HDMIMIX_PWRDNREQN,
+                       .hskack = IMX8MP_HDMIMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HDMIMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_HDMI_PHY] = {
+               .genpd = {
+                       .name = "hdmi-phy",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HDMI_PHY_Pxx_REQ,
+                       .map = IMX8MP_HDMI_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HDMI),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = {
+               .genpd = {
+                       .name = "mipi-phy2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ,
+                       .map = IMX8MP_MIPI_PHY2_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MIPI2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HSIOMIX_Pxx_REQ,
+                       .map = IMX8MP_HSIOMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
+                       .hskack = IMX8MP_HSIOMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HSIOMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = {
+               .genpd = {
+                       .name = "mediamix-isp-dwp",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ,
+                       .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP),
+       },
+};
+
+static const struct regmap_range imx8mp_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                IMX8MP_GPC_PGC_CPU_MAPPING),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC),
+                                GPC_PGC_SR(IMX8MP_PGC_NOC)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1),
+                                GPC_PGC_SR(IMX8MP_PGC_MIPI1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE),
+                                GPC_PGC_SR(IMX8MP_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1),
+                                GPC_PGC_SR(IMX8MP_PGC_USB1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2),
+                                GPC_PGC_SR(IMX8MP_PGC_USB2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_MLMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D),
+                                GPC_PGC_SR(IMX8MP_PGC_GPU2D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_GPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_VPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D),
+                                GPC_PGC_SR(IMX8MP_PGC_GPU3D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_G1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_G2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI),
+                                GPC_PGC_SR(IMX8MP_PGC_HDMI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2),
+                                GPC_PGC_SR(IMX8MP_PGC_MIPI2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP),
+                                GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_DDRMIX)),
+};
+
+static const struct regmap_access_table imx8mp_access_table = {
+       .yes_ranges     = imx8mp_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mp_yes_ranges),
+};
+
+static const struct imx_pgc_regs imx8mp_pgc_regs = {
+       .map = IMX8MP_GPC_PGC_CPU_MAPPING,
+       .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
+       .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
+       .hsk = IMX8MP_GPC_PU_PWRHSK,
+};
+static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
+       .domains = imx8mp_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
+       .reg_access_table = &imx8mp_access_table,
+       .pgc_regs = &imx8mp_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+       [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits  = {
+                       .pxx = 0, /* no power sequence control */
+                       .map = 0, /* no power sequence control */
+                       .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
+               },
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
+                       .map = IMX8MN_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_OTG1),
+       },
+
+       [IMX8MN_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MN_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_DISPMIX] = {
+               .genpd = {
+                       .name = "dispmix",
+               },
+                       .bits  = {
+                       .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ,
+                       .map = IMX8MN_DISPMIX_A53_DOMAIN,
+                       .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_DISPMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name = "mipi",
+               },
+                       .bits  = {
+                       .pxx = IMX8MN_MIPI_SW_Pxx_REQ,
+                       .map = IMX8MN_MIPI_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_MIPI),
+       },
+};
+
+static const struct regmap_range imx8mn_yes_ranges[] = {
+       regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                        GPC_PU_PWRHSK),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI),
+                        GPC_PGC_SR(IMX8MN_PGC_MIPI)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1),
+                        GPC_PGC_SR(IMX8MN_PGC_OTG1)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1),
+                        GPC_PGC_SR(IMX8MN_PGC_DDR1)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX),
+                        GPC_PGC_SR(IMX8MN_PGC_GPUMIX)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX),
+                        GPC_PGC_SR(IMX8MN_PGC_DISPMIX)),
+};
+
+static const struct regmap_access_table imx8mn_access_table = {
+       .yes_ranges     = imx8mn_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mn_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
+       .domains = imx8mn_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
+       .reg_access_table = &imx8mn_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static int imx_pgc_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pgc_domain *domain = pdev->dev.platform_data;
+       int ret;
+
+       domain->dev = &pdev->dev;
+
+       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
+       if (IS_ERR(domain->regulator)) {
+               if (PTR_ERR(domain->regulator) != -ENODEV)
+                       return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
+                                            "Failed to get domain's regulator\n");
+       } else if (domain->voltage) {
+               regulator_set_voltage(domain->regulator,
+                                     domain->voltage, domain->voltage);
+       }
+
+       domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks);
+       if (domain->num_clks < 0)
+               return dev_err_probe(domain->dev, domain->num_clks,
+                                    "Failed to get domain's clocks\n");
+
+       domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev);
+       if (IS_ERR(domain->reset))
+               return dev_err_probe(domain->dev, PTR_ERR(domain->reset),
+                                    "Failed to get domain's resets\n");
+
+       pm_runtime_enable(domain->dev);
+
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, domain->bits.map);
+
+       ret = pm_genpd_init(&domain->genpd, NULL, true);
+       if (ret) {
+               dev_err(domain->dev, "Failed to init power domain\n");
+               goto out_domain_unmap;
+       }
+
+       if (IS_ENABLED(CONFIG_LOCKDEP) &&
+           of_property_read_bool(domain->dev->of_node, "power-domains"))
+               lockdep_set_subclass(&domain->genpd.mlock, 1);
+
+       ret = of_genpd_add_provider_simple(domain->dev->of_node,
+                                          &domain->genpd);
+       if (ret) {
+               dev_err(domain->dev, "Failed to add genpd provider\n");
+               goto out_genpd_remove;
+       }
+
+       return 0;
+
+out_genpd_remove:
+       pm_genpd_remove(&domain->genpd);
+out_domain_unmap:
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, 0);
+       pm_runtime_disable(domain->dev);
+
+       return ret;
+}
+
+static int imx_pgc_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pgc_domain *domain = pdev->dev.platform_data;
+
+       of_genpd_del_provider(domain->dev->of_node);
+       pm_genpd_remove(&domain->genpd);
+
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, 0);
+
+       pm_runtime_disable(domain->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx_pgc_domain_suspend(struct device *dev)
+{
+       int ret;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domain and more importantly power it up again
+        * after resume, without tripping over our usage of runtime PM to
+        * power up/down the nested domains.
+        */
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int imx_pgc_domain_resume(struct device *dev)
+{
+       return pm_runtime_put(dev);
+}
+#endif
+
+static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
+};
+
+static const struct platform_device_id imx_pgc_domain_id[] = {
+       { "imx-pgc-domain", },
+       { },
+};
+
+static struct platform_driver imx_pgc_domain_driver = {
+       .driver = {
+               .name = "imx-pgc",
+               .pm = &imx_pgc_domain_pm_ops,
+       },
+       .probe    = imx_pgc_domain_probe,
+       .remove   = imx_pgc_domain_remove,
+       .id_table = imx_pgc_domain_id,
+};
+builtin_platform_driver(imx_pgc_domain_driver)
+
+static int imx_gpcv2_probe(struct platform_device *pdev)
+{
+       const struct imx_pgc_domain_data *domain_data =
+                       of_device_get_match_data(&pdev->dev);
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = domain_data->reg_access_table,
+               .wr_table       = domain_data->reg_access_table,
+               .max_register   = SZ_4K,
+       };
+       struct device *dev = &pdev->dev;
+       struct device_node *pgc_np, *np;
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+
+       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
+       if (!pgc_np) {
+               dev_err(dev, "No power domains specified in DT\n");
+               return -EINVAL;
+       }
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(dev, "failed to init regmap (%d)\n", ret);
+               return ret;
+       }
+
+       for_each_child_of_node(pgc_np, np) {
+               struct platform_device *pd_pdev;
+               struct imx_pgc_domain *domain;
+               u32 domain_index;
+
+               if (!of_device_is_available(np))
+                       continue;
+
+               ret = of_property_read_u32(np, "reg", &domain_index);
+               if (ret) {
+                       dev_err(dev, "Failed to read 'reg' property\n");
+                       of_node_put(np);
+                       return ret;
+               }
+
+               if (domain_index >= domain_data->domains_num) {
+                       dev_warn(dev,
+                                "Domain index %d is out of bounds\n",
+                                domain_index);
+                       continue;
+               }
+
+               pd_pdev = platform_device_alloc("imx-pgc-domain",
+                                               domain_index);
+               if (!pd_pdev) {
+                       dev_err(dev, "Failed to allocate platform device\n");
+                       of_node_put(np);
+                       return -ENOMEM;
+               }
+
+               ret = platform_device_add_data(pd_pdev,
+                                              &domain_data->domains[domain_index],
+                                              sizeof(domain_data->domains[domain_index]));
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+
+               domain = pd_pdev->dev.platform_data;
+               domain->regmap = regmap;
+               domain->regs = domain_data->pgc_regs;
+
+               domain->genpd.power_on  = imx_pgc_power_up;
+               domain->genpd.power_off = imx_pgc_power_down;
+
+               pd_pdev->dev.parent = dev;
+               device_set_node(&pd_pdev->dev, of_fwnode_handle(np));
+
+               ret = platform_device_add(pd_pdev);
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id imx_gpcv2_dt_ids[] = {
+       { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
+       { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
+       { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, },
+       { .compatible = "fsl,imx8mp-gpc", .data = &imx8mp_pgc_domain_data, },
+       { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
+       { }
+};
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpcv2",
+               .of_match_table = imx_gpcv2_dt_ids,
+       },
+       .probe = imx_gpcv2_probe,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/genpd/imx/imx8m-blk-ctrl.c b/drivers/genpd/imx/imx8m-blk-ctrl.c
new file mode 100644 (file)
index 0000000..afbca0d
--- /dev/null
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/power/imx8mp-power.h>
+#include <dt-bindings/power/imx8mq-power.h>
+
+#define BLK_SFT_RSTN   0x0
+#define BLK_CLK_EN     0x4
+#define BLK_MIPI_RESET_DIV     0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
+
+struct imx8m_blk_ctrl_domain;
+
+struct imx8m_blk_ctrl {
+       struct device *dev;
+       struct notifier_block power_nb;
+       struct device *bus_power_dev;
+       struct regmap *regmap;
+       struct imx8m_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+};
+
+struct imx8m_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       const char * const *path_names;
+       const char *gpc_name;
+       int num_clks;
+       int num_paths;
+       u32 rst_mask;
+       u32 clk_mask;
+
+       /*
+        * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
+        * which is used to control the reset for the MIPI Phy.
+        * Since it's only present in certain circumstances,
+        * an if-statement should be used before setting and clearing this
+        * register.
+        */
+       u32 mipi_phy_rst_mask;
+};
+
+#define DOMAIN_MAX_CLKS 4
+#define DOMAIN_MAX_PATHS 4
+
+struct imx8m_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx8m_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
+       struct device *power_dev;
+       struct imx8m_blk_ctrl *bc;
+       int num_paths;
+};
+
+struct imx8m_blk_ctrl_data {
+       int max_reg;
+       notifier_fn_t power_notifier_fn;
+       const struct imx8m_blk_ctrl_domain_data *domains;
+       int num_domains;
+};
+
+static inline struct imx8m_blk_ctrl_domain *
+to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
+}
+
+static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
+       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
+       struct imx8m_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       /* make sure bus domain is awake */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               dev_err(bc->dev, "failed to power up bus domain\n");
+               return ret;
+       }
+
+       /* put devices into reset */
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       if (data->mipi_phy_rst_mask)
+               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       /* enable upstream and blk-ctrl clocks to allow reset to propagate */
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               goto bus_put;
+       }
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* power up upstream GPC domain */
+       ret = pm_runtime_get_sync(domain->power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up peripheral domain\n");
+               goto clk_disable;
+       }
+
+       /* wait for reset to propagate */
+       udelay(5);
+
+       /* release reset */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       if (data->mipi_phy_rst_mask)
+               regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
+       if (ret)
+               dev_err(bc->dev, "failed to set icc bw\n");
+
+       /* disable upstream clocks */
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       return 0;
+
+clk_disable:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+bus_put:
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
+       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
+       struct imx8m_blk_ctrl *bc = domain->bc;
+
+       /* put devices into reset and disable clocks */
+       if (data->mipi_phy_rst_mask)
+               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* power down upstream GPC domain */
+       pm_runtime_put(domain->power_dev);
+
+       /* allow bus domain to suspend */
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+
+static struct lock_class_key blk_ctrl_genpd_lock_class;
+
+static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
+{
+       const struct imx8m_blk_ctrl_data *bc_data;
+       struct device *dev = &pdev->dev;
+       struct imx8m_blk_ctrl *bc;
+       void __iomem *base;
+       int i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       bc_data = of_device_get_match_data(dev);
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap_config.max_register = bc_data->max_reg;
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
+                                  sizeof(struct imx8m_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = bc_data->num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, bc_data->num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
+       if (IS_ERR(bc->bus_power_dev)) {
+               if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
+                       return dev_err_probe(dev, -EPROBE_DEFER,
+                                            "failed to attach power domain \"bus\"\n");
+               else
+                       return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
+                                            "failed to attach power domain \"bus\"\n");
+       }
+
+       for (i = 0; i < bc_data->num_domains; i++) {
+               const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+               domain->num_paths = data->num_paths;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               for (j = 0; j < data->num_paths; j++) {
+                       domain->paths[j].name = data->path_names[j];
+                       /* Fake value for now, just let ICC could configure NoC mode/priority */
+                       domain->paths[j].avg_bw = 1;
+                       domain->paths[j].peak_bw = 1;
+               }
+
+               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
+               if (ret) {
+                       if (ret != -EPROBE_DEFER) {
+                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
+                               domain->num_paths = 0;
+                       } else {
+                               dev_err_probe(dev, ret, "failed to get noc entries\n");
+                               goto cleanup_pds;
+                       }
+               }
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->power_dev =
+                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
+               if (IS_ERR(domain->power_dev)) {
+                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
+                                     "failed to attach power domain \"%s\"\n",
+                                     data->gpc_name);
+                       ret = PTR_ERR(domain->power_dev);
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8m_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8m_blk_ctrl_power_off;
+               domain->bc = bc;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret,
+                                     "failed to init power domain \"%s\"\n",
+                                     data->gpc_name);
+                       dev_pm_domain_detach(domain->power_dev, true);
+                       goto cleanup_pds;
+               }
+
+               /*
+                * We use runtime PM to trigger power on/off of the upstream GPC
+                * domain, as a strict hierarchical parent/child power domain
+                * setup doesn't allow us to meet the sequencing requirements.
+                * This means we have nested locking of genpd locks, without the
+                * nesting being visible at the genpd level, so we need a
+                * separate lock class to make lockdep aware of the fact that
+                * this are separate domain locks that can be nested without a
+                * self-deadlock.
+                */
+               lockdep_set_class(&domain->genpd.mlock,
+                                 &blk_ctrl_genpd_lock_class);
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
+       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power notifier\n");
+               goto cleanup_provider;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       ret = devm_of_platform_populate(dev);
+       if (ret)
+               goto cleanup_provider;
+
+       return 0;
+
+cleanup_provider:
+       of_genpd_del_provider(dev->of_node);
+cleanup_pds:
+       for (i--; i >= 0; i--) {
+               pm_genpd_remove(&bc->domains[i].genpd);
+               dev_pm_domain_detach(bc->domains[i].power_dev, true);
+       }
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+               dev_pm_domain_detach(domain->power_dev, true);
+       }
+
+       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx8m_blk_ctrl_suspend(struct device *dev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
+       int ret, i;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domains and more importantly power them up again
+        * after resume, without tripping over our usage of runtime PM to
+        * control the upstream GPC domains. Things happen in the right order
+        * in the system suspend/resume paths due to the device parent/child
+        * hierarchy.
+        */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               return ret;
+       }
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++) {
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+
+               ret = pm_runtime_get_sync(domain->power_dev);
+               if (ret < 0) {
+                       pm_runtime_put_noidle(domain->power_dev);
+                       goto out_fail;
+               }
+       }
+
+       return 0;
+
+out_fail:
+       for (i--; i >= 0; i--)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_resume(struct device *dev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
+       int i;
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
+};
+
+static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
+                                    unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /*
+        * The ADB in the VPUMIX domain has no separate reset and clock
+        * enable bits, but is ungated together with the VPU clocks. To
+        * allow the handshake with the GPC to progress we put the VPUs
+        * in reset and ungate the clocks.
+        */
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /* set "fuse" bits to enable the VPUs */
+               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
+       [IMX8MM_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+       },
+       [IMX8MM_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+       },
+       [IMX8MM_VPUBLK_PD_H1] = {
+               .name = "vpublk-h1",
+               .clk_names = (const char *[]){ "h1", },
+               .num_clks = 1,
+               .gpc_name = "h1",
+               .rst_mask = BIT(2),
+               .clk_mask = BIT(2),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x18,
+       .power_notifier_fn = imx8mm_vpu_power_notifier,
+       .domains = imx8mm_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
+};
+
+static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
+       [IMX8MP_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+               .path_names = (const char *[]){"g1"},
+               .num_paths = 1,
+       },
+       [IMX8MP_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+               .path_names = (const char *[]){"g2"},
+               .num_paths = 1,
+       },
+       [IMX8MP_VPUBLK_PD_VC8000E] = {
+               .name = "vpublk-vc8000e",
+               .clk_names = (const char *[]){ "vc8000e", },
+               .num_clks = 1,
+               .gpc_name = "vc8000e",
+               .rst_mask = BIT(2),
+               .clk_mask = BIT(2),
+               .path_names = (const char *[]){"vc8000e"},
+               .num_paths = 1,
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x18,
+       .power_notifier_fn = imx8mm_vpu_power_notifier,
+       .domains = imx8mp_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
+};
+
+static int imx8mm_disp_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       if (action == GENPD_NOTIFY_ON)
+               udelay(5);
+
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
+       [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
+               .name = "dispblk-csi-bridge",
+               .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
+                                              "csi-bridge-core", },
+               .num_clks = 3,
+               .gpc_name = "csi-bridge",
+               .rst_mask = BIT(0) | BIT(1) | BIT(2),
+               .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
+       },
+       [IMX8MM_DISPBLK_PD_LCDIF] = {
+               .name = "dispblk-lcdif",
+               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+               .num_clks = 3,
+               .gpc_name = "lcdif",
+               .clk_mask = BIT(6) | BIT(7),
+       },
+       [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
+               .name = "dispblk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi",
+               .rst_mask = BIT(5),
+               .clk_mask = BIT(8) | BIT(9),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
+               .name = "dispblk-mipi-csi",
+               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi",
+               .rst_mask = BIT(3) | BIT(4),
+               .clk_mask = BIT(10) | BIT(11),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
+       .max_reg = 0x2c,
+       .power_notifier_fn = imx8mm_disp_power_notifier,
+       .domains = imx8mm_disp_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
+};
+
+
+static int imx8mn_disp_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       if (action == GENPD_NOTIFY_ON)
+               udelay(5);
+
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
+       [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
+               .name = "dispblk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi",
+               .rst_mask = BIT(0) | BIT(1),
+               .clk_mask = BIT(0) | BIT(1),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
+               .name = "dispblk-mipi-csi",
+               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi",
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+       [IMX8MN_DISPBLK_PD_LCDIF] = {
+               .name = "dispblk-lcdif",
+               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+               .num_clks = 3,
+               .gpc_name = "lcdif",
+               .rst_mask = BIT(4) | BIT(5),
+               .clk_mask = BIT(4) | BIT(5),
+       },
+       [IMX8MN_DISPBLK_PD_ISI] = {
+               .name = "dispblk-isi",
+               .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
+                                               "disp_apb_root"},
+               .num_clks = 4,
+               .gpc_name = "isi",
+               .rst_mask = BIT(6) | BIT(7),
+               .clk_mask = BIT(6) | BIT(7),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
+       .max_reg = 0x84,
+       .power_notifier_fn = imx8mn_disp_power_notifier,
+       .domains = imx8mn_disp_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
+};
+
+#define LCDIF_ARCACHE_CTRL     0x4c
+#define  LCDIF_1_RD_HURRY      GENMASK(15, 13)
+#define  LCDIF_0_RD_HURRY      GENMASK(12, 10)
+
+static int imx8mp_media_power_notifier(struct notifier_block *nb,
+                               unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /*
+                * Set panic read hurry level for both LCDIF interfaces to
+                * maximum priority to minimize chances of display FIFO
+                * underflow.
+                */
+               regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL,
+                               FIELD_PREP(LCDIF_1_RD_HURRY, 7) |
+                               FIELD_PREP(LCDIF_0_RD_HURRY, 7));
+       }
+
+       return NOTIFY_OK;
+}
+
+/*
+ * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
+ * section 13.2.2, 13.2.3
+ * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
+ */
+static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
+       [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
+               .name = "mediablk-mipi-dsi-1",
+               .clk_names = (const char *[]){ "apb", "phy", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi1",
+               .rst_mask = BIT(0) | BIT(1),
+               .clk_mask = BIT(0) | BIT(1),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
+               .name = "mediablk-mipi-csi2-1",
+               .clk_names = (const char *[]){ "apb", "cam1" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi1",
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+       [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
+               .name = "mediablk-lcdif-1",
+               .clk_names = (const char *[]){ "disp1", "apb", "axi", },
+               .num_clks = 3,
+               .gpc_name = "lcdif1",
+               .rst_mask = BIT(4) | BIT(5) | BIT(23),
+               .clk_mask = BIT(4) | BIT(5) | BIT(23),
+               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_ISI] = {
+               .name = "mediablk-isi",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "isi",
+               .rst_mask = BIT(6) | BIT(7),
+               .clk_mask = BIT(6) | BIT(7),
+               .path_names = (const char *[]){"isi0", "isi1", "isi2"},
+               .num_paths = 3,
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
+               .name = "mediablk-mipi-csi2-2",
+               .clk_names = (const char *[]){ "apb", "cam2" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi2",
+               .rst_mask = BIT(9) | BIT(10),
+               .clk_mask = BIT(9) | BIT(10),
+               .mipi_phy_rst_mask = BIT(30),
+       },
+       [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
+               .name = "mediablk-lcdif-2",
+               .clk_names = (const char *[]){ "disp2", "apb", "axi", },
+               .num_clks = 3,
+               .gpc_name = "lcdif2",
+               .rst_mask = BIT(11) | BIT(12) | BIT(24),
+               .clk_mask = BIT(11) | BIT(12) | BIT(24),
+               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_ISP] = {
+               .name = "mediablk-isp",
+               .clk_names = (const char *[]){ "isp", "axi", "apb" },
+               .num_clks = 3,
+               .gpc_name = "isp",
+               .rst_mask = BIT(16) | BIT(17) | BIT(18),
+               .clk_mask = BIT(16) | BIT(17) | BIT(18),
+               .path_names = (const char *[]){"isp0", "isp1"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_DWE] = {
+               .name = "mediablk-dwe",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "dwe",
+               .rst_mask = BIT(19) | BIT(20) | BIT(21),
+               .clk_mask = BIT(19) | BIT(20) | BIT(21),
+               .path_names = (const char *[]){"dwe"},
+               .num_paths = 1,
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
+               .name = "mediablk-mipi-dsi-2",
+               .clk_names = (const char *[]){ "phy", },
+               .num_clks = 1,
+               .gpc_name = "mipi-dsi2",
+               .rst_mask = BIT(22),
+               .clk_mask = BIT(22),
+               .mipi_phy_rst_mask = BIT(29),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
+       .max_reg = 0x138,
+       .power_notifier_fn = imx8mp_media_power_notifier,
+       .domains = imx8mp_media_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
+};
+
+static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
+                                    unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /*
+        * The ADB in the VPUMIX domain has no separate reset and clock
+        * enable bits, but is ungated and reset together with the VPUs. The
+        * reset and clock enable inputs to the ADB is a logical OR of the
+        * VPU bits. In order to set the G2 fuse bits, the G2 clock must
+        * also be enabled.
+        */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /* set "fuse" bits to enable the VPUs */
+               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
+       [IMX8MQ_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+       },
+       [IMX8MQ_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x14,
+       .power_notifier_fn = imx8mq_vpu_power_notifier,
+       .domains = imx8mq_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
+};
+
+static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx8mm-vpu-blk-ctrl",
+               .data = &imx8mm_vpu_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mm-disp-blk-ctrl",
+               .data = &imx8mm_disp_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mn-disp-blk-ctrl",
+               .data = &imx8mn_disp_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mp-media-blk-ctrl",
+               .data = &imx8mp_media_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mq-vpu-blk-ctrl",
+               .data = &imx8mq_vpu_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mp-vpu-blk-ctrl",
+               .data = &imx8mp_vpu_blk_ctl_dev_data
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
+
+static struct platform_driver imx8m_blk_ctrl_driver = {
+       .probe = imx8m_blk_ctrl_probe,
+       .remove = imx8m_blk_ctrl_remove,
+       .driver = {
+               .name = "imx8m-blk-ctrl",
+               .pm = &imx8m_blk_ctrl_pm_ops,
+               .of_match_table = imx8m_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx8m_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx8mp-blk-ctrl.c b/drivers/genpd/imx/imx8mp-blk-ctrl.c
new file mode 100644 (file)
index 0000000..870aecc
--- /dev/null
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/power/imx8mp-power.h>
+
+#define GPR_REG0               0x0
+#define  PCIE_CLOCK_MODULE_EN  BIT(0)
+#define  USB_CLOCK_MODULE_EN   BIT(1)
+#define  PCIE_PHY_APB_RST      BIT(4)
+#define  PCIE_PHY_INIT_RST     BIT(5)
+#define GPR_REG1               0x4
+#define  PLL_LOCK              BIT(13)
+#define GPR_REG2               0x8
+#define  P_PLL_MASK            GENMASK(5, 0)
+#define  M_PLL_MASK            GENMASK(15, 6)
+#define  S_PLL_MASK            GENMASK(18, 16)
+#define GPR_REG3               0xc
+#define  PLL_CKE               BIT(17)
+#define  PLL_RST               BIT(31)
+
+struct imx8mp_blk_ctrl_domain;
+
+struct imx8mp_blk_ctrl {
+       struct device *dev;
+       struct notifier_block power_nb;
+       struct device *bus_power_dev;
+       struct regmap *regmap;
+       struct imx8mp_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+};
+
+struct imx8mp_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       int num_clks;
+       const char * const *path_names;
+       int num_paths;
+       const char *gpc_name;
+};
+
+#define DOMAIN_MAX_CLKS 2
+#define DOMAIN_MAX_PATHS 3
+
+struct imx8mp_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx8mp_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
+       struct device *power_dev;
+       struct imx8mp_blk_ctrl *bc;
+       int num_paths;
+       int id;
+};
+
+struct imx8mp_blk_ctrl_data {
+       int max_reg;
+       int (*probe) (struct imx8mp_blk_ctrl *bc);
+       notifier_fn_t power_notifier_fn;
+       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       const struct imx8mp_blk_ctrl_domain_data *domains;
+       int num_domains;
+};
+
+static inline struct imx8mp_blk_ctrl_domain *
+to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
+}
+
+struct clk_hsio_pll {
+       struct clk_hw   hw;
+       struct regmap *regmap;
+};
+
+static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_hsio_pll, hw);
+}
+
+static int clk_hsio_pll_prepare(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+       u32 val;
+
+       /* set the PLL configuration */
+       regmap_update_bits(clk->regmap, GPR_REG2,
+                          P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
+                          FIELD_PREP(P_PLL_MASK, 12) |
+                          FIELD_PREP(M_PLL_MASK, 800) |
+                          FIELD_PREP(S_PLL_MASK, 4));
+
+       /* de-assert PLL reset */
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
+
+       /* enable PLL */
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
+
+       return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
+                                       val & PLL_LOCK, 10, 100);
+}
+
+static void clk_hsio_pll_unprepare(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
+}
+
+static int clk_hsio_pll_is_prepared(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+
+       return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK);
+}
+
+static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       return 100000000;
+}
+
+static const struct clk_ops clk_hsio_pll_ops = {
+       .prepare = clk_hsio_pll_prepare,
+       .unprepare = clk_hsio_pll_unprepare,
+       .is_prepared = clk_hsio_pll_is_prepared,
+       .recalc_rate = clk_hsio_pll_recalc_rate,
+};
+
+static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
+{
+       struct clk_hsio_pll *clk_hsio_pll;
+       struct clk_hw *hw;
+       struct clk_init_data init = {};
+       int ret;
+
+       clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
+       if (!clk_hsio_pll)
+               return -ENOMEM;
+
+       init.name = "hsio_pll";
+       init.ops = &clk_hsio_pll_ops;
+       init.parent_names = (const char *[]){"osc_24m"};
+       init.num_parents = 1;
+
+       clk_hsio_pll->regmap = bc->regmap;
+       clk_hsio_pll->hw.init = &init;
+
+       hw = &clk_hsio_pll->hw;
+       ret = devm_clk_hw_register(bc->dev, hw);
+       if (ret)
+               return ret;
+
+       return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw);
+}
+
+static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
+                                         struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HSIOBLK_PD_USB:
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE:
+               regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+               regmap_set_bits(bc->regmap, GPR_REG0,
+                               PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+               break;
+       default:
+               break;
+       }
+}
+
+static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
+                                          struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HSIOBLK_PD_USB:
+               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE:
+               regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+               regmap_clear_bits(bc->regmap, GPR_REG0,
+                                 PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+               break;
+       default:
+               break;
+       }
+}
+
+static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
+                                                power_nb);
+       struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
+       int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
+       int ret;
+
+       switch (action) {
+       case GENPD_NOTIFY_ON:
+               /*
+                * enable USB clock for a moment for the power-on ADB handshake
+                * to proceed
+                */
+               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
+               if (ret)
+                       return NOTIFY_BAD;
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+
+               udelay(5);
+
+               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               clk_bulk_disable_unprepare(num_clks, usb_clk);
+               break;
+       case GENPD_NOTIFY_PRE_OFF:
+               /* enable USB clock for the power-down ADB handshake to work */
+               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
+               if (ret)
+                       return NOTIFY_BAD;
+
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case GENPD_NOTIFY_OFF:
+               clk_bulk_disable_unprepare(num_clks, usb_clk);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
+       [IMX8MP_HSIOBLK_PD_USB] = {
+               .name = "hsioblk-usb",
+               .clk_names = (const char *[]){ "usb" },
+               .num_clks = 1,
+               .gpc_name = "usb",
+               .path_names = (const char *[]){"usb1", "usb2"},
+               .num_paths = 2,
+       },
+       [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
+               .name = "hsioblk-usb-phy1",
+               .gpc_name = "usb-phy1",
+       },
+       [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
+               .name = "hsioblk-usb-phy2",
+               .gpc_name = "usb-phy2",
+       },
+       [IMX8MP_HSIOBLK_PD_PCIE] = {
+               .name = "hsioblk-pcie",
+               .clk_names = (const char *[]){ "pcie" },
+               .num_clks = 1,
+               .gpc_name = "pcie",
+               .path_names = (const char *[]){"noc-pcie", "pcie"},
+               .num_paths = 2,
+       },
+       [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
+               .name = "hsioblk-pcie-phy",
+               .gpc_name = "pcie-phy",
+       },
+};
+
+static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
+       .max_reg = 0x24,
+       .probe = imx8mp_hsio_blk_ctrl_probe,
+       .power_on = imx8mp_hsio_blk_ctrl_power_on,
+       .power_off = imx8mp_hsio_blk_ctrl_power_off,
+       .power_notifier_fn = imx8mp_hsio_power_notifier,
+       .domains = imx8mp_hsio_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
+};
+
+#define HDMI_RTX_RESET_CTL0    0x20
+#define HDMI_RTX_CLK_CTL0      0x40
+#define HDMI_RTX_CLK_CTL1      0x50
+#define HDMI_RTX_CLK_CTL2      0x60
+#define HDMI_RTX_CLK_CTL3      0x70
+#define HDMI_RTX_CLK_CTL4      0x80
+#define HDMI_TX_CONTROL0       0x200
+#define  HDMI_LCDIF_NOC_HURRY_MASK             GENMASK(14, 12)
+
+static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
+                                         struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HDMIBLK_PD_IRQSTEER:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
+               break;
+       case IMX8MP_HDMIBLK_PD_LCDIF:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                               BIT(16) | BIT(17) | BIT(18) |
+                               BIT(19) | BIT(20));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                               BIT(4) | BIT(5) | BIT(6));
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0,
+                               FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7));
+               break;
+       case IMX8MP_HDMIBLK_PD_PAI:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
+               break;
+       case IMX8MP_HDMIBLK_PD_PVI:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
+               break;
+       case IMX8MP_HDMIBLK_PD_TRNG:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                               BIT(2) | BIT(4) | BIT(5));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
+                               BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+                               BIT(18) | BIT(19) | BIT(20) | BIT(21));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                               BIT(7) | BIT(10) | BIT(11));
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDCP:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
+               break;
+       case IMX8MP_HDMIBLK_PD_HRV:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
+               break;
+       default:
+               break;
+       }
+}
+
+static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
+                                          struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HDMIBLK_PD_IRQSTEER:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
+               break;
+       case IMX8MP_HDMIBLK_PD_LCDIF:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                                 BIT(4) | BIT(5) | BIT(6));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                                 BIT(16) | BIT(17) | BIT(18) |
+                                 BIT(19) | BIT(20));
+               break;
+       case IMX8MP_HDMIBLK_PD_PAI:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
+               break;
+       case IMX8MP_HDMIBLK_PD_PVI:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
+               break;
+       case IMX8MP_HDMIBLK_PD_TRNG:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX:
+               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                                 BIT(7) | BIT(10) | BIT(11));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
+                                 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+                                 BIT(18) | BIT(19) | BIT(20) | BIT(21));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                                 BIT(2) | BIT(4) | BIT(5));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDCP:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
+               break;
+       case IMX8MP_HDMIBLK_PD_HRV:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
+               break;
+       default:
+               break;
+       }
+}
+
+static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON)
+               return NOTIFY_OK;
+
+       /*
+        * Contrary to other blk-ctrls the reset and clock don't clear when the
+        * power domain is powered down. To ensure the proper reset pulsing,
+        * first clear them all to asserted state, then enable the bus clocks
+        * and then release the ADB reset.
+        */
+       regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
+       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
+       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
+       regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                       BIT(0) | BIT(1) | BIT(10));
+       regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       udelay(5);
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
+       [IMX8MP_HDMIBLK_PD_IRQSTEER] = {
+               .name = "hdmiblk-irqsteer",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "irqsteer",
+       },
+       [IMX8MP_HDMIBLK_PD_LCDIF] = {
+               .name = "hdmiblk-lcdif",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "lcdif",
+               .path_names = (const char *[]){"lcdif-hdmi"},
+               .num_paths = 1,
+       },
+       [IMX8MP_HDMIBLK_PD_PAI] = {
+               .name = "hdmiblk-pai",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "pai",
+       },
+       [IMX8MP_HDMIBLK_PD_PVI] = {
+               .name = "hdmiblk-pvi",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "pvi",
+       },
+       [IMX8MP_HDMIBLK_PD_TRNG] = {
+               .name = "hdmiblk-trng",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "trng",
+       },
+       [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
+               .name = "hdmiblk-hdmi-tx",
+               .clk_names = (const char *[]){ "apb", "ref_266m" },
+               .num_clks = 2,
+               .gpc_name = "hdmi-tx",
+       },
+       [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
+               .name = "hdmiblk-hdmi-tx-phy",
+               .clk_names = (const char *[]){ "apb", "ref_24m" },
+               .num_clks = 2,
+               .gpc_name = "hdmi-tx-phy",
+       },
+       [IMX8MP_HDMIBLK_PD_HRV] = {
+               .name = "hdmiblk-hrv",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "hrv",
+               .path_names = (const char *[]){"hrv"},
+               .num_paths = 1,
+       },
+       [IMX8MP_HDMIBLK_PD_HDCP] = {
+               .name = "hdmiblk-hdcp",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "hdcp",
+               .path_names = (const char *[]){"hdcp"},
+               .num_paths = 1,
+       },
+};
+
+static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
+       .max_reg = 0x23c,
+       .power_on = imx8mp_hdmi_blk_ctrl_power_on,
+       .power_off = imx8mp_hdmi_blk_ctrl_power_off,
+       .power_notifier_fn = imx8mp_hdmi_power_notifier,
+       .domains = imx8mp_hdmi_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
+};
+
+static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+       struct imx8mp_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       /* make sure bus domain is awake */
+       ret = pm_runtime_resume_and_get(bc->bus_power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up bus domain\n");
+               return ret;
+       }
+
+       /* enable upstream clocks */
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               goto bus_put;
+       }
+
+       /* domain specific blk-ctrl manipulation */
+       bc->power_on(bc, domain);
+
+       /* power up upstream GPC domain */
+       ret = pm_runtime_resume_and_get(domain->power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up peripheral domain\n");
+               goto clk_disable;
+       }
+
+       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
+       if (ret)
+               dev_err(bc->dev, "failed to set icc bw\n");
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       return 0;
+
+clk_disable:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+bus_put:
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+       struct imx8mp_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               return ret;
+       }
+
+       /* domain specific blk-ctrl manipulation */
+       bc->power_off(bc, domain);
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       /* power down upstream GPC domain */
+       pm_runtime_put(domain->power_dev);
+
+       /* allow bus domain to suspend */
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+
+static struct lock_class_key blk_ctrl_genpd_lock_class;
+
+static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
+{
+       const struct imx8mp_blk_ctrl_data *bc_data;
+       struct device *dev = &pdev->dev;
+       struct imx8mp_blk_ctrl *bc;
+       void __iomem *base;
+       int num_domains, i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       bc_data = of_device_get_match_data(dev);
+       num_domains = bc_data->num_domains;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap_config.max_register = bc_data->max_reg;
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, num_domains,
+                                  sizeof(struct imx8mp_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
+       if (IS_ERR(bc->bus_power_dev))
+               return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
+                                    "failed to attach bus power domain\n");
+
+       bc->power_off = bc_data->power_off;
+       bc->power_on = bc_data->power_on;
+
+       for (i = 0; i < num_domains; i++) {
+               const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+               domain->num_paths = data->num_paths;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               for (j = 0; j < data->num_paths; j++) {
+                       domain->paths[j].name = data->path_names[j];
+                       /* Fake value for now, just let ICC could configure NoC mode/priority */
+                       domain->paths[j].avg_bw = 1;
+                       domain->paths[j].peak_bw = 1;
+               }
+
+               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
+               if (ret) {
+                       if (ret != -EPROBE_DEFER) {
+                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
+                               domain->num_paths = 0;
+                       } else {
+                               dev_err_probe(dev, ret, "failed to get noc entries\n");
+                               goto cleanup_pds;
+                       }
+               }
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->power_dev =
+                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
+               if (IS_ERR(domain->power_dev)) {
+                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
+                                     "failed to attach power domain %s\n",
+                                     data->gpc_name);
+                       ret = PTR_ERR(domain->power_dev);
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
+               domain->bc = bc;
+               domain->id = i;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to init power domain\n");
+                       dev_pm_domain_detach(domain->power_dev, true);
+                       goto cleanup_pds;
+               }
+
+               /*
+                * We use runtime PM to trigger power on/off of the upstream GPC
+                * domain, as a strict hierarchical parent/child power domain
+                * setup doesn't allow us to meet the sequencing requirements.
+                * This means we have nested locking of genpd locks, without the
+                * nesting being visible at the genpd level, so we need a
+                * separate lock class to make lockdep aware of the fact that
+                * this are separate domain locks that can be nested without a
+                * self-deadlock.
+                */
+               lockdep_set_class(&domain->genpd.mlock,
+                                 &blk_ctrl_genpd_lock_class);
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
+       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power notifier\n");
+               goto cleanup_provider;
+       }
+
+       if (bc_data->probe) {
+               ret = bc_data->probe(bc);
+               if (ret)
+                       goto cleanup_provider;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       return 0;
+
+cleanup_provider:
+       of_genpd_del_provider(dev->of_node);
+cleanup_pds:
+       for (i--; i >= 0; i--) {
+               pm_genpd_remove(&bc->domains[i].genpd);
+               dev_pm_domain_detach(bc->domains[i].power_dev, true);
+       }
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+               dev_pm_domain_detach(domain->power_dev, true);
+       }
+
+       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx8mp_blk_ctrl_suspend(struct device *dev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
+       int ret, i;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domains and more importantly power them up again
+        * after resume, without tripping over our usage of runtime PM to
+        * control the upstream GPC domains. Things happen in the right order
+        * in the system suspend/resume paths due to the device parent/child
+        * hierarchy.
+        */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               return ret;
+       }
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++) {
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+
+               ret = pm_runtime_get_sync(domain->power_dev);
+               if (ret < 0) {
+                       pm_runtime_put_noidle(domain->power_dev);
+                       goto out_fail;
+               }
+       }
+
+       return 0;
+
+out_fail:
+       for (i--; i >= 0; i--)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_resume(struct device *dev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
+       int i;
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
+                               imx8mp_blk_ctrl_resume)
+};
+
+static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx8mp-hsio-blk-ctrl",
+               .data = &imx8mp_hsio_blk_ctl_dev_data,
+       }, {
+               .compatible = "fsl,imx8mp-hdmi-blk-ctrl",
+               .data = &imx8mp_hdmi_blk_ctl_dev_data,
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
+
+static struct platform_driver imx8mp_blk_ctrl_driver = {
+       .probe = imx8mp_blk_ctrl_probe,
+       .remove = imx8mp_blk_ctrl_remove,
+       .driver = {
+               .name = "imx8mp-blk-ctrl",
+               .pm = &imx8mp_blk_ctrl_pm_ops,
+               .of_match_table = imx8mp_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx8mp_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx93-blk-ctrl.c b/drivers/genpd/imx/imx93-blk-ctrl.c
new file mode 100644 (file)
index 0000000..2c60032
--- /dev/null
@@ -0,0 +1,436 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/sizes.h>
+
+#include <dt-bindings/power/fsl,imx93-power.h>
+
+#define BLK_SFT_RSTN   0x0
+#define BLK_CLK_EN     0x4
+#define BLK_MAX_CLKS   4
+
+#define DOMAIN_MAX_CLKS 4
+
+#define LCDIF_QOS_REG          0xC
+#define LCDIF_DEFAULT_QOS_OFF  12
+#define LCDIF_CFG_QOS_OFF      8
+
+#define PXP_QOS_REG            0x10
+#define PXP_R_DEFAULT_QOS_OFF  28
+#define PXP_R_CFG_QOS_OFF      24
+#define PXP_W_DEFAULT_QOS_OFF  20
+#define PXP_W_CFG_QOS_OFF      16
+
+#define ISI_CACHE_REG          0x14
+
+#define ISI_QOS_REG            0x1C
+#define ISI_V_DEFAULT_QOS_OFF  28
+#define ISI_V_CFG_QOS_OFF      24
+#define ISI_U_DEFAULT_QOS_OFF  20
+#define ISI_U_CFG_QOS_OFF      16
+#define ISI_Y_R_DEFAULT_QOS_OFF        12
+#define ISI_Y_R_CFG_QOS_OFF    8
+#define ISI_Y_W_DEFAULT_QOS_OFF        4
+#define ISI_Y_W_CFG_QOS_OFF    0
+
+#define PRIO_MASK              0xF
+
+#define PRIO(X)                        (X)
+
+struct imx93_blk_ctrl_domain;
+
+struct imx93_blk_ctrl {
+       struct device *dev;
+       struct regmap *regmap;
+       int num_clks;
+       struct clk_bulk_data clks[BLK_MAX_CLKS];
+       struct imx93_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+};
+
+#define DOMAIN_MAX_QOS 4
+
+struct imx93_blk_ctrl_qos {
+       u32 reg;
+       u32 cfg_off;
+       u32 default_prio;
+       u32 cfg_prio;
+};
+
+struct imx93_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       int num_clks;
+       u32 rst_mask;
+       u32 clk_mask;
+       int num_qos;
+       struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
+};
+
+struct imx93_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx93_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct imx93_blk_ctrl *bc;
+};
+
+struct imx93_blk_ctrl_data {
+       const struct imx93_blk_ctrl_domain_data *domains;
+       int num_domains;
+       const char * const *clk_names;
+       int num_clks;
+       const struct regmap_access_table *reg_access_table;
+};
+
+static inline struct imx93_blk_ctrl_domain *
+to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
+}
+
+static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
+{
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+       const struct imx93_blk_ctrl_qos *qos;
+       u32 val, mask;
+       int i;
+
+       for (i = 0; i < data->num_qos; i++) {
+               qos = &data->qos[i];
+
+               mask = PRIO_MASK << qos->cfg_off;
+               mask |= PRIO_MASK << (qos->cfg_off + 4);
+               val = qos->cfg_prio << qos->cfg_off;
+               val |= qos->default_prio << (qos->cfg_off + 4);
+
+               regmap_write_bits(bc->regmap, qos->reg, mask, val);
+
+               dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
+       }
+
+       return 0;
+}
+
+static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable bus clocks\n");
+               return ret;
+       }
+
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+               dev_err(bc->dev, "failed to enable clocks\n");
+               return ret;
+       }
+
+       ret = pm_runtime_get_sync(bc->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->dev);
+               dev_err(bc->dev, "failed to power up domain\n");
+               goto disable_clk;
+       }
+
+       /* ungate clk */
+       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* release reset */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+
+       dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
+
+       return imx93_blk_ctrl_set_qos(domain);
+
+disable_clk:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+
+       return ret;
+}
+
+static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+
+       dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
+
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       pm_runtime_put(bc->dev);
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+
+       return 0;
+}
+
+static int imx93_blk_ctrl_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
+       struct imx93_blk_ctrl *bc;
+       void __iomem *base;
+       int i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = bc_data->reg_access_table,
+               .wr_table       = bc_data->reg_access_table,
+               .max_register   = SZ_4K,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
+                                  sizeof(struct imx93_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = bc_data->num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, bc_data->num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       for (i = 0; i < bc_data->num_clks; i++)
+               bc->clks[i].id = bc_data->clk_names[i];
+       bc->num_clks = bc_data->num_clks;
+
+       ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to get bus clock\n");
+               return ret;
+       }
+
+       for (i = 0; i < bc_data->num_domains; i++) {
+               const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx93_blk_ctrl_power_on;
+               domain->genpd.power_off = imx93_blk_ctrl_power_off;
+               domain->bc = bc;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to init power domain\n");
+                       goto cleanup_pds;
+               }
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       pm_runtime_enable(dev);
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       return 0;
+
+cleanup_pds:
+       for (i--; i >= 0; i--)
+               pm_genpd_remove(&bc->domains[i].genpd);
+
+       return ret;
+}
+
+static int imx93_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+       }
+
+       return 0;
+}
+
+static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
+       [IMX93_MEDIABLK_PD_MIPI_DSI] = {
+               .name = "mediablk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi" },
+               .num_clks = 1,
+               .rst_mask = BIT(11) | BIT(12),
+               .clk_mask = BIT(11) | BIT(12),
+       },
+       [IMX93_MEDIABLK_PD_MIPI_CSI] = {
+               .name = "mediablk-mipi-csi",
+               .clk_names = (const char *[]){ "cam", "csi" },
+               .num_clks = 2,
+               .rst_mask = BIT(9) | BIT(10),
+               .clk_mask = BIT(9) | BIT(10),
+       },
+       [IMX93_MEDIABLK_PD_PXP] = {
+               .name = "mediablk-pxp",
+               .clk_names = (const char *[]){ "pxp" },
+               .num_clks = 1,
+               .rst_mask = BIT(7) | BIT(8),
+               .clk_mask = BIT(7) | BIT(8),
+               .num_qos = 2,
+               .qos = {
+                       {
+                               .reg = PXP_QOS_REG,
+                               .cfg_off = PXP_R_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(6),
+                       }, {
+                               .reg = PXP_QOS_REG,
+                               .cfg_off = PXP_W_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(6),
+                       }
+               }
+       },
+       [IMX93_MEDIABLK_PD_LCDIF] = {
+               .name = "mediablk-lcdif",
+               .clk_names = (const char *[]){ "disp", "lcdif" },
+               .num_clks = 2,
+               .rst_mask = BIT(4) | BIT(5) | BIT(6),
+               .clk_mask = BIT(4) | BIT(5) | BIT(6),
+               .num_qos = 1,
+               .qos = {
+                       {
+                       .reg = LCDIF_QOS_REG,
+                       .cfg_off = LCDIF_CFG_QOS_OFF,
+                       .default_prio = PRIO(3),
+                       .cfg_prio = PRIO(7),
+                       }
+               }
+       },
+       [IMX93_MEDIABLK_PD_ISI] = {
+               .name = "mediablk-isi",
+               .clk_names = (const char *[]){ "isi" },
+               .num_clks = 1,
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .num_qos = 4,
+               .qos = {
+                       {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_Y_W_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_Y_R_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_U_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_V_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }
+               }
+       },
+};
+
+static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
+       regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
+       regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
+       regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
+};
+
+static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
+       .yes_ranges = imx93_media_blk_ctl_yes_ranges,
+       .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
+};
+
+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,
+       .reg_access_table = &imx93_media_blk_ctl_access_table,
+};
+
+static const struct of_device_id imx93_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx93-media-blk-ctrl",
+               .data = &imx93_media_blk_ctl_dev_data
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
+
+static struct platform_driver imx93_blk_ctrl_driver = {
+       .probe = imx93_blk_ctrl_probe,
+       .remove = imx93_blk_ctrl_remove,
+       .driver = {
+               .name = "imx93-blk-ctrl",
+               .of_match_table = imx93_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx93_blk_ctrl_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx93-pd.c b/drivers/genpd/imx/imx93-pd.c
new file mode 100644 (file)
index 0000000..832deee
--- /dev/null
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+
+#define MIX_SLICE_SW_CTRL_OFF          0x20
+#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK        BIT(4)
+#define SLICE_SW_CTRL_PDN_SOFT_MASK    BIT(31)
+
+#define MIX_FUNC_STAT_OFF              0xB4
+
+#define FUNC_STAT_PSW_STAT_MASK                BIT(0)
+#define FUNC_STAT_RST_STAT_MASK                BIT(2)
+#define FUNC_STAT_ISO_STAT_MASK                BIT(4)
+
+struct imx93_power_domain {
+       struct generic_pm_domain genpd;
+       struct device *dev;
+       void __iomem *addr;
+       struct clk_bulk_data *clks;
+       int num_clks;
+       bool init_off;
+};
+
+#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd)
+
+static int imx93_pd_on(struct generic_pm_domain *genpd)
+{
+       struct imx93_power_domain *domain = to_imx93_pd(genpd);
+       void __iomem *addr = domain->addr;
+       u32 val;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+       if (ret) {
+               dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name);
+               return ret;
+       }
+
+       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
+       val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK;
+       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
+
+       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
+                                !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000);
+       if (ret) {
+               dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int imx93_pd_off(struct generic_pm_domain *genpd)
+{
+       struct imx93_power_domain *domain = to_imx93_pd(genpd);
+       void __iomem *addr = domain->addr;
+       int ret;
+       u32 val;
+
+       /* Power off MIX */
+       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
+       val |= SLICE_SW_CTRL_PDN_SOFT_MASK;
+       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
+
+       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
+                                val & FUNC_STAT_PSW_STAT_MASK, 1, 1000);
+       if (ret) {
+               dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val);
+               return ret;
+       }
+
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return 0;
+};
+
+static int imx93_pd_remove(struct platform_device *pdev)
+{
+       struct imx93_power_domain *domain = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+
+       if (!domain->init_off)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       of_genpd_del_provider(np);
+       pm_genpd_remove(&domain->genpd);
+
+       return 0;
+}
+
+static int imx93_pd_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct imx93_power_domain *domain;
+       int ret;
+
+       domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
+       if (!domain)
+               return -ENOMEM;
+
+       domain->addr = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(domain->addr))
+               return PTR_ERR(domain->addr);
+
+       domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks);
+       if (domain->num_clks < 0)
+               return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n");
+
+       domain->genpd.name = dev_name(dev);
+       domain->genpd.power_off = imx93_pd_off;
+       domain->genpd.power_on = imx93_pd_on;
+       domain->dev = dev;
+
+       domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK;
+       /* Just to sync the status of hardware */
+       if (!domain->init_off) {
+               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable clocks for domain: %s\n",
+                               domain->genpd.name);
+                       return ret;
+               }
+       }
+
+       ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
+       if (ret)
+               goto err_clk_unprepare;
+
+       platform_set_drvdata(pdev, domain);
+
+       ret = of_genpd_add_provider_simple(np, &domain->genpd);
+       if (ret)
+               goto err_genpd_remove;
+
+       return 0;
+
+err_genpd_remove:
+       pm_genpd_remove(&domain->genpd);
+
+err_clk_unprepare:
+       if (!domain->init_off)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return ret;
+}
+
+static const struct of_device_id imx93_pd_ids[] = {
+       { .compatible = "fsl,imx93-src-slice" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, imx93_pd_ids);
+
+static struct platform_driver imx93_power_domain_driver = {
+       .driver = {
+               .name   = "imx93_power_domain",
+               .of_match_table = imx93_pd_ids,
+       },
+       .probe = imx93_pd_probe,
+       .remove = imx93_pd_remove,
+};
+module_platform_driver(imx93_power_domain_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_DESCRIPTION("NXP i.MX93 power domain driver");
+MODULE_LICENSE("GPL");
index a28c44a1f16aff6f9cf948f40ffe98f8b7b186d6..3ad321ca608a6a39a26e102b5283397acb6e5c46 100644 (file)
@@ -2,10 +2,5 @@
 ifeq ($(CONFIG_ARM),y)
 obj-$(CONFIG_ARCH_MXC) += soc-imx.o
 endif
-obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
-obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
 obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
-obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o
-obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
+obj-$(CONFIG_SOC_IMX9) += imx93-src.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
deleted file mode 100644 (file)
index 90a8b2c..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-#define GPC_CNTR               0x000
-
-#define GPC_PGC_CTRL_OFFS      0x0
-#define GPC_PGC_PUPSCR_OFFS    0x4
-#define GPC_PGC_PDNSCR_OFFS    0x8
-#define GPC_PGC_SW2ISO_SHIFT   0x8
-#define GPC_PGC_SW_SHIFT       0x0
-
-#define GPC_PGC_PCI_PDN                0x200
-#define GPC_PGC_PCI_SR         0x20c
-
-#define GPC_PGC_GPU_PDN                0x260
-#define GPC_PGC_GPU_PUPSCR     0x264
-#define GPC_PGC_GPU_PDNSCR     0x268
-#define GPC_PGC_GPU_SR         0x26c
-
-#define GPC_PGC_DISP_PDN       0x240
-#define GPC_PGC_DISP_SR                0x24c
-
-#define GPU_VPU_PUP_REQ                BIT(1)
-#define GPU_VPU_PDN_REQ                BIT(0)
-
-#define GPC_CLK_MAX            7
-
-#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
-
-struct imx_pm_domain {
-       struct generic_pm_domain base;
-       struct regmap *regmap;
-       struct regulator *supply;
-       struct clk *clk[GPC_CLK_MAX];
-       int num_clks;
-       unsigned int reg_offs;
-       signed char cntr_pdn_bit;
-       unsigned int ipg_rate_mhz;
-};
-
-static inline struct imx_pm_domain *
-to_imx_pm_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx_pm_domain, base);
-}
-
-static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
-       int iso, iso2sw;
-       u32 val;
-
-       /* Read ISO and ISO2SW power down delays */
-       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
-       iso = val & 0x3f;
-       iso2sw = (val >> 8) & 0x3f;
-
-       /* Gate off domain when powered down */
-       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
-                          0x1, 0x1);
-
-       /* Request GPC to power down domain */
-       val = BIT(pd->cntr_pdn_bit);
-       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
-
-       if (pd->supply)
-               regulator_disable(pd->supply);
-
-       return 0;
-}
-
-static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
-       int i, ret;
-       u32 val, req;
-
-       if (pd->supply) {
-               ret = regulator_enable(pd->supply);
-               if (ret) {
-                       pr_err("%s: failed to enable regulator: %d\n",
-                              __func__, ret);
-                       return ret;
-               }
-       }
-
-       /* Enable reset clocks for all devices in the domain */
-       for (i = 0; i < pd->num_clks; i++)
-               clk_prepare_enable(pd->clk[i]);
-
-       /* Gate off domain when powered down */
-       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
-                          0x1, 0x1);
-
-       /* Request GPC to power up domain */
-       req = BIT(pd->cntr_pdn_bit + 1);
-       regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
-
-       /* Wait for the PGC to handle the request */
-       ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
-                                      1, 50);
-       if (ret)
-               pr_err("powerup request on domain %s timed out\n", genpd->name);
-
-       /* Wait for reset to propagate through peripherals */
-       usleep_range(5, 10);
-
-       /* Disable reset clocks for all devices in the domain */
-       for (i = 0; i < pd->num_clks; i++)
-               clk_disable_unprepare(pd->clk[i]);
-
-       return 0;
-}
-
-static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
-{
-       int i, ret;
-
-       for (i = 0; ; i++) {
-               struct clk *clk = of_clk_get(dev->of_node, i);
-               if (IS_ERR(clk))
-                       break;
-               if (i >= GPC_CLK_MAX) {
-                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
-                       ret = -EINVAL;
-                       goto clk_err;
-               }
-               domain->clk[i] = clk;
-       }
-       domain->num_clks = i;
-
-       return 0;
-
-clk_err:
-       while (i--)
-               clk_put(domain->clk[i]);
-
-       return ret;
-}
-
-static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
-{
-       int i;
-
-       for (i = domain->num_clks - 1; i >= 0; i--)
-               clk_put(domain->clk[i]);
-}
-
-static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
-{
-       /* try to get the domain supply regulator */
-       domain->supply = devm_regulator_get_optional(dev, "power");
-       if (IS_ERR(domain->supply)) {
-               if (PTR_ERR(domain->supply) == -ENODEV)
-                       domain->supply = NULL;
-               else
-                       return PTR_ERR(domain->supply);
-       }
-
-       /* try to get all clocks needed for reset propagation */
-       return imx_pgc_get_clocks(dev, domain);
-}
-
-static int imx_pgc_power_domain_probe(struct platform_device *pdev)
-{
-       struct imx_pm_domain *domain = pdev->dev.platform_data;
-       struct device *dev = &pdev->dev;
-       int ret;
-
-       /* if this PD is associated with a DT node try to parse it */
-       if (dev->of_node) {
-               ret = imx_pgc_parse_dt(dev, domain);
-               if (ret)
-                       return ret;
-       }
-
-       /* initially power on the domain */
-       if (domain->base.power_on)
-               domain->base.power_on(&domain->base);
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               pm_genpd_init(&domain->base, NULL, false);
-               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
-               if (ret)
-                       goto genpd_err;
-       }
-
-       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
-
-       return 0;
-
-genpd_err:
-       pm_genpd_remove(&domain->base);
-       imx_pgc_put_clocks(domain);
-
-       return ret;
-}
-
-static int imx_pgc_power_domain_remove(struct platform_device *pdev)
-{
-       struct imx_pm_domain *domain = pdev->dev.platform_data;
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               of_genpd_del_provider(pdev->dev.of_node);
-               pm_genpd_remove(&domain->base);
-               imx_pgc_put_clocks(domain);
-       }
-
-       return 0;
-}
-
-static const struct platform_device_id imx_pgc_power_domain_id[] = {
-       { "imx-pgc-power-domain"},
-       { },
-};
-
-static struct platform_driver imx_pgc_power_domain_driver = {
-       .driver = {
-               .name = "imx-pgc-pd",
-       },
-       .probe = imx_pgc_power_domain_probe,
-       .remove = imx_pgc_power_domain_remove,
-       .id_table = imx_pgc_power_domain_id,
-};
-builtin_platform_driver(imx_pgc_power_domain_driver)
-
-#define GPC_PGC_DOMAIN_ARM     0
-#define GPC_PGC_DOMAIN_PU      1
-#define GPC_PGC_DOMAIN_DISPLAY 2
-#define GPC_PGC_DOMAIN_PCI     3
-
-static struct genpd_power_state imx6_pm_domain_pu_state = {
-       .power_off_latency_ns = 25000,
-       .power_on_latency_ns = 2000000,
-};
-
-static struct imx_pm_domain imx_gpc_domains[] = {
-       [GPC_PGC_DOMAIN_ARM] = {
-               .base = {
-                       .name = "ARM",
-                       .flags = GENPD_FLAG_ALWAYS_ON,
-               },
-       },
-       [GPC_PGC_DOMAIN_PU] = {
-               .base = {
-                       .name = "PU",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-                       .states = &imx6_pm_domain_pu_state,
-                       .state_count = 1,
-               },
-               .reg_offs = 0x260,
-               .cntr_pdn_bit = 0,
-       },
-       [GPC_PGC_DOMAIN_DISPLAY] = {
-               .base = {
-                       .name = "DISPLAY",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-               },
-               .reg_offs = 0x240,
-               .cntr_pdn_bit = 4,
-       },
-       [GPC_PGC_DOMAIN_PCI] = {
-               .base = {
-                       .name = "PCI",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-               },
-               .reg_offs = 0x200,
-               .cntr_pdn_bit = 6,
-       },
-};
-
-struct imx_gpc_dt_data {
-       int num_domains;
-       bool err009619_present;
-       bool err006287_present;
-};
-
-static const struct imx_gpc_dt_data imx6q_dt_data = {
-       .num_domains = 2,
-       .err009619_present = false,
-       .err006287_present = false,
-};
-
-static const struct imx_gpc_dt_data imx6qp_dt_data = {
-       .num_domains = 2,
-       .err009619_present = true,
-       .err006287_present = false,
-};
-
-static const struct imx_gpc_dt_data imx6sl_dt_data = {
-       .num_domains = 3,
-       .err009619_present = false,
-       .err006287_present = true,
-};
-
-static const struct imx_gpc_dt_data imx6sx_dt_data = {
-       .num_domains = 4,
-       .err009619_present = false,
-       .err006287_present = false,
-};
-
-static const struct of_device_id imx_gpc_dt_ids[] = {
-       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
-       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
-       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
-       { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data },
-       { }
-};
-
-static const struct regmap_range yes_ranges[] = {
-       regmap_reg_range(GPC_CNTR, GPC_CNTR),
-       regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR),
-       regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR),
-       regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR),
-};
-
-static const struct regmap_access_table access_table = {
-       .yes_ranges     = yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
-};
-
-static const struct regmap_config imx_gpc_regmap_config = {
-       .reg_bits = 32,
-       .val_bits = 32,
-       .reg_stride = 4,
-       .rd_table = &access_table,
-       .wr_table = &access_table,
-       .max_register = 0x2ac,
-       .fast_io = true,
-};
-
-static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
-       &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
-       &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
-};
-
-static struct genpd_onecell_data imx_gpc_onecell_data = {
-       .domains = imx_gpc_onecell_domains,
-       .num_domains = 2,
-};
-
-static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
-                              unsigned int num_domains)
-{
-       struct imx_pm_domain *domain;
-       int i, ret;
-
-       for (i = 0; i < num_domains; i++) {
-               domain = &imx_gpc_domains[i];
-               domain->regmap = regmap;
-               domain->ipg_rate_mhz = 66;
-
-               if (i == 1) {
-                       domain->supply = devm_regulator_get(dev, "pu");
-                       if (IS_ERR(domain->supply))
-                               return PTR_ERR(domain->supply);
-
-                       ret = imx_pgc_get_clocks(dev, domain);
-                       if (ret)
-                               goto clk_err;
-
-                       domain->base.power_on(&domain->base);
-               }
-       }
-
-       for (i = 0; i < num_domains; i++)
-               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               ret = of_genpd_add_provider_onecell(dev->of_node,
-                                                   &imx_gpc_onecell_data);
-               if (ret)
-                       goto genpd_err;
-       }
-
-       return 0;
-
-genpd_err:
-       for (i = 0; i < num_domains; i++)
-               pm_genpd_remove(&imx_gpc_domains[i].base);
-       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
-clk_err:
-       return ret;
-}
-
-static int imx_gpc_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *of_id =
-                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
-       const struct imx_gpc_dt_data *of_id_data = of_id->data;
-       struct device_node *pgc_node;
-       struct regmap *regmap;
-       void __iomem *base;
-       int ret;
-
-       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
-           !pgc_node)
-               return 0;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
-                                          &imx_gpc_regmap_config);
-       if (IS_ERR(regmap)) {
-               ret = PTR_ERR(regmap);
-               dev_err(&pdev->dev, "failed to init regmap: %d\n",
-                       ret);
-               return ret;
-       }
-
-       /*
-        * Disable PU power down by runtime PM if ERR009619 is present.
-        *
-        * The PRE clock will be paused for several cycles when turning on the
-        * PU domain LDO from power down state. If PRE is in use at that time,
-        * the IPU/PRG cannot get the correct display data from the PRE.
-        *
-        * This is not a concern when the whole system enters suspend state, so
-        * it's safe to power down PU in this case.
-        */
-       if (of_id_data->err009619_present)
-               imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
-                               GENPD_FLAG_RPM_ALWAYS_ON;
-
-       /* Keep DISP always on if ERR006287 is present */
-       if (of_id_data->err006287_present)
-               imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
-                               GENPD_FLAG_ALWAYS_ON;
-
-       if (!pgc_node) {
-               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
-                                         of_id_data->num_domains);
-               if (ret)
-                       return ret;
-       } else {
-               struct imx_pm_domain *domain;
-               struct platform_device *pd_pdev;
-               struct device_node *np;
-               struct clk *ipg_clk;
-               unsigned int ipg_rate_mhz;
-               int domain_index;
-
-               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
-               if (IS_ERR(ipg_clk))
-                       return PTR_ERR(ipg_clk);
-               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
-
-               for_each_child_of_node(pgc_node, np) {
-                       ret = of_property_read_u32(np, "reg", &domain_index);
-                       if (ret) {
-                               of_node_put(np);
-                               return ret;
-                       }
-                       if (domain_index >= of_id_data->num_domains)
-                               continue;
-
-                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
-                                                       domain_index);
-                       if (!pd_pdev) {
-                               of_node_put(np);
-                               return -ENOMEM;
-                       }
-
-                       ret = platform_device_add_data(pd_pdev,
-                                                      &imx_gpc_domains[domain_index],
-                                                      sizeof(imx_gpc_domains[domain_index]));
-                       if (ret) {
-                               platform_device_put(pd_pdev);
-                               of_node_put(np);
-                               return ret;
-                       }
-                       domain = pd_pdev->dev.platform_data;
-                       domain->regmap = regmap;
-                       domain->ipg_rate_mhz = ipg_rate_mhz;
-
-                       pd_pdev->dev.parent = &pdev->dev;
-                       pd_pdev->dev.of_node = np;
-
-                       ret = platform_device_add(pd_pdev);
-                       if (ret) {
-                               platform_device_put(pd_pdev);
-                               of_node_put(np);
-                               return ret;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int imx_gpc_remove(struct platform_device *pdev)
-{
-       struct device_node *pgc_node;
-       int ret;
-
-       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
-           !pgc_node)
-               return 0;
-
-       /*
-        * If the old DT binding is used the toplevel driver needs to
-        * de-register the power domains
-        */
-       if (!pgc_node) {
-               of_genpd_del_provider(pdev->dev.of_node);
-
-               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
-               if (ret)
-                       return ret;
-               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
-
-               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpc",
-               .of_match_table = imx_gpc_dt_ids,
-       },
-       .probe = imx_gpc_probe,
-       .remove = imx_gpc_remove,
-};
-builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
deleted file mode 100644 (file)
index 4b3300b..0000000
+++ /dev/null
@@ -1,1550 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2017 Impinj, Inc
- * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
- *
- * Based on the code of analogus driver:
- *
- * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/clk.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/sizes.h>
-#include <dt-bindings/power/imx7-power.h>
-#include <dt-bindings/power/imx8mq-power.h>
-#include <dt-bindings/power/imx8mm-power.h>
-#include <dt-bindings/power/imx8mn-power.h>
-#include <dt-bindings/power/imx8mp-power.h>
-
-#define GPC_LPCR_A_CORE_BSC                    0x000
-
-#define GPC_PGC_CPU_MAPPING            0x0ec
-#define IMX8MP_GPC_PGC_CPU_MAPPING     0x1cc
-
-#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN                BIT(6)
-#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN                BIT(5)
-#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN                BIT(4)
-#define IMX7_PCIE_PHY_A_CORE_DOMAIN            BIT(3)
-#define IMX7_MIPI_PHY_A_CORE_DOMAIN            BIT(2)
-
-#define IMX8M_PCIE2_A53_DOMAIN                 BIT(15)
-#define IMX8M_MIPI_CSI2_A53_DOMAIN             BIT(14)
-#define IMX8M_MIPI_CSI1_A53_DOMAIN             BIT(13)
-#define IMX8M_DISP_A53_DOMAIN                  BIT(12)
-#define IMX8M_HDMI_A53_DOMAIN                  BIT(11)
-#define IMX8M_VPU_A53_DOMAIN                   BIT(10)
-#define IMX8M_GPU_A53_DOMAIN                   BIT(9)
-#define IMX8M_DDR2_A53_DOMAIN                  BIT(8)
-#define IMX8M_DDR1_A53_DOMAIN                  BIT(7)
-#define IMX8M_OTG2_A53_DOMAIN                  BIT(5)
-#define IMX8M_OTG1_A53_DOMAIN                  BIT(4)
-#define IMX8M_PCIE1_A53_DOMAIN                 BIT(3)
-#define IMX8M_MIPI_A53_DOMAIN                  BIT(2)
-
-#define IMX8MM_VPUH1_A53_DOMAIN                        BIT(15)
-#define IMX8MM_VPUG2_A53_DOMAIN                        BIT(14)
-#define IMX8MM_VPUG1_A53_DOMAIN                        BIT(13)
-#define IMX8MM_DISPMIX_A53_DOMAIN              BIT(12)
-#define IMX8MM_VPUMIX_A53_DOMAIN               BIT(10)
-#define IMX8MM_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MM_GPU_A53_DOMAIN                  (BIT(8) | BIT(11))
-#define IMX8MM_DDR1_A53_DOMAIN                 BIT(7)
-#define IMX8MM_OTG2_A53_DOMAIN                 BIT(5)
-#define IMX8MM_OTG1_A53_DOMAIN                 BIT(4)
-#define IMX8MM_PCIE_A53_DOMAIN                 BIT(3)
-#define IMX8MM_MIPI_A53_DOMAIN                 BIT(2)
-
-#define IMX8MN_DISPMIX_A53_DOMAIN              BIT(12)
-#define IMX8MN_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MN_DDR1_A53_DOMAIN         BIT(7)
-#define IMX8MN_OTG1_A53_DOMAIN         BIT(4)
-#define IMX8MN_MIPI_A53_DOMAIN         BIT(2)
-
-#define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20)
-#define IMX8MP_HSIOMIX_A53_DOMAIN              BIT(19)
-#define IMX8MP_MIPI_PHY2_A53_DOMAIN            BIT(18)
-#define IMX8MP_HDMI_PHY_A53_DOMAIN             BIT(17)
-#define IMX8MP_HDMIMIX_A53_DOMAIN              BIT(16)
-#define IMX8MP_VPU_VC8000E_A53_DOMAIN          BIT(15)
-#define IMX8MP_VPU_G2_A53_DOMAIN               BIT(14)
-#define IMX8MP_VPU_G1_A53_DOMAIN               BIT(13)
-#define IMX8MP_MEDIAMIX_A53_DOMAIN             BIT(12)
-#define IMX8MP_GPU3D_A53_DOMAIN                        BIT(11)
-#define IMX8MP_VPUMIX_A53_DOMAIN               BIT(10)
-#define IMX8MP_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MP_GPU2D_A53_DOMAIN                        BIT(8)
-#define IMX8MP_AUDIOMIX_A53_DOMAIN             BIT(7)
-#define IMX8MP_MLMIX_A53_DOMAIN                        BIT(6)
-#define IMX8MP_USB2_PHY_A53_DOMAIN             BIT(5)
-#define IMX8MP_USB1_PHY_A53_DOMAIN             BIT(4)
-#define IMX8MP_PCIE_PHY_A53_DOMAIN             BIT(3)
-#define IMX8MP_MIPI_PHY1_A53_DOMAIN            BIT(2)
-
-#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ   0x0d8
-#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ   0x0e4
-
-#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
-#define GPC_PU_PGC_SW_PDN_REQ          0x104
-
-#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ           BIT(4)
-#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ           BIT(3)
-#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ           BIT(2)
-#define IMX7_PCIE_PHY_SW_Pxx_REQ               BIT(1)
-#define IMX7_MIPI_PHY_SW_Pxx_REQ               BIT(0)
-
-#define IMX8M_PCIE2_SW_Pxx_REQ                 BIT(13)
-#define IMX8M_MIPI_CSI2_SW_Pxx_REQ             BIT(12)
-#define IMX8M_MIPI_CSI1_SW_Pxx_REQ             BIT(11)
-#define IMX8M_DISP_SW_Pxx_REQ                  BIT(10)
-#define IMX8M_HDMI_SW_Pxx_REQ                  BIT(9)
-#define IMX8M_VPU_SW_Pxx_REQ                   BIT(8)
-#define IMX8M_GPU_SW_Pxx_REQ                   BIT(7)
-#define IMX8M_DDR2_SW_Pxx_REQ                  BIT(6)
-#define IMX8M_DDR1_SW_Pxx_REQ                  BIT(5)
-#define IMX8M_OTG2_SW_Pxx_REQ                  BIT(3)
-#define IMX8M_OTG1_SW_Pxx_REQ                  BIT(2)
-#define IMX8M_PCIE1_SW_Pxx_REQ                 BIT(1)
-#define IMX8M_MIPI_SW_Pxx_REQ                  BIT(0)
-
-#define IMX8MM_VPUH1_SW_Pxx_REQ                        BIT(13)
-#define IMX8MM_VPUG2_SW_Pxx_REQ                        BIT(12)
-#define IMX8MM_VPUG1_SW_Pxx_REQ                        BIT(11)
-#define IMX8MM_DISPMIX_SW_Pxx_REQ              BIT(10)
-#define IMX8MM_VPUMIX_SW_Pxx_REQ               BIT(8)
-#define IMX8MM_GPUMIX_SW_Pxx_REQ               BIT(7)
-#define IMX8MM_GPU_SW_Pxx_REQ                  (BIT(6) | BIT(9))
-#define IMX8MM_DDR1_SW_Pxx_REQ                 BIT(5)
-#define IMX8MM_OTG2_SW_Pxx_REQ                 BIT(3)
-#define IMX8MM_OTG1_SW_Pxx_REQ                 BIT(2)
-#define IMX8MM_PCIE_SW_Pxx_REQ                 BIT(1)
-#define IMX8MM_MIPI_SW_Pxx_REQ                 BIT(0)
-
-#define IMX8MN_DISPMIX_SW_Pxx_REQ              BIT(10)
-#define IMX8MN_GPUMIX_SW_Pxx_REQ               BIT(7)
-#define IMX8MN_DDR1_SW_Pxx_REQ         BIT(5)
-#define IMX8MN_OTG1_SW_Pxx_REQ         BIT(2)
-#define IMX8MN_MIPI_SW_Pxx_REQ         BIT(0)
-
-#define IMX8MP_DDRMIX_Pxx_REQ                  BIT(19)
-#define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ           BIT(18)
-#define IMX8MP_HSIOMIX_Pxx_REQ                 BIT(17)
-#define IMX8MP_MIPI_PHY2_Pxx_REQ               BIT(16)
-#define IMX8MP_HDMI_PHY_Pxx_REQ                        BIT(15)
-#define IMX8MP_HDMIMIX_Pxx_REQ                 BIT(14)
-#define IMX8MP_VPU_VC8K_Pxx_REQ                        BIT(13)
-#define IMX8MP_VPU_G2_Pxx_REQ                  BIT(12)
-#define IMX8MP_VPU_G1_Pxx_REQ                  BIT(11)
-#define IMX8MP_MEDIMIX_Pxx_REQ                 BIT(10)
-#define IMX8MP_GPU_3D_Pxx_REQ                  BIT(9)
-#define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ     BIT(8)
-#define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ         BIT(7)
-#define IMX8MP_GPU_2D_Pxx_REQ                  BIT(6)
-#define IMX8MP_AUDIOMIX_Pxx_REQ                        BIT(5)
-#define IMX8MP_MLMIX_Pxx_REQ                   BIT(4)
-#define IMX8MP_USB2_PHY_Pxx_REQ                        BIT(3)
-#define IMX8MP_USB1_PHY_Pxx_REQ                        BIT(2)
-#define IMX8MP_PCIE_PHY_SW_Pxx_REQ             BIT(1)
-#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ            BIT(0)
-
-#define GPC_M4_PU_PDN_FLG              0x1bc
-
-#define IMX8MP_GPC_PU_PWRHSK           0x190
-#define GPC_PU_PWRHSK                  0x1fc
-
-#define IMX8M_GPU_HSK_PWRDNACKN                        BIT(26)
-#define IMX8M_VPU_HSK_PWRDNACKN                        BIT(25)
-#define IMX8M_DISP_HSK_PWRDNACKN               BIT(24)
-#define IMX8M_GPU_HSK_PWRDNREQN                        BIT(6)
-#define IMX8M_VPU_HSK_PWRDNREQN                        BIT(5)
-#define IMX8M_DISP_HSK_PWRDNREQN               BIT(4)
-
-#define IMX8MM_GPUMIX_HSK_PWRDNACKN            BIT(29)
-#define IMX8MM_GPU_HSK_PWRDNACKN               (BIT(27) | BIT(28))
-#define IMX8MM_VPUMIX_HSK_PWRDNACKN            BIT(26)
-#define IMX8MM_DISPMIX_HSK_PWRDNACKN           BIT(25)
-#define IMX8MM_HSIO_HSK_PWRDNACKN              (BIT(23) | BIT(24))
-#define IMX8MM_GPUMIX_HSK_PWRDNREQN            BIT(11)
-#define IMX8MM_GPU_HSK_PWRDNREQN               (BIT(9) | BIT(10))
-#define IMX8MM_VPUMIX_HSK_PWRDNREQN            BIT(8)
-#define IMX8MM_DISPMIX_HSK_PWRDNREQN           BIT(7)
-#define IMX8MM_HSIO_HSK_PWRDNREQN              (BIT(5) | BIT(6))
-
-#define IMX8MN_GPUMIX_HSK_PWRDNACKN            (BIT(29) | BIT(27))
-#define IMX8MN_DISPMIX_HSK_PWRDNACKN           BIT(25)
-#define IMX8MN_HSIO_HSK_PWRDNACKN              BIT(23)
-#define IMX8MN_GPUMIX_HSK_PWRDNREQN            (BIT(11) | BIT(9))
-#define IMX8MN_DISPMIX_HSK_PWRDNREQN           BIT(7)
-#define IMX8MN_HSIO_HSK_PWRDNREQN              BIT(5)
-
-#define IMX8MP_MEDIAMIX_PWRDNACKN              BIT(30)
-#define IMX8MP_HDMIMIX_PWRDNACKN               BIT(29)
-#define IMX8MP_HSIOMIX_PWRDNACKN               BIT(28)
-#define IMX8MP_VPUMIX_PWRDNACKN                        BIT(26)
-#define IMX8MP_GPUMIX_PWRDNACKN                        BIT(25)
-#define IMX8MP_MLMIX_PWRDNACKN                 (BIT(23) | BIT(24))
-#define IMX8MP_AUDIOMIX_PWRDNACKN              (BIT(20) | BIT(31))
-#define IMX8MP_MEDIAMIX_PWRDNREQN              BIT(14)
-#define IMX8MP_HDMIMIX_PWRDNREQN               BIT(13)
-#define IMX8MP_HSIOMIX_PWRDNREQN               BIT(12)
-#define IMX8MP_VPUMIX_PWRDNREQN                        BIT(10)
-#define IMX8MP_GPUMIX_PWRDNREQN                        BIT(9)
-#define IMX8MP_MLMIX_PWRDNREQN                 (BIT(7) | BIT(8))
-#define IMX8MP_AUDIOMIX_PWRDNREQN              (BIT(4) | BIT(15))
-
-/*
- * The PGC offset values in Reference Manual
- * (Rev. 1, 01/2018 and the older ones) GPC chapter's
- * GPC_PGC memory map are incorrect, below offset
- * values are from design RTL.
- */
-#define IMX7_PGC_MIPI                  16
-#define IMX7_PGC_PCIE                  17
-#define IMX7_PGC_USB_HSIC              20
-
-#define IMX8M_PGC_MIPI                 16
-#define IMX8M_PGC_PCIE1                        17
-#define IMX8M_PGC_OTG1                 18
-#define IMX8M_PGC_OTG2                 19
-#define IMX8M_PGC_DDR1                 21
-#define IMX8M_PGC_GPU                  23
-#define IMX8M_PGC_VPU                  24
-#define IMX8M_PGC_DISP                 26
-#define IMX8M_PGC_MIPI_CSI1            27
-#define IMX8M_PGC_MIPI_CSI2            28
-#define IMX8M_PGC_PCIE2                        29
-
-#define IMX8MM_PGC_MIPI                        16
-#define IMX8MM_PGC_PCIE                        17
-#define IMX8MM_PGC_OTG1                        18
-#define IMX8MM_PGC_OTG2                        19
-#define IMX8MM_PGC_DDR1                        21
-#define IMX8MM_PGC_GPU2D               22
-#define IMX8MM_PGC_GPUMIX              23
-#define IMX8MM_PGC_VPUMIX              24
-#define IMX8MM_PGC_GPU3D               25
-#define IMX8MM_PGC_DISPMIX             26
-#define IMX8MM_PGC_VPUG1               27
-#define IMX8MM_PGC_VPUG2               28
-#define IMX8MM_PGC_VPUH1               29
-
-#define IMX8MN_PGC_MIPI                16
-#define IMX8MN_PGC_OTG1                18
-#define IMX8MN_PGC_DDR1                21
-#define IMX8MN_PGC_GPUMIX              23
-#define IMX8MN_PGC_DISPMIX             26
-
-#define IMX8MP_PGC_NOC                 9
-#define IMX8MP_PGC_MIPI1               12
-#define IMX8MP_PGC_PCIE                        13
-#define IMX8MP_PGC_USB1                        14
-#define IMX8MP_PGC_USB2                        15
-#define IMX8MP_PGC_MLMIX               16
-#define IMX8MP_PGC_AUDIOMIX            17
-#define IMX8MP_PGC_GPU2D               18
-#define IMX8MP_PGC_GPUMIX              19
-#define IMX8MP_PGC_VPUMIX              20
-#define IMX8MP_PGC_GPU3D               21
-#define IMX8MP_PGC_MEDIAMIX            22
-#define IMX8MP_PGC_VPU_G1              23
-#define IMX8MP_PGC_VPU_G2              24
-#define IMX8MP_PGC_VPU_VC8000E         25
-#define IMX8MP_PGC_HDMIMIX             26
-#define IMX8MP_PGC_HDMI                        27
-#define IMX8MP_PGC_MIPI2               28
-#define IMX8MP_PGC_HSIOMIX             29
-#define IMX8MP_PGC_MEDIA_ISP_DWP       30
-#define IMX8MP_PGC_DDRMIX              31
-
-#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
-#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
-
-#define GPC_PGC_CTRL_PCR               BIT(0)
-
-struct imx_pgc_regs {
-       u16 map;
-       u16 pup;
-       u16 pdn;
-       u16 hsk;
-};
-
-struct imx_pgc_domain {
-       struct generic_pm_domain genpd;
-       struct regmap *regmap;
-       const struct imx_pgc_regs *regs;
-       struct regulator *regulator;
-       struct reset_control *reset;
-       struct clk_bulk_data *clks;
-       int num_clks;
-
-       unsigned long pgc;
-
-       const struct {
-               u32 pxx;
-               u32 map;
-               u32 hskreq;
-               u32 hskack;
-       } bits;
-
-       const int voltage;
-       const bool keep_clocks;
-       struct device *dev;
-
-       unsigned int pgc_sw_pup_reg;
-       unsigned int pgc_sw_pdn_reg;
-};
-
-struct imx_pgc_domain_data {
-       const struct imx_pgc_domain *domains;
-       size_t domains_num;
-       const struct regmap_access_table *reg_access_table;
-       const struct imx_pgc_regs *pgc_regs;
-};
-
-static inline struct imx_pgc_domain *
-to_imx_pgc_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx_pgc_domain, genpd);
-}
-
-static int imx_pgc_power_up(struct generic_pm_domain *genpd)
-{
-       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
-       u32 reg_val, pgc;
-       int ret;
-
-       ret = pm_runtime_get_sync(domain->dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(domain->dev);
-               return ret;
-       }
-
-       if (!IS_ERR(domain->regulator)) {
-               ret = regulator_enable(domain->regulator);
-               if (ret) {
-                       dev_err(domain->dev,
-                               "failed to enable regulator: %pe\n",
-                               ERR_PTR(ret));
-                       goto out_put_pm;
-               }
-       }
-
-       reset_control_assert(domain->reset);
-
-       /* Enable reset clocks for all devices in the domain */
-       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-       if (ret) {
-               dev_err(domain->dev, "failed to enable reset clocks\n");
-               goto out_regulator_disable;
-       }
-
-       /* delays for reset to propagate */
-       udelay(5);
-
-       if (domain->bits.pxx) {
-               /* request the domain to power up */
-               regmap_update_bits(domain->regmap, domain->regs->pup,
-                                  domain->bits.pxx, domain->bits.pxx);
-               /*
-                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
-                * for PUP_REQ/PDN_REQ bit to be cleared
-                */
-               ret = regmap_read_poll_timeout(domain->regmap,
-                                              domain->regs->pup, reg_val,
-                                              !(reg_val & domain->bits.pxx),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to command PGC\n");
-                       goto out_clk_disable;
-               }
-
-               /* disable power control */
-               for_each_set_bit(pgc, &domain->pgc, 32) {
-                       regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
-                                         GPC_PGC_CTRL_PCR);
-               }
-       }
-
-       /* delay for reset to propagate */
-       udelay(5);
-
-       reset_control_deassert(domain->reset);
-
-       /* request the ADB400 to power up */
-       if (domain->bits.hskreq) {
-               regmap_update_bits(domain->regmap, domain->regs->hsk,
-                                  domain->bits.hskreq, domain->bits.hskreq);
-
-               /*
-                * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
-                *                                (reg_val & domain->bits.hskack), 0,
-                *                                USEC_PER_MSEC);
-                * Technically we need the commented code to wait handshake. But that needs
-                * the BLK-CTL module BUS clk-en bit being set.
-                *
-                * There is a separate BLK-CTL module and we will have such a driver for it,
-                * that driver will set the BUS clk-en bit and handshake will be triggered
-                * automatically there. Just add a delay and suppose the handshake finish
-                * after that.
-                */
-       }
-
-       /* Disable reset clocks for all devices in the domain */
-       if (!domain->keep_clocks)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return 0;
-
-out_clk_disable:
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-out_regulator_disable:
-       if (!IS_ERR(domain->regulator))
-               regulator_disable(domain->regulator);
-out_put_pm:
-       pm_runtime_put(domain->dev);
-
-       return ret;
-}
-
-static int imx_pgc_power_down(struct generic_pm_domain *genpd)
-{
-       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
-       u32 reg_val, pgc;
-       int ret;
-
-       /* Enable reset clocks for all devices in the domain */
-       if (!domain->keep_clocks) {
-               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-               if (ret) {
-                       dev_err(domain->dev, "failed to enable reset clocks\n");
-                       return ret;
-               }
-       }
-
-       /* request the ADB400 to power down */
-       if (domain->bits.hskreq) {
-               regmap_clear_bits(domain->regmap, domain->regs->hsk,
-                                 domain->bits.hskreq);
-
-               ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
-                                              reg_val,
-                                              !(reg_val & domain->bits.hskack),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to power down ADB400\n");
-                       goto out_clk_disable;
-               }
-       }
-
-       if (domain->bits.pxx) {
-               /* enable power control */
-               for_each_set_bit(pgc, &domain->pgc, 32) {
-                       regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
-                                          GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
-               }
-
-               /* request the domain to power down */
-               regmap_update_bits(domain->regmap, domain->regs->pdn,
-                                  domain->bits.pxx, domain->bits.pxx);
-               /*
-                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
-                * for PUP_REQ/PDN_REQ bit to be cleared
-                */
-               ret = regmap_read_poll_timeout(domain->regmap,
-                                              domain->regs->pdn, reg_val,
-                                              !(reg_val & domain->bits.pxx),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to command PGC\n");
-                       goto out_clk_disable;
-               }
-       }
-
-       /* Disable reset clocks for all devices in the domain */
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       if (!IS_ERR(domain->regulator)) {
-               ret = regulator_disable(domain->regulator);
-               if (ret) {
-                       dev_err(domain->dev,
-                               "failed to disable regulator: %pe\n",
-                               ERR_PTR(ret));
-                       return ret;
-               }
-       }
-
-       pm_runtime_put_sync_suspend(domain->dev);
-
-       return 0;
-
-out_clk_disable:
-       if (!domain->keep_clocks)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return ret;
-}
-
-static const struct imx_pgc_domain imx7_pgc_domains[] = {
-       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
-               .genpd = {
-                       .name      = "mipi-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
-                       .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1000000,
-               .pgc       = BIT(IMX7_PGC_MIPI),
-       },
-
-       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
-               .genpd = {
-                       .name      = "pcie-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
-                       .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1000000,
-               .pgc       = BIT(IMX7_PGC_PCIE),
-       },
-
-       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
-               .genpd = {
-                       .name      = "usb-hsic-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
-                       .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1200000,
-               .pgc       = BIT(IMX7_PGC_USB_HSIC),
-       },
-};
-
-static const struct regmap_range imx7_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_M4_PU_PDN_FLG),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
-                                GPC_PGC_SR(IMX7_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
-                                GPC_PGC_SR(IMX7_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
-                                GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
-};
-
-static const struct regmap_access_table imx7_access_table = {
-       .yes_ranges     = imx7_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
-};
-
-static const struct imx_pgc_regs imx7_pgc_regs = {
-       .map = GPC_PGC_CPU_MAPPING,
-       .pup = GPC_PU_PGC_SW_PUP_REQ,
-       .pdn = GPC_PU_PGC_SW_PDN_REQ,
-       .hsk = GPC_PU_PWRHSK,
-};
-
-static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
-       .domains = imx7_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx7_pgc_domains),
-       .reg_access_table = &imx7_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8m_pgc_domains[] = {
-       [IMX8M_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name      = "mipi",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_A53_DOMAIN,
-               },
-               .pgc       = BIT(IMX8M_PGC_MIPI),
-       },
-
-       [IMX8M_POWER_DOMAIN_PCIE1] = {
-               .genpd = {
-                       .name = "pcie1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
-                       .map = IMX8M_PCIE1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_PCIE1),
-       },
-
-       [IMX8M_POWER_DOMAIN_USB_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_OTG1_SW_Pxx_REQ,
-                       .map = IMX8M_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_OTG1),
-       },
-
-       [IMX8M_POWER_DOMAIN_USB_OTG2] = {
-               .genpd = {
-                       .name = "usb-otg2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_OTG2_SW_Pxx_REQ,
-                       .map = IMX8M_OTG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_OTG2),
-       },
-
-       [IMX8M_POWER_DOMAIN_DDR1] = {
-               .genpd = {
-                       .name = "ddr1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_DDR1_SW_Pxx_REQ,
-                       .map = IMX8M_DDR2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_DDR1),
-       },
-
-       [IMX8M_POWER_DOMAIN_GPU] = {
-               .genpd = {
-                       .name = "gpu",
-               },
-               .bits  = {
-                       .pxx = IMX8M_GPU_SW_Pxx_REQ,
-                       .map = IMX8M_GPU_A53_DOMAIN,
-                       .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
-                       .hskack = IMX8M_GPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_GPU),
-       },
-
-       [IMX8M_POWER_DOMAIN_VPU] = {
-               .genpd = {
-                       .name = "vpu",
-               },
-               .bits  = {
-                       .pxx = IMX8M_VPU_SW_Pxx_REQ,
-                       .map = IMX8M_VPU_A53_DOMAIN,
-                       .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
-                       .hskack = IMX8M_VPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_VPU),
-               .keep_clocks = true,
-       },
-
-       [IMX8M_POWER_DOMAIN_DISP] = {
-               .genpd = {
-                       .name = "disp",
-               },
-               .bits  = {
-                       .pxx = IMX8M_DISP_SW_Pxx_REQ,
-                       .map = IMX8M_DISP_A53_DOMAIN,
-                       .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
-                       .hskack = IMX8M_DISP_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_DISP),
-       },
-
-       [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
-               .genpd = {
-                       .name = "mipi-csi1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_MIPI_CSI1),
-       },
-
-       [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
-               .genpd = {
-                       .name = "mipi-csi2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_MIPI_CSI2),
-       },
-
-       [IMX8M_POWER_DOMAIN_PCIE2] = {
-               .genpd = {
-                       .name = "pcie2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
-                       .map = IMX8M_PCIE2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_PCIE2),
-       },
-};
-
-static const struct regmap_range imx8m_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_PU_PWRHSK),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
-                                GPC_PGC_SR(IMX8M_PGC_PCIE1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
-                                GPC_PGC_SR(IMX8M_PGC_OTG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
-                                GPC_PGC_SR(IMX8M_PGC_OTG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
-                                GPC_PGC_SR(IMX8M_PGC_DDR1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
-                                GPC_PGC_SR(IMX8M_PGC_GPU)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
-                                GPC_PGC_SR(IMX8M_PGC_VPU)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
-                                GPC_PGC_SR(IMX8M_PGC_DISP)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
-                                GPC_PGC_SR(IMX8M_PGC_PCIE2)),
-};
-
-static const struct regmap_access_table imx8m_access_table = {
-       .yes_ranges     = imx8m_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8m_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
-       .domains = imx8m_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
-       .reg_access_table = &imx8m_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
-       [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits  = {
-                       .pxx = 0, /* no power sequence control */
-                       .map = 0, /* no power sequence control */
-                       .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
-               },
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_PCIE] = {
-               .genpd = {
-                       .name = "pcie",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
-                       .map = IMX8MM_PCIE_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_PCIE),
-       },
-
-       [IMX8MM_POWER_DOMAIN_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
-                       .map = IMX8MM_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_OTG1),
-       },
-
-       [IMX8MM_POWER_DOMAIN_OTG2] = {
-               .genpd = {
-                       .name = "usb-otg2",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
-                       .map = IMX8MM_OTG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_OTG2),
-       },
-
-       [IMX8MM_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_GPU] = {
-               .genpd = {
-                       .name = "gpu",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_GPU_SW_Pxx_REQ,
-                       .map = IMX8MM_GPU_A53_DOMAIN,
-                       .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUMIX] = {
-               .genpd = {
-                       .name = "vpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUG1] = {
-               .genpd = {
-                       .name = "vpu-g1",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUG1),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUG2] = {
-               .genpd = {
-                       .name = "vpu-g2",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUG2),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUH1] = {
-               .genpd = {
-                       .name = "vpu-h1",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUH1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUH1),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_DISPMIX] = {
-               .genpd = {
-                       .name = "dispmix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_DISPMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_DISPMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name = "mipi",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
-                       .map = IMX8MM_MIPI_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_MIPI),
-       },
-};
-
-static const struct regmap_range imx8mm_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_PU_PWRHSK),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
-                                GPC_PGC_SR(IMX8MM_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
-                                GPC_PGC_SR(IMX8MM_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
-                                GPC_PGC_SR(IMX8MM_PGC_OTG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
-                                GPC_PGC_SR(IMX8MM_PGC_OTG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
-                                GPC_PGC_SR(IMX8MM_PGC_DDR1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
-                                GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
-                                GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
-};
-
-static const struct regmap_access_table imx8mm_access_table = {
-       .yes_ranges     = imx8mm_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mm_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
-       .domains = imx8mm_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
-       .reg_access_table = &imx8mm_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
-       [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = {
-               .genpd = {
-                       .name = "mipi-phy1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ,
-                       .map = IMX8MP_MIPI_PHY1_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MIPI1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
-               .genpd = {
-                       .name = "pcie-phy1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
-                       .map = IMX8MP_PCIE_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_PCIE),
-       },
-
-       [IMX8MP_POWER_DOMAIN_USB1_PHY] = {
-               .genpd = {
-                       .name = "usb-otg1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_USB1_PHY_Pxx_REQ,
-                       .map = IMX8MP_USB1_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_USB1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_USB2_PHY] = {
-               .genpd = {
-                       .name = "usb-otg2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_USB2_PHY_Pxx_REQ,
-                       .map = IMX8MP_USB2_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_USB2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MLMIX] = {
-               .genpd = {
-                       .name = "mlmix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MLMIX_Pxx_REQ,
-                       .map = IMX8MP_MLMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_MLMIX_PWRDNREQN,
-                       .hskack = IMX8MP_MLMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MLMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_AUDIOMIX] = {
-               .genpd = {
-                       .name = "audiomix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_AUDIOMIX_Pxx_REQ,
-                       .map = IMX8MP_AUDIOMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN,
-                       .hskack = IMX8MP_AUDIOMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_AUDIOMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPU2D] = {
-               .genpd = {
-                       .name = "gpu2d",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_2D_Pxx_REQ,
-                       .map = IMX8MP_GPU2D_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPU2D),
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ,
-                       .map = IMX8MP_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_GPUMIX_PWRDNREQN,
-                       .hskack = IMX8MP_GPUMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPUMIX] = {
-               .genpd = {
-                       .name = "vpumix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ,
-                       .map = IMX8MP_VPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_VPUMIX_PWRDNREQN,
-                       .hskack = IMX8MP_VPUMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPU3D] = {
-               .genpd = {
-                       .name = "gpu3d",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_3D_Pxx_REQ,
-                       .map = IMX8MP_GPU3D_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPU3D),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
-               .genpd = {
-                       .name = "mediamix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MEDIMIX_Pxx_REQ,
-                       .map = IMX8MP_MEDIAMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
-                       .hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MEDIAMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_G1] = {
-               .genpd = {
-                       .name = "vpu-g1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_G1_Pxx_REQ,
-                       .map = IMX8MP_VPU_G1_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_G1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_G2] = {
-               .genpd = {
-                       .name = "vpu-g2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_G2_Pxx_REQ,
-                       .map = IMX8MP_VPU_G2_A53_DOMAIN
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_G2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = {
-               .genpd = {
-                       .name = "vpu-h1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_VC8K_Pxx_REQ,
-                       .map = IMX8MP_VPU_VC8000E_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_VC8000E),
-       },
-
-       [IMX8MP_POWER_DOMAIN_HDMIMIX] = {
-               .genpd = {
-                       .name = "hdmimix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HDMIMIX_Pxx_REQ,
-                       .map = IMX8MP_HDMIMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_HDMIMIX_PWRDNREQN,
-                       .hskack = IMX8MP_HDMIMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HDMIMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_HDMI_PHY] = {
-               .genpd = {
-                       .name = "hdmi-phy",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HDMI_PHY_Pxx_REQ,
-                       .map = IMX8MP_HDMI_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HDMI),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = {
-               .genpd = {
-                       .name = "mipi-phy2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ,
-                       .map = IMX8MP_MIPI_PHY2_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MIPI2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HSIOMIX_Pxx_REQ,
-                       .map = IMX8MP_HSIOMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
-                       .hskack = IMX8MP_HSIOMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HSIOMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = {
-               .genpd = {
-                       .name = "mediamix-isp-dwp",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ,
-                       .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP),
-       },
-};
-
-static const struct regmap_range imx8mp_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                IMX8MP_GPC_PGC_CPU_MAPPING),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC),
-                                GPC_PGC_SR(IMX8MP_PGC_NOC)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1),
-                                GPC_PGC_SR(IMX8MP_PGC_MIPI1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE),
-                                GPC_PGC_SR(IMX8MP_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1),
-                                GPC_PGC_SR(IMX8MP_PGC_USB1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2),
-                                GPC_PGC_SR(IMX8MP_PGC_USB2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_MLMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D),
-                                GPC_PGC_SR(IMX8MP_PGC_GPU2D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_GPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_VPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D),
-                                GPC_PGC_SR(IMX8MP_PGC_GPU3D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_G1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_G2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI),
-                                GPC_PGC_SR(IMX8MP_PGC_HDMI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2),
-                                GPC_PGC_SR(IMX8MP_PGC_MIPI2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP),
-                                GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_DDRMIX)),
-};
-
-static const struct regmap_access_table imx8mp_access_table = {
-       .yes_ranges     = imx8mp_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mp_yes_ranges),
-};
-
-static const struct imx_pgc_regs imx8mp_pgc_regs = {
-       .map = IMX8MP_GPC_PGC_CPU_MAPPING,
-       .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
-       .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
-       .hsk = IMX8MP_GPC_PU_PWRHSK,
-};
-static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
-       .domains = imx8mp_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
-       .reg_access_table = &imx8mp_access_table,
-       .pgc_regs = &imx8mp_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
-       [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits  = {
-                       .pxx = 0, /* no power sequence control */
-                       .map = 0, /* no power sequence control */
-                       .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
-               },
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
-                       .map = IMX8MN_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_OTG1),
-       },
-
-       [IMX8MN_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MN_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_DISPMIX] = {
-               .genpd = {
-                       .name = "dispmix",
-               },
-                       .bits  = {
-                       .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ,
-                       .map = IMX8MN_DISPMIX_A53_DOMAIN,
-                       .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_DISPMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name = "mipi",
-               },
-                       .bits  = {
-                       .pxx = IMX8MN_MIPI_SW_Pxx_REQ,
-                       .map = IMX8MN_MIPI_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_MIPI),
-       },
-};
-
-static const struct regmap_range imx8mn_yes_ranges[] = {
-       regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                        GPC_PU_PWRHSK),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI),
-                        GPC_PGC_SR(IMX8MN_PGC_MIPI)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1),
-                        GPC_PGC_SR(IMX8MN_PGC_OTG1)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1),
-                        GPC_PGC_SR(IMX8MN_PGC_DDR1)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX),
-                        GPC_PGC_SR(IMX8MN_PGC_GPUMIX)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX),
-                        GPC_PGC_SR(IMX8MN_PGC_DISPMIX)),
-};
-
-static const struct regmap_access_table imx8mn_access_table = {
-       .yes_ranges     = imx8mn_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mn_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
-       .domains = imx8mn_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
-       .reg_access_table = &imx8mn_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static int imx_pgc_domain_probe(struct platform_device *pdev)
-{
-       struct imx_pgc_domain *domain = pdev->dev.platform_data;
-       int ret;
-
-       domain->dev = &pdev->dev;
-
-       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
-       if (IS_ERR(domain->regulator)) {
-               if (PTR_ERR(domain->regulator) != -ENODEV)
-                       return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
-                                            "Failed to get domain's regulator\n");
-       } else if (domain->voltage) {
-               regulator_set_voltage(domain->regulator,
-                                     domain->voltage, domain->voltage);
-       }
-
-       domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks);
-       if (domain->num_clks < 0)
-               return dev_err_probe(domain->dev, domain->num_clks,
-                                    "Failed to get domain's clocks\n");
-
-       domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev);
-       if (IS_ERR(domain->reset))
-               return dev_err_probe(domain->dev, PTR_ERR(domain->reset),
-                                    "Failed to get domain's resets\n");
-
-       pm_runtime_enable(domain->dev);
-
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, domain->bits.map);
-
-       ret = pm_genpd_init(&domain->genpd, NULL, true);
-       if (ret) {
-               dev_err(domain->dev, "Failed to init power domain\n");
-               goto out_domain_unmap;
-       }
-
-       if (IS_ENABLED(CONFIG_LOCKDEP) &&
-           of_property_read_bool(domain->dev->of_node, "power-domains"))
-               lockdep_set_subclass(&domain->genpd.mlock, 1);
-
-       ret = of_genpd_add_provider_simple(domain->dev->of_node,
-                                          &domain->genpd);
-       if (ret) {
-               dev_err(domain->dev, "Failed to add genpd provider\n");
-               goto out_genpd_remove;
-       }
-
-       return 0;
-
-out_genpd_remove:
-       pm_genpd_remove(&domain->genpd);
-out_domain_unmap:
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, 0);
-       pm_runtime_disable(domain->dev);
-
-       return ret;
-}
-
-static int imx_pgc_domain_remove(struct platform_device *pdev)
-{
-       struct imx_pgc_domain *domain = pdev->dev.platform_data;
-
-       of_genpd_del_provider(domain->dev->of_node);
-       pm_genpd_remove(&domain->genpd);
-
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, 0);
-
-       pm_runtime_disable(domain->dev);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx_pgc_domain_suspend(struct device *dev)
-{
-       int ret;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domain and more importantly power it up again
-        * after resume, without tripping over our usage of runtime PM to
-        * power up/down the nested domains.
-        */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(dev);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int imx_pgc_domain_resume(struct device *dev)
-{
-       return pm_runtime_put(dev);
-}
-#endif
-
-static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
-};
-
-static const struct platform_device_id imx_pgc_domain_id[] = {
-       { "imx-pgc-domain", },
-       { },
-};
-
-static struct platform_driver imx_pgc_domain_driver = {
-       .driver = {
-               .name = "imx-pgc",
-               .pm = &imx_pgc_domain_pm_ops,
-       },
-       .probe    = imx_pgc_domain_probe,
-       .remove   = imx_pgc_domain_remove,
-       .id_table = imx_pgc_domain_id,
-};
-builtin_platform_driver(imx_pgc_domain_driver)
-
-static int imx_gpcv2_probe(struct platform_device *pdev)
-{
-       const struct imx_pgc_domain_data *domain_data =
-                       of_device_get_match_data(&pdev->dev);
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-               .rd_table       = domain_data->reg_access_table,
-               .wr_table       = domain_data->reg_access_table,
-               .max_register   = SZ_4K,
-       };
-       struct device *dev = &pdev->dev;
-       struct device_node *pgc_np, *np;
-       struct regmap *regmap;
-       void __iomem *base;
-       int ret;
-
-       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
-       if (!pgc_np) {
-               dev_err(dev, "No power domains specified in DT\n");
-               return -EINVAL;
-       }
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(regmap)) {
-               ret = PTR_ERR(regmap);
-               dev_err(dev, "failed to init regmap (%d)\n", ret);
-               return ret;
-       }
-
-       for_each_child_of_node(pgc_np, np) {
-               struct platform_device *pd_pdev;
-               struct imx_pgc_domain *domain;
-               u32 domain_index;
-
-               if (!of_device_is_available(np))
-                       continue;
-
-               ret = of_property_read_u32(np, "reg", &domain_index);
-               if (ret) {
-                       dev_err(dev, "Failed to read 'reg' property\n");
-                       of_node_put(np);
-                       return ret;
-               }
-
-               if (domain_index >= domain_data->domains_num) {
-                       dev_warn(dev,
-                                "Domain index %d is out of bounds\n",
-                                domain_index);
-                       continue;
-               }
-
-               pd_pdev = platform_device_alloc("imx-pgc-domain",
-                                               domain_index);
-               if (!pd_pdev) {
-                       dev_err(dev, "Failed to allocate platform device\n");
-                       of_node_put(np);
-                       return -ENOMEM;
-               }
-
-               ret = platform_device_add_data(pd_pdev,
-                                              &domain_data->domains[domain_index],
-                                              sizeof(domain_data->domains[domain_index]));
-               if (ret) {
-                       platform_device_put(pd_pdev);
-                       of_node_put(np);
-                       return ret;
-               }
-
-               domain = pd_pdev->dev.platform_data;
-               domain->regmap = regmap;
-               domain->regs = domain_data->pgc_regs;
-
-               domain->genpd.power_on  = imx_pgc_power_up;
-               domain->genpd.power_off = imx_pgc_power_down;
-
-               pd_pdev->dev.parent = dev;
-               device_set_node(&pd_pdev->dev, of_fwnode_handle(np));
-
-               ret = platform_device_add(pd_pdev);
-               if (ret) {
-                       platform_device_put(pd_pdev);
-                       of_node_put(np);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static const struct of_device_id imx_gpcv2_dt_ids[] = {
-       { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
-       { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
-       { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, },
-       { .compatible = "fsl,imx8mp-gpc", .data = &imx8mp_pgc_domain_data, },
-       { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
-       { }
-};
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpcv2",
-               .of_match_table = imx_gpcv2_dt_ids,
-       },
-       .probe = imx_gpcv2_probe,
-};
-builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c
deleted file mode 100644 (file)
index afbca0d..0000000
+++ /dev/null
@@ -1,898 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/*
- * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/bitfield.h>
-#include <linux/device.h>
-#include <linux/interconnect.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/clk.h>
-
-#include <dt-bindings/power/imx8mm-power.h>
-#include <dt-bindings/power/imx8mn-power.h>
-#include <dt-bindings/power/imx8mp-power.h>
-#include <dt-bindings/power/imx8mq-power.h>
-
-#define BLK_SFT_RSTN   0x0
-#define BLK_CLK_EN     0x4
-#define BLK_MIPI_RESET_DIV     0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
-
-struct imx8m_blk_ctrl_domain;
-
-struct imx8m_blk_ctrl {
-       struct device *dev;
-       struct notifier_block power_nb;
-       struct device *bus_power_dev;
-       struct regmap *regmap;
-       struct imx8m_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-};
-
-struct imx8m_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       const char * const *path_names;
-       const char *gpc_name;
-       int num_clks;
-       int num_paths;
-       u32 rst_mask;
-       u32 clk_mask;
-
-       /*
-        * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
-        * which is used to control the reset for the MIPI Phy.
-        * Since it's only present in certain circumstances,
-        * an if-statement should be used before setting and clearing this
-        * register.
-        */
-       u32 mipi_phy_rst_mask;
-};
-
-#define DOMAIN_MAX_CLKS 4
-#define DOMAIN_MAX_PATHS 4
-
-struct imx8m_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx8m_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
-       struct device *power_dev;
-       struct imx8m_blk_ctrl *bc;
-       int num_paths;
-};
-
-struct imx8m_blk_ctrl_data {
-       int max_reg;
-       notifier_fn_t power_notifier_fn;
-       const struct imx8m_blk_ctrl_domain_data *domains;
-       int num_domains;
-};
-
-static inline struct imx8m_blk_ctrl_domain *
-to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
-}
-
-static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
-       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
-       struct imx8m_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       /* make sure bus domain is awake */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               dev_err(bc->dev, "failed to power up bus domain\n");
-               return ret;
-       }
-
-       /* put devices into reset */
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       if (data->mipi_phy_rst_mask)
-               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       /* enable upstream and blk-ctrl clocks to allow reset to propagate */
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               goto bus_put;
-       }
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* power up upstream GPC domain */
-       ret = pm_runtime_get_sync(domain->power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up peripheral domain\n");
-               goto clk_disable;
-       }
-
-       /* wait for reset to propagate */
-       udelay(5);
-
-       /* release reset */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       if (data->mipi_phy_rst_mask)
-               regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
-       if (ret)
-               dev_err(bc->dev, "failed to set icc bw\n");
-
-       /* disable upstream clocks */
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       return 0;
-
-clk_disable:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-bus_put:
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
-       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
-       struct imx8m_blk_ctrl *bc = domain->bc;
-
-       /* put devices into reset and disable clocks */
-       if (data->mipi_phy_rst_mask)
-               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* power down upstream GPC domain */
-       pm_runtime_put(domain->power_dev);
-
-       /* allow bus domain to suspend */
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-
-static struct lock_class_key blk_ctrl_genpd_lock_class;
-
-static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
-{
-       const struct imx8m_blk_ctrl_data *bc_data;
-       struct device *dev = &pdev->dev;
-       struct imx8m_blk_ctrl *bc;
-       void __iomem *base;
-       int i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       bc_data = of_device_get_match_data(dev);
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap_config.max_register = bc_data->max_reg;
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
-                                  sizeof(struct imx8m_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = bc_data->num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, bc_data->num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
-       if (IS_ERR(bc->bus_power_dev)) {
-               if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
-                       return dev_err_probe(dev, -EPROBE_DEFER,
-                                            "failed to attach power domain \"bus\"\n");
-               else
-                       return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
-                                            "failed to attach power domain \"bus\"\n");
-       }
-
-       for (i = 0; i < bc_data->num_domains; i++) {
-               const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-               domain->num_paths = data->num_paths;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               for (j = 0; j < data->num_paths; j++) {
-                       domain->paths[j].name = data->path_names[j];
-                       /* Fake value for now, just let ICC could configure NoC mode/priority */
-                       domain->paths[j].avg_bw = 1;
-                       domain->paths[j].peak_bw = 1;
-               }
-
-               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
-               if (ret) {
-                       if (ret != -EPROBE_DEFER) {
-                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
-                               domain->num_paths = 0;
-                       } else {
-                               dev_err_probe(dev, ret, "failed to get noc entries\n");
-                               goto cleanup_pds;
-                       }
-               }
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->power_dev =
-                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
-               if (IS_ERR(domain->power_dev)) {
-                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
-                                     "failed to attach power domain \"%s\"\n",
-                                     data->gpc_name);
-                       ret = PTR_ERR(domain->power_dev);
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx8m_blk_ctrl_power_on;
-               domain->genpd.power_off = imx8m_blk_ctrl_power_off;
-               domain->bc = bc;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret,
-                                     "failed to init power domain \"%s\"\n",
-                                     data->gpc_name);
-                       dev_pm_domain_detach(domain->power_dev, true);
-                       goto cleanup_pds;
-               }
-
-               /*
-                * We use runtime PM to trigger power on/off of the upstream GPC
-                * domain, as a strict hierarchical parent/child power domain
-                * setup doesn't allow us to meet the sequencing requirements.
-                * This means we have nested locking of genpd locks, without the
-                * nesting being visible at the genpd level, so we need a
-                * separate lock class to make lockdep aware of the fact that
-                * this are separate domain locks that can be nested without a
-                * self-deadlock.
-                */
-               lockdep_set_class(&domain->genpd.mlock,
-                                 &blk_ctrl_genpd_lock_class);
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
-       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power notifier\n");
-               goto cleanup_provider;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       ret = devm_of_platform_populate(dev);
-       if (ret)
-               goto cleanup_provider;
-
-       return 0;
-
-cleanup_provider:
-       of_genpd_del_provider(dev->of_node);
-cleanup_pds:
-       for (i--; i >= 0; i--) {
-               pm_genpd_remove(&bc->domains[i].genpd);
-               dev_pm_domain_detach(bc->domains[i].power_dev, true);
-       }
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-               dev_pm_domain_detach(domain->power_dev, true);
-       }
-
-       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx8m_blk_ctrl_suspend(struct device *dev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
-       int ret, i;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domains and more importantly power them up again
-        * after resume, without tripping over our usage of runtime PM to
-        * control the upstream GPC domains. Things happen in the right order
-        * in the system suspend/resume paths due to the device parent/child
-        * hierarchy.
-        */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               return ret;
-       }
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++) {
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-
-               ret = pm_runtime_get_sync(domain->power_dev);
-               if (ret < 0) {
-                       pm_runtime_put_noidle(domain->power_dev);
-                       goto out_fail;
-               }
-       }
-
-       return 0;
-
-out_fail:
-       for (i--; i >= 0; i--)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_resume(struct device *dev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
-       int i;
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
-};
-
-static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
-                                    unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /*
-        * The ADB in the VPUMIX domain has no separate reset and clock
-        * enable bits, but is ungated together with the VPU clocks. To
-        * allow the handshake with the GPC to progress we put the VPUs
-        * in reset and ungate the clocks.
-        */
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /* set "fuse" bits to enable the VPUs */
-               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
-       [IMX8MM_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-       },
-       [IMX8MM_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-       },
-       [IMX8MM_VPUBLK_PD_H1] = {
-               .name = "vpublk-h1",
-               .clk_names = (const char *[]){ "h1", },
-               .num_clks = 1,
-               .gpc_name = "h1",
-               .rst_mask = BIT(2),
-               .clk_mask = BIT(2),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x18,
-       .power_notifier_fn = imx8mm_vpu_power_notifier,
-       .domains = imx8mm_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
-};
-
-static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
-       [IMX8MP_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-               .path_names = (const char *[]){"g1"},
-               .num_paths = 1,
-       },
-       [IMX8MP_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-               .path_names = (const char *[]){"g2"},
-               .num_paths = 1,
-       },
-       [IMX8MP_VPUBLK_PD_VC8000E] = {
-               .name = "vpublk-vc8000e",
-               .clk_names = (const char *[]){ "vc8000e", },
-               .num_clks = 1,
-               .gpc_name = "vc8000e",
-               .rst_mask = BIT(2),
-               .clk_mask = BIT(2),
-               .path_names = (const char *[]){"vc8000e"},
-               .num_paths = 1,
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x18,
-       .power_notifier_fn = imx8mm_vpu_power_notifier,
-       .domains = imx8mp_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
-};
-
-static int imx8mm_disp_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       if (action == GENPD_NOTIFY_ON)
-               udelay(5);
-
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
-       [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
-               .name = "dispblk-csi-bridge",
-               .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
-                                              "csi-bridge-core", },
-               .num_clks = 3,
-               .gpc_name = "csi-bridge",
-               .rst_mask = BIT(0) | BIT(1) | BIT(2),
-               .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
-       },
-       [IMX8MM_DISPBLK_PD_LCDIF] = {
-               .name = "dispblk-lcdif",
-               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
-               .num_clks = 3,
-               .gpc_name = "lcdif",
-               .clk_mask = BIT(6) | BIT(7),
-       },
-       [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
-               .name = "dispblk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi",
-               .rst_mask = BIT(5),
-               .clk_mask = BIT(8) | BIT(9),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
-               .name = "dispblk-mipi-csi",
-               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi",
-               .rst_mask = BIT(3) | BIT(4),
-               .clk_mask = BIT(10) | BIT(11),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
-       .max_reg = 0x2c,
-       .power_notifier_fn = imx8mm_disp_power_notifier,
-       .domains = imx8mm_disp_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
-};
-
-
-static int imx8mn_disp_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       if (action == GENPD_NOTIFY_ON)
-               udelay(5);
-
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
-       [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
-               .name = "dispblk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi",
-               .rst_mask = BIT(0) | BIT(1),
-               .clk_mask = BIT(0) | BIT(1),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
-               .name = "dispblk-mipi-csi",
-               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi",
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-       [IMX8MN_DISPBLK_PD_LCDIF] = {
-               .name = "dispblk-lcdif",
-               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
-               .num_clks = 3,
-               .gpc_name = "lcdif",
-               .rst_mask = BIT(4) | BIT(5),
-               .clk_mask = BIT(4) | BIT(5),
-       },
-       [IMX8MN_DISPBLK_PD_ISI] = {
-               .name = "dispblk-isi",
-               .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
-                                               "disp_apb_root"},
-               .num_clks = 4,
-               .gpc_name = "isi",
-               .rst_mask = BIT(6) | BIT(7),
-               .clk_mask = BIT(6) | BIT(7),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
-       .max_reg = 0x84,
-       .power_notifier_fn = imx8mn_disp_power_notifier,
-       .domains = imx8mn_disp_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
-};
-
-#define LCDIF_ARCACHE_CTRL     0x4c
-#define  LCDIF_1_RD_HURRY      GENMASK(15, 13)
-#define  LCDIF_0_RD_HURRY      GENMASK(12, 10)
-
-static int imx8mp_media_power_notifier(struct notifier_block *nb,
-                               unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /*
-                * Set panic read hurry level for both LCDIF interfaces to
-                * maximum priority to minimize chances of display FIFO
-                * underflow.
-                */
-               regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL,
-                               FIELD_PREP(LCDIF_1_RD_HURRY, 7) |
-                               FIELD_PREP(LCDIF_0_RD_HURRY, 7));
-       }
-
-       return NOTIFY_OK;
-}
-
-/*
- * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
- * section 13.2.2, 13.2.3
- * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
- */
-static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
-       [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
-               .name = "mediablk-mipi-dsi-1",
-               .clk_names = (const char *[]){ "apb", "phy", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi1",
-               .rst_mask = BIT(0) | BIT(1),
-               .clk_mask = BIT(0) | BIT(1),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
-               .name = "mediablk-mipi-csi2-1",
-               .clk_names = (const char *[]){ "apb", "cam1" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi1",
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-       [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
-               .name = "mediablk-lcdif-1",
-               .clk_names = (const char *[]){ "disp1", "apb", "axi", },
-               .num_clks = 3,
-               .gpc_name = "lcdif1",
-               .rst_mask = BIT(4) | BIT(5) | BIT(23),
-               .clk_mask = BIT(4) | BIT(5) | BIT(23),
-               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_ISI] = {
-               .name = "mediablk-isi",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "isi",
-               .rst_mask = BIT(6) | BIT(7),
-               .clk_mask = BIT(6) | BIT(7),
-               .path_names = (const char *[]){"isi0", "isi1", "isi2"},
-               .num_paths = 3,
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
-               .name = "mediablk-mipi-csi2-2",
-               .clk_names = (const char *[]){ "apb", "cam2" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi2",
-               .rst_mask = BIT(9) | BIT(10),
-               .clk_mask = BIT(9) | BIT(10),
-               .mipi_phy_rst_mask = BIT(30),
-       },
-       [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
-               .name = "mediablk-lcdif-2",
-               .clk_names = (const char *[]){ "disp2", "apb", "axi", },
-               .num_clks = 3,
-               .gpc_name = "lcdif2",
-               .rst_mask = BIT(11) | BIT(12) | BIT(24),
-               .clk_mask = BIT(11) | BIT(12) | BIT(24),
-               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_ISP] = {
-               .name = "mediablk-isp",
-               .clk_names = (const char *[]){ "isp", "axi", "apb" },
-               .num_clks = 3,
-               .gpc_name = "isp",
-               .rst_mask = BIT(16) | BIT(17) | BIT(18),
-               .clk_mask = BIT(16) | BIT(17) | BIT(18),
-               .path_names = (const char *[]){"isp0", "isp1"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_DWE] = {
-               .name = "mediablk-dwe",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "dwe",
-               .rst_mask = BIT(19) | BIT(20) | BIT(21),
-               .clk_mask = BIT(19) | BIT(20) | BIT(21),
-               .path_names = (const char *[]){"dwe"},
-               .num_paths = 1,
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
-               .name = "mediablk-mipi-dsi-2",
-               .clk_names = (const char *[]){ "phy", },
-               .num_clks = 1,
-               .gpc_name = "mipi-dsi2",
-               .rst_mask = BIT(22),
-               .clk_mask = BIT(22),
-               .mipi_phy_rst_mask = BIT(29),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
-       .max_reg = 0x138,
-       .power_notifier_fn = imx8mp_media_power_notifier,
-       .domains = imx8mp_media_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
-};
-
-static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
-                                    unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /*
-        * The ADB in the VPUMIX domain has no separate reset and clock
-        * enable bits, but is ungated and reset together with the VPUs. The
-        * reset and clock enable inputs to the ADB is a logical OR of the
-        * VPU bits. In order to set the G2 fuse bits, the G2 clock must
-        * also be enabled.
-        */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /* set "fuse" bits to enable the VPUs */
-               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
-       [IMX8MQ_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-       },
-       [IMX8MQ_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x14,
-       .power_notifier_fn = imx8mq_vpu_power_notifier,
-       .domains = imx8mq_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
-};
-
-static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx8mm-vpu-blk-ctrl",
-               .data = &imx8mm_vpu_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mm-disp-blk-ctrl",
-               .data = &imx8mm_disp_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mn-disp-blk-ctrl",
-               .data = &imx8mn_disp_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mp-media-blk-ctrl",
-               .data = &imx8mp_media_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mq-vpu-blk-ctrl",
-               .data = &imx8mq_vpu_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mp-vpu-blk-ctrl",
-               .data = &imx8mp_vpu_blk_ctl_dev_data
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
-
-static struct platform_driver imx8m_blk_ctrl_driver = {
-       .probe = imx8m_blk_ctrl_probe,
-       .remove = imx8m_blk_ctrl_remove,
-       .driver = {
-               .name = "imx8m-blk-ctrl",
-               .pm = &imx8m_blk_ctrl_pm_ops,
-               .of_match_table = imx8m_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx8m_blk_ctrl_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c
deleted file mode 100644 (file)
index 870aecc..0000000
+++ /dev/null
@@ -1,867 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/*
- * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/interconnect.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-
-#include <dt-bindings/power/imx8mp-power.h>
-
-#define GPR_REG0               0x0
-#define  PCIE_CLOCK_MODULE_EN  BIT(0)
-#define  USB_CLOCK_MODULE_EN   BIT(1)
-#define  PCIE_PHY_APB_RST      BIT(4)
-#define  PCIE_PHY_INIT_RST     BIT(5)
-#define GPR_REG1               0x4
-#define  PLL_LOCK              BIT(13)
-#define GPR_REG2               0x8
-#define  P_PLL_MASK            GENMASK(5, 0)
-#define  M_PLL_MASK            GENMASK(15, 6)
-#define  S_PLL_MASK            GENMASK(18, 16)
-#define GPR_REG3               0xc
-#define  PLL_CKE               BIT(17)
-#define  PLL_RST               BIT(31)
-
-struct imx8mp_blk_ctrl_domain;
-
-struct imx8mp_blk_ctrl {
-       struct device *dev;
-       struct notifier_block power_nb;
-       struct device *bus_power_dev;
-       struct regmap *regmap;
-       struct imx8mp_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-};
-
-struct imx8mp_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       int num_clks;
-       const char * const *path_names;
-       int num_paths;
-       const char *gpc_name;
-};
-
-#define DOMAIN_MAX_CLKS 2
-#define DOMAIN_MAX_PATHS 3
-
-struct imx8mp_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx8mp_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
-       struct device *power_dev;
-       struct imx8mp_blk_ctrl *bc;
-       int num_paths;
-       int id;
-};
-
-struct imx8mp_blk_ctrl_data {
-       int max_reg;
-       int (*probe) (struct imx8mp_blk_ctrl *bc);
-       notifier_fn_t power_notifier_fn;
-       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       const struct imx8mp_blk_ctrl_domain_data *domains;
-       int num_domains;
-};
-
-static inline struct imx8mp_blk_ctrl_domain *
-to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
-}
-
-struct clk_hsio_pll {
-       struct clk_hw   hw;
-       struct regmap *regmap;
-};
-
-static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
-{
-       return container_of(hw, struct clk_hsio_pll, hw);
-}
-
-static int clk_hsio_pll_prepare(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-       u32 val;
-
-       /* set the PLL configuration */
-       regmap_update_bits(clk->regmap, GPR_REG2,
-                          P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
-                          FIELD_PREP(P_PLL_MASK, 12) |
-                          FIELD_PREP(M_PLL_MASK, 800) |
-                          FIELD_PREP(S_PLL_MASK, 4));
-
-       /* de-assert PLL reset */
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
-
-       /* enable PLL */
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
-
-       return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
-                                       val & PLL_LOCK, 10, 100);
-}
-
-static void clk_hsio_pll_unprepare(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
-}
-
-static int clk_hsio_pll_is_prepared(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-
-       return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK);
-}
-
-static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
-{
-       return 100000000;
-}
-
-static const struct clk_ops clk_hsio_pll_ops = {
-       .prepare = clk_hsio_pll_prepare,
-       .unprepare = clk_hsio_pll_unprepare,
-       .is_prepared = clk_hsio_pll_is_prepared,
-       .recalc_rate = clk_hsio_pll_recalc_rate,
-};
-
-static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
-{
-       struct clk_hsio_pll *clk_hsio_pll;
-       struct clk_hw *hw;
-       struct clk_init_data init = {};
-       int ret;
-
-       clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
-       if (!clk_hsio_pll)
-               return -ENOMEM;
-
-       init.name = "hsio_pll";
-       init.ops = &clk_hsio_pll_ops;
-       init.parent_names = (const char *[]){"osc_24m"};
-       init.num_parents = 1;
-
-       clk_hsio_pll->regmap = bc->regmap;
-       clk_hsio_pll->hw.init = &init;
-
-       hw = &clk_hsio_pll->hw;
-       ret = devm_clk_hw_register(bc->dev, hw);
-       if (ret)
-               return ret;
-
-       return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw);
-}
-
-static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
-                                         struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HSIOBLK_PD_USB:
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE:
-               regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
-               regmap_set_bits(bc->regmap, GPR_REG0,
-                               PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
-               break;
-       default:
-               break;
-       }
-}
-
-static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
-                                          struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HSIOBLK_PD_USB:
-               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE:
-               regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
-               regmap_clear_bits(bc->regmap, GPR_REG0,
-                                 PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
-               break;
-       default:
-               break;
-       }
-}
-
-static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
-                                                power_nb);
-       struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
-       int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
-       int ret;
-
-       switch (action) {
-       case GENPD_NOTIFY_ON:
-               /*
-                * enable USB clock for a moment for the power-on ADB handshake
-                * to proceed
-                */
-               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
-               if (ret)
-                       return NOTIFY_BAD;
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-
-               udelay(5);
-
-               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               clk_bulk_disable_unprepare(num_clks, usb_clk);
-               break;
-       case GENPD_NOTIFY_PRE_OFF:
-               /* enable USB clock for the power-down ADB handshake to work */
-               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
-               if (ret)
-                       return NOTIFY_BAD;
-
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case GENPD_NOTIFY_OFF:
-               clk_bulk_disable_unprepare(num_clks, usb_clk);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
-       [IMX8MP_HSIOBLK_PD_USB] = {
-               .name = "hsioblk-usb",
-               .clk_names = (const char *[]){ "usb" },
-               .num_clks = 1,
-               .gpc_name = "usb",
-               .path_names = (const char *[]){"usb1", "usb2"},
-               .num_paths = 2,
-       },
-       [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
-               .name = "hsioblk-usb-phy1",
-               .gpc_name = "usb-phy1",
-       },
-       [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
-               .name = "hsioblk-usb-phy2",
-               .gpc_name = "usb-phy2",
-       },
-       [IMX8MP_HSIOBLK_PD_PCIE] = {
-               .name = "hsioblk-pcie",
-               .clk_names = (const char *[]){ "pcie" },
-               .num_clks = 1,
-               .gpc_name = "pcie",
-               .path_names = (const char *[]){"noc-pcie", "pcie"},
-               .num_paths = 2,
-       },
-       [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
-               .name = "hsioblk-pcie-phy",
-               .gpc_name = "pcie-phy",
-       },
-};
-
-static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
-       .max_reg = 0x24,
-       .probe = imx8mp_hsio_blk_ctrl_probe,
-       .power_on = imx8mp_hsio_blk_ctrl_power_on,
-       .power_off = imx8mp_hsio_blk_ctrl_power_off,
-       .power_notifier_fn = imx8mp_hsio_power_notifier,
-       .domains = imx8mp_hsio_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
-};
-
-#define HDMI_RTX_RESET_CTL0    0x20
-#define HDMI_RTX_CLK_CTL0      0x40
-#define HDMI_RTX_CLK_CTL1      0x50
-#define HDMI_RTX_CLK_CTL2      0x60
-#define HDMI_RTX_CLK_CTL3      0x70
-#define HDMI_RTX_CLK_CTL4      0x80
-#define HDMI_TX_CONTROL0       0x200
-#define  HDMI_LCDIF_NOC_HURRY_MASK             GENMASK(14, 12)
-
-static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
-                                         struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HDMIBLK_PD_IRQSTEER:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
-               break;
-       case IMX8MP_HDMIBLK_PD_LCDIF:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(16) | BIT(17) | BIT(18) |
-                               BIT(19) | BIT(20));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                               BIT(4) | BIT(5) | BIT(6));
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0,
-                               FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7));
-               break;
-       case IMX8MP_HDMIBLK_PD_PAI:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
-               break;
-       case IMX8MP_HDMIBLK_PD_PVI:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
-               break;
-       case IMX8MP_HDMIBLK_PD_TRNG:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(2) | BIT(4) | BIT(5));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
-                               BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
-                               BIT(18) | BIT(19) | BIT(20) | BIT(21));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                               BIT(7) | BIT(10) | BIT(11));
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
-               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDCP:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
-               break;
-       case IMX8MP_HDMIBLK_PD_HRV:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
-               break;
-       default:
-               break;
-       }
-}
-
-static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
-                                          struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HDMIBLK_PD_IRQSTEER:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
-               break;
-       case IMX8MP_HDMIBLK_PD_LCDIF:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                                 BIT(4) | BIT(5) | BIT(6));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(16) | BIT(17) | BIT(18) |
-                                 BIT(19) | BIT(20));
-               break;
-       case IMX8MP_HDMIBLK_PD_PAI:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
-               break;
-       case IMX8MP_HDMIBLK_PD_PVI:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
-               break;
-       case IMX8MP_HDMIBLK_PD_TRNG:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX:
-               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                                 BIT(7) | BIT(10) | BIT(11));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
-                                 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
-                                 BIT(18) | BIT(19) | BIT(20) | BIT(21));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(2) | BIT(4) | BIT(5));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDCP:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
-               break;
-       case IMX8MP_HDMIBLK_PD_HRV:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
-               break;
-       default:
-               break;
-       }
-}
-
-static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON)
-               return NOTIFY_OK;
-
-       /*
-        * Contrary to other blk-ctrls the reset and clock don't clear when the
-        * power domain is powered down. To ensure the proper reset pulsing,
-        * first clear them all to asserted state, then enable the bus clocks
-        * and then release the ADB reset.
-        */
-       regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
-       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
-       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
-       regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                       BIT(0) | BIT(1) | BIT(10));
-       regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       udelay(5);
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
-       [IMX8MP_HDMIBLK_PD_IRQSTEER] = {
-               .name = "hdmiblk-irqsteer",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "irqsteer",
-       },
-       [IMX8MP_HDMIBLK_PD_LCDIF] = {
-               .name = "hdmiblk-lcdif",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "lcdif",
-               .path_names = (const char *[]){"lcdif-hdmi"},
-               .num_paths = 1,
-       },
-       [IMX8MP_HDMIBLK_PD_PAI] = {
-               .name = "hdmiblk-pai",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "pai",
-       },
-       [IMX8MP_HDMIBLK_PD_PVI] = {
-               .name = "hdmiblk-pvi",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "pvi",
-       },
-       [IMX8MP_HDMIBLK_PD_TRNG] = {
-               .name = "hdmiblk-trng",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "trng",
-       },
-       [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
-               .name = "hdmiblk-hdmi-tx",
-               .clk_names = (const char *[]){ "apb", "ref_266m" },
-               .num_clks = 2,
-               .gpc_name = "hdmi-tx",
-       },
-       [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
-               .name = "hdmiblk-hdmi-tx-phy",
-               .clk_names = (const char *[]){ "apb", "ref_24m" },
-               .num_clks = 2,
-               .gpc_name = "hdmi-tx-phy",
-       },
-       [IMX8MP_HDMIBLK_PD_HRV] = {
-               .name = "hdmiblk-hrv",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "hrv",
-               .path_names = (const char *[]){"hrv"},
-               .num_paths = 1,
-       },
-       [IMX8MP_HDMIBLK_PD_HDCP] = {
-               .name = "hdmiblk-hdcp",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "hdcp",
-               .path_names = (const char *[]){"hdcp"},
-               .num_paths = 1,
-       },
-};
-
-static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
-       .max_reg = 0x23c,
-       .power_on = imx8mp_hdmi_blk_ctrl_power_on,
-       .power_off = imx8mp_hdmi_blk_ctrl_power_off,
-       .power_notifier_fn = imx8mp_hdmi_power_notifier,
-       .domains = imx8mp_hdmi_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
-};
-
-static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
-       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
-       struct imx8mp_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       /* make sure bus domain is awake */
-       ret = pm_runtime_resume_and_get(bc->bus_power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up bus domain\n");
-               return ret;
-       }
-
-       /* enable upstream clocks */
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               goto bus_put;
-       }
-
-       /* domain specific blk-ctrl manipulation */
-       bc->power_on(bc, domain);
-
-       /* power up upstream GPC domain */
-       ret = pm_runtime_resume_and_get(domain->power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up peripheral domain\n");
-               goto clk_disable;
-       }
-
-       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
-       if (ret)
-               dev_err(bc->dev, "failed to set icc bw\n");
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       return 0;
-
-clk_disable:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-bus_put:
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
-       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
-       struct imx8mp_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               return ret;
-       }
-
-       /* domain specific blk-ctrl manipulation */
-       bc->power_off(bc, domain);
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       /* power down upstream GPC domain */
-       pm_runtime_put(domain->power_dev);
-
-       /* allow bus domain to suspend */
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-
-static struct lock_class_key blk_ctrl_genpd_lock_class;
-
-static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
-{
-       const struct imx8mp_blk_ctrl_data *bc_data;
-       struct device *dev = &pdev->dev;
-       struct imx8mp_blk_ctrl *bc;
-       void __iomem *base;
-       int num_domains, i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       bc_data = of_device_get_match_data(dev);
-       num_domains = bc_data->num_domains;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap_config.max_register = bc_data->max_reg;
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, num_domains,
-                                  sizeof(struct imx8mp_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
-       if (IS_ERR(bc->bus_power_dev))
-               return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
-                                    "failed to attach bus power domain\n");
-
-       bc->power_off = bc_data->power_off;
-       bc->power_on = bc_data->power_on;
-
-       for (i = 0; i < num_domains; i++) {
-               const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-               domain->num_paths = data->num_paths;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               for (j = 0; j < data->num_paths; j++) {
-                       domain->paths[j].name = data->path_names[j];
-                       /* Fake value for now, just let ICC could configure NoC mode/priority */
-                       domain->paths[j].avg_bw = 1;
-                       domain->paths[j].peak_bw = 1;
-               }
-
-               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
-               if (ret) {
-                       if (ret != -EPROBE_DEFER) {
-                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
-                               domain->num_paths = 0;
-                       } else {
-                               dev_err_probe(dev, ret, "failed to get noc entries\n");
-                               goto cleanup_pds;
-                       }
-               }
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->power_dev =
-                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
-               if (IS_ERR(domain->power_dev)) {
-                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
-                                     "failed to attach power domain %s\n",
-                                     data->gpc_name);
-                       ret = PTR_ERR(domain->power_dev);
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
-               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
-               domain->bc = bc;
-               domain->id = i;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to init power domain\n");
-                       dev_pm_domain_detach(domain->power_dev, true);
-                       goto cleanup_pds;
-               }
-
-               /*
-                * We use runtime PM to trigger power on/off of the upstream GPC
-                * domain, as a strict hierarchical parent/child power domain
-                * setup doesn't allow us to meet the sequencing requirements.
-                * This means we have nested locking of genpd locks, without the
-                * nesting being visible at the genpd level, so we need a
-                * separate lock class to make lockdep aware of the fact that
-                * this are separate domain locks that can be nested without a
-                * self-deadlock.
-                */
-               lockdep_set_class(&domain->genpd.mlock,
-                                 &blk_ctrl_genpd_lock_class);
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
-       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power notifier\n");
-               goto cleanup_provider;
-       }
-
-       if (bc_data->probe) {
-               ret = bc_data->probe(bc);
-               if (ret)
-                       goto cleanup_provider;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       return 0;
-
-cleanup_provider:
-       of_genpd_del_provider(dev->of_node);
-cleanup_pds:
-       for (i--; i >= 0; i--) {
-               pm_genpd_remove(&bc->domains[i].genpd);
-               dev_pm_domain_detach(bc->domains[i].power_dev, true);
-       }
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-               dev_pm_domain_detach(domain->power_dev, true);
-       }
-
-       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx8mp_blk_ctrl_suspend(struct device *dev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
-       int ret, i;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domains and more importantly power them up again
-        * after resume, without tripping over our usage of runtime PM to
-        * control the upstream GPC domains. Things happen in the right order
-        * in the system suspend/resume paths due to the device parent/child
-        * hierarchy.
-        */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               return ret;
-       }
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++) {
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-
-               ret = pm_runtime_get_sync(domain->power_dev);
-               if (ret < 0) {
-                       pm_runtime_put_noidle(domain->power_dev);
-                       goto out_fail;
-               }
-       }
-
-       return 0;
-
-out_fail:
-       for (i--; i >= 0; i--)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_resume(struct device *dev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
-       int i;
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
-                               imx8mp_blk_ctrl_resume)
-};
-
-static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx8mp-hsio-blk-ctrl",
-               .data = &imx8mp_hsio_blk_ctl_dev_data,
-       }, {
-               .compatible = "fsl,imx8mp-hdmi-blk-ctrl",
-               .data = &imx8mp_hdmi_blk_ctl_dev_data,
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
-
-static struct platform_driver imx8mp_blk_ctrl_driver = {
-       .probe = imx8mp_blk_ctrl_probe,
-       .remove = imx8mp_blk_ctrl_remove,
-       .driver = {
-               .name = "imx8mp-blk-ctrl",
-               .pm = &imx8mp_blk_ctrl_pm_ops,
-               .of_match_table = imx8mp_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx8mp_blk_ctrl_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/soc/imx/imx93-blk-ctrl.c b/drivers/soc/imx/imx93-blk-ctrl.c
deleted file mode 100644 (file)
index 2c60032..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/sizes.h>
-
-#include <dt-bindings/power/fsl,imx93-power.h>
-
-#define BLK_SFT_RSTN   0x0
-#define BLK_CLK_EN     0x4
-#define BLK_MAX_CLKS   4
-
-#define DOMAIN_MAX_CLKS 4
-
-#define LCDIF_QOS_REG          0xC
-#define LCDIF_DEFAULT_QOS_OFF  12
-#define LCDIF_CFG_QOS_OFF      8
-
-#define PXP_QOS_REG            0x10
-#define PXP_R_DEFAULT_QOS_OFF  28
-#define PXP_R_CFG_QOS_OFF      24
-#define PXP_W_DEFAULT_QOS_OFF  20
-#define PXP_W_CFG_QOS_OFF      16
-
-#define ISI_CACHE_REG          0x14
-
-#define ISI_QOS_REG            0x1C
-#define ISI_V_DEFAULT_QOS_OFF  28
-#define ISI_V_CFG_QOS_OFF      24
-#define ISI_U_DEFAULT_QOS_OFF  20
-#define ISI_U_CFG_QOS_OFF      16
-#define ISI_Y_R_DEFAULT_QOS_OFF        12
-#define ISI_Y_R_CFG_QOS_OFF    8
-#define ISI_Y_W_DEFAULT_QOS_OFF        4
-#define ISI_Y_W_CFG_QOS_OFF    0
-
-#define PRIO_MASK              0xF
-
-#define PRIO(X)                        (X)
-
-struct imx93_blk_ctrl_domain;
-
-struct imx93_blk_ctrl {
-       struct device *dev;
-       struct regmap *regmap;
-       int num_clks;
-       struct clk_bulk_data clks[BLK_MAX_CLKS];
-       struct imx93_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-};
-
-#define DOMAIN_MAX_QOS 4
-
-struct imx93_blk_ctrl_qos {
-       u32 reg;
-       u32 cfg_off;
-       u32 default_prio;
-       u32 cfg_prio;
-};
-
-struct imx93_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       int num_clks;
-       u32 rst_mask;
-       u32 clk_mask;
-       int num_qos;
-       struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
-};
-
-struct imx93_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx93_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct imx93_blk_ctrl *bc;
-};
-
-struct imx93_blk_ctrl_data {
-       const struct imx93_blk_ctrl_domain_data *domains;
-       int num_domains;
-       const char * const *clk_names;
-       int num_clks;
-       const struct regmap_access_table *reg_access_table;
-};
-
-static inline struct imx93_blk_ctrl_domain *
-to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
-}
-
-static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
-{
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-       const struct imx93_blk_ctrl_qos *qos;
-       u32 val, mask;
-       int i;
-
-       for (i = 0; i < data->num_qos; i++) {
-               qos = &data->qos[i];
-
-               mask = PRIO_MASK << qos->cfg_off;
-               mask |= PRIO_MASK << (qos->cfg_off + 4);
-               val = qos->cfg_prio << qos->cfg_off;
-               val |= qos->default_prio << (qos->cfg_off + 4);
-
-               regmap_write_bits(bc->regmap, qos->reg, mask, val);
-
-               dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
-       }
-
-       return 0;
-}
-
-static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable bus clocks\n");
-               return ret;
-       }
-
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-               dev_err(bc->dev, "failed to enable clocks\n");
-               return ret;
-       }
-
-       ret = pm_runtime_get_sync(bc->dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->dev);
-               dev_err(bc->dev, "failed to power up domain\n");
-               goto disable_clk;
-       }
-
-       /* ungate clk */
-       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* release reset */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-
-       dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
-
-       return imx93_blk_ctrl_set_qos(domain);
-
-disable_clk:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-
-       return ret;
-}
-
-static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-
-       dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
-
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       pm_runtime_put(bc->dev);
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-
-       return 0;
-}
-
-static int imx93_blk_ctrl_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
-       struct imx93_blk_ctrl *bc;
-       void __iomem *base;
-       int i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-               .rd_table       = bc_data->reg_access_table,
-               .wr_table       = bc_data->reg_access_table,
-               .max_register   = SZ_4K,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
-                                  sizeof(struct imx93_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = bc_data->num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, bc_data->num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       for (i = 0; i < bc_data->num_clks; i++)
-               bc->clks[i].id = bc_data->clk_names[i];
-       bc->num_clks = bc_data->num_clks;
-
-       ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to get bus clock\n");
-               return ret;
-       }
-
-       for (i = 0; i < bc_data->num_domains; i++) {
-               const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx93_blk_ctrl_power_on;
-               domain->genpd.power_off = imx93_blk_ctrl_power_off;
-               domain->bc = bc;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to init power domain\n");
-                       goto cleanup_pds;
-               }
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       pm_runtime_enable(dev);
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       return 0;
-
-cleanup_pds:
-       for (i--; i >= 0; i--)
-               pm_genpd_remove(&bc->domains[i].genpd);
-
-       return ret;
-}
-
-static int imx93_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-       }
-
-       return 0;
-}
-
-static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
-       [IMX93_MEDIABLK_PD_MIPI_DSI] = {
-               .name = "mediablk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi" },
-               .num_clks = 1,
-               .rst_mask = BIT(11) | BIT(12),
-               .clk_mask = BIT(11) | BIT(12),
-       },
-       [IMX93_MEDIABLK_PD_MIPI_CSI] = {
-               .name = "mediablk-mipi-csi",
-               .clk_names = (const char *[]){ "cam", "csi" },
-               .num_clks = 2,
-               .rst_mask = BIT(9) | BIT(10),
-               .clk_mask = BIT(9) | BIT(10),
-       },
-       [IMX93_MEDIABLK_PD_PXP] = {
-               .name = "mediablk-pxp",
-               .clk_names = (const char *[]){ "pxp" },
-               .num_clks = 1,
-               .rst_mask = BIT(7) | BIT(8),
-               .clk_mask = BIT(7) | BIT(8),
-               .num_qos = 2,
-               .qos = {
-                       {
-                               .reg = PXP_QOS_REG,
-                               .cfg_off = PXP_R_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(6),
-                       }, {
-                               .reg = PXP_QOS_REG,
-                               .cfg_off = PXP_W_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(6),
-                       }
-               }
-       },
-       [IMX93_MEDIABLK_PD_LCDIF] = {
-               .name = "mediablk-lcdif",
-               .clk_names = (const char *[]){ "disp", "lcdif" },
-               .num_clks = 2,
-               .rst_mask = BIT(4) | BIT(5) | BIT(6),
-               .clk_mask = BIT(4) | BIT(5) | BIT(6),
-               .num_qos = 1,
-               .qos = {
-                       {
-                       .reg = LCDIF_QOS_REG,
-                       .cfg_off = LCDIF_CFG_QOS_OFF,
-                       .default_prio = PRIO(3),
-                       .cfg_prio = PRIO(7),
-                       }
-               }
-       },
-       [IMX93_MEDIABLK_PD_ISI] = {
-               .name = "mediablk-isi",
-               .clk_names = (const char *[]){ "isi" },
-               .num_clks = 1,
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .num_qos = 4,
-               .qos = {
-                       {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_Y_W_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_Y_R_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_U_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_V_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }
-               }
-       },
-};
-
-static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
-       regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
-       regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
-       regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
-};
-
-static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
-       .yes_ranges = imx93_media_blk_ctl_yes_ranges,
-       .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
-};
-
-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,
-       .reg_access_table = &imx93_media_blk_ctl_access_table,
-};
-
-static const struct of_device_id imx93_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx93-media-blk-ctrl",
-               .data = &imx93_media_blk_ctl_dev_data
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
-
-static struct platform_driver imx93_blk_ctrl_driver = {
-       .probe = imx93_blk_ctrl_probe,
-       .remove = imx93_blk_ctrl_remove,
-       .driver = {
-               .name = "imx93-blk-ctrl",
-               .of_match_table = imx93_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx93_blk_ctrl_driver);
-
-MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
-MODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/soc/imx/imx93-pd.c b/drivers/soc/imx/imx93-pd.c
deleted file mode 100644 (file)
index 832deee..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2022 NXP
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/of_device.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-
-#define MIX_SLICE_SW_CTRL_OFF          0x20
-#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK        BIT(4)
-#define SLICE_SW_CTRL_PDN_SOFT_MASK    BIT(31)
-
-#define MIX_FUNC_STAT_OFF              0xB4
-
-#define FUNC_STAT_PSW_STAT_MASK                BIT(0)
-#define FUNC_STAT_RST_STAT_MASK                BIT(2)
-#define FUNC_STAT_ISO_STAT_MASK                BIT(4)
-
-struct imx93_power_domain {
-       struct generic_pm_domain genpd;
-       struct device *dev;
-       void __iomem *addr;
-       struct clk_bulk_data *clks;
-       int num_clks;
-       bool init_off;
-};
-
-#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd)
-
-static int imx93_pd_on(struct generic_pm_domain *genpd)
-{
-       struct imx93_power_domain *domain = to_imx93_pd(genpd);
-       void __iomem *addr = domain->addr;
-       u32 val;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-       if (ret) {
-               dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name);
-               return ret;
-       }
-
-       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
-       val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK;
-       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
-
-       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
-                                !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000);
-       if (ret) {
-               dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int imx93_pd_off(struct generic_pm_domain *genpd)
-{
-       struct imx93_power_domain *domain = to_imx93_pd(genpd);
-       void __iomem *addr = domain->addr;
-       int ret;
-       u32 val;
-
-       /* Power off MIX */
-       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
-       val |= SLICE_SW_CTRL_PDN_SOFT_MASK;
-       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
-
-       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
-                                val & FUNC_STAT_PSW_STAT_MASK, 1, 1000);
-       if (ret) {
-               dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val);
-               return ret;
-       }
-
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return 0;
-};
-
-static int imx93_pd_remove(struct platform_device *pdev)
-{
-       struct imx93_power_domain *domain = platform_get_drvdata(pdev);
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-
-       if (!domain->init_off)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       of_genpd_del_provider(np);
-       pm_genpd_remove(&domain->genpd);
-
-       return 0;
-}
-
-static int imx93_pd_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct imx93_power_domain *domain;
-       int ret;
-
-       domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
-       if (!domain)
-               return -ENOMEM;
-
-       domain->addr = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(domain->addr))
-               return PTR_ERR(domain->addr);
-
-       domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks);
-       if (domain->num_clks < 0)
-               return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n");
-
-       domain->genpd.name = dev_name(dev);
-       domain->genpd.power_off = imx93_pd_off;
-       domain->genpd.power_on = imx93_pd_on;
-       domain->dev = dev;
-
-       domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK;
-       /* Just to sync the status of hardware */
-       if (!domain->init_off) {
-               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-               if (ret) {
-                       dev_err(domain->dev, "failed to enable clocks for domain: %s\n",
-                               domain->genpd.name);
-                       return ret;
-               }
-       }
-
-       ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
-       if (ret)
-               goto err_clk_unprepare;
-
-       platform_set_drvdata(pdev, domain);
-
-       ret = of_genpd_add_provider_simple(np, &domain->genpd);
-       if (ret)
-               goto err_genpd_remove;
-
-       return 0;
-
-err_genpd_remove:
-       pm_genpd_remove(&domain->genpd);
-
-err_clk_unprepare:
-       if (!domain->init_off)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return ret;
-}
-
-static const struct of_device_id imx93_pd_ids[] = {
-       { .compatible = "fsl,imx93-src-slice" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, imx93_pd_ids);
-
-static struct platform_driver imx93_power_domain_driver = {
-       .driver = {
-               .name   = "imx93_power_domain",
-               .of_match_table = imx93_pd_ids,
-       },
-       .probe = imx93_pd_probe,
-       .remove = imx93_pd_remove,
-};
-module_platform_driver(imx93_power_domain_driver);
-
-MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
-MODULE_DESCRIPTION("NXP i.MX93 power domain driver");
-MODULE_LICENSE("GPL");