Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 /*
0004  * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
0005  */
0006 
0007 #include <linux/device.h>
0008 #include <linux/module.h>
0009 #include <linux/of_device.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/pm_domain.h>
0012 #include <linux/pm_runtime.h>
0013 #include <linux/regmap.h>
0014 #include <linux/clk.h>
0015 
0016 #include <dt-bindings/power/imx8mm-power.h>
0017 #include <dt-bindings/power/imx8mn-power.h>
0018 #include <dt-bindings/power/imx8mp-power.h>
0019 #include <dt-bindings/power/imx8mq-power.h>
0020 
0021 #define BLK_SFT_RSTN    0x0
0022 #define BLK_CLK_EN  0x4
0023 #define BLK_MIPI_RESET_DIV  0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
0024 
0025 struct imx8m_blk_ctrl_domain;
0026 
0027 struct imx8m_blk_ctrl {
0028     struct device *dev;
0029     struct notifier_block power_nb;
0030     struct device *bus_power_dev;
0031     struct regmap *regmap;
0032     struct imx8m_blk_ctrl_domain *domains;
0033     struct genpd_onecell_data onecell_data;
0034 };
0035 
0036 struct imx8m_blk_ctrl_domain_data {
0037     const char *name;
0038     const char * const *clk_names;
0039     int num_clks;
0040     const char *gpc_name;
0041     u32 rst_mask;
0042     u32 clk_mask;
0043 
0044     /*
0045      * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
0046      * which is used to control the reset for the MIPI Phy.
0047      * Since it's only present in certain circumstances,
0048      * an if-statement should be used before setting and clearing this
0049      * register.
0050      */
0051     u32 mipi_phy_rst_mask;
0052 };
0053 
0054 #define DOMAIN_MAX_CLKS 4
0055 
0056 struct imx8m_blk_ctrl_domain {
0057     struct generic_pm_domain genpd;
0058     const struct imx8m_blk_ctrl_domain_data *data;
0059     struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
0060     struct device *power_dev;
0061     struct imx8m_blk_ctrl *bc;
0062 };
0063 
0064 struct imx8m_blk_ctrl_data {
0065     int max_reg;
0066     notifier_fn_t power_notifier_fn;
0067     const struct imx8m_blk_ctrl_domain_data *domains;
0068     int num_domains;
0069 };
0070 
0071 static inline struct imx8m_blk_ctrl_domain *
0072 to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
0073 {
0074     return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
0075 }
0076 
0077 static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
0078 {
0079     struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
0080     const struct imx8m_blk_ctrl_domain_data *data = domain->data;
0081     struct imx8m_blk_ctrl *bc = domain->bc;
0082     int ret;
0083 
0084     /* make sure bus domain is awake */
0085     ret = pm_runtime_get_sync(bc->bus_power_dev);
0086     if (ret < 0) {
0087         pm_runtime_put_noidle(bc->bus_power_dev);
0088         dev_err(bc->dev, "failed to power up bus domain\n");
0089         return ret;
0090     }
0091 
0092     /* put devices into reset */
0093     regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
0094     if (data->mipi_phy_rst_mask)
0095         regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
0096 
0097     /* enable upstream and blk-ctrl clocks to allow reset to propagate */
0098     ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
0099     if (ret) {
0100         dev_err(bc->dev, "failed to enable clocks\n");
0101         goto bus_put;
0102     }
0103     regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
0104 
0105     /* power up upstream GPC domain */
0106     ret = pm_runtime_get_sync(domain->power_dev);
0107     if (ret < 0) {
0108         dev_err(bc->dev, "failed to power up peripheral domain\n");
0109         goto clk_disable;
0110     }
0111 
0112     /* wait for reset to propagate */
0113     udelay(5);
0114 
0115     /* release reset */
0116     regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
0117     if (data->mipi_phy_rst_mask)
0118         regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
0119 
0120     /* disable upstream clocks */
0121     clk_bulk_disable_unprepare(data->num_clks, domain->clks);
0122 
0123     return 0;
0124 
0125 clk_disable:
0126     clk_bulk_disable_unprepare(data->num_clks, domain->clks);
0127 bus_put:
0128     pm_runtime_put(bc->bus_power_dev);
0129 
0130     return ret;
0131 }
0132 
0133 static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
0134 {
0135     struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
0136     const struct imx8m_blk_ctrl_domain_data *data = domain->data;
0137     struct imx8m_blk_ctrl *bc = domain->bc;
0138 
0139     /* put devices into reset and disable clocks */
0140     if (data->mipi_phy_rst_mask)
0141         regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
0142 
0143     regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
0144     regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
0145 
0146     /* power down upstream GPC domain */
0147     pm_runtime_put(domain->power_dev);
0148 
0149     /* allow bus domain to suspend */
0150     pm_runtime_put(bc->bus_power_dev);
0151 
0152     return 0;
0153 }
0154 
0155 static struct generic_pm_domain *
0156 imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
0157 {
0158     struct genpd_onecell_data *onecell_data = data;
0159     unsigned int index = args->args[0];
0160 
0161     if (args->args_count != 1 ||
0162         index >= onecell_data->num_domains)
0163         return ERR_PTR(-EINVAL);
0164 
0165     return onecell_data->domains[index];
0166 }
0167 
0168 static struct lock_class_key blk_ctrl_genpd_lock_class;
0169 
0170 static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
0171 {
0172     const struct imx8m_blk_ctrl_data *bc_data;
0173     struct device *dev = &pdev->dev;
0174     struct imx8m_blk_ctrl *bc;
0175     void __iomem *base;
0176     int i, ret;
0177 
0178     struct regmap_config regmap_config = {
0179         .reg_bits   = 32,
0180         .val_bits   = 32,
0181         .reg_stride = 4,
0182     };
0183 
0184     bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
0185     if (!bc)
0186         return -ENOMEM;
0187 
0188     bc->dev = dev;
0189 
0190     bc_data = of_device_get_match_data(dev);
0191 
0192     base = devm_platform_ioremap_resource(pdev, 0);
0193     if (IS_ERR(base))
0194         return PTR_ERR(base);
0195 
0196     regmap_config.max_register = bc_data->max_reg;
0197     bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
0198     if (IS_ERR(bc->regmap))
0199         return dev_err_probe(dev, PTR_ERR(bc->regmap),
0200                      "failed to init regmap\n");
0201 
0202     bc->domains = devm_kcalloc(dev, bc_data->num_domains,
0203                    sizeof(struct imx8m_blk_ctrl_domain),
0204                    GFP_KERNEL);
0205     if (!bc->domains)
0206         return -ENOMEM;
0207 
0208     bc->onecell_data.num_domains = bc_data->num_domains;
0209     bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
0210     bc->onecell_data.domains =
0211         devm_kcalloc(dev, bc_data->num_domains,
0212                  sizeof(struct generic_pm_domain *), GFP_KERNEL);
0213     if (!bc->onecell_data.domains)
0214         return -ENOMEM;
0215 
0216     bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
0217     if (IS_ERR(bc->bus_power_dev))
0218         return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
0219                      "failed to attach power domain \"bus\"\n");
0220 
0221     for (i = 0; i < bc_data->num_domains; i++) {
0222         const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
0223         struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
0224         int j;
0225 
0226         domain->data = data;
0227 
0228         for (j = 0; j < data->num_clks; j++)
0229             domain->clks[j].id = data->clk_names[j];
0230 
0231         ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
0232         if (ret) {
0233             dev_err_probe(dev, ret, "failed to get clock\n");
0234             goto cleanup_pds;
0235         }
0236 
0237         domain->power_dev =
0238             dev_pm_domain_attach_by_name(dev, data->gpc_name);
0239         if (IS_ERR(domain->power_dev)) {
0240             dev_err_probe(dev, PTR_ERR(domain->power_dev),
0241                       "failed to attach power domain \"%s\"\n",
0242                       data->gpc_name);
0243             ret = PTR_ERR(domain->power_dev);
0244             goto cleanup_pds;
0245         }
0246 
0247         domain->genpd.name = data->name;
0248         domain->genpd.power_on = imx8m_blk_ctrl_power_on;
0249         domain->genpd.power_off = imx8m_blk_ctrl_power_off;
0250         domain->bc = bc;
0251 
0252         ret = pm_genpd_init(&domain->genpd, NULL, true);
0253         if (ret) {
0254             dev_err_probe(dev, ret,
0255                       "failed to init power domain \"%s\"\n",
0256                       data->gpc_name);
0257             dev_pm_domain_detach(domain->power_dev, true);
0258             goto cleanup_pds;
0259         }
0260 
0261         /*
0262          * We use runtime PM to trigger power on/off of the upstream GPC
0263          * domain, as a strict hierarchical parent/child power domain
0264          * setup doesn't allow us to meet the sequencing requirements.
0265          * This means we have nested locking of genpd locks, without the
0266          * nesting being visible at the genpd level, so we need a
0267          * separate lock class to make lockdep aware of the fact that
0268          * this are separate domain locks that can be nested without a
0269          * self-deadlock.
0270          */
0271         lockdep_set_class(&domain->genpd.mlock,
0272                   &blk_ctrl_genpd_lock_class);
0273 
0274         bc->onecell_data.domains[i] = &domain->genpd;
0275     }
0276 
0277     ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
0278     if (ret) {
0279         dev_err_probe(dev, ret, "failed to add power domain provider\n");
0280         goto cleanup_pds;
0281     }
0282 
0283     bc->power_nb.notifier_call = bc_data->power_notifier_fn;
0284     ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
0285     if (ret) {
0286         dev_err_probe(dev, ret, "failed to add power notifier\n");
0287         goto cleanup_provider;
0288     }
0289 
0290     dev_set_drvdata(dev, bc);
0291 
0292     return 0;
0293 
0294 cleanup_provider:
0295     of_genpd_del_provider(dev->of_node);
0296 cleanup_pds:
0297     for (i--; i >= 0; i--) {
0298         pm_genpd_remove(&bc->domains[i].genpd);
0299         dev_pm_domain_detach(bc->domains[i].power_dev, true);
0300     }
0301 
0302     dev_pm_domain_detach(bc->bus_power_dev, true);
0303 
0304     return ret;
0305 }
0306 
0307 static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
0308 {
0309     struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
0310     int i;
0311 
0312     of_genpd_del_provider(pdev->dev.of_node);
0313 
0314     for (i = 0; bc->onecell_data.num_domains; i++) {
0315         struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
0316 
0317         pm_genpd_remove(&domain->genpd);
0318         dev_pm_domain_detach(domain->power_dev, true);
0319     }
0320 
0321     dev_pm_genpd_remove_notifier(bc->bus_power_dev);
0322 
0323     dev_pm_domain_detach(bc->bus_power_dev, true);
0324 
0325     return 0;
0326 }
0327 
0328 #ifdef CONFIG_PM_SLEEP
0329 static int imx8m_blk_ctrl_suspend(struct device *dev)
0330 {
0331     struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
0332     int ret, i;
0333 
0334     /*
0335      * This may look strange, but is done so the generic PM_SLEEP code
0336      * can power down our domains and more importantly power them up again
0337      * after resume, without tripping over our usage of runtime PM to
0338      * control the upstream GPC domains. Things happen in the right order
0339      * in the system suspend/resume paths due to the device parent/child
0340      * hierarchy.
0341      */
0342     ret = pm_runtime_get_sync(bc->bus_power_dev);
0343     if (ret < 0) {
0344         pm_runtime_put_noidle(bc->bus_power_dev);
0345         return ret;
0346     }
0347 
0348     for (i = 0; i < bc->onecell_data.num_domains; i++) {
0349         struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
0350 
0351         ret = pm_runtime_get_sync(domain->power_dev);
0352         if (ret < 0) {
0353             pm_runtime_put_noidle(domain->power_dev);
0354             goto out_fail;
0355         }
0356     }
0357 
0358     return 0;
0359 
0360 out_fail:
0361     for (i--; i >= 0; i--)
0362         pm_runtime_put(bc->domains[i].power_dev);
0363 
0364     pm_runtime_put(bc->bus_power_dev);
0365 
0366     return ret;
0367 }
0368 
0369 static int imx8m_blk_ctrl_resume(struct device *dev)
0370 {
0371     struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
0372     int i;
0373 
0374     for (i = 0; i < bc->onecell_data.num_domains; i++)
0375         pm_runtime_put(bc->domains[i].power_dev);
0376 
0377     pm_runtime_put(bc->bus_power_dev);
0378 
0379     return 0;
0380 }
0381 #endif
0382 
0383 static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
0384     SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
0385 };
0386 
0387 static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
0388                      unsigned long action, void *data)
0389 {
0390     struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
0391                          power_nb);
0392 
0393     if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
0394         return NOTIFY_OK;
0395 
0396     /*
0397      * The ADB in the VPUMIX domain has no separate reset and clock
0398      * enable bits, but is ungated together with the VPU clocks. To
0399      * allow the handshake with the GPC to progress we put the VPUs
0400      * in reset and ungate the clocks.
0401      */
0402     regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
0403     regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
0404 
0405     if (action == GENPD_NOTIFY_ON) {
0406         /*
0407          * On power up we have no software backchannel to the GPC to
0408          * wait for the ADB handshake to happen, so we just delay for a
0409          * bit. On power down the GPC driver waits for the handshake.
0410          */
0411         udelay(5);
0412 
0413         /* set "fuse" bits to enable the VPUs */
0414         regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
0415         regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
0416         regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
0417         regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
0418     }
0419 
0420     return NOTIFY_OK;
0421 }
0422 
0423 static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
0424     [IMX8MM_VPUBLK_PD_G1] = {
0425         .name = "vpublk-g1",
0426         .clk_names = (const char *[]){ "g1", },
0427         .num_clks = 1,
0428         .gpc_name = "g1",
0429         .rst_mask = BIT(1),
0430         .clk_mask = BIT(1),
0431     },
0432     [IMX8MM_VPUBLK_PD_G2] = {
0433         .name = "vpublk-g2",
0434         .clk_names = (const char *[]){ "g2", },
0435         .num_clks = 1,
0436         .gpc_name = "g2",
0437         .rst_mask = BIT(0),
0438         .clk_mask = BIT(0),
0439     },
0440     [IMX8MM_VPUBLK_PD_H1] = {
0441         .name = "vpublk-h1",
0442         .clk_names = (const char *[]){ "h1", },
0443         .num_clks = 1,
0444         .gpc_name = "h1",
0445         .rst_mask = BIT(2),
0446         .clk_mask = BIT(2),
0447     },
0448 };
0449 
0450 static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
0451     .max_reg = 0x18,
0452     .power_notifier_fn = imx8mm_vpu_power_notifier,
0453     .domains = imx8mm_vpu_blk_ctl_domain_data,
0454     .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
0455 };
0456 
0457 static int imx8mm_disp_power_notifier(struct notifier_block *nb,
0458                       unsigned long action, void *data)
0459 {
0460     struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
0461                          power_nb);
0462 
0463     if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
0464         return NOTIFY_OK;
0465 
0466     /* Enable bus clock and deassert bus reset */
0467     regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
0468     regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
0469 
0470     /*
0471      * On power up we have no software backchannel to the GPC to
0472      * wait for the ADB handshake to happen, so we just delay for a
0473      * bit. On power down the GPC driver waits for the handshake.
0474      */
0475     if (action == GENPD_NOTIFY_ON)
0476         udelay(5);
0477 
0478 
0479     return NOTIFY_OK;
0480 }
0481 
0482 static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
0483     [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
0484         .name = "dispblk-csi-bridge",
0485         .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
0486                            "csi-bridge-core", },
0487         .num_clks = 3,
0488         .gpc_name = "csi-bridge",
0489         .rst_mask = BIT(0) | BIT(1) | BIT(2),
0490         .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
0491     },
0492     [IMX8MM_DISPBLK_PD_LCDIF] = {
0493         .name = "dispblk-lcdif",
0494         .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
0495         .num_clks = 3,
0496         .gpc_name = "lcdif",
0497         .clk_mask = BIT(6) | BIT(7),
0498     },
0499     [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
0500         .name = "dispblk-mipi-dsi",
0501         .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
0502         .num_clks = 2,
0503         .gpc_name = "mipi-dsi",
0504         .rst_mask = BIT(5),
0505         .clk_mask = BIT(8) | BIT(9),
0506         .mipi_phy_rst_mask = BIT(17),
0507     },
0508     [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
0509         .name = "dispblk-mipi-csi",
0510         .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
0511         .num_clks = 2,
0512         .gpc_name = "mipi-csi",
0513         .rst_mask = BIT(3) | BIT(4),
0514         .clk_mask = BIT(10) | BIT(11),
0515         .mipi_phy_rst_mask = BIT(16),
0516     },
0517 };
0518 
0519 static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
0520     .max_reg = 0x2c,
0521     .power_notifier_fn = imx8mm_disp_power_notifier,
0522     .domains = imx8mm_disp_blk_ctl_domain_data,
0523     .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
0524 };
0525 
0526 
0527 static int imx8mn_disp_power_notifier(struct notifier_block *nb,
0528                       unsigned long action, void *data)
0529 {
0530     struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
0531                          power_nb);
0532 
0533     if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
0534         return NOTIFY_OK;
0535 
0536     /* Enable bus clock and deassert bus reset */
0537     regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
0538     regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
0539 
0540     /*
0541      * On power up we have no software backchannel to the GPC to
0542      * wait for the ADB handshake to happen, so we just delay for a
0543      * bit. On power down the GPC driver waits for the handshake.
0544      */
0545     if (action == GENPD_NOTIFY_ON)
0546         udelay(5);
0547 
0548 
0549     return NOTIFY_OK;
0550 }
0551 
0552 static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
0553     [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
0554         .name = "dispblk-mipi-dsi",
0555         .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
0556         .num_clks = 2,
0557         .gpc_name = "mipi-dsi",
0558         .rst_mask = BIT(0) | BIT(1),
0559         .clk_mask = BIT(0) | BIT(1),
0560         .mipi_phy_rst_mask = BIT(17),
0561     },
0562     [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
0563         .name = "dispblk-mipi-csi",
0564         .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
0565         .num_clks = 2,
0566         .gpc_name = "mipi-csi",
0567         .rst_mask = BIT(2) | BIT(3),
0568         .clk_mask = BIT(2) | BIT(3),
0569         .mipi_phy_rst_mask = BIT(16),
0570     },
0571     [IMX8MN_DISPBLK_PD_LCDIF] = {
0572         .name = "dispblk-lcdif",
0573         .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
0574         .num_clks = 3,
0575         .gpc_name = "lcdif",
0576         .rst_mask = BIT(4) | BIT(5),
0577         .clk_mask = BIT(4) | BIT(5),
0578     },
0579     [IMX8MN_DISPBLK_PD_ISI] = {
0580         .name = "dispblk-isi",
0581         .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
0582                         "disp_apb_root"},
0583         .num_clks = 4,
0584         .gpc_name = "isi",
0585         .rst_mask = BIT(6) | BIT(7),
0586         .clk_mask = BIT(6) | BIT(7),
0587     },
0588 };
0589 
0590 static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
0591     .max_reg = 0x84,
0592     .power_notifier_fn = imx8mn_disp_power_notifier,
0593     .domains = imx8mn_disp_blk_ctl_domain_data,
0594     .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
0595 };
0596 
0597 static int imx8mp_media_power_notifier(struct notifier_block *nb,
0598                 unsigned long action, void *data)
0599 {
0600     struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
0601                          power_nb);
0602 
0603     if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
0604         return NOTIFY_OK;
0605 
0606     /* Enable bus clock and deassert bus reset */
0607     regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
0608     regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
0609 
0610     /*
0611      * On power up we have no software backchannel to the GPC to
0612      * wait for the ADB handshake to happen, so we just delay for a
0613      * bit. On power down the GPC driver waits for the handshake.
0614      */
0615     if (action == GENPD_NOTIFY_ON)
0616         udelay(5);
0617 
0618     return NOTIFY_OK;
0619 }
0620 
0621 /*
0622  * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
0623  * section 13.2.2, 13.2.3
0624  * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
0625  */
0626 static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
0627     [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
0628         .name = "mediablk-mipi-dsi-1",
0629         .clk_names = (const char *[]){ "apb", "phy", },
0630         .num_clks = 2,
0631         .gpc_name = "mipi-dsi1",
0632         .rst_mask = BIT(0) | BIT(1),
0633         .clk_mask = BIT(0) | BIT(1),
0634         .mipi_phy_rst_mask = BIT(17),
0635     },
0636     [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
0637         .name = "mediablk-mipi-csi2-1",
0638         .clk_names = (const char *[]){ "apb", "cam1" },
0639         .num_clks = 2,
0640         .gpc_name = "mipi-csi1",
0641         .rst_mask = BIT(2) | BIT(3),
0642         .clk_mask = BIT(2) | BIT(3),
0643         .mipi_phy_rst_mask = BIT(16),
0644     },
0645     [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
0646         .name = "mediablk-lcdif-1",
0647         .clk_names = (const char *[]){ "disp1", "apb", "axi", },
0648         .num_clks = 3,
0649         .gpc_name = "lcdif1",
0650         .rst_mask = BIT(4) | BIT(5) | BIT(23),
0651         .clk_mask = BIT(4) | BIT(5) | BIT(23),
0652     },
0653     [IMX8MP_MEDIABLK_PD_ISI] = {
0654         .name = "mediablk-isi",
0655         .clk_names = (const char *[]){ "axi", "apb" },
0656         .num_clks = 2,
0657         .gpc_name = "isi",
0658         .rst_mask = BIT(6) | BIT(7),
0659         .clk_mask = BIT(6) | BIT(7),
0660     },
0661     [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
0662         .name = "mediablk-mipi-csi2-2",
0663         .clk_names = (const char *[]){ "apb", "cam2" },
0664         .num_clks = 2,
0665         .gpc_name = "mipi-csi2",
0666         .rst_mask = BIT(9) | BIT(10),
0667         .clk_mask = BIT(9) | BIT(10),
0668         .mipi_phy_rst_mask = BIT(30),
0669     },
0670     [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
0671         .name = "mediablk-lcdif-2",
0672         .clk_names = (const char *[]){ "disp2", "apb", "axi", },
0673         .num_clks = 3,
0674         .gpc_name = "lcdif2",
0675         .rst_mask = BIT(11) | BIT(12) | BIT(24),
0676         .clk_mask = BIT(11) | BIT(12) | BIT(24),
0677     },
0678     [IMX8MP_MEDIABLK_PD_ISP] = {
0679         .name = "mediablk-isp",
0680         .clk_names = (const char *[]){ "isp", "axi", "apb" },
0681         .num_clks = 3,
0682         .gpc_name = "isp",
0683         .rst_mask = BIT(16) | BIT(17) | BIT(18),
0684         .clk_mask = BIT(16) | BIT(17) | BIT(18),
0685     },
0686     [IMX8MP_MEDIABLK_PD_DWE] = {
0687         .name = "mediablk-dwe",
0688         .clk_names = (const char *[]){ "axi", "apb" },
0689         .num_clks = 2,
0690         .gpc_name = "dwe",
0691         .rst_mask = BIT(19) | BIT(20) | BIT(21),
0692         .clk_mask = BIT(19) | BIT(20) | BIT(21),
0693     },
0694     [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
0695         .name = "mediablk-mipi-dsi-2",
0696         .clk_names = (const char *[]){ "phy", },
0697         .num_clks = 1,
0698         .gpc_name = "mipi-dsi2",
0699         .rst_mask = BIT(22),
0700         .clk_mask = BIT(22),
0701         .mipi_phy_rst_mask = BIT(29),
0702     },
0703 };
0704 
0705 static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
0706     .max_reg = 0x138,
0707     .power_notifier_fn = imx8mp_media_power_notifier,
0708     .domains = imx8mp_media_blk_ctl_domain_data,
0709     .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
0710 };
0711 
0712 static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
0713                      unsigned long action, void *data)
0714 {
0715     struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
0716                          power_nb);
0717 
0718     if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
0719         return NOTIFY_OK;
0720 
0721     /*
0722      * The ADB in the VPUMIX domain has no separate reset and clock
0723      * enable bits, but is ungated and reset together with the VPUs. The
0724      * reset and clock enable inputs to the ADB is a logical OR of the
0725      * VPU bits. In order to set the G2 fuse bits, the G2 clock must
0726      * also be enabled.
0727      */
0728     regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
0729     regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
0730 
0731     if (action == GENPD_NOTIFY_ON) {
0732         /*
0733          * On power up we have no software backchannel to the GPC to
0734          * wait for the ADB handshake to happen, so we just delay for a
0735          * bit. On power down the GPC driver waits for the handshake.
0736          */
0737         udelay(5);
0738 
0739         /* set "fuse" bits to enable the VPUs */
0740         regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
0741         regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
0742         regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
0743     }
0744 
0745     return NOTIFY_OK;
0746 }
0747 
0748 static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
0749     [IMX8MQ_VPUBLK_PD_G1] = {
0750         .name = "vpublk-g1",
0751         .clk_names = (const char *[]){ "g1", },
0752         .num_clks = 1,
0753         .gpc_name = "g1",
0754         .rst_mask = BIT(1),
0755         .clk_mask = BIT(1),
0756     },
0757     [IMX8MQ_VPUBLK_PD_G2] = {
0758         .name = "vpublk-g2",
0759         .clk_names = (const char *[]){ "g2", },
0760         .num_clks = 1,
0761         .gpc_name = "g2",
0762         .rst_mask = BIT(0),
0763         .clk_mask = BIT(0),
0764     },
0765 };
0766 
0767 static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
0768     .max_reg = 0x14,
0769     .power_notifier_fn = imx8mq_vpu_power_notifier,
0770     .domains = imx8mq_vpu_blk_ctl_domain_data,
0771     .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
0772 };
0773 
0774 static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
0775     {
0776         .compatible = "fsl,imx8mm-vpu-blk-ctrl",
0777         .data = &imx8mm_vpu_blk_ctl_dev_data
0778     }, {
0779         .compatible = "fsl,imx8mm-disp-blk-ctrl",
0780         .data = &imx8mm_disp_blk_ctl_dev_data
0781     }, {
0782         .compatible = "fsl,imx8mn-disp-blk-ctrl",
0783         .data = &imx8mn_disp_blk_ctl_dev_data
0784     }, {
0785         .compatible = "fsl,imx8mp-media-blk-ctrl",
0786         .data = &imx8mp_media_blk_ctl_dev_data
0787     }, {
0788         .compatible = "fsl,imx8mq-vpu-blk-ctrl",
0789         .data = &imx8mq_vpu_blk_ctl_dev_data
0790     }, {
0791         /* Sentinel */
0792     }
0793 };
0794 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
0795 
0796 static struct platform_driver imx8m_blk_ctrl_driver = {
0797     .probe = imx8m_blk_ctrl_probe,
0798     .remove = imx8m_blk_ctrl_remove,
0799     .driver = {
0800         .name = "imx8m-blk-ctrl",
0801         .pm = &imx8m_blk_ctrl_pm_ops,
0802         .of_match_table = imx8m_blk_ctrl_of_match,
0803     },
0804 };
0805 module_platform_driver(imx8m_blk_ctrl_driver);