imx8mp-blk-ctrl.c (19663B)
1// SPDX-License-Identifier: GPL-2.0+ 2 3/* 4 * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de> 5 */ 6 7#include <linux/clk.h> 8#include <linux/device.h> 9#include <linux/module.h> 10#include <linux/of_device.h> 11#include <linux/platform_device.h> 12#include <linux/pm_domain.h> 13#include <linux/pm_runtime.h> 14#include <linux/regmap.h> 15 16#include <dt-bindings/power/imx8mp-power.h> 17 18#define GPR_REG0 0x0 19#define PCIE_CLOCK_MODULE_EN BIT(0) 20#define USB_CLOCK_MODULE_EN BIT(1) 21 22struct imx8mp_blk_ctrl_domain; 23 24struct imx8mp_blk_ctrl { 25 struct device *dev; 26 struct notifier_block power_nb; 27 struct device *bus_power_dev; 28 struct regmap *regmap; 29 struct imx8mp_blk_ctrl_domain *domains; 30 struct genpd_onecell_data onecell_data; 31 void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); 32 void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); 33}; 34 35struct imx8mp_blk_ctrl_domain_data { 36 const char *name; 37 const char * const *clk_names; 38 int num_clks; 39 const char *gpc_name; 40}; 41 42#define DOMAIN_MAX_CLKS 2 43 44struct imx8mp_blk_ctrl_domain { 45 struct generic_pm_domain genpd; 46 const struct imx8mp_blk_ctrl_domain_data *data; 47 struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; 48 struct device *power_dev; 49 struct imx8mp_blk_ctrl *bc; 50 int id; 51}; 52 53struct imx8mp_blk_ctrl_data { 54 int max_reg; 55 notifier_fn_t power_notifier_fn; 56 void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); 57 void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); 58 const struct imx8mp_blk_ctrl_domain_data *domains; 59 int num_domains; 60}; 61 62static inline struct imx8mp_blk_ctrl_domain * 63to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd) 64{ 65 return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd); 66} 67 68static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, 69 struct imx8mp_blk_ctrl_domain *domain) 70{ 71 switch (domain->id) { 72 case IMX8MP_HSIOBLK_PD_USB: 73 regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); 74 break; 75 case IMX8MP_HSIOBLK_PD_PCIE: 76 regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); 77 break; 78 default: 79 break; 80 } 81} 82 83static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, 84 struct imx8mp_blk_ctrl_domain *domain) 85{ 86 switch (domain->id) { 87 case IMX8MP_HSIOBLK_PD_USB: 88 regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); 89 break; 90 case IMX8MP_HSIOBLK_PD_PCIE: 91 regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); 92 break; 93 default: 94 break; 95 } 96} 97 98static int imx8mp_hsio_power_notifier(struct notifier_block *nb, 99 unsigned long action, void *data) 100{ 101 struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl, 102 power_nb); 103 struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks; 104 int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks; 105 int ret; 106 107 switch (action) { 108 case GENPD_NOTIFY_ON: 109 /* 110 * enable USB clock for a moment for the power-on ADB handshake 111 * to proceed 112 */ 113 ret = clk_bulk_prepare_enable(num_clks, usb_clk); 114 if (ret) 115 return NOTIFY_BAD; 116 regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); 117 118 udelay(5); 119 120 regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); 121 clk_bulk_disable_unprepare(num_clks, usb_clk); 122 break; 123 case GENPD_NOTIFY_PRE_OFF: 124 /* enable USB clock for the power-down ADB handshake to work */ 125 ret = clk_bulk_prepare_enable(num_clks, usb_clk); 126 if (ret) 127 return NOTIFY_BAD; 128 129 regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); 130 break; 131 case GENPD_NOTIFY_OFF: 132 clk_bulk_disable_unprepare(num_clks, usb_clk); 133 break; 134 default: 135 break; 136 } 137 138 return NOTIFY_OK; 139} 140 141static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = { 142 [IMX8MP_HSIOBLK_PD_USB] = { 143 .name = "hsioblk-usb", 144 .clk_names = (const char *[]){ "usb" }, 145 .num_clks = 1, 146 .gpc_name = "usb", 147 }, 148 [IMX8MP_HSIOBLK_PD_USB_PHY1] = { 149 .name = "hsioblk-usb-phy1", 150 .gpc_name = "usb-phy1", 151 }, 152 [IMX8MP_HSIOBLK_PD_USB_PHY2] = { 153 .name = "hsioblk-usb-phy2", 154 .gpc_name = "usb-phy2", 155 }, 156 [IMX8MP_HSIOBLK_PD_PCIE] = { 157 .name = "hsioblk-pcie", 158 .clk_names = (const char *[]){ "pcie" }, 159 .num_clks = 1, 160 .gpc_name = "pcie", 161 }, 162 [IMX8MP_HSIOBLK_PD_PCIE_PHY] = { 163 .name = "hsioblk-pcie-phy", 164 .gpc_name = "pcie-phy", 165 }, 166}; 167 168static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = { 169 .max_reg = 0x24, 170 .power_on = imx8mp_hsio_blk_ctrl_power_on, 171 .power_off = imx8mp_hsio_blk_ctrl_power_off, 172 .power_notifier_fn = imx8mp_hsio_power_notifier, 173 .domains = imx8mp_hsio_domain_data, 174 .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data), 175}; 176 177#define HDMI_RTX_RESET_CTL0 0x20 178#define HDMI_RTX_CLK_CTL0 0x40 179#define HDMI_RTX_CLK_CTL1 0x50 180#define HDMI_RTX_CLK_CTL2 0x60 181#define HDMI_RTX_CLK_CTL3 0x70 182#define HDMI_RTX_CLK_CTL4 0x80 183#define HDMI_TX_CONTROL0 0x200 184 185static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, 186 struct imx8mp_blk_ctrl_domain *domain) 187{ 188 switch (domain->id) { 189 case IMX8MP_HDMIBLK_PD_IRQSTEER: 190 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9)); 191 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16)); 192 break; 193 case IMX8MP_HDMIBLK_PD_LCDIF: 194 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, 195 BIT(7) | BIT(16) | BIT(17) | BIT(18) | 196 BIT(19) | BIT(20)); 197 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); 198 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, 199 BIT(4) | BIT(5) | BIT(6)); 200 break; 201 case IMX8MP_HDMIBLK_PD_PAI: 202 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17)); 203 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18)); 204 break; 205 case IMX8MP_HDMIBLK_PD_PVI: 206 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28)); 207 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22)); 208 break; 209 case IMX8MP_HDMIBLK_PD_TRNG: 210 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30)); 211 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20)); 212 break; 213 case IMX8MP_HDMIBLK_PD_HDMI_TX: 214 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, 215 BIT(2) | BIT(4) | BIT(5)); 216 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, 217 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | 218 BIT(18) | BIT(19) | BIT(20) | BIT(21)); 219 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, 220 BIT(7) | BIT(10) | BIT(11)); 221 regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1)); 222 break; 223 case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: 224 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); 225 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); 226 regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); 227 break; 228 default: 229 break; 230 } 231} 232 233static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, 234 struct imx8mp_blk_ctrl_domain *domain) 235{ 236 switch (domain->id) { 237 case IMX8MP_HDMIBLK_PD_IRQSTEER: 238 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9)); 239 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16)); 240 break; 241 case IMX8MP_HDMIBLK_PD_LCDIF: 242 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, 243 BIT(4) | BIT(5) | BIT(6)); 244 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); 245 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, 246 BIT(7) | BIT(16) | BIT(17) | BIT(18) | 247 BIT(19) | BIT(20)); 248 break; 249 case IMX8MP_HDMIBLK_PD_PAI: 250 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18)); 251 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17)); 252 break; 253 case IMX8MP_HDMIBLK_PD_PVI: 254 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22)); 255 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28)); 256 break; 257 case IMX8MP_HDMIBLK_PD_TRNG: 258 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20)); 259 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30)); 260 break; 261 case IMX8MP_HDMIBLK_PD_HDMI_TX: 262 regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1)); 263 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, 264 BIT(7) | BIT(10) | BIT(11)); 265 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, 266 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | 267 BIT(18) | BIT(19) | BIT(20) | BIT(21)); 268 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, 269 BIT(2) | BIT(4) | BIT(5)); 270 break; 271 case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: 272 regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); 273 regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); 274 regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); 275 break; 276 default: 277 break; 278 } 279} 280 281static int imx8mp_hdmi_power_notifier(struct notifier_block *nb, 282 unsigned long action, void *data) 283{ 284 struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl, 285 power_nb); 286 287 if (action != GENPD_NOTIFY_ON) 288 return NOTIFY_OK; 289 290 /* 291 * Contrary to other blk-ctrls the reset and clock don't clear when the 292 * power domain is powered down. To ensure the proper reset pulsing, 293 * first clear them all to asserted state, then enable the bus clocks 294 * and then release the ADB reset. 295 */ 296 regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0); 297 regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0); 298 regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0); 299 regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, 300 BIT(0) | BIT(1) | BIT(10)); 301 regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0)); 302 303 /* 304 * On power up we have no software backchannel to the GPC to 305 * wait for the ADB handshake to happen, so we just delay for a 306 * bit. On power down the GPC driver waits for the handshake. 307 */ 308 udelay(5); 309 310 return NOTIFY_OK; 311} 312 313static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = { 314 [IMX8MP_HDMIBLK_PD_IRQSTEER] = { 315 .name = "hdmiblk-irqsteer", 316 .clk_names = (const char *[]){ "apb" }, 317 .num_clks = 1, 318 .gpc_name = "irqsteer", 319 }, 320 [IMX8MP_HDMIBLK_PD_LCDIF] = { 321 .name = "hdmiblk-lcdif", 322 .clk_names = (const char *[]){ "axi", "apb" }, 323 .num_clks = 2, 324 .gpc_name = "lcdif", 325 }, 326 [IMX8MP_HDMIBLK_PD_PAI] = { 327 .name = "hdmiblk-pai", 328 .clk_names = (const char *[]){ "apb" }, 329 .num_clks = 1, 330 .gpc_name = "pai", 331 }, 332 [IMX8MP_HDMIBLK_PD_PVI] = { 333 .name = "hdmiblk-pvi", 334 .clk_names = (const char *[]){ "apb" }, 335 .num_clks = 1, 336 .gpc_name = "pvi", 337 }, 338 [IMX8MP_HDMIBLK_PD_TRNG] = { 339 .name = "hdmiblk-trng", 340 .clk_names = (const char *[]){ "apb" }, 341 .num_clks = 1, 342 .gpc_name = "trng", 343 }, 344 [IMX8MP_HDMIBLK_PD_HDMI_TX] = { 345 .name = "hdmiblk-hdmi-tx", 346 .clk_names = (const char *[]){ "apb", "ref_266m" }, 347 .num_clks = 2, 348 .gpc_name = "hdmi-tx", 349 }, 350 [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = { 351 .name = "hdmiblk-hdmi-tx-phy", 352 .clk_names = (const char *[]){ "apb", "ref_24m" }, 353 .num_clks = 2, 354 .gpc_name = "hdmi-tx-phy", 355 }, 356}; 357 358static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = { 359 .max_reg = 0x23c, 360 .power_on = imx8mp_hdmi_blk_ctrl_power_on, 361 .power_off = imx8mp_hdmi_blk_ctrl_power_off, 362 .power_notifier_fn = imx8mp_hdmi_power_notifier, 363 .domains = imx8mp_hdmi_domain_data, 364 .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data), 365}; 366 367static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd) 368{ 369 struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd); 370 const struct imx8mp_blk_ctrl_domain_data *data = domain->data; 371 struct imx8mp_blk_ctrl *bc = domain->bc; 372 int ret; 373 374 /* make sure bus domain is awake */ 375 ret = pm_runtime_resume_and_get(bc->bus_power_dev); 376 if (ret < 0) { 377 dev_err(bc->dev, "failed to power up bus domain\n"); 378 return ret; 379 } 380 381 /* enable upstream clocks */ 382 ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); 383 if (ret) { 384 dev_err(bc->dev, "failed to enable clocks\n"); 385 goto bus_put; 386 } 387 388 /* domain specific blk-ctrl manipulation */ 389 bc->power_on(bc, domain); 390 391 /* power up upstream GPC domain */ 392 ret = pm_runtime_resume_and_get(domain->power_dev); 393 if (ret < 0) { 394 dev_err(bc->dev, "failed to power up peripheral domain\n"); 395 goto clk_disable; 396 } 397 398 clk_bulk_disable_unprepare(data->num_clks, domain->clks); 399 400 return 0; 401 402clk_disable: 403 clk_bulk_disable_unprepare(data->num_clks, domain->clks); 404bus_put: 405 pm_runtime_put(bc->bus_power_dev); 406 407 return ret; 408} 409 410static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd) 411{ 412 struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd); 413 const struct imx8mp_blk_ctrl_domain_data *data = domain->data; 414 struct imx8mp_blk_ctrl *bc = domain->bc; 415 int ret; 416 417 ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); 418 if (ret) { 419 dev_err(bc->dev, "failed to enable clocks\n"); 420 return ret; 421 } 422 423 /* domain specific blk-ctrl manipulation */ 424 bc->power_off(bc, domain); 425 426 clk_bulk_disable_unprepare(data->num_clks, domain->clks); 427 428 /* power down upstream GPC domain */ 429 pm_runtime_put(domain->power_dev); 430 431 /* allow bus domain to suspend */ 432 pm_runtime_put(bc->bus_power_dev); 433 434 return 0; 435} 436 437static struct generic_pm_domain * 438imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data) 439{ 440 struct genpd_onecell_data *onecell_data = data; 441 unsigned int index = args->args[0]; 442 443 if (args->args_count != 1 || 444 index >= onecell_data->num_domains) 445 return ERR_PTR(-EINVAL); 446 447 return onecell_data->domains[index]; 448} 449 450static struct lock_class_key blk_ctrl_genpd_lock_class; 451 452static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) 453{ 454 const struct imx8mp_blk_ctrl_data *bc_data; 455 struct device *dev = &pdev->dev; 456 struct imx8mp_blk_ctrl *bc; 457 void __iomem *base; 458 int num_domains, i, ret; 459 460 struct regmap_config regmap_config = { 461 .reg_bits = 32, 462 .val_bits = 32, 463 .reg_stride = 4, 464 }; 465 466 bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); 467 if (!bc) 468 return -ENOMEM; 469 470 bc->dev = dev; 471 472 bc_data = of_device_get_match_data(dev); 473 num_domains = bc_data->num_domains; 474 475 base = devm_platform_ioremap_resource(pdev, 0); 476 if (IS_ERR(base)) 477 return PTR_ERR(base); 478 479 regmap_config.max_register = bc_data->max_reg; 480 bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config); 481 if (IS_ERR(bc->regmap)) 482 return dev_err_probe(dev, PTR_ERR(bc->regmap), 483 "failed to init regmap\n"); 484 485 bc->domains = devm_kcalloc(dev, num_domains, 486 sizeof(struct imx8mp_blk_ctrl_domain), 487 GFP_KERNEL); 488 if (!bc->domains) 489 return -ENOMEM; 490 491 bc->onecell_data.num_domains = num_domains; 492 bc->onecell_data.xlate = imx8m_blk_ctrl_xlate; 493 bc->onecell_data.domains = 494 devm_kcalloc(dev, num_domains, 495 sizeof(struct generic_pm_domain *), GFP_KERNEL); 496 if (!bc->onecell_data.domains) 497 return -ENOMEM; 498 499 bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus"); 500 if (IS_ERR(bc->bus_power_dev)) 501 return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), 502 "failed to attach bus power domain\n"); 503 504 bc->power_off = bc_data->power_off; 505 bc->power_on = bc_data->power_on; 506 507 for (i = 0; i < num_domains; i++) { 508 const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i]; 509 struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; 510 int j; 511 512 domain->data = data; 513 514 for (j = 0; j < data->num_clks; j++) 515 domain->clks[j].id = data->clk_names[j]; 516 517 ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); 518 if (ret) { 519 dev_err_probe(dev, ret, "failed to get clock\n"); 520 goto cleanup_pds; 521 } 522 523 domain->power_dev = 524 dev_pm_domain_attach_by_name(dev, data->gpc_name); 525 if (IS_ERR(domain->power_dev)) { 526 dev_err_probe(dev, PTR_ERR(domain->power_dev), 527 "failed to attach power domain %s\n", 528 data->gpc_name); 529 ret = PTR_ERR(domain->power_dev); 530 goto cleanup_pds; 531 } 532 dev_set_name(domain->power_dev, "%s", data->name); 533 534 domain->genpd.name = data->name; 535 domain->genpd.power_on = imx8mp_blk_ctrl_power_on; 536 domain->genpd.power_off = imx8mp_blk_ctrl_power_off; 537 domain->bc = bc; 538 domain->id = i; 539 540 ret = pm_genpd_init(&domain->genpd, NULL, true); 541 if (ret) { 542 dev_err_probe(dev, ret, "failed to init power domain\n"); 543 dev_pm_domain_detach(domain->power_dev, true); 544 goto cleanup_pds; 545 } 546 547 /* 548 * We use runtime PM to trigger power on/off of the upstream GPC 549 * domain, as a strict hierarchical parent/child power domain 550 * setup doesn't allow us to meet the sequencing requirements. 551 * This means we have nested locking of genpd locks, without the 552 * nesting being visible at the genpd level, so we need a 553 * separate lock class to make lockdep aware of the fact that 554 * this are separate domain locks that can be nested without a 555 * self-deadlock. 556 */ 557 lockdep_set_class(&domain->genpd.mlock, 558 &blk_ctrl_genpd_lock_class); 559 560 bc->onecell_data.domains[i] = &domain->genpd; 561 } 562 563 ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data); 564 if (ret) { 565 dev_err_probe(dev, ret, "failed to add power domain provider\n"); 566 goto cleanup_pds; 567 } 568 569 bc->power_nb.notifier_call = bc_data->power_notifier_fn; 570 ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb); 571 if (ret) { 572 dev_err_probe(dev, ret, "failed to add power notifier\n"); 573 goto cleanup_provider; 574 } 575 576 dev_set_drvdata(dev, bc); 577 578 return 0; 579 580cleanup_provider: 581 of_genpd_del_provider(dev->of_node); 582cleanup_pds: 583 for (i--; i >= 0; i--) { 584 pm_genpd_remove(&bc->domains[i].genpd); 585 dev_pm_domain_detach(bc->domains[i].power_dev, true); 586 } 587 588 dev_pm_domain_detach(bc->bus_power_dev, true); 589 590 return ret; 591} 592 593static int imx8mp_blk_ctrl_remove(struct platform_device *pdev) 594{ 595 struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev); 596 int i; 597 598 of_genpd_del_provider(pdev->dev.of_node); 599 600 for (i = 0; bc->onecell_data.num_domains; i++) { 601 struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; 602 603 pm_genpd_remove(&domain->genpd); 604 dev_pm_domain_detach(domain->power_dev, true); 605 } 606 607 dev_pm_genpd_remove_notifier(bc->bus_power_dev); 608 609 dev_pm_domain_detach(bc->bus_power_dev, true); 610 611 return 0; 612} 613 614#ifdef CONFIG_PM_SLEEP 615static int imx8mp_blk_ctrl_suspend(struct device *dev) 616{ 617 struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev); 618 int ret, i; 619 620 /* 621 * This may look strange, but is done so the generic PM_SLEEP code 622 * can power down our domains and more importantly power them up again 623 * after resume, without tripping over our usage of runtime PM to 624 * control the upstream GPC domains. Things happen in the right order 625 * in the system suspend/resume paths due to the device parent/child 626 * hierarchy. 627 */ 628 ret = pm_runtime_get_sync(bc->bus_power_dev); 629 if (ret < 0) { 630 pm_runtime_put_noidle(bc->bus_power_dev); 631 return ret; 632 } 633 634 for (i = 0; i < bc->onecell_data.num_domains; i++) { 635 struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; 636 637 ret = pm_runtime_get_sync(domain->power_dev); 638 if (ret < 0) { 639 pm_runtime_put_noidle(domain->power_dev); 640 goto out_fail; 641 } 642 } 643 644 return 0; 645 646out_fail: 647 for (i--; i >= 0; i--) 648 pm_runtime_put(bc->domains[i].power_dev); 649 650 pm_runtime_put(bc->bus_power_dev); 651 652 return ret; 653} 654 655static int imx8mp_blk_ctrl_resume(struct device *dev) 656{ 657 struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev); 658 int i; 659 660 for (i = 0; i < bc->onecell_data.num_domains; i++) 661 pm_runtime_put(bc->domains[i].power_dev); 662 663 pm_runtime_put(bc->bus_power_dev); 664 665 return 0; 666} 667#endif 668 669static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = { 670 SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend, 671 imx8mp_blk_ctrl_resume) 672}; 673 674static const struct of_device_id imx8mp_blk_ctrl_of_match[] = { 675 { 676 .compatible = "fsl,imx8mp-hsio-blk-ctrl", 677 .data = &imx8mp_hsio_blk_ctl_dev_data, 678 }, { 679 .compatible = "fsl,imx8mp-hdmi-blk-ctrl", 680 .data = &imx8mp_hdmi_blk_ctl_dev_data, 681 }, { 682 /* Sentinel */ 683 } 684}; 685MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match); 686 687static struct platform_driver imx8mp_blk_ctrl_driver = { 688 .probe = imx8mp_blk_ctrl_probe, 689 .remove = imx8mp_blk_ctrl_remove, 690 .driver = { 691 .name = "imx8mp-blk-ctrl", 692 .pm = &imx8mp_blk_ctrl_pm_ops, 693 .of_match_table = imx8mp_blk_ctrl_of_match, 694 }, 695}; 696module_platform_driver(imx8mp_blk_ctrl_driver);