Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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