Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 /*
0004  * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/module.h>
0010 #include <linux/of_device.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_domain.h>
0013 #include <linux/pm_runtime.h>
0014 #include <linux/regmap.h>
0015 
0016 #include <dt-bindings/power/imx8mp-power.h>
0017 
0018 #define GPR_REG0        0x0
0019 #define  PCIE_CLOCK_MODULE_EN   BIT(0)
0020 #define  USB_CLOCK_MODULE_EN    BIT(1)
0021 
0022 struct imx8mp_blk_ctrl_domain;
0023 
0024 struct imx8mp_blk_ctrl {
0025     struct device *dev;
0026     struct notifier_block power_nb;
0027     struct device *bus_power_dev;
0028     struct regmap *regmap;
0029     struct imx8mp_blk_ctrl_domain *domains;
0030     struct genpd_onecell_data onecell_data;
0031     void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
0032     void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
0033 };
0034 
0035 struct imx8mp_blk_ctrl_domain_data {
0036     const char *name;
0037     const char * const *clk_names;
0038     int num_clks;
0039     const char *gpc_name;
0040 };
0041 
0042 #define DOMAIN_MAX_CLKS 2
0043 
0044 struct imx8mp_blk_ctrl_domain {
0045     struct generic_pm_domain genpd;
0046     const struct imx8mp_blk_ctrl_domain_data *data;
0047     struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
0048     struct device *power_dev;
0049     struct imx8mp_blk_ctrl *bc;
0050     int id;
0051 };
0052 
0053 struct imx8mp_blk_ctrl_data {
0054     int max_reg;
0055     notifier_fn_t power_notifier_fn;
0056     void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
0057     void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
0058     const struct imx8mp_blk_ctrl_domain_data *domains;
0059     int num_domains;
0060 };
0061 
0062 static inline struct imx8mp_blk_ctrl_domain *
0063 to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
0064 {
0065     return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
0066 }
0067 
0068 static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
0069                       struct imx8mp_blk_ctrl_domain *domain)
0070 {
0071     switch (domain->id) {
0072     case IMX8MP_HSIOBLK_PD_USB:
0073         regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
0074         break;
0075     case IMX8MP_HSIOBLK_PD_PCIE:
0076         regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
0077         break;
0078     default:
0079         break;
0080     }
0081 }
0082 
0083 static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
0084                        struct imx8mp_blk_ctrl_domain *domain)
0085 {
0086     switch (domain->id) {
0087     case IMX8MP_HSIOBLK_PD_USB:
0088         regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
0089         break;
0090     case IMX8MP_HSIOBLK_PD_PCIE:
0091         regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
0092         break;
0093     default:
0094         break;
0095     }
0096 }
0097 
0098 static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
0099                       unsigned long action, void *data)
0100 {
0101     struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
0102                          power_nb);
0103     struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
0104     int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
0105     int ret;
0106 
0107     switch (action) {
0108     case GENPD_NOTIFY_ON:
0109         /*
0110          * enable USB clock for a moment for the power-on ADB handshake
0111          * to proceed
0112          */
0113         ret = clk_bulk_prepare_enable(num_clks, usb_clk);
0114         if (ret)
0115             return NOTIFY_BAD;
0116         regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
0117 
0118         udelay(5);
0119 
0120         regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
0121         clk_bulk_disable_unprepare(num_clks, usb_clk);
0122         break;
0123     case GENPD_NOTIFY_PRE_OFF:
0124         /* enable USB clock for the power-down ADB handshake to work */
0125         ret = clk_bulk_prepare_enable(num_clks, usb_clk);
0126         if (ret)
0127             return NOTIFY_BAD;
0128 
0129         regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
0130         break;
0131     case GENPD_NOTIFY_OFF:
0132         clk_bulk_disable_unprepare(num_clks, usb_clk);
0133         break;
0134     default:
0135         break;
0136     }
0137 
0138     return NOTIFY_OK;
0139 }
0140 
0141 static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
0142     [IMX8MP_HSIOBLK_PD_USB] = {
0143         .name = "hsioblk-usb",
0144         .clk_names = (const char *[]){ "usb" },
0145         .num_clks = 1,
0146         .gpc_name = "usb",
0147     },
0148     [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
0149         .name = "hsioblk-usb-phy1",
0150         .gpc_name = "usb-phy1",
0151     },
0152     [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
0153         .name = "hsioblk-usb-phy2",
0154         .gpc_name = "usb-phy2",
0155     },
0156     [IMX8MP_HSIOBLK_PD_PCIE] = {
0157         .name = "hsioblk-pcie",
0158         .clk_names = (const char *[]){ "pcie" },
0159         .num_clks = 1,
0160         .gpc_name = "pcie",
0161     },
0162     [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
0163         .name = "hsioblk-pcie-phy",
0164         .gpc_name = "pcie-phy",
0165     },
0166 };
0167 
0168 static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
0169     .max_reg = 0x24,
0170     .power_on = imx8mp_hsio_blk_ctrl_power_on,
0171     .power_off = imx8mp_hsio_blk_ctrl_power_off,
0172     .power_notifier_fn = imx8mp_hsio_power_notifier,
0173     .domains = imx8mp_hsio_domain_data,
0174     .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
0175 };
0176 
0177 #define HDMI_RTX_RESET_CTL0 0x20
0178 #define HDMI_RTX_CLK_CTL0   0x40
0179 #define HDMI_RTX_CLK_CTL1   0x50
0180 #define HDMI_RTX_CLK_CTL2   0x60
0181 #define HDMI_RTX_CLK_CTL3   0x70
0182 #define HDMI_RTX_CLK_CTL4   0x80
0183 #define HDMI_TX_CONTROL0    0x200
0184 
0185 static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
0186                       struct imx8mp_blk_ctrl_domain *domain)
0187 {
0188     switch (domain->id) {
0189     case IMX8MP_HDMIBLK_PD_IRQSTEER:
0190         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
0191         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
0192         break;
0193     case IMX8MP_HDMIBLK_PD_LCDIF:
0194         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
0195                 BIT(7) | BIT(16) | BIT(17) | BIT(18) |
0196                 BIT(19) | BIT(20));
0197         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
0198         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
0199                 BIT(4) | BIT(5) | BIT(6));
0200         break;
0201     case IMX8MP_HDMIBLK_PD_PAI:
0202         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
0203         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
0204         break;
0205     case IMX8MP_HDMIBLK_PD_PVI:
0206         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
0207         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
0208         break;
0209     case IMX8MP_HDMIBLK_PD_TRNG:
0210         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
0211         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
0212         break;
0213     case IMX8MP_HDMIBLK_PD_HDMI_TX:
0214         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
0215                 BIT(2) | BIT(4) | BIT(5));
0216         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
0217                 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
0218                 BIT(18) | BIT(19) | BIT(20) | BIT(21));
0219         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
0220                 BIT(7) | BIT(10) | BIT(11));
0221         regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
0222         break;
0223     case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
0224         regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
0225         regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
0226         regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
0227         break;
0228     default:
0229         break;
0230     }
0231 }
0232 
0233 static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
0234                        struct imx8mp_blk_ctrl_domain *domain)
0235 {
0236     switch (domain->id) {
0237     case IMX8MP_HDMIBLK_PD_IRQSTEER:
0238         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
0239         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
0240         break;
0241     case IMX8MP_HDMIBLK_PD_LCDIF:
0242         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
0243                   BIT(4) | BIT(5) | BIT(6));
0244         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
0245         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
0246                   BIT(7) | BIT(16) | BIT(17) | BIT(18) |
0247                   BIT(19) | BIT(20));
0248         break;
0249     case IMX8MP_HDMIBLK_PD_PAI:
0250         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
0251         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
0252         break;
0253     case IMX8MP_HDMIBLK_PD_PVI:
0254         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
0255         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
0256         break;
0257     case IMX8MP_HDMIBLK_PD_TRNG:
0258         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
0259         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
0260         break;
0261     case IMX8MP_HDMIBLK_PD_HDMI_TX:
0262         regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
0263         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
0264                   BIT(7) | BIT(10) | BIT(11));
0265         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
0266                   BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
0267                   BIT(18) | BIT(19) | BIT(20) | BIT(21));
0268         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
0269                   BIT(2) | BIT(4) | BIT(5));
0270         break;
0271     case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
0272         regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
0273         regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
0274         regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
0275         break;
0276     default:
0277         break;
0278     }
0279 }
0280 
0281 static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
0282                       unsigned long action, void *data)
0283 {
0284     struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
0285                          power_nb);
0286 
0287     if (action != GENPD_NOTIFY_ON)
0288         return NOTIFY_OK;
0289 
0290     /*
0291      * Contrary to other blk-ctrls the reset and clock don't clear when the
0292      * power domain is powered down. To ensure the proper reset pulsing,
0293      * first clear them all to asserted state, then enable the bus clocks
0294      * and then release the ADB reset.
0295      */
0296     regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
0297     regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
0298     regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
0299     regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
0300             BIT(0) | BIT(1) | BIT(10));
0301     regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
0302 
0303     /*
0304      * On power up we have no software backchannel to the GPC to
0305      * wait for the ADB handshake to happen, so we just delay for a
0306      * bit. On power down the GPC driver waits for the handshake.
0307      */
0308     udelay(5);
0309 
0310     return NOTIFY_OK;
0311 }
0312 
0313 static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
0314     [IMX8MP_HDMIBLK_PD_IRQSTEER] = {
0315         .name = "hdmiblk-irqsteer",
0316         .clk_names = (const char *[]){ "apb" },
0317         .num_clks = 1,
0318         .gpc_name = "irqsteer",
0319     },
0320     [IMX8MP_HDMIBLK_PD_LCDIF] = {
0321         .name = "hdmiblk-lcdif",
0322         .clk_names = (const char *[]){ "axi", "apb" },
0323         .num_clks = 2,
0324         .gpc_name = "lcdif",
0325     },
0326     [IMX8MP_HDMIBLK_PD_PAI] = {
0327         .name = "hdmiblk-pai",
0328         .clk_names = (const char *[]){ "apb" },
0329         .num_clks = 1,
0330         .gpc_name = "pai",
0331     },
0332     [IMX8MP_HDMIBLK_PD_PVI] = {
0333         .name = "hdmiblk-pvi",
0334         .clk_names = (const char *[]){ "apb" },
0335         .num_clks = 1,
0336         .gpc_name = "pvi",
0337     },
0338     [IMX8MP_HDMIBLK_PD_TRNG] = {
0339         .name = "hdmiblk-trng",
0340         .clk_names = (const char *[]){ "apb" },
0341         .num_clks = 1,
0342         .gpc_name = "trng",
0343     },
0344     [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
0345         .name = "hdmiblk-hdmi-tx",
0346         .clk_names = (const char *[]){ "apb", "ref_266m" },
0347         .num_clks = 2,
0348         .gpc_name = "hdmi-tx",
0349     },
0350     [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
0351         .name = "hdmiblk-hdmi-tx-phy",
0352         .clk_names = (const char *[]){ "apb", "ref_24m" },
0353         .num_clks = 2,
0354         .gpc_name = "hdmi-tx-phy",
0355     },
0356 };
0357 
0358 static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
0359     .max_reg = 0x23c,
0360     .power_on = imx8mp_hdmi_blk_ctrl_power_on,
0361     .power_off = imx8mp_hdmi_blk_ctrl_power_off,
0362     .power_notifier_fn = imx8mp_hdmi_power_notifier,
0363     .domains = imx8mp_hdmi_domain_data,
0364     .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
0365 };
0366 
0367 static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
0368 {
0369     struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
0370     const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
0371     struct imx8mp_blk_ctrl *bc = domain->bc;
0372     int ret;
0373 
0374     /* make sure bus domain is awake */
0375     ret = pm_runtime_resume_and_get(bc->bus_power_dev);
0376     if (ret < 0) {
0377         dev_err(bc->dev, "failed to power up bus domain\n");
0378         return ret;
0379     }
0380 
0381     /* enable upstream clocks */
0382     ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
0383     if (ret) {
0384         dev_err(bc->dev, "failed to enable clocks\n");
0385         goto bus_put;
0386     }
0387 
0388     /* domain specific blk-ctrl manipulation */
0389     bc->power_on(bc, domain);
0390 
0391     /* power up upstream GPC domain */
0392     ret = pm_runtime_resume_and_get(domain->power_dev);
0393     if (ret < 0) {
0394         dev_err(bc->dev, "failed to power up peripheral domain\n");
0395         goto clk_disable;
0396     }
0397 
0398     clk_bulk_disable_unprepare(data->num_clks, domain->clks);
0399 
0400     return 0;
0401 
0402 clk_disable:
0403     clk_bulk_disable_unprepare(data->num_clks, domain->clks);
0404 bus_put:
0405     pm_runtime_put(bc->bus_power_dev);
0406 
0407     return ret;
0408 }
0409 
0410 static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
0411 {
0412     struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
0413     const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
0414     struct imx8mp_blk_ctrl *bc = domain->bc;
0415     int ret;
0416 
0417     ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
0418     if (ret) {
0419         dev_err(bc->dev, "failed to enable clocks\n");
0420         return ret;
0421     }
0422 
0423     /* domain specific blk-ctrl manipulation */
0424     bc->power_off(bc, domain);
0425 
0426     clk_bulk_disable_unprepare(data->num_clks, domain->clks);
0427 
0428     /* power down upstream GPC domain */
0429     pm_runtime_put(domain->power_dev);
0430 
0431     /* allow bus domain to suspend */
0432     pm_runtime_put(bc->bus_power_dev);
0433 
0434     return 0;
0435 }
0436 
0437 static struct generic_pm_domain *
0438 imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
0439 {
0440     struct genpd_onecell_data *onecell_data = data;
0441     unsigned int index = args->args[0];
0442 
0443     if (args->args_count != 1 ||
0444         index >= onecell_data->num_domains)
0445         return ERR_PTR(-EINVAL);
0446 
0447     return onecell_data->domains[index];
0448 }
0449 
0450 static struct lock_class_key blk_ctrl_genpd_lock_class;
0451 
0452 static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
0453 {
0454     const struct imx8mp_blk_ctrl_data *bc_data;
0455     struct device *dev = &pdev->dev;
0456     struct imx8mp_blk_ctrl *bc;
0457     void __iomem *base;
0458     int num_domains, i, ret;
0459 
0460     struct regmap_config regmap_config = {
0461         .reg_bits   = 32,
0462         .val_bits   = 32,
0463         .reg_stride = 4,
0464     };
0465 
0466     bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
0467     if (!bc)
0468         return -ENOMEM;
0469 
0470     bc->dev = dev;
0471 
0472     bc_data = of_device_get_match_data(dev);
0473     num_domains = bc_data->num_domains;
0474 
0475     base = devm_platform_ioremap_resource(pdev, 0);
0476     if (IS_ERR(base))
0477         return PTR_ERR(base);
0478 
0479     regmap_config.max_register = bc_data->max_reg;
0480     bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
0481     if (IS_ERR(bc->regmap))
0482         return dev_err_probe(dev, PTR_ERR(bc->regmap),
0483                      "failed to init regmap\n");
0484 
0485     bc->domains = devm_kcalloc(dev, num_domains,
0486                    sizeof(struct imx8mp_blk_ctrl_domain),
0487                    GFP_KERNEL);
0488     if (!bc->domains)
0489         return -ENOMEM;
0490 
0491     bc->onecell_data.num_domains = num_domains;
0492     bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
0493     bc->onecell_data.domains =
0494         devm_kcalloc(dev, num_domains,
0495                  sizeof(struct generic_pm_domain *), GFP_KERNEL);
0496     if (!bc->onecell_data.domains)
0497         return -ENOMEM;
0498 
0499     bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
0500     if (IS_ERR(bc->bus_power_dev))
0501         return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
0502                      "failed to attach bus power domain\n");
0503 
0504     bc->power_off = bc_data->power_off;
0505     bc->power_on = bc_data->power_on;
0506 
0507     for (i = 0; i < num_domains; i++) {
0508         const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
0509         struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
0510         int j;
0511 
0512         domain->data = data;
0513 
0514         for (j = 0; j < data->num_clks; j++)
0515             domain->clks[j].id = data->clk_names[j];
0516 
0517         ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
0518         if (ret) {
0519             dev_err_probe(dev, ret, "failed to get clock\n");
0520             goto cleanup_pds;
0521         }
0522 
0523         domain->power_dev =
0524             dev_pm_domain_attach_by_name(dev, data->gpc_name);
0525         if (IS_ERR(domain->power_dev)) {
0526             dev_err_probe(dev, PTR_ERR(domain->power_dev),
0527                       "failed to attach power domain %s\n",
0528                       data->gpc_name);
0529             ret = PTR_ERR(domain->power_dev);
0530             goto cleanup_pds;
0531         }
0532         dev_set_name(domain->power_dev, "%s", data->name);
0533 
0534         domain->genpd.name = data->name;
0535         domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
0536         domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
0537         domain->bc = bc;
0538         domain->id = i;
0539 
0540         ret = pm_genpd_init(&domain->genpd, NULL, true);
0541         if (ret) {
0542             dev_err_probe(dev, ret, "failed to init power domain\n");
0543             dev_pm_domain_detach(domain->power_dev, true);
0544             goto cleanup_pds;
0545         }
0546 
0547         /*
0548          * We use runtime PM to trigger power on/off of the upstream GPC
0549          * domain, as a strict hierarchical parent/child power domain
0550          * setup doesn't allow us to meet the sequencing requirements.
0551          * This means we have nested locking of genpd locks, without the
0552          * nesting being visible at the genpd level, so we need a
0553          * separate lock class to make lockdep aware of the fact that
0554          * this are separate domain locks that can be nested without a
0555          * self-deadlock.
0556          */
0557         lockdep_set_class(&domain->genpd.mlock,
0558                   &blk_ctrl_genpd_lock_class);
0559 
0560         bc->onecell_data.domains[i] = &domain->genpd;
0561     }
0562 
0563     ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
0564     if (ret) {
0565         dev_err_probe(dev, ret, "failed to add power domain provider\n");
0566         goto cleanup_pds;
0567     }
0568 
0569     bc->power_nb.notifier_call = bc_data->power_notifier_fn;
0570     ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
0571     if (ret) {
0572         dev_err_probe(dev, ret, "failed to add power notifier\n");
0573         goto cleanup_provider;
0574     }
0575 
0576     dev_set_drvdata(dev, bc);
0577 
0578     return 0;
0579 
0580 cleanup_provider:
0581     of_genpd_del_provider(dev->of_node);
0582 cleanup_pds:
0583     for (i--; i >= 0; i--) {
0584         pm_genpd_remove(&bc->domains[i].genpd);
0585         dev_pm_domain_detach(bc->domains[i].power_dev, true);
0586     }
0587 
0588     dev_pm_domain_detach(bc->bus_power_dev, true);
0589 
0590     return ret;
0591 }
0592 
0593 static int imx8mp_blk_ctrl_remove(struct platform_device *pdev)
0594 {
0595     struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
0596     int i;
0597 
0598     of_genpd_del_provider(pdev->dev.of_node);
0599 
0600     for (i = 0; bc->onecell_data.num_domains; i++) {
0601         struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
0602 
0603         pm_genpd_remove(&domain->genpd);
0604         dev_pm_domain_detach(domain->power_dev, true);
0605     }
0606 
0607     dev_pm_genpd_remove_notifier(bc->bus_power_dev);
0608 
0609     dev_pm_domain_detach(bc->bus_power_dev, true);
0610 
0611     return 0;
0612 }
0613 
0614 #ifdef CONFIG_PM_SLEEP
0615 static int imx8mp_blk_ctrl_suspend(struct device *dev)
0616 {
0617     struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
0618     int ret, i;
0619 
0620     /*
0621      * This may look strange, but is done so the generic PM_SLEEP code
0622      * can power down our domains and more importantly power them up again
0623      * after resume, without tripping over our usage of runtime PM to
0624      * control the upstream GPC domains. Things happen in the right order
0625      * in the system suspend/resume paths due to the device parent/child
0626      * hierarchy.
0627      */
0628     ret = pm_runtime_get_sync(bc->bus_power_dev);
0629     if (ret < 0) {
0630         pm_runtime_put_noidle(bc->bus_power_dev);
0631         return ret;
0632     }
0633 
0634     for (i = 0; i < bc->onecell_data.num_domains; i++) {
0635         struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
0636 
0637         ret = pm_runtime_get_sync(domain->power_dev);
0638         if (ret < 0) {
0639             pm_runtime_put_noidle(domain->power_dev);
0640             goto out_fail;
0641         }
0642     }
0643 
0644     return 0;
0645 
0646 out_fail:
0647     for (i--; i >= 0; i--)
0648         pm_runtime_put(bc->domains[i].power_dev);
0649 
0650     pm_runtime_put(bc->bus_power_dev);
0651 
0652     return ret;
0653 }
0654 
0655 static int imx8mp_blk_ctrl_resume(struct device *dev)
0656 {
0657     struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
0658     int i;
0659 
0660     for (i = 0; i < bc->onecell_data.num_domains; i++)
0661         pm_runtime_put(bc->domains[i].power_dev);
0662 
0663     pm_runtime_put(bc->bus_power_dev);
0664 
0665     return 0;
0666 }
0667 #endif
0668 
0669 static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
0670     SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
0671                 imx8mp_blk_ctrl_resume)
0672 };
0673 
0674 static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
0675     {
0676         .compatible = "fsl,imx8mp-hsio-blk-ctrl",
0677         .data = &imx8mp_hsio_blk_ctl_dev_data,
0678     }, {
0679         .compatible = "fsl,imx8mp-hdmi-blk-ctrl",
0680         .data = &imx8mp_hdmi_blk_ctl_dev_data,
0681     }, {
0682         /* Sentinel */
0683     }
0684 };
0685 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
0686 
0687 static struct platform_driver imx8mp_blk_ctrl_driver = {
0688     .probe = imx8mp_blk_ctrl_probe,
0689     .remove = imx8mp_blk_ctrl_remove,
0690     .driver = {
0691         .name = "imx8mp-blk-ctrl",
0692         .pm = &imx8mp_blk_ctrl_pm_ops,
0693         .of_match_table = imx8mp_blk_ctrl_of_match,
0694     },
0695 };
0696 module_platform_driver(imx8mp_blk_ctrl_driver);