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