at v4.13 489 lines 12 kB view raw
1/* 2 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 3 * Copyright 2011-2013 Freescale Semiconductor, Inc. 4 * 5 * The code contained herein is licensed under the GNU General Public 6 * License. You may obtain a copy of the GNU General Public License 7 * Version 2 or later at the following locations: 8 * 9 * http://www.opensource.org/licenses/gpl-license.html 10 * http://www.gnu.org/copyleft/gpl.html 11 */ 12 13#include <linux/clk.h> 14#include <linux/delay.h> 15#include <linux/io.h> 16#include <linux/of_device.h> 17#include <linux/platform_device.h> 18#include <linux/pm_domain.h> 19#include <linux/regmap.h> 20#include <linux/regulator/consumer.h> 21 22#define GPC_CNTR 0x000 23 24#define GPC_PGC_CTRL_OFFS 0x0 25#define GPC_PGC_PUPSCR_OFFS 0x4 26#define GPC_PGC_PDNSCR_OFFS 0x8 27#define GPC_PGC_SW2ISO_SHIFT 0x8 28#define GPC_PGC_SW_SHIFT 0x0 29 30#define GPC_PGC_GPU_PDN 0x260 31#define GPC_PGC_GPU_PUPSCR 0x264 32#define GPC_PGC_GPU_PDNSCR 0x268 33 34#define GPU_VPU_PUP_REQ BIT(1) 35#define GPU_VPU_PDN_REQ BIT(0) 36 37#define GPC_CLK_MAX 6 38 39#define PGC_DOMAIN_FLAG_NO_PD BIT(0) 40 41struct imx_pm_domain { 42 struct generic_pm_domain base; 43 struct regmap *regmap; 44 struct regulator *supply; 45 struct clk *clk[GPC_CLK_MAX]; 46 int num_clks; 47 unsigned int reg_offs; 48 signed char cntr_pdn_bit; 49 unsigned int ipg_rate_mhz; 50 unsigned int flags; 51}; 52 53static inline struct imx_pm_domain * 54to_imx_pm_domain(struct generic_pm_domain *genpd) 55{ 56 return container_of(genpd, struct imx_pm_domain, base); 57} 58 59static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) 60{ 61 struct imx_pm_domain *pd = to_imx_pm_domain(genpd); 62 int iso, iso2sw; 63 u32 val; 64 65 if (pd->flags & PGC_DOMAIN_FLAG_NO_PD) 66 return -EBUSY; 67 68 /* Read ISO and ISO2SW power down delays */ 69 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); 70 iso = val & 0x3f; 71 iso2sw = (val >> 8) & 0x3f; 72 73 /* Gate off domain when powered down */ 74 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, 75 0x1, 0x1); 76 77 /* Request GPC to power down domain */ 78 val = BIT(pd->cntr_pdn_bit); 79 regmap_update_bits(pd->regmap, GPC_CNTR, val, val); 80 81 /* Wait ISO + ISO2SW IPG clock cycles */ 82 udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz)); 83 84 if (pd->supply) 85 regulator_disable(pd->supply); 86 87 return 0; 88} 89 90static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) 91{ 92 struct imx_pm_domain *pd = to_imx_pm_domain(genpd); 93 int i, ret, sw, sw2iso; 94 u32 val; 95 96 if (pd->supply) { 97 ret = regulator_enable(pd->supply); 98 if (ret) { 99 pr_err("%s: failed to enable regulator: %d\n", 100 __func__, ret); 101 return ret; 102 } 103 } 104 105 /* Enable reset clocks for all devices in the domain */ 106 for (i = 0; i < pd->num_clks; i++) 107 clk_prepare_enable(pd->clk[i]); 108 109 /* Gate off domain when powered down */ 110 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, 111 0x1, 0x1); 112 113 /* Read ISO and ISO2SW power up delays */ 114 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); 115 sw = val & 0x3f; 116 sw2iso = (val >> 8) & 0x3f; 117 118 /* Request GPC to power up domain */ 119 val = BIT(pd->cntr_pdn_bit + 1); 120 regmap_update_bits(pd->regmap, GPC_CNTR, val, val); 121 122 /* Wait ISO + ISO2SW IPG clock cycles */ 123 udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz)); 124 125 /* Disable reset clocks for all devices in the domain */ 126 for (i = 0; i < pd->num_clks; i++) 127 clk_disable_unprepare(pd->clk[i]); 128 129 return 0; 130} 131 132static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain) 133{ 134 int i, ret; 135 136 for (i = 0; ; i++) { 137 struct clk *clk = of_clk_get(dev->of_node, i); 138 if (IS_ERR(clk)) 139 break; 140 if (i >= GPC_CLK_MAX) { 141 dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); 142 ret = -EINVAL; 143 goto clk_err; 144 } 145 domain->clk[i] = clk; 146 } 147 domain->num_clks = i; 148 149 return 0; 150 151clk_err: 152 while (i--) 153 clk_put(domain->clk[i]); 154 155 return ret; 156} 157 158static void imx_pgc_put_clocks(struct imx_pm_domain *domain) 159{ 160 int i; 161 162 for (i = domain->num_clks - 1; i >= 0; i--) 163 clk_put(domain->clk[i]); 164} 165 166static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain) 167{ 168 /* try to get the domain supply regulator */ 169 domain->supply = devm_regulator_get_optional(dev, "power"); 170 if (IS_ERR(domain->supply)) { 171 if (PTR_ERR(domain->supply) == -ENODEV) 172 domain->supply = NULL; 173 else 174 return PTR_ERR(domain->supply); 175 } 176 177 /* try to get all clocks needed for reset propagation */ 178 return imx_pgc_get_clocks(dev, domain); 179} 180 181static int imx_pgc_power_domain_probe(struct platform_device *pdev) 182{ 183 struct imx_pm_domain *domain = pdev->dev.platform_data; 184 struct device *dev = &pdev->dev; 185 int ret; 186 187 /* if this PD is associated with a DT node try to parse it */ 188 if (dev->of_node) { 189 ret = imx_pgc_parse_dt(dev, domain); 190 if (ret) 191 return ret; 192 } 193 194 /* initially power on the domain */ 195 if (domain->base.power_on) 196 domain->base.power_on(&domain->base); 197 198 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 199 pm_genpd_init(&domain->base, NULL, false); 200 ret = of_genpd_add_provider_simple(dev->of_node, &domain->base); 201 if (ret) 202 goto genpd_err; 203 } 204 205 device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE); 206 207 return 0; 208 209genpd_err: 210 pm_genpd_remove(&domain->base); 211 imx_pgc_put_clocks(domain); 212 213 return ret; 214} 215 216static int imx_pgc_power_domain_remove(struct platform_device *pdev) 217{ 218 struct imx_pm_domain *domain = pdev->dev.platform_data; 219 220 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 221 of_genpd_del_provider(pdev->dev.of_node); 222 pm_genpd_remove(&domain->base); 223 imx_pgc_put_clocks(domain); 224 } 225 226 return 0; 227} 228 229static const struct platform_device_id imx_pgc_power_domain_id[] = { 230 { "imx-pgc-power-domain"}, 231 { }, 232}; 233 234static struct platform_driver imx_pgc_power_domain_driver = { 235 .driver = { 236 .name = "imx-pgc-pd", 237 }, 238 .probe = imx_pgc_power_domain_probe, 239 .remove = imx_pgc_power_domain_remove, 240 .id_table = imx_pgc_power_domain_id, 241}; 242builtin_platform_driver(imx_pgc_power_domain_driver) 243 244#define GPC_PGC_DOMAIN_ARM 0 245#define GPC_PGC_DOMAIN_PU 1 246#define GPC_PGC_DOMAIN_DISPLAY 2 247 248static struct genpd_power_state imx6_pm_domain_pu_state = { 249 .power_off_latency_ns = 25000, 250 .power_on_latency_ns = 2000000, 251}; 252 253static struct imx_pm_domain imx_gpc_domains[] = { 254 { 255 .base = { 256 .name = "ARM", 257 }, 258 }, { 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 .base = { 270 .name = "DISPLAY", 271 .power_off = imx6_pm_domain_power_off, 272 .power_on = imx6_pm_domain_power_on, 273 }, 274 .reg_offs = 0x240, 275 .cntr_pdn_bit = 4, 276 } 277}; 278 279struct imx_gpc_dt_data { 280 int num_domains; 281 bool err009619_present; 282}; 283 284static const struct imx_gpc_dt_data imx6q_dt_data = { 285 .num_domains = 2, 286 .err009619_present = false, 287}; 288 289static const struct imx_gpc_dt_data imx6qp_dt_data = { 290 .num_domains = 2, 291 .err009619_present = true, 292}; 293 294static const struct imx_gpc_dt_data imx6sl_dt_data = { 295 .num_domains = 3, 296 .err009619_present = false, 297}; 298 299static const struct of_device_id imx_gpc_dt_ids[] = { 300 { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data }, 301 { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data }, 302 { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data }, 303 { } 304}; 305 306static const struct regmap_config imx_gpc_regmap_config = { 307 .reg_bits = 32, 308 .val_bits = 32, 309 .reg_stride = 4, 310 .max_register = 0x2ac, 311}; 312 313static struct generic_pm_domain *imx_gpc_onecell_domains[] = { 314 &imx_gpc_domains[0].base, 315 &imx_gpc_domains[1].base, 316}; 317 318static struct genpd_onecell_data imx_gpc_onecell_data = { 319 .domains = imx_gpc_onecell_domains, 320 .num_domains = 2, 321}; 322 323static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap, 324 unsigned int num_domains) 325{ 326 struct imx_pm_domain *domain; 327 int i, ret; 328 329 for (i = 0; i < num_domains; i++) { 330 domain = &imx_gpc_domains[i]; 331 domain->regmap = regmap; 332 domain->ipg_rate_mhz = 66; 333 334 if (i == 1) { 335 domain->supply = devm_regulator_get(dev, "pu"); 336 if (IS_ERR(domain->supply)) 337 return PTR_ERR(domain->supply);; 338 339 ret = imx_pgc_get_clocks(dev, domain); 340 if (ret) 341 goto clk_err; 342 343 domain->base.power_on(&domain->base); 344 } 345 } 346 347 for (i = 0; i < num_domains; i++) 348 pm_genpd_init(&imx_gpc_domains[i].base, NULL, false); 349 350 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { 351 ret = of_genpd_add_provider_onecell(dev->of_node, 352 &imx_gpc_onecell_data); 353 if (ret) 354 goto genpd_err; 355 } 356 357 return 0; 358 359genpd_err: 360 for (i = 0; i < num_domains; i++) 361 pm_genpd_remove(&imx_gpc_domains[i].base); 362 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 363clk_err: 364 return ret; 365} 366 367static int imx_gpc_probe(struct platform_device *pdev) 368{ 369 const struct of_device_id *of_id = 370 of_match_device(imx_gpc_dt_ids, &pdev->dev); 371 const struct imx_gpc_dt_data *of_id_data = of_id->data; 372 struct device_node *pgc_node; 373 struct regmap *regmap; 374 struct resource *res; 375 void __iomem *base; 376 int ret; 377 378 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); 379 380 /* bail out if DT too old and doesn't provide the necessary info */ 381 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && 382 !pgc_node) 383 return 0; 384 385 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 386 base = devm_ioremap_resource(&pdev->dev, res); 387 if (IS_ERR(base)) 388 return PTR_ERR(base); 389 390 regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, 391 &imx_gpc_regmap_config); 392 if (IS_ERR(regmap)) { 393 ret = PTR_ERR(regmap); 394 dev_err(&pdev->dev, "failed to init regmap: %d\n", 395 ret); 396 return ret; 397 } 398 399 /* Disable PU power down in normal operation if ERR009619 is present */ 400 if (of_id_data->err009619_present) 401 imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |= 402 PGC_DOMAIN_FLAG_NO_PD; 403 404 if (!pgc_node) { 405 ret = imx_gpc_old_dt_init(&pdev->dev, regmap, 406 of_id_data->num_domains); 407 if (ret) 408 return ret; 409 } else { 410 struct imx_pm_domain *domain; 411 struct platform_device *pd_pdev; 412 struct device_node *np; 413 struct clk *ipg_clk; 414 unsigned int ipg_rate_mhz; 415 int domain_index; 416 417 ipg_clk = devm_clk_get(&pdev->dev, "ipg"); 418 if (IS_ERR(ipg_clk)) 419 return PTR_ERR(ipg_clk); 420 ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000; 421 422 for_each_child_of_node(pgc_node, np) { 423 ret = of_property_read_u32(np, "reg", &domain_index); 424 if (ret) { 425 of_node_put(np); 426 return ret; 427 } 428 if (domain_index >= of_id_data->num_domains) 429 continue; 430 431 domain = &imx_gpc_domains[domain_index]; 432 domain->regmap = regmap; 433 domain->ipg_rate_mhz = ipg_rate_mhz; 434 435 pd_pdev = platform_device_alloc("imx-pgc-power-domain", 436 domain_index); 437 if (!pd_pdev) { 438 of_node_put(np); 439 return -ENOMEM; 440 } 441 pd_pdev->dev.platform_data = domain; 442 pd_pdev->dev.parent = &pdev->dev; 443 pd_pdev->dev.of_node = np; 444 445 ret = platform_device_add(pd_pdev); 446 if (ret) { 447 platform_device_put(pd_pdev); 448 of_node_put(np); 449 return ret; 450 } 451 } 452 } 453 454 return 0; 455} 456 457static int imx_gpc_remove(struct platform_device *pdev) 458{ 459 int ret; 460 461 /* 462 * If the old DT binding is used the toplevel driver needs to 463 * de-register the power domains 464 */ 465 if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) { 466 of_genpd_del_provider(pdev->dev.of_node); 467 468 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base); 469 if (ret) 470 return ret; 471 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); 472 473 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base); 474 if (ret) 475 return ret; 476 } 477 478 return 0; 479} 480 481static struct platform_driver imx_gpc_driver = { 482 .driver = { 483 .name = "imx-gpc", 484 .of_match_table = imx_gpc_dt_ids, 485 }, 486 .probe = imx_gpc_probe, 487 .remove = imx_gpc_remove, 488}; 489builtin_platform_driver(imx_gpc_driver)