1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Power domain driver for Broadcom BCM2835 4 * 5 * Copyright (C) 2018 Broadcom 6 */ 7 8 #include <dt-bindings/soc/bcm2835-pm.h> 9 #include <linux/clk.h> 10 #include <linux/delay.h> 11 #include <linux/io.h> 12 #include <linux/mfd/bcm2835-pm.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_domain.h> 16 #include <linux/reset-controller.h> 17 #include <linux/types.h> 18 19 #define PM_GNRIC 0x00 20 #define PM_AUDIO 0x04 21 #define PM_STATUS 0x18 22 #define PM_RSTC 0x1c 23 #define PM_RSTS 0x20 24 #define PM_WDOG 0x24 25 #define PM_PADS0 0x28 26 #define PM_PADS2 0x2c 27 #define PM_PADS3 0x30 28 #define PM_PADS4 0x34 29 #define PM_PADS5 0x38 30 #define PM_PADS6 0x3c 31 #define PM_CAM0 0x44 32 #define PM_CAM0_LDOHPEN BIT(2) 33 #define PM_CAM0_LDOLPEN BIT(1) 34 #define PM_CAM0_CTRLEN BIT(0) 35 36 #define PM_CAM1 0x48 37 #define PM_CAM1_LDOHPEN BIT(2) 38 #define PM_CAM1_LDOLPEN BIT(1) 39 #define PM_CAM1_CTRLEN BIT(0) 40 41 #define PM_CCP2TX 0x4c 42 #define PM_CCP2TX_LDOEN BIT(1) 43 #define PM_CCP2TX_CTRLEN BIT(0) 44 45 #define PM_DSI0 0x50 46 #define PM_DSI0_LDOHPEN BIT(2) 47 #define PM_DSI0_LDOLPEN BIT(1) 48 #define PM_DSI0_CTRLEN BIT(0) 49 50 #define PM_DSI1 0x54 51 #define PM_DSI1_LDOHPEN BIT(2) 52 #define PM_DSI1_LDOLPEN BIT(1) 53 #define PM_DSI1_CTRLEN BIT(0) 54 55 #define PM_HDMI 0x58 56 #define PM_HDMI_RSTDR BIT(19) 57 #define PM_HDMI_LDOPD BIT(1) 58 #define PM_HDMI_CTRLEN BIT(0) 59 60 #define PM_USB 0x5c 61 /* The power gates must be enabled with this bit before enabling the LDO in the 62 * USB block. 63 */ 64 #define PM_USB_CTRLEN BIT(0) 65 66 #define PM_PXLDO 0x60 67 #define PM_PXBG 0x64 68 #define PM_DFT 0x68 69 #define PM_SMPS 0x6c 70 #define PM_XOSC 0x70 71 #define PM_SPAREW 0x74 72 #define PM_SPARER 0x78 73 #define PM_AVS_RSTDR 0x7c 74 #define PM_AVS_STAT 0x80 75 #define PM_AVS_EVENT 0x84 76 #define PM_AVS_INTEN 0x88 77 #define PM_DUMMY 0xfc 78 79 #define PM_IMAGE 0x108 80 #define PM_GRAFX 0x10c 81 #define PM_PROC 0x110 82 #define PM_GRAFX_2712 0x304 83 #define PM_ENAB BIT(12) 84 #define PM_ISPRSTN BIT(8) 85 #define PM_H264RSTN BIT(7) 86 #define PM_PERIRSTN BIT(6) 87 #define PM_V3DRSTN BIT(6) 88 #define PM_ISFUNC BIT(5) 89 #define PM_MRDONE BIT(4) 90 #define PM_MEMREP BIT(3) 91 #define PM_ISPOW BIT(2) 92 #define PM_POWOK BIT(1) 93 #define PM_POWUP BIT(0) 94 #define PM_INRUSH_SHIFT 13 95 #define PM_INRUSH_3_5_MA 0 96 #define PM_INRUSH_5_MA 1 97 #define PM_INRUSH_10_MA 2 98 #define PM_INRUSH_20_MA 3 99 #define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT) 100 101 #define PM_PASSWORD 0x5a000000 102 103 #define PM_WDOG_TIME_SET 0x000fffff 104 #define PM_RSTC_WRCFG_CLR 0xffffffcf 105 #define PM_RSTS_HADWRH_SET 0x00000040 106 #define PM_RSTC_WRCFG_SET 0x00000030 107 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 108 #define PM_RSTC_RESET 0x00000102 109 110 #define PM_READ(reg) readl(power->base + (reg)) 111 #define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg)) 112 113 #define ASB_BRDG_VERSION 0x00 114 #define ASB_CPR_CTRL 0x04 115 116 #define ASB_V3D_S_CTRL 0x08 117 #define ASB_V3D_M_CTRL 0x0c 118 #define ASB_ISP_S_CTRL 0x10 119 #define ASB_ISP_M_CTRL 0x14 120 #define ASB_H264_S_CTRL 0x18 121 #define ASB_H264_M_CTRL 0x1c 122 123 #define ASB_REQ_STOP BIT(0) 124 #define ASB_ACK BIT(1) 125 #define ASB_EMPTY BIT(2) 126 #define ASB_FULL BIT(3) 127 128 #define ASB_AXI_BRDG_ID 0x20 129 130 #define BCM2835_BRDG_ID 0x62726467 131 132 struct bcm2835_power_domain { 133 struct generic_pm_domain base; 134 struct bcm2835_power *power; 135 u32 domain; 136 struct clk *clk; 137 }; 138 139 struct bcm2835_power { 140 struct device *dev; 141 /* PM registers. */ 142 void __iomem *base; 143 /* AXI Async bridge registers. */ 144 void __iomem *asb; 145 /* RPiVid bridge registers. */ 146 void __iomem *rpivid_asb; 147 148 struct genpd_onecell_data pd_xlate; 149 struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT]; 150 struct reset_controller_dev reset; 151 }; 152 153 static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) 154 { 155 void __iomem *base = power->asb; 156 u64 start; 157 u32 val; 158 159 switch (reg) { 160 case 0: 161 return 0; 162 case ASB_V3D_S_CTRL: 163 case ASB_V3D_M_CTRL: 164 if (power->rpivid_asb) 165 base = power->rpivid_asb; 166 break; 167 } 168 169 start = ktime_get_ns(); 170 171 /* Enable the module's async AXI bridges. */ 172 if (enable) { 173 val = readl(base + reg) & ~ASB_REQ_STOP; 174 } else { 175 val = readl(base + reg) | ASB_REQ_STOP; 176 } 177 writel(PM_PASSWORD | val, base + reg); 178 179 while (!!(readl(base + reg) & ASB_ACK) == enable) { 180 cpu_relax(); 181 if (ktime_get_ns() - start >= 1000) 182 return -ETIMEDOUT; 183 } 184 185 return 0; 186 } 187 188 static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg) 189 { 190 return bcm2835_asb_control(power, reg, true); 191 } 192 193 static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg) 194 { 195 return bcm2835_asb_control(power, reg, false); 196 } 197 198 static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg) 199 { 200 struct bcm2835_power *power = pd->power; 201 202 /* We don't run this on BCM2711 */ 203 if (power->rpivid_asb) 204 return 0; 205 206 /* Enable functional isolation */ 207 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC); 208 209 /* Enable electrical isolation */ 210 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); 211 212 /* Open the power switches. */ 213 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP); 214 215 return 0; 216 } 217 218 static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg) 219 { 220 struct bcm2835_power *power = pd->power; 221 struct device *dev = power->dev; 222 u64 start; 223 int ret; 224 int inrush; 225 bool powok; 226 227 /* We don't run this on BCM2711 */ 228 if (power->rpivid_asb) 229 return 0; 230 231 /* If it was already powered on by the fw, leave it that way. */ 232 if (PM_READ(pm_reg) & PM_POWUP) 233 return 0; 234 235 /* Enable power. Allowing too much current at once may result 236 * in POWOK never getting set, so start low and ramp it up as 237 * necessary to succeed. 238 */ 239 powok = false; 240 for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) { 241 PM_WRITE(pm_reg, 242 (PM_READ(pm_reg) & ~PM_INRUSH_MASK) | 243 (inrush << PM_INRUSH_SHIFT) | 244 PM_POWUP); 245 246 start = ktime_get_ns(); 247 while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) { 248 cpu_relax(); 249 if (ktime_get_ns() - start >= 3000) 250 break; 251 } 252 } 253 if (!powok) { 254 dev_err(dev, "Timeout waiting for %s power OK\n", 255 pd->base.name); 256 ret = -ETIMEDOUT; 257 goto err_disable_powup; 258 } 259 260 /* Disable electrical isolation */ 261 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW); 262 263 /* Repair memory */ 264 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP); 265 start = ktime_get_ns(); 266 while (!(PM_READ(pm_reg) & PM_MRDONE)) { 267 cpu_relax(); 268 if (ktime_get_ns() - start >= 1000) { 269 dev_err(dev, "Timeout waiting for %s memory repair\n", 270 pd->base.name); 271 ret = -ETIMEDOUT; 272 goto err_disable_ispow; 273 } 274 } 275 276 /* Disable functional isolation */ 277 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC); 278 279 return 0; 280 281 err_disable_ispow: 282 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); 283 err_disable_powup: 284 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK)); 285 return ret; 286 } 287 288 static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd, 289 u32 pm_reg, 290 u32 asb_m_reg, 291 u32 asb_s_reg, 292 u32 reset_flags) 293 { 294 struct bcm2835_power *power = pd->power; 295 int ret; 296 297 ret = clk_prepare_enable(pd->clk); 298 if (ret) { 299 dev_err(power->dev, "Failed to enable clock for %s\n", 300 pd->base.name); 301 return ret; 302 } 303 304 /* Wait 32 clocks for reset to propagate, 1 us will be enough */ 305 udelay(1); 306 307 clk_disable_unprepare(pd->clk); 308 309 /* Deassert the resets. */ 310 PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags); 311 312 ret = clk_prepare_enable(pd->clk); 313 if (ret) { 314 dev_err(power->dev, "Failed to enable clock for %s\n", 315 pd->base.name); 316 goto err_enable_resets; 317 } 318 319 ret = bcm2835_asb_enable(power, asb_m_reg); 320 if (ret) { 321 dev_err(power->dev, "Failed to enable ASB master for %s\n", 322 pd->base.name); 323 goto err_disable_clk; 324 } 325 ret = bcm2835_asb_enable(power, asb_s_reg); 326 if (ret) { 327 dev_err(power->dev, "Failed to enable ASB slave for %s\n", 328 pd->base.name); 329 goto err_disable_asb_master; 330 } 331 332 return 0; 333 334 err_disable_asb_master: 335 bcm2835_asb_disable(power, asb_m_reg); 336 err_disable_clk: 337 clk_disable_unprepare(pd->clk); 338 err_enable_resets: 339 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); 340 return ret; 341 } 342 343 static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd, 344 u32 pm_reg, 345 u32 asb_m_reg, 346 u32 asb_s_reg, 347 u32 reset_flags) 348 { 349 struct bcm2835_power *power = pd->power; 350 int ret; 351 352 ret = bcm2835_asb_disable(power, asb_s_reg); 353 if (ret) { 354 dev_warn(power->dev, "Failed to disable ASB slave for %s\n", 355 pd->base.name); 356 return ret; 357 } 358 ret = bcm2835_asb_disable(power, asb_m_reg); 359 if (ret) { 360 dev_warn(power->dev, "Failed to disable ASB master for %s\n", 361 pd->base.name); 362 bcm2835_asb_enable(power, asb_s_reg); 363 return ret; 364 } 365 366 clk_disable_unprepare(pd->clk); 367 368 /* Assert the resets. */ 369 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); 370 371 return 0; 372 } 373 374 static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain) 375 { 376 struct bcm2835_power_domain *pd = 377 container_of(domain, struct bcm2835_power_domain, base); 378 struct bcm2835_power *power = pd->power; 379 380 switch (pd->domain) { 381 case BCM2835_POWER_DOMAIN_GRAFX: 382 return bcm2835_power_power_on(pd, PM_GRAFX); 383 384 case BCM2835_POWER_DOMAIN_GRAFX_V3D: 385 if (!power->asb) 386 return bcm2835_asb_power_on(pd, PM_GRAFX_2712, 387 0, 0, PM_V3DRSTN); 388 return bcm2835_asb_power_on(pd, PM_GRAFX, 389 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, 390 PM_V3DRSTN); 391 392 case BCM2835_POWER_DOMAIN_IMAGE: 393 return bcm2835_power_power_on(pd, PM_IMAGE); 394 395 case BCM2835_POWER_DOMAIN_IMAGE_PERI: 396 return bcm2835_asb_power_on(pd, PM_IMAGE, 397 0, 0, 398 PM_PERIRSTN); 399 400 case BCM2835_POWER_DOMAIN_IMAGE_ISP: 401 return bcm2835_asb_power_on(pd, PM_IMAGE, 402 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, 403 PM_ISPRSTN); 404 405 case BCM2835_POWER_DOMAIN_IMAGE_H264: 406 return bcm2835_asb_power_on(pd, PM_IMAGE, 407 ASB_H264_M_CTRL, ASB_H264_S_CTRL, 408 PM_H264RSTN); 409 410 case BCM2835_POWER_DOMAIN_USB: 411 PM_WRITE(PM_USB, PM_USB_CTRLEN); 412 return 0; 413 414 case BCM2835_POWER_DOMAIN_DSI0: 415 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); 416 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN); 417 return 0; 418 419 case BCM2835_POWER_DOMAIN_DSI1: 420 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); 421 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN); 422 return 0; 423 424 case BCM2835_POWER_DOMAIN_CCP2TX: 425 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); 426 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN); 427 return 0; 428 429 case BCM2835_POWER_DOMAIN_HDMI: 430 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR); 431 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN); 432 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD); 433 usleep_range(100, 200); 434 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR); 435 return 0; 436 437 default: 438 dev_err(power->dev, "Invalid domain %d\n", pd->domain); 439 return -EINVAL; 440 } 441 } 442 443 static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain) 444 { 445 struct bcm2835_power_domain *pd = 446 container_of(domain, struct bcm2835_power_domain, base); 447 struct bcm2835_power *power = pd->power; 448 449 switch (pd->domain) { 450 case BCM2835_POWER_DOMAIN_GRAFX: 451 return bcm2835_power_power_off(pd, PM_GRAFX); 452 453 case BCM2835_POWER_DOMAIN_GRAFX_V3D: 454 if (!power->asb) 455 return bcm2835_asb_power_off(pd, PM_GRAFX_2712, 456 0, 0, PM_V3DRSTN); 457 return bcm2835_asb_power_off(pd, PM_GRAFX, 458 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, 459 PM_V3DRSTN); 460 461 case BCM2835_POWER_DOMAIN_IMAGE: 462 return bcm2835_power_power_off(pd, PM_IMAGE); 463 464 case BCM2835_POWER_DOMAIN_IMAGE_PERI: 465 return bcm2835_asb_power_off(pd, PM_IMAGE, 466 0, 0, 467 PM_PERIRSTN); 468 469 case BCM2835_POWER_DOMAIN_IMAGE_ISP: 470 return bcm2835_asb_power_off(pd, PM_IMAGE, 471 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, 472 PM_ISPRSTN); 473 474 case BCM2835_POWER_DOMAIN_IMAGE_H264: 475 return bcm2835_asb_power_off(pd, PM_IMAGE, 476 ASB_H264_M_CTRL, ASB_H264_S_CTRL, 477 PM_H264RSTN); 478 479 case BCM2835_POWER_DOMAIN_USB: 480 PM_WRITE(PM_USB, 0); 481 return 0; 482 483 case BCM2835_POWER_DOMAIN_DSI0: 484 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); 485 PM_WRITE(PM_DSI0, 0); 486 return 0; 487 488 case BCM2835_POWER_DOMAIN_DSI1: 489 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); 490 PM_WRITE(PM_DSI1, 0); 491 return 0; 492 493 case BCM2835_POWER_DOMAIN_CCP2TX: 494 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); 495 PM_WRITE(PM_CCP2TX, 0); 496 return 0; 497 498 case BCM2835_POWER_DOMAIN_HDMI: 499 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD); 500 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN); 501 return 0; 502 503 default: 504 dev_err(power->dev, "Invalid domain %d\n", pd->domain); 505 return -EINVAL; 506 } 507 } 508 509 static int 510 bcm2835_init_power_domain(struct bcm2835_power *power, 511 int pd_xlate_index, const char *name) 512 { 513 struct device *dev = power->dev; 514 struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index]; 515 516 dom->clk = devm_clk_get_optional(dev->parent, name); 517 if (IS_ERR(dom->clk)) 518 return dev_err_probe(dev, PTR_ERR(dom->clk), "Failed to get clock %s\n", 519 name); 520 521 dom->base.name = name; 522 dom->base.flags = GENPD_FLAG_ACTIVE_WAKEUP; 523 dom->base.power_on = bcm2835_power_pd_power_on; 524 dom->base.power_off = bcm2835_power_pd_power_off; 525 526 dom->domain = pd_xlate_index; 527 dom->power = power; 528 529 /* XXX: on/off at boot? */ 530 pm_genpd_init(&dom->base, NULL, true); 531 532 power->pd_xlate.domains[pd_xlate_index] = &dom->base; 533 534 return 0; 535 } 536 537 /** bcm2835_reset_reset - Resets a block that has a reset line in the 538 * PM block. 539 * 540 * The consumer of the reset controller must have the power domain up 541 * -- there's no reset ability with the power domain down. To reset 542 * the sub-block, we just disable its access to memory through the 543 * ASB, reset, and re-enable. 544 */ 545 static int bcm2835_reset_reset(struct reset_controller_dev *rcdev, 546 unsigned long id) 547 { 548 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power, 549 reset); 550 struct bcm2835_power_domain *pd; 551 int ret; 552 553 switch (id) { 554 case BCM2835_RESET_V3D: 555 pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D]; 556 break; 557 case BCM2835_RESET_H264: 558 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264]; 559 break; 560 case BCM2835_RESET_ISP: 561 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP]; 562 break; 563 default: 564 dev_err(power->dev, "Bad reset id %ld\n", id); 565 return -EINVAL; 566 } 567 568 ret = bcm2835_power_pd_power_off(&pd->base); 569 if (ret) 570 return ret; 571 572 return bcm2835_power_pd_power_on(&pd->base); 573 } 574 575 static int bcm2835_reset_status(struct reset_controller_dev *rcdev, 576 unsigned long id) 577 { 578 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power, 579 reset); 580 581 switch (id) { 582 case BCM2835_RESET_V3D: 583 return !PM_READ(PM_GRAFX & PM_V3DRSTN); 584 case BCM2835_RESET_H264: 585 return !PM_READ(PM_IMAGE & PM_H264RSTN); 586 case BCM2835_RESET_ISP: 587 return !PM_READ(PM_IMAGE & PM_ISPRSTN); 588 default: 589 return -EINVAL; 590 } 591 } 592 593 static const struct reset_control_ops bcm2835_reset_ops = { 594 .reset = bcm2835_reset_reset, 595 .status = bcm2835_reset_status, 596 }; 597 598 static const char *const power_domain_names[] = { 599 [BCM2835_POWER_DOMAIN_GRAFX] = "grafx", 600 [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d", 601 602 [BCM2835_POWER_DOMAIN_IMAGE] = "image", 603 [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image", 604 [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264", 605 [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp", 606 607 [BCM2835_POWER_DOMAIN_USB] = "usb", 608 [BCM2835_POWER_DOMAIN_DSI0] = "dsi0", 609 [BCM2835_POWER_DOMAIN_DSI1] = "dsi1", 610 [BCM2835_POWER_DOMAIN_CAM0] = "cam0", 611 [BCM2835_POWER_DOMAIN_CAM1] = "cam1", 612 [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx", 613 [BCM2835_POWER_DOMAIN_HDMI] = "hdmi", 614 }; 615 616 static int bcm2835_power_probe(struct platform_device *pdev) 617 { 618 struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent); 619 struct device *dev = &pdev->dev; 620 struct bcm2835_power *power; 621 static const struct { 622 int parent, child; 623 } domain_deps[] = { 624 { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D }, 625 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI }, 626 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 }, 627 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP }, 628 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB }, 629 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 }, 630 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 }, 631 }; 632 int ret = 0, i; 633 u32 id; 634 635 power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); 636 if (!power) 637 return -ENOMEM; 638 platform_set_drvdata(pdev, power); 639 640 power->dev = dev; 641 power->base = pm->base; 642 power->asb = pm->asb; 643 power->rpivid_asb = pm->rpivid_asb; 644 645 if (power->asb) { 646 id = readl(power->asb + ASB_AXI_BRDG_ID); 647 if (id != BCM2835_BRDG_ID /* "BRDG" */) { 648 dev_err(dev, "ASB register ID returned 0x%08x\n", id); 649 return -ENODEV; 650 } 651 } 652 653 if (power->rpivid_asb) { 654 id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID); 655 if (id != BCM2835_BRDG_ID /* "BRDG" */) { 656 dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n", 657 id); 658 return -ENODEV; 659 } 660 } 661 662 power->pd_xlate.domains = devm_kcalloc(dev, 663 ARRAY_SIZE(power_domain_names), 664 sizeof(*power->pd_xlate.domains), 665 GFP_KERNEL); 666 if (!power->pd_xlate.domains) 667 return -ENOMEM; 668 669 power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names); 670 671 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { 672 ret = bcm2835_init_power_domain(power, i, power_domain_names[i]); 673 if (ret) 674 goto fail; 675 } 676 677 for (i = 0; i < ARRAY_SIZE(domain_deps); i++) { 678 pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base, 679 &power->domains[domain_deps[i].child].base); 680 } 681 682 power->reset.owner = THIS_MODULE; 683 power->reset.nr_resets = BCM2835_RESET_COUNT; 684 power->reset.ops = &bcm2835_reset_ops; 685 power->reset.of_node = dev->parent->of_node; 686 687 ret = devm_reset_controller_register(dev, &power->reset); 688 if (ret) 689 goto fail; 690 691 of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate); 692 693 dev_info(dev, "Broadcom BCM2835 power domains driver"); 694 return 0; 695 696 fail: 697 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { 698 struct generic_pm_domain *dom = &power->domains[i].base; 699 700 if (dom->name) 701 pm_genpd_remove(dom); 702 } 703 return ret; 704 } 705 706 static struct platform_driver bcm2835_power_driver = { 707 .probe = bcm2835_power_probe, 708 .driver = { 709 .name = "bcm2835-power", 710 }, 711 }; 712 module_platform_driver(bcm2835_power_driver); 713 714 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); 715 MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset"); 716