1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 4 * Copyright 2011-2013 Freescale Semiconductor, Inc. 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/delay.h> 9 #include <linux/io.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/pm_domain.h> 13 #include <linux/property.h> 14 #include <linux/regmap.h> 15 #include <linux/regulator/consumer.h> 16 17 #define GPC_CNTR 0x000 18 19 #define GPC_PGC_CTRL_OFFS 0x0 20 #define GPC_PGC_PUPSCR_OFFS 0x4 21 #define GPC_PGC_PDNSCR_OFFS 0x8 22 #define GPC_PGC_SW2ISO_SHIFT 0x8 23 #define GPC_PGC_SW_SHIFT 0x0 24 25 #define GPC_PGC_PCI_PDN 0x200 26 #define GPC_PGC_PCI_SR 0x20c 27 28 #define GPC_PGC_GPU_PDN 0x260 29 #define GPC_PGC_GPU_PUPSCR 0x264 30 #define GPC_PGC_GPU_PDNSCR 0x268 31 #define GPC_PGC_GPU_SR 0x26c 32 33 #define GPC_PGC_DISP_PDN 0x240 34 #define GPC_PGC_DISP_SR 0x24c 35 36 #define GPU_VPU_PUP_REQ BIT(1) 37 #define GPU_VPU_PDN_REQ BIT(0) 38 39 #define GPC_CLK_MAX 7 40 41 #define PGC_DOMAIN_FLAG_NO_PD BIT(0) 42 43 struct imx_pm_domain { 44 struct generic_pm_domain base; 45 struct regmap *regmap; 46 struct regulator *supply; 47 struct clk *clk[GPC_CLK_MAX]; 48 int num_clks; 49 unsigned int reg_offs; 50 signed char cntr_pdn_bit; 51 unsigned int ipg_rate_mhz; 52 }; 53 54 static inline struct imx_pm_domain * 55 to_imx_pm_domain(struct generic_pm_domain *genpd) 56 { 57 return container_of(genpd, struct imx_pm_domain, base); 58 } 59 60 static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) 61 { 62 struct imx_pm_domain *pd = to_imx_pm_domain(genpd); 63 int iso, iso2sw; 64 u32 val; 65 66 /* Read ISO and ISO2SW power down delays */ 67 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val); 68 iso = val & 0x3f; 69 iso2sw = (val >> 8) & 0x3f; 70 71 /* Gate off domain when powered down */ 72 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, 73 0x1, 0x1); 74 75 /* Request GPC to power down domain */ 76 val = BIT(pd->cntr_pdn_bit); 77 regmap_update_bits(pd->regmap, GPC_CNTR, val, val); 78 79 /* Wait ISO + ISO2SW IPG clock cycles */ 80 udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz)); 81 82 if (pd->supply) 83 regulator_disable(pd->supply); 84 85 return 0; 86 } 87 88 static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) 89 { 90 struct imx_pm_domain *pd = to_imx_pm_domain(genpd); 91 int i, ret; 92 u32 val, req; 93 94 if (pd->supply) { 95 ret = regulator_enable(pd->supply); 96 if (ret) { 97 pr_err("%s: failed to enable regulator: %d\n", 98 __func__, ret); 99 return ret; 100 } 101 } 102 103 /* Enable reset clocks for all devices in the domain */ 104 for (i = 0; i < pd->num_clks; i++) 105 clk_prepare_enable(pd->clk[i]); 106 107 /* Gate off domain when powered down */ 108 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, 109 0x1, 0x1); 110 111 /* Request GPC to power up domain */ 112 req = BIT(pd->cntr_pdn_bit + 1); 113 regmap_update_bits(pd->regmap, GPC_CNTR, req, req); 114 115 /* Wait for the PGC to handle the request */ 116 ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req), 117 1, 50); 118 if (ret) 119 pr_err("powerup request on domain %s timed out\n", genpd->name); 120 121 /* Wait for reset to propagate through peripherals */ 122 usleep_range(5, 10); 123 124 /* Disable reset clocks for all devices in the domain */ 125 for (i = 0; i < pd->num_clks; i++) 126 clk_disable_unprepare(pd->clk[i]); 127 128 return 0; 129 } 130 131 static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain) 132 { 133 int i, ret; 134 135 for (i = 0; ; i++) { 136 struct clk *clk = of_clk_get(dev->of_node, i); 137 if (IS_ERR(clk)) 138 break; 139 if (i >= GPC_CLK_MAX) { 140 dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); 141 ret = -EINVAL; 142 goto clk_err; 143 } 144 domain->clk[i] = clk; 145 } 146 domain->num_clks = i; 147 148 return 0; 149 150 clk_err: 151 while (i--) 152 clk_put(domain->clk[i]); 153 154 return ret; 155 } 156 157 static void imx_pgc_put_clocks(struct imx_pm_domain *domain) 158 { 159 int i; 160 161 for (i = domain->num_clks - 1; i >= 0; i--) 162 clk_put(domain->clk[i]); 163 } 164 165 static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain) 166 { 167 /* try to get the domain supply regulator */ 168 domain->supply = devm_regulator_get_optional(dev, "power"); 169 if (IS_ERR(domain->supply)) { 170 if (PTR_ERR(domain->supply) == -ENODEV) 171 domain->supply = NULL; 172 else 173 return PTR_ERR(domain->supply); 174 } 175 176 /* try to get all clocks needed for reset propagation */ 177 return imx_pgc_get_clocks(dev, domain); 178 } 179 180 static int imx_pgc_power_domain_probe(struct platform_device *pdev) 181 { 182 struct imx_pm_domain *domain = pdev->dev.platform_data; 183 struct device *dev = &pdev->dev; 184 int ret; 185 186 /* if this PD is associated with a DT node try to parse it */ 187 if (dev->of_node) { 188 ret = imx_pgc_parse_dt(dev, domain); 189 if (ret) 190 return ret; 191 } 192 193 /* initially power on the domain */ 194 if (domain->base.power_on) 195 domain->base.power_on(&domain->base); 196 197 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 198 pm_genpd_init(&domain->base, NULL, false); 199 ret = of_genpd_add_provider_simple(dev->of_node, &domain->base); 200 if (ret) 201 goto genpd_err; 202 } 203 204 device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER); 205 206 return 0; 207 208 genpd_err: 209 pm_genpd_remove(&domain->base); 210 imx_pgc_put_clocks(domain); 211 212 return ret; 213 } 214 215 static void imx_pgc_power_domain_remove(struct platform_device *pdev) 216 { 217 struct imx_pm_domain *domain = pdev->dev.platform_data; 218 219 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 220 of_genpd_del_provider(pdev->dev.of_node); 221 pm_genpd_remove(&domain->base); 222 imx_pgc_put_clocks(domain); 223 } 224 } 225 226 static const struct platform_device_id imx_pgc_power_domain_id[] = { 227 { "imx-pgc-power-domain"}, 228 { }, 229 }; 230 231 static struct platform_driver imx_pgc_power_domain_driver = { 232 .driver = { 233 .name = "imx-pgc-pd", 234 }, 235 .probe = imx_pgc_power_domain_probe, 236 .remove_new = imx_pgc_power_domain_remove, 237 .id_table = imx_pgc_power_domain_id, 238 }; 239 builtin_platform_driver(imx_pgc_power_domain_driver) 240 241 #define GPC_PGC_DOMAIN_ARM 0 242 #define GPC_PGC_DOMAIN_PU 1 243 #define GPC_PGC_DOMAIN_DISPLAY 2 244 #define GPC_PGC_DOMAIN_PCI 3 245 246 static struct genpd_power_state imx6_pm_domain_pu_state = { 247 .power_off_latency_ns = 25000, 248 .power_on_latency_ns = 2000000, 249 }; 250 251 static struct imx_pm_domain imx_gpc_domains[] = { 252 [GPC_PGC_DOMAIN_ARM] = { 253 .base = { 254 .name = "ARM", 255 .flags = GENPD_FLAG_ALWAYS_ON, 256 }, 257 }, 258 [GPC_PGC_DOMAIN_PU] = { 259 .base = { 260 .name = "PU", 261 .power_off = imx6_pm_domain_power_off, 262 .power_on = imx6_pm_domain_power_on, 263 .states = &imx6_pm_domain_pu_state, 264 .state_count = 1, 265 }, 266 .reg_offs = 0x260, 267 .cntr_pdn_bit = 0, 268 }, 269 [GPC_PGC_DOMAIN_DISPLAY] = { 270 .base = { 271 .name = "DISPLAY", 272 .power_off = imx6_pm_domain_power_off, 273 .power_on = imx6_pm_domain_power_on, 274 }, 275 .reg_offs = 0x240, 276 .cntr_pdn_bit = 4, 277 }, 278 [GPC_PGC_DOMAIN_PCI] = { 279 .base = { 280 .name = "PCI", 281 .power_off = imx6_pm_domain_power_off, 282 .power_on = imx6_pm_domain_power_on, 283 }, 284 .reg_offs = 0x200, 285 .cntr_pdn_bit = 6, 286 }, 287 }; 288 289 struct imx_gpc_dt_data { 290 int num_domains; 291 bool err009619_present; 292 bool err006287_present; 293 }; 294 295 static const struct imx_gpc_dt_data imx6q_dt_data = { 296 .num_domains = 2, 297 .err009619_present = false, 298 .err006287_present = false, 299 }; 300 301 static const struct imx_gpc_dt_data imx6qp_dt_data = { 302 .num_domains = 2, 303 .err009619_present = true, 304 .err006287_present = false, 305 }; 306 307 static const struct imx_gpc_dt_data imx6sl_dt_data = { 308 .num_domains = 3, 309 .err009619_present = false, 310 .err006287_present = true, 311 }; 312 313 static const struct imx_gpc_dt_data imx6sx_dt_data = { 314 .num_domains = 4, 315 .err009619_present = false, 316 .err006287_present = false, 317 }; 318 319 static const struct of_device_id imx_gpc_dt_ids[] = { 320 { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data }, 321 { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data }, 322 { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data }, 323 { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data }, 324 { } 325 }; 326 327 static const struct regmap_range yes_ranges[] = { 328 regmap_reg_range(GPC_CNTR, GPC_CNTR), 329 regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR), 330 regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR), 331 regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR), 332 }; 333 334 static const struct regmap_access_table access_table = { 335 .yes_ranges = yes_ranges, 336 .n_yes_ranges = ARRAY_SIZE(yes_ranges), 337 }; 338 339 static const struct regmap_config imx_gpc_regmap_config = { 340 .reg_bits = 32, 341 .val_bits = 32, 342 .reg_stride = 4, 343 .rd_table = &access_table, 344 .wr_table = &access_table, 345 .max_register = 0x2ac, 346 .fast_io = true, 347 }; 348 349 static struct generic_pm_domain *imx_gpc_onecell_domains[] = { 350 &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base, 351 &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base, 352 }; 353 354 static struct genpd_onecell_data imx_gpc_onecell_data = { 355 .domains = imx_gpc_onecell_domains, 356 .num_domains = 2, 357 }; 358 359 static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap, 360 unsigned int num_domains) 361 { 362 struct imx_pm_domain *domain; 363 int i, ret; 364 365 for (i = 0; i < num_domains; i++) { 366 domain = &imx_gpc_domains[i]; 367 domain->regmap = regmap; 368 domain->ipg_rate_mhz = 66; 369 370 if (i == 1) { 371 domain->supply = devm_regulator_get(dev, "pu"); 372 if (IS_ERR(domain->supply)) 373 return PTR_ERR(domain->supply); 374 375 ret = imx_pgc_get_clocks(dev, domain); 376 if (ret) 377 goto clk_err; 378 379 domain->base.power_on(&domain->base); 380 } 381 } 382 383 for (i = 0; i < num_domains; i++) 384 pm_genpd_init(&imx_gpc_domains[i].base, NULL, false); 385 386 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 387 ret = of_genpd_add_provider_onecell(dev->of_node, 388 &imx_gpc_onecell_data); 389 if (ret) 390 goto genpd_err; 391 } 392 393 return 0; 394 395 genpd_err: 396 for (i = 0; i < num_domains; i++) 397 pm_genpd_remove(&imx_gpc_domains[i].base); 398 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 399 clk_err: 400 return ret; 401 } 402 403 static int imx_gpc_probe(struct platform_device *pdev) 404 { 405 const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev); 406 struct device_node *pgc_node; 407 struct regmap *regmap; 408 void __iomem *base; 409 int ret; 410 411 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); 412 413 /* bail out if DT too old and doesn't provide the necessary info */ 414 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && 415 !pgc_node) 416 return 0; 417 418 base = devm_platform_ioremap_resource(pdev, 0); 419 if (IS_ERR(base)) 420 return PTR_ERR(base); 421 422 regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, 423 &imx_gpc_regmap_config); 424 if (IS_ERR(regmap)) { 425 ret = PTR_ERR(regmap); 426 dev_err(&pdev->dev, "failed to init regmap: %d\n", 427 ret); 428 return ret; 429 } 430 431 /* 432 * Disable PU power down by runtime PM if ERR009619 is present. 433 * 434 * The PRE clock will be paused for several cycles when turning on the 435 * PU domain LDO from power down state. If PRE is in use at that time, 436 * the IPU/PRG cannot get the correct display data from the PRE. 437 * 438 * This is not a concern when the whole system enters suspend state, so 439 * it's safe to power down PU in this case. 440 */ 441 if (of_id_data->err009619_present) 442 imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |= 443 GENPD_FLAG_RPM_ALWAYS_ON; 444 445 /* Keep DISP always on if ERR006287 is present */ 446 if (of_id_data->err006287_present) 447 imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |= 448 GENPD_FLAG_ALWAYS_ON; 449 450 if (!pgc_node) { 451 ret = imx_gpc_old_dt_init(&pdev->dev, regmap, 452 of_id_data->num_domains); 453 if (ret) 454 return ret; 455 } else { 456 struct imx_pm_domain *domain; 457 struct platform_device *pd_pdev; 458 struct clk *ipg_clk; 459 unsigned int ipg_rate_mhz; 460 int domain_index; 461 462 ipg_clk = devm_clk_get(&pdev->dev, "ipg"); 463 if (IS_ERR(ipg_clk)) 464 return PTR_ERR(ipg_clk); 465 ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000; 466 467 for_each_child_of_node_scoped(pgc_node, np) { 468 ret = of_property_read_u32(np, "reg", &domain_index); 469 if (ret) 470 return ret; 471 472 if (domain_index >= of_id_data->num_domains) 473 continue; 474 475 pd_pdev = platform_device_alloc("imx-pgc-power-domain", 476 domain_index); 477 if (!pd_pdev) 478 return -ENOMEM; 479 480 ret = platform_device_add_data(pd_pdev, 481 &imx_gpc_domains[domain_index], 482 sizeof(imx_gpc_domains[domain_index])); 483 if (ret) { 484 platform_device_put(pd_pdev); 485 return ret; 486 } 487 domain = pd_pdev->dev.platform_data; 488 domain->regmap = regmap; 489 domain->ipg_rate_mhz = ipg_rate_mhz; 490 491 pd_pdev->dev.parent = &pdev->dev; 492 pd_pdev->dev.of_node = np; 493 pd_pdev->dev.fwnode = of_fwnode_handle(np); 494 495 ret = platform_device_add(pd_pdev); 496 if (ret) { 497 platform_device_put(pd_pdev); 498 return ret; 499 } 500 } 501 } 502 503 return 0; 504 } 505 506 static void imx_gpc_remove(struct platform_device *pdev) 507 { 508 struct device_node *pgc_node; 509 int ret; 510 511 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); 512 513 /* bail out if DT too old and doesn't provide the necessary info */ 514 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && 515 !pgc_node) 516 return; 517 518 /* 519 * If the old DT binding is used the toplevel driver needs to 520 * de-register the power domains 521 */ 522 if (!pgc_node) { 523 of_genpd_del_provider(pdev->dev.of_node); 524 525 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base); 526 if (ret) { 527 dev_err(&pdev->dev, "Failed to remove PU power domain (%pe)\n", 528 ERR_PTR(ret)); 529 return; 530 } 531 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 532 533 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base); 534 if (ret) { 535 dev_err(&pdev->dev, "Failed to remove ARM power domain (%pe)\n", 536 ERR_PTR(ret)); 537 return; 538 } 539 } 540 } 541 542 static struct platform_driver imx_gpc_driver = { 543 .driver = { 544 .name = "imx-gpc", 545 .of_match_table = imx_gpc_dt_ids, 546 }, 547 .probe = imx_gpc_probe, 548 .remove_new = imx_gpc_remove, 549 }; 550 builtin_platform_driver(imx_gpc_driver) 551