1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2017 Impinj, Inc 4 * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 5 * 6 * Based on the code of analogus driver: 7 * 8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 9 */ 10 11#include <linux/clk.h> 12#include <linux/of_device.h> 13#include <linux/platform_device.h> 14#include <linux/pm_domain.h> 15#include <linux/regmap.h> 16#include <linux/regulator/consumer.h> 17#include <linux/sizes.h> 18#include <dt-bindings/power/imx7-power.h> 19#include <dt-bindings/power/imx8mq-power.h> 20 21#define GPC_LPCR_A_CORE_BSC 0x000 22 23#define GPC_PGC_CPU_MAPPING 0x0ec 24 25#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) 26#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) 27#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) 28#define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3) 29#define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2) 30 31#define IMX8M_PCIE2_A53_DOMAIN BIT(15) 32#define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14) 33#define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13) 34#define IMX8M_DISP_A53_DOMAIN BIT(12) 35#define IMX8M_HDMI_A53_DOMAIN BIT(11) 36#define IMX8M_VPU_A53_DOMAIN BIT(10) 37#define IMX8M_GPU_A53_DOMAIN BIT(9) 38#define IMX8M_DDR2_A53_DOMAIN BIT(8) 39#define IMX8M_DDR1_A53_DOMAIN BIT(7) 40#define IMX8M_OTG2_A53_DOMAIN BIT(5) 41#define IMX8M_OTG1_A53_DOMAIN BIT(4) 42#define IMX8M_PCIE1_A53_DOMAIN BIT(3) 43#define IMX8M_MIPI_A53_DOMAIN BIT(2) 44 45#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 46#define GPC_PU_PGC_SW_PDN_REQ 0x104 47 48#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4) 49#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3) 50#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2) 51#define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1) 52#define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0) 53 54#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) 55#define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12) 56#define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11) 57#define IMX8M_DISP_SW_Pxx_REQ BIT(10) 58#define IMX8M_HDMI_SW_Pxx_REQ BIT(9) 59#define IMX8M_VPU_SW_Pxx_REQ BIT(8) 60#define IMX8M_GPU_SW_Pxx_REQ BIT(7) 61#define IMX8M_DDR2_SW_Pxx_REQ BIT(6) 62#define IMX8M_DDR1_SW_Pxx_REQ BIT(5) 63#define IMX8M_OTG2_SW_Pxx_REQ BIT(3) 64#define IMX8M_OTG1_SW_Pxx_REQ BIT(2) 65#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) 66#define IMX8M_MIPI_SW_Pxx_REQ BIT(0) 67 68#define GPC_M4_PU_PDN_FLG 0x1bc 69 70#define GPC_PU_PWRHSK 0x1fc 71 72#define IMX8M_GPU_HSK_PWRDNREQN BIT(6) 73#define IMX8M_VPU_HSK_PWRDNREQN BIT(5) 74#define IMX8M_DISP_HSK_PWRDNREQN BIT(4) 75 76/* 77 * The PGC offset values in Reference Manual 78 * (Rev. 1, 01/2018 and the older ones) GPC chapter's 79 * GPC_PGC memory map are incorrect, below offset 80 * values are from design RTL. 81 */ 82#define IMX7_PGC_MIPI 16 83#define IMX7_PGC_PCIE 17 84#define IMX7_PGC_USB_HSIC 20 85 86#define IMX8M_PGC_MIPI 16 87#define IMX8M_PGC_PCIE1 17 88#define IMX8M_PGC_OTG1 18 89#define IMX8M_PGC_OTG2 19 90#define IMX8M_PGC_DDR1 21 91#define IMX8M_PGC_GPU 23 92#define IMX8M_PGC_VPU 24 93#define IMX8M_PGC_DISP 26 94#define IMX8M_PGC_MIPI_CSI1 27 95#define IMX8M_PGC_MIPI_CSI2 28 96#define IMX8M_PGC_PCIE2 29 97 98#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) 99#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) 100 101#define GPC_PGC_CTRL_PCR BIT(0) 102 103#define GPC_CLK_MAX 6 104 105struct imx_pgc_domain { 106 struct generic_pm_domain genpd; 107 struct regmap *regmap; 108 struct regulator *regulator; 109 struct clk *clk[GPC_CLK_MAX]; 110 int num_clks; 111 112 unsigned int pgc; 113 114 const struct { 115 u32 pxx; 116 u32 map; 117 u32 hsk; 118 } bits; 119 120 const int voltage; 121 struct device *dev; 122}; 123 124struct imx_pgc_domain_data { 125 const struct imx_pgc_domain *domains; 126 size_t domains_num; 127 const struct regmap_access_table *reg_access_table; 128}; 129 130static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, 131 bool on) 132{ 133 struct imx_pgc_domain *domain = container_of(genpd, 134 struct imx_pgc_domain, 135 genpd); 136 unsigned int offset = on ? 137 GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ; 138 const bool enable_power_control = !on; 139 const bool has_regulator = !IS_ERR(domain->regulator); 140 int i, ret = 0; 141 u32 pxx_req; 142 143 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, 144 domain->bits.map, domain->bits.map); 145 146 if (has_regulator && on) { 147 ret = regulator_enable(domain->regulator); 148 if (ret) { 149 dev_err(domain->dev, "failed to enable regulator\n"); 150 goto unmap; 151 } 152 } 153 154 /* Enable reset clocks for all devices in the domain */ 155 for (i = 0; i < domain->num_clks; i++) 156 clk_prepare_enable(domain->clk[i]); 157 158 if (enable_power_control) 159 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 160 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); 161 162 if (domain->bits.hsk) 163 regmap_update_bits(domain->regmap, GPC_PU_PWRHSK, 164 domain->bits.hsk, on ? domain->bits.hsk : 0); 165 166 regmap_update_bits(domain->regmap, offset, 167 domain->bits.pxx, domain->bits.pxx); 168 169 /* 170 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait 171 * for PUP_REQ/PDN_REQ bit to be cleared 172 */ 173 ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req, 174 !(pxx_req & domain->bits.pxx), 175 0, USEC_PER_MSEC); 176 if (ret) { 177 dev_err(domain->dev, "failed to command PGC\n"); 178 /* 179 * If we were in a process of enabling a 180 * domain and failed we might as well disable 181 * the regulator we just enabled. And if it 182 * was the opposite situation and we failed to 183 * power down -- keep the regulator on 184 */ 185 on = !on; 186 } 187 188 if (enable_power_control) 189 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 190 GPC_PGC_CTRL_PCR, 0); 191 192 /* Disable reset clocks for all devices in the domain */ 193 for (i = 0; i < domain->num_clks; i++) 194 clk_disable_unprepare(domain->clk[i]); 195 196 if (has_regulator && !on) { 197 int err; 198 199 err = regulator_disable(domain->regulator); 200 if (err) 201 dev_err(domain->dev, 202 "failed to disable regulator: %d\n", err); 203 /* Preserve earlier error code */ 204 ret = ret ?: err; 205 } 206unmap: 207 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, 208 domain->bits.map, 0); 209 return ret; 210} 211 212static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) 213{ 214 return imx_gpc_pu_pgc_sw_pxx_req(genpd, true); 215} 216 217static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) 218{ 219 return imx_gpc_pu_pgc_sw_pxx_req(genpd, false); 220} 221 222static const struct imx_pgc_domain imx7_pgc_domains[] = { 223 [IMX7_POWER_DOMAIN_MIPI_PHY] = { 224 .genpd = { 225 .name = "mipi-phy", 226 }, 227 .bits = { 228 .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ, 229 .map = IMX7_MIPI_PHY_A_CORE_DOMAIN, 230 }, 231 .voltage = 1000000, 232 .pgc = IMX7_PGC_MIPI, 233 }, 234 235 [IMX7_POWER_DOMAIN_PCIE_PHY] = { 236 .genpd = { 237 .name = "pcie-phy", 238 }, 239 .bits = { 240 .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ, 241 .map = IMX7_PCIE_PHY_A_CORE_DOMAIN, 242 }, 243 .voltage = 1000000, 244 .pgc = IMX7_PGC_PCIE, 245 }, 246 247 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { 248 .genpd = { 249 .name = "usb-hsic-phy", 250 }, 251 .bits = { 252 .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ, 253 .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN, 254 }, 255 .voltage = 1200000, 256 .pgc = IMX7_PGC_USB_HSIC, 257 }, 258}; 259 260static const struct regmap_range imx7_yes_ranges[] = { 261 regmap_reg_range(GPC_LPCR_A_CORE_BSC, 262 GPC_M4_PU_PDN_FLG), 263 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI), 264 GPC_PGC_SR(IMX7_PGC_MIPI)), 265 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE), 266 GPC_PGC_SR(IMX7_PGC_PCIE)), 267 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC), 268 GPC_PGC_SR(IMX7_PGC_USB_HSIC)), 269}; 270 271static const struct regmap_access_table imx7_access_table = { 272 .yes_ranges = imx7_yes_ranges, 273 .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges), 274}; 275 276static const struct imx_pgc_domain_data imx7_pgc_domain_data = { 277 .domains = imx7_pgc_domains, 278 .domains_num = ARRAY_SIZE(imx7_pgc_domains), 279 .reg_access_table = &imx7_access_table, 280}; 281 282static const struct imx_pgc_domain imx8m_pgc_domains[] = { 283 [IMX8M_POWER_DOMAIN_MIPI] = { 284 .genpd = { 285 .name = "mipi", 286 }, 287 .bits = { 288 .pxx = IMX8M_MIPI_SW_Pxx_REQ, 289 .map = IMX8M_MIPI_A53_DOMAIN, 290 }, 291 .pgc = IMX8M_PGC_MIPI, 292 }, 293 294 [IMX8M_POWER_DOMAIN_PCIE1] = { 295 .genpd = { 296 .name = "pcie1", 297 }, 298 .bits = { 299 .pxx = IMX8M_PCIE1_SW_Pxx_REQ, 300 .map = IMX8M_PCIE1_A53_DOMAIN, 301 }, 302 .pgc = IMX8M_PGC_PCIE1, 303 }, 304 305 [IMX8M_POWER_DOMAIN_USB_OTG1] = { 306 .genpd = { 307 .name = "usb-otg1", 308 }, 309 .bits = { 310 .pxx = IMX8M_OTG1_SW_Pxx_REQ, 311 .map = IMX8M_OTG1_A53_DOMAIN, 312 }, 313 .pgc = IMX8M_PGC_OTG1, 314 }, 315 316 [IMX8M_POWER_DOMAIN_USB_OTG2] = { 317 .genpd = { 318 .name = "usb-otg2", 319 }, 320 .bits = { 321 .pxx = IMX8M_OTG2_SW_Pxx_REQ, 322 .map = IMX8M_OTG2_A53_DOMAIN, 323 }, 324 .pgc = IMX8M_PGC_OTG2, 325 }, 326 327 [IMX8M_POWER_DOMAIN_DDR1] = { 328 .genpd = { 329 .name = "ddr1", 330 }, 331 .bits = { 332 .pxx = IMX8M_DDR1_SW_Pxx_REQ, 333 .map = IMX8M_DDR2_A53_DOMAIN, 334 }, 335 .pgc = IMX8M_PGC_DDR1, 336 }, 337 338 [IMX8M_POWER_DOMAIN_GPU] = { 339 .genpd = { 340 .name = "gpu", 341 }, 342 .bits = { 343 .pxx = IMX8M_GPU_SW_Pxx_REQ, 344 .map = IMX8M_GPU_A53_DOMAIN, 345 .hsk = IMX8M_GPU_HSK_PWRDNREQN, 346 }, 347 .pgc = IMX8M_PGC_GPU, 348 }, 349 350 [IMX8M_POWER_DOMAIN_VPU] = { 351 .genpd = { 352 .name = "vpu", 353 }, 354 .bits = { 355 .pxx = IMX8M_VPU_SW_Pxx_REQ, 356 .map = IMX8M_VPU_A53_DOMAIN, 357 .hsk = IMX8M_VPU_HSK_PWRDNREQN, 358 }, 359 .pgc = IMX8M_PGC_VPU, 360 }, 361 362 [IMX8M_POWER_DOMAIN_DISP] = { 363 .genpd = { 364 .name = "disp", 365 }, 366 .bits = { 367 .pxx = IMX8M_DISP_SW_Pxx_REQ, 368 .map = IMX8M_DISP_A53_DOMAIN, 369 .hsk = IMX8M_DISP_HSK_PWRDNREQN, 370 }, 371 .pgc = IMX8M_PGC_DISP, 372 }, 373 374 [IMX8M_POWER_DOMAIN_MIPI_CSI1] = { 375 .genpd = { 376 .name = "mipi-csi1", 377 }, 378 .bits = { 379 .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ, 380 .map = IMX8M_MIPI_CSI1_A53_DOMAIN, 381 }, 382 .pgc = IMX8M_PGC_MIPI_CSI1, 383 }, 384 385 [IMX8M_POWER_DOMAIN_MIPI_CSI2] = { 386 .genpd = { 387 .name = "mipi-csi2", 388 }, 389 .bits = { 390 .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ, 391 .map = IMX8M_MIPI_CSI2_A53_DOMAIN, 392 }, 393 .pgc = IMX8M_PGC_MIPI_CSI2, 394 }, 395 396 [IMX8M_POWER_DOMAIN_PCIE2] = { 397 .genpd = { 398 .name = "pcie2", 399 }, 400 .bits = { 401 .pxx = IMX8M_PCIE2_SW_Pxx_REQ, 402 .map = IMX8M_PCIE2_A53_DOMAIN, 403 }, 404 .pgc = IMX8M_PGC_PCIE2, 405 }, 406}; 407 408static const struct regmap_range imx8m_yes_ranges[] = { 409 regmap_reg_range(GPC_LPCR_A_CORE_BSC, 410 GPC_PU_PWRHSK), 411 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI), 412 GPC_PGC_SR(IMX8M_PGC_MIPI)), 413 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1), 414 GPC_PGC_SR(IMX8M_PGC_PCIE1)), 415 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1), 416 GPC_PGC_SR(IMX8M_PGC_OTG1)), 417 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2), 418 GPC_PGC_SR(IMX8M_PGC_OTG2)), 419 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1), 420 GPC_PGC_SR(IMX8M_PGC_DDR1)), 421 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU), 422 GPC_PGC_SR(IMX8M_PGC_GPU)), 423 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU), 424 GPC_PGC_SR(IMX8M_PGC_VPU)), 425 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP), 426 GPC_PGC_SR(IMX8M_PGC_DISP)), 427 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1), 428 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)), 429 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2), 430 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)), 431 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2), 432 GPC_PGC_SR(IMX8M_PGC_PCIE2)), 433}; 434 435static const struct regmap_access_table imx8m_access_table = { 436 .yes_ranges = imx8m_yes_ranges, 437 .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges), 438}; 439 440static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { 441 .domains = imx8m_pgc_domains, 442 .domains_num = ARRAY_SIZE(imx8m_pgc_domains), 443 .reg_access_table = &imx8m_access_table, 444}; 445 446static int imx_pgc_get_clocks(struct imx_pgc_domain *domain) 447{ 448 int i, ret; 449 450 for (i = 0; ; i++) { 451 struct clk *clk = of_clk_get(domain->dev->of_node, i); 452 if (IS_ERR(clk)) 453 break; 454 if (i >= GPC_CLK_MAX) { 455 dev_err(domain->dev, "more than %d clocks\n", 456 GPC_CLK_MAX); 457 ret = -EINVAL; 458 goto clk_err; 459 } 460 domain->clk[i] = clk; 461 } 462 domain->num_clks = i; 463 464 return 0; 465 466clk_err: 467 while (i--) 468 clk_put(domain->clk[i]); 469 470 return ret; 471} 472 473static void imx_pgc_put_clocks(struct imx_pgc_domain *domain) 474{ 475 int i; 476 477 for (i = domain->num_clks - 1; i >= 0; i--) 478 clk_put(domain->clk[i]); 479} 480 481static int imx_pgc_domain_probe(struct platform_device *pdev) 482{ 483 struct imx_pgc_domain *domain = pdev->dev.platform_data; 484 int ret; 485 486 domain->dev = &pdev->dev; 487 488 domain->regulator = devm_regulator_get_optional(domain->dev, "power"); 489 if (IS_ERR(domain->regulator)) { 490 if (PTR_ERR(domain->regulator) != -ENODEV) 491 return dev_err_probe(domain->dev, PTR_ERR(domain->regulator), 492 "Failed to get domain's regulator\n"); 493 } else if (domain->voltage) { 494 regulator_set_voltage(domain->regulator, 495 domain->voltage, domain->voltage); 496 } 497 498 ret = imx_pgc_get_clocks(domain); 499 if (ret) 500 return dev_err_probe(domain->dev, ret, "Failed to get domain's clocks\n"); 501 502 ret = pm_genpd_init(&domain->genpd, NULL, true); 503 if (ret) { 504 dev_err(domain->dev, "Failed to init power domain\n"); 505 imx_pgc_put_clocks(domain); 506 return ret; 507 } 508 509 ret = of_genpd_add_provider_simple(domain->dev->of_node, 510 &domain->genpd); 511 if (ret) { 512 dev_err(domain->dev, "Failed to add genpd provider\n"); 513 pm_genpd_remove(&domain->genpd); 514 imx_pgc_put_clocks(domain); 515 } 516 517 return ret; 518} 519 520static int imx_pgc_domain_remove(struct platform_device *pdev) 521{ 522 struct imx_pgc_domain *domain = pdev->dev.platform_data; 523 524 of_genpd_del_provider(domain->dev->of_node); 525 pm_genpd_remove(&domain->genpd); 526 imx_pgc_put_clocks(domain); 527 528 return 0; 529} 530 531static const struct platform_device_id imx_pgc_domain_id[] = { 532 { "imx-pgc-domain", }, 533 { }, 534}; 535 536static struct platform_driver imx_pgc_domain_driver = { 537 .driver = { 538 .name = "imx-pgc", 539 }, 540 .probe = imx_pgc_domain_probe, 541 .remove = imx_pgc_domain_remove, 542 .id_table = imx_pgc_domain_id, 543}; 544builtin_platform_driver(imx_pgc_domain_driver) 545 546static int imx_gpcv2_probe(struct platform_device *pdev) 547{ 548 const struct imx_pgc_domain_data *domain_data = 549 of_device_get_match_data(&pdev->dev); 550 551 struct regmap_config regmap_config = { 552 .reg_bits = 32, 553 .val_bits = 32, 554 .reg_stride = 4, 555 .rd_table = domain_data->reg_access_table, 556 .wr_table = domain_data->reg_access_table, 557 .max_register = SZ_4K, 558 }; 559 struct device *dev = &pdev->dev; 560 struct device_node *pgc_np, *np; 561 struct regmap *regmap; 562 void __iomem *base; 563 int ret; 564 565 pgc_np = of_get_child_by_name(dev->of_node, "pgc"); 566 if (!pgc_np) { 567 dev_err(dev, "No power domains specified in DT\n"); 568 return -EINVAL; 569 } 570 571 base = devm_platform_ioremap_resource(pdev, 0); 572 if (IS_ERR(base)) 573 return PTR_ERR(base); 574 575 regmap = devm_regmap_init_mmio(dev, base, ®map_config); 576 if (IS_ERR(regmap)) { 577 ret = PTR_ERR(regmap); 578 dev_err(dev, "failed to init regmap (%d)\n", ret); 579 return ret; 580 } 581 582 for_each_child_of_node(pgc_np, np) { 583 struct platform_device *pd_pdev; 584 struct imx_pgc_domain *domain; 585 u32 domain_index; 586 587 ret = of_property_read_u32(np, "reg", &domain_index); 588 if (ret) { 589 dev_err(dev, "Failed to read 'reg' property\n"); 590 of_node_put(np); 591 return ret; 592 } 593 594 if (domain_index >= domain_data->domains_num) { 595 dev_warn(dev, 596 "Domain index %d is out of bounds\n", 597 domain_index); 598 continue; 599 } 600 601 pd_pdev = platform_device_alloc("imx-pgc-domain", 602 domain_index); 603 if (!pd_pdev) { 604 dev_err(dev, "Failed to allocate platform device\n"); 605 of_node_put(np); 606 return -ENOMEM; 607 } 608 609 ret = platform_device_add_data(pd_pdev, 610 &domain_data->domains[domain_index], 611 sizeof(domain_data->domains[domain_index])); 612 if (ret) { 613 platform_device_put(pd_pdev); 614 of_node_put(np); 615 return ret; 616 } 617 618 domain = pd_pdev->dev.platform_data; 619 domain->regmap = regmap; 620 domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req; 621 domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req; 622 623 pd_pdev->dev.parent = dev; 624 pd_pdev->dev.of_node = np; 625 626 ret = platform_device_add(pd_pdev); 627 if (ret) { 628 platform_device_put(pd_pdev); 629 of_node_put(np); 630 return ret; 631 } 632 } 633 634 return 0; 635} 636 637static const struct of_device_id imx_gpcv2_dt_ids[] = { 638 { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, 639 { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, }, 640 { } 641}; 642 643static struct platform_driver imx_gpc_driver = { 644 .driver = { 645 .name = "imx-gpcv2", 646 .of_match_table = imx_gpcv2_dt_ids, 647 }, 648 .probe = imx_gpcv2_probe, 649}; 650builtin_platform_driver(imx_gpc_driver) 651