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 int 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 return 0; 226 } 227 228 static const struct platform_device_id imx_pgc_power_domain_id[] = { 229 { "imx-pgc-power-domain"}, 230 { }, 231 }; 232 233 static struct platform_driver imx_pgc_power_domain_driver = { 234 .driver = { 235 .name = "imx-pgc-pd", 236 }, 237 .probe = imx_pgc_power_domain_probe, 238 .remove = imx_pgc_power_domain_remove, 239 .id_table = imx_pgc_power_domain_id, 240 }; 241 builtin_platform_driver(imx_pgc_power_domain_driver) 242 243 #define GPC_PGC_DOMAIN_ARM 0 244 #define GPC_PGC_DOMAIN_PU 1 245 #define GPC_PGC_DOMAIN_DISPLAY 2 246 #define GPC_PGC_DOMAIN_PCI 3 247 248 static struct genpd_power_state imx6_pm_domain_pu_state = { 249 .power_off_latency_ns = 25000, 250 .power_on_latency_ns = 2000000, 251 }; 252 253 static struct imx_pm_domain imx_gpc_domains[] = { 254 [GPC_PGC_DOMAIN_ARM] = { 255 .base = { 256 .name = "ARM", 257 .flags = GENPD_FLAG_ALWAYS_ON, 258 }, 259 }, 260 [GPC_PGC_DOMAIN_PU] = { 261 .base = { 262 .name = "PU", 263 .power_off = imx6_pm_domain_power_off, 264 .power_on = imx6_pm_domain_power_on, 265 .states = &imx6_pm_domain_pu_state, 266 .state_count = 1, 267 }, 268 .reg_offs = 0x260, 269 .cntr_pdn_bit = 0, 270 }, 271 [GPC_PGC_DOMAIN_DISPLAY] = { 272 .base = { 273 .name = "DISPLAY", 274 .power_off = imx6_pm_domain_power_off, 275 .power_on = imx6_pm_domain_power_on, 276 }, 277 .reg_offs = 0x240, 278 .cntr_pdn_bit = 4, 279 }, 280 [GPC_PGC_DOMAIN_PCI] = { 281 .base = { 282 .name = "PCI", 283 .power_off = imx6_pm_domain_power_off, 284 .power_on = imx6_pm_domain_power_on, 285 }, 286 .reg_offs = 0x200, 287 .cntr_pdn_bit = 6, 288 }, 289 }; 290 291 struct imx_gpc_dt_data { 292 int num_domains; 293 bool err009619_present; 294 bool err006287_present; 295 }; 296 297 static const struct imx_gpc_dt_data imx6q_dt_data = { 298 .num_domains = 2, 299 .err009619_present = false, 300 .err006287_present = false, 301 }; 302 303 static const struct imx_gpc_dt_data imx6qp_dt_data = { 304 .num_domains = 2, 305 .err009619_present = true, 306 .err006287_present = false, 307 }; 308 309 static const struct imx_gpc_dt_data imx6sl_dt_data = { 310 .num_domains = 3, 311 .err009619_present = false, 312 .err006287_present = true, 313 }; 314 315 static const struct imx_gpc_dt_data imx6sx_dt_data = { 316 .num_domains = 4, 317 .err009619_present = false, 318 .err006287_present = false, 319 }; 320 321 static const struct of_device_id imx_gpc_dt_ids[] = { 322 { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data }, 323 { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data }, 324 { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data }, 325 { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data }, 326 { } 327 }; 328 329 static const struct regmap_range yes_ranges[] = { 330 regmap_reg_range(GPC_CNTR, GPC_CNTR), 331 regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR), 332 regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR), 333 regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR), 334 }; 335 336 static const struct regmap_access_table access_table = { 337 .yes_ranges = yes_ranges, 338 .n_yes_ranges = ARRAY_SIZE(yes_ranges), 339 }; 340 341 static const struct regmap_config imx_gpc_regmap_config = { 342 .reg_bits = 32, 343 .val_bits = 32, 344 .reg_stride = 4, 345 .rd_table = &access_table, 346 .wr_table = &access_table, 347 .max_register = 0x2ac, 348 .fast_io = true, 349 }; 350 351 static struct generic_pm_domain *imx_gpc_onecell_domains[] = { 352 &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base, 353 &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base, 354 }; 355 356 static struct genpd_onecell_data imx_gpc_onecell_data = { 357 .domains = imx_gpc_onecell_domains, 358 .num_domains = 2, 359 }; 360 361 static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap, 362 unsigned int num_domains) 363 { 364 struct imx_pm_domain *domain; 365 int i, ret; 366 367 for (i = 0; i < num_domains; i++) { 368 domain = &imx_gpc_domains[i]; 369 domain->regmap = regmap; 370 domain->ipg_rate_mhz = 66; 371 372 if (i == 1) { 373 domain->supply = devm_regulator_get(dev, "pu"); 374 if (IS_ERR(domain->supply)) 375 return PTR_ERR(domain->supply); 376 377 ret = imx_pgc_get_clocks(dev, domain); 378 if (ret) 379 goto clk_err; 380 381 domain->base.power_on(&domain->base); 382 } 383 } 384 385 for (i = 0; i < num_domains; i++) 386 pm_genpd_init(&imx_gpc_domains[i].base, NULL, false); 387 388 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 389 ret = of_genpd_add_provider_onecell(dev->of_node, 390 &imx_gpc_onecell_data); 391 if (ret) 392 goto genpd_err; 393 } 394 395 return 0; 396 397 genpd_err: 398 for (i = 0; i < num_domains; i++) 399 pm_genpd_remove(&imx_gpc_domains[i].base); 400 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 401 clk_err: 402 return ret; 403 } 404 405 static int imx_gpc_probe(struct platform_device *pdev) 406 { 407 const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev); 408 struct device_node *pgc_node; 409 struct regmap *regmap; 410 void __iomem *base; 411 int ret; 412 413 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); 414 415 /* bail out if DT too old and doesn't provide the necessary info */ 416 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && 417 !pgc_node) 418 return 0; 419 420 base = devm_platform_ioremap_resource(pdev, 0); 421 if (IS_ERR(base)) 422 return PTR_ERR(base); 423 424 regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, 425 &imx_gpc_regmap_config); 426 if (IS_ERR(regmap)) { 427 ret = PTR_ERR(regmap); 428 dev_err(&pdev->dev, "failed to init regmap: %d\n", 429 ret); 430 return ret; 431 } 432 433 /* 434 * Disable PU power down by runtime PM if ERR009619 is present. 435 * 436 * The PRE clock will be paused for several cycles when turning on the 437 * PU domain LDO from power down state. If PRE is in use at that time, 438 * the IPU/PRG cannot get the correct display data from the PRE. 439 * 440 * This is not a concern when the whole system enters suspend state, so 441 * it's safe to power down PU in this case. 442 */ 443 if (of_id_data->err009619_present) 444 imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |= 445 GENPD_FLAG_RPM_ALWAYS_ON; 446 447 /* Keep DISP always on if ERR006287 is present */ 448 if (of_id_data->err006287_present) 449 imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |= 450 GENPD_FLAG_ALWAYS_ON; 451 452 if (!pgc_node) { 453 ret = imx_gpc_old_dt_init(&pdev->dev, regmap, 454 of_id_data->num_domains); 455 if (ret) 456 return ret; 457 } else { 458 struct imx_pm_domain *domain; 459 struct platform_device *pd_pdev; 460 struct device_node *np; 461 struct clk *ipg_clk; 462 unsigned int ipg_rate_mhz; 463 int domain_index; 464 465 ipg_clk = devm_clk_get(&pdev->dev, "ipg"); 466 if (IS_ERR(ipg_clk)) 467 return PTR_ERR(ipg_clk); 468 ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000; 469 470 for_each_child_of_node(pgc_node, np) { 471 ret = of_property_read_u32(np, "reg", &domain_index); 472 if (ret) { 473 of_node_put(np); 474 return ret; 475 } 476 if (domain_index >= of_id_data->num_domains) 477 continue; 478 479 pd_pdev = platform_device_alloc("imx-pgc-power-domain", 480 domain_index); 481 if (!pd_pdev) { 482 of_node_put(np); 483 return -ENOMEM; 484 } 485 486 ret = platform_device_add_data(pd_pdev, 487 &imx_gpc_domains[domain_index], 488 sizeof(imx_gpc_domains[domain_index])); 489 if (ret) { 490 platform_device_put(pd_pdev); 491 of_node_put(np); 492 return ret; 493 } 494 domain = pd_pdev->dev.platform_data; 495 domain->regmap = regmap; 496 domain->ipg_rate_mhz = ipg_rate_mhz; 497 498 pd_pdev->dev.parent = &pdev->dev; 499 pd_pdev->dev.of_node = np; 500 pd_pdev->dev.fwnode = of_fwnode_handle(np); 501 502 ret = platform_device_add(pd_pdev); 503 if (ret) { 504 platform_device_put(pd_pdev); 505 of_node_put(np); 506 return ret; 507 } 508 } 509 } 510 511 return 0; 512 } 513 514 static int imx_gpc_remove(struct platform_device *pdev) 515 { 516 struct device_node *pgc_node; 517 int ret; 518 519 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); 520 521 /* bail out if DT too old and doesn't provide the necessary info */ 522 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && 523 !pgc_node) 524 return 0; 525 526 /* 527 * If the old DT binding is used the toplevel driver needs to 528 * de-register the power domains 529 */ 530 if (!pgc_node) { 531 of_genpd_del_provider(pdev->dev.of_node); 532 533 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base); 534 if (ret) 535 return ret; 536 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 537 538 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base); 539 if (ret) 540 return ret; 541 } 542 543 return 0; 544 } 545 546 static struct platform_driver imx_gpc_driver = { 547 .driver = { 548 .name = "imx-gpc", 549 .of_match_table = imx_gpc_dt_ids, 550 }, 551 .probe = imx_gpc_probe, 552 .remove = imx_gpc_remove, 553 }; 554 builtin_platform_driver(imx_gpc_driver) 555