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_ENAB BIT(12) 83 #define PM_ISPRSTN BIT(8) 84 #define PM_H264RSTN BIT(7) 85 #define PM_PERIRSTN BIT(6) 86 #define PM_V3DRSTN BIT(6) 87 #define PM_ISFUNC BIT(5) 88 #define PM_MRDONE BIT(4) 89 #define PM_MEMREP BIT(3) 90 #define PM_ISPOW BIT(2) 91 #define PM_POWOK BIT(1) 92 #define PM_POWUP BIT(0) 93 #define PM_INRUSH_SHIFT 13 94 #define PM_INRUSH_3_5_MA 0 95 #define PM_INRUSH_5_MA 1 96 #define PM_INRUSH_10_MA 2 97 #define PM_INRUSH_20_MA 3 98 #define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT) 99 100 #define PM_PASSWORD 0x5a000000 101 102 #define PM_WDOG_TIME_SET 0x000fffff 103 #define PM_RSTC_WRCFG_CLR 0xffffffcf 104 #define PM_RSTS_HADWRH_SET 0x00000040 105 #define PM_RSTC_WRCFG_SET 0x00000030 106 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 107 #define PM_RSTC_RESET 0x00000102 108 109 #define PM_READ(reg) readl(power->base + (reg)) 110 #define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg)) 111 112 #define ASB_BRDG_VERSION 0x00 113 #define ASB_CPR_CTRL 0x04 114 115 #define ASB_V3D_S_CTRL 0x08 116 #define ASB_V3D_M_CTRL 0x0c 117 #define ASB_ISP_S_CTRL 0x10 118 #define ASB_ISP_M_CTRL 0x14 119 #define ASB_H264_S_CTRL 0x18 120 #define ASB_H264_M_CTRL 0x1c 121 122 #define ASB_REQ_STOP BIT(0) 123 #define ASB_ACK BIT(1) 124 #define ASB_EMPTY BIT(2) 125 #define ASB_FULL BIT(3) 126 127 #define ASB_AXI_BRDG_ID 0x20 128 129 #define BCM2835_BRDG_ID 0x62726467 130 131 struct bcm2835_power_domain { 132 struct generic_pm_domain base; 133 struct bcm2835_power *power; 134 u32 domain; 135 struct clk *clk; 136 }; 137 138 struct bcm2835_power { 139 struct device *dev; 140 /* PM registers. */ 141 void __iomem *base; 142 /* AXI Async bridge registers. */ 143 void __iomem *asb; 144 /* RPiVid bridge registers. */ 145 void __iomem *rpivid_asb; 146 147 struct genpd_onecell_data pd_xlate; 148 struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT]; 149 struct reset_controller_dev reset; 150 }; 151 152 static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) 153 { 154 void __iomem *base = power->asb; 155 u64 start; 156 u32 val; 157 158 switch (reg) { 159 case 0: 160 return 0; 161 case ASB_V3D_S_CTRL: 162 case ASB_V3D_M_CTRL: 163 if (power->rpivid_asb) 164 base = power->rpivid_asb; 165 break; 166 } 167 168 start = ktime_get_ns(); 169 170 /* Enable the module's async AXI bridges. */ 171 if (enable) { 172 val = readl(base + reg) & ~ASB_REQ_STOP; 173 } else { 174 val = readl(base + reg) | ASB_REQ_STOP; 175 } 176 writel(PM_PASSWORD | val, base + reg); 177 178 while (readl(base + reg) & ASB_ACK) { 179 cpu_relax(); 180 if (ktime_get_ns() - start >= 1000) 181 return -ETIMEDOUT; 182 } 183 184 return 0; 185 } 186 187 static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg) 188 { 189 return bcm2835_asb_control(power, reg, true); 190 } 191 192 static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg) 193 { 194 return bcm2835_asb_control(power, reg, false); 195 } 196 197 static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg) 198 { 199 struct bcm2835_power *power = pd->power; 200 201 /* We don't run this on BCM2711 */ 202 if (power->rpivid_asb) 203 return 0; 204 205 /* Enable functional isolation */ 206 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC); 207 208 /* Enable electrical isolation */ 209 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); 210 211 /* Open the power switches. */ 212 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP); 213 214 return 0; 215 } 216 217 static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg) 218 { 219 struct bcm2835_power *power = pd->power; 220 struct device *dev = power->dev; 221 u64 start; 222 int ret; 223 int inrush; 224 bool powok; 225 226 /* We don't run this on BCM2711 */ 227 if (power->rpivid_asb) 228 return 0; 229 230 /* If it was already powered on by the fw, leave it that way. */ 231 if (PM_READ(pm_reg) & PM_POWUP) 232 return 0; 233 234 /* Enable power. Allowing too much current at once may result 235 * in POWOK never getting set, so start low and ramp it up as 236 * necessary to succeed. 237 */ 238 powok = false; 239 for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) { 240 PM_WRITE(pm_reg, 241 (PM_READ(pm_reg) & ~PM_INRUSH_MASK) | 242 (inrush << PM_INRUSH_SHIFT) | 243 PM_POWUP); 244 245 start = ktime_get_ns(); 246 while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) { 247 cpu_relax(); 248 if (ktime_get_ns() - start >= 3000) 249 break; 250 } 251 } 252 if (!powok) { 253 dev_err(dev, "Timeout waiting for %s power OK\n", 254 pd->base.name); 255 ret = -ETIMEDOUT; 256 goto err_disable_powup; 257 } 258 259 /* Disable electrical isolation */ 260 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW); 261 262 /* Repair memory */ 263 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP); 264 start = ktime_get_ns(); 265 while (!(PM_READ(pm_reg) & PM_MRDONE)) { 266 cpu_relax(); 267 if (ktime_get_ns() - start >= 1000) { 268 dev_err(dev, "Timeout waiting for %s memory repair\n", 269 pd->base.name); 270 ret = -ETIMEDOUT; 271 goto err_disable_ispow; 272 } 273 } 274 275 /* Disable functional isolation */ 276 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC); 277 278 return 0; 279 280 err_disable_ispow: 281 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); 282 err_disable_powup: 283 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK)); 284 return ret; 285 } 286 287 static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd, 288 u32 pm_reg, 289 u32 asb_m_reg, 290 u32 asb_s_reg, 291 u32 reset_flags) 292 { 293 struct bcm2835_power *power = pd->power; 294 int ret; 295 296 ret = clk_prepare_enable(pd->clk); 297 if (ret) { 298 dev_err(power->dev, "Failed to enable clock for %s\n", 299 pd->base.name); 300 return ret; 301 } 302 303 /* Wait 32 clocks for reset to propagate, 1 us will be enough */ 304 udelay(1); 305 306 clk_disable_unprepare(pd->clk); 307 308 /* Deassert the resets. */ 309 PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags); 310 311 ret = clk_prepare_enable(pd->clk); 312 if (ret) { 313 dev_err(power->dev, "Failed to enable clock for %s\n", 314 pd->base.name); 315 goto err_enable_resets; 316 } 317 318 ret = bcm2835_asb_enable(power, asb_m_reg); 319 if (ret) { 320 dev_err(power->dev, "Failed to enable ASB master for %s\n", 321 pd->base.name); 322 goto err_disable_clk; 323 } 324 ret = bcm2835_asb_enable(power, asb_s_reg); 325 if (ret) { 326 dev_err(power->dev, "Failed to enable ASB slave for %s\n", 327 pd->base.name); 328 goto err_disable_asb_master; 329 } 330 331 return 0; 332 333 err_disable_asb_master: 334 bcm2835_asb_disable(power, asb_m_reg); 335 err_disable_clk: 336 clk_disable_unprepare(pd->clk); 337 err_enable_resets: 338 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); 339 return ret; 340 } 341 342 static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd, 343 u32 pm_reg, 344 u32 asb_m_reg, 345 u32 asb_s_reg, 346 u32 reset_flags) 347 { 348 struct bcm2835_power *power = pd->power; 349 int ret; 350 351 ret = bcm2835_asb_disable(power, asb_s_reg); 352 if (ret) { 353 dev_warn(power->dev, "Failed to disable ASB slave for %s\n", 354 pd->base.name); 355 return ret; 356 } 357 ret = bcm2835_asb_disable(power, asb_m_reg); 358 if (ret) { 359 dev_warn(power->dev, "Failed to disable ASB master for %s\n", 360 pd->base.name); 361 bcm2835_asb_enable(power, asb_s_reg); 362 return ret; 363 } 364 365 clk_disable_unprepare(pd->clk); 366 367 /* Assert the resets. */ 368 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); 369 370 return 0; 371 } 372 373 static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain) 374 { 375 struct bcm2835_power_domain *pd = 376 container_of(domain, struct bcm2835_power_domain, base); 377 struct bcm2835_power *power = pd->power; 378 379 switch (pd->domain) { 380 case BCM2835_POWER_DOMAIN_GRAFX: 381 return bcm2835_power_power_on(pd, PM_GRAFX); 382 383 case BCM2835_POWER_DOMAIN_GRAFX_V3D: 384 return bcm2835_asb_power_on(pd, PM_GRAFX, 385 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, 386 PM_V3DRSTN); 387 388 case BCM2835_POWER_DOMAIN_IMAGE: 389 return bcm2835_power_power_on(pd, PM_IMAGE); 390 391 case BCM2835_POWER_DOMAIN_IMAGE_PERI: 392 return bcm2835_asb_power_on(pd, PM_IMAGE, 393 0, 0, 394 PM_PERIRSTN); 395 396 case BCM2835_POWER_DOMAIN_IMAGE_ISP: 397 return bcm2835_asb_power_on(pd, PM_IMAGE, 398 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, 399 PM_ISPRSTN); 400 401 case BCM2835_POWER_DOMAIN_IMAGE_H264: 402 return bcm2835_asb_power_on(pd, PM_IMAGE, 403 ASB_H264_M_CTRL, ASB_H264_S_CTRL, 404 PM_H264RSTN); 405 406 case BCM2835_POWER_DOMAIN_USB: 407 PM_WRITE(PM_USB, PM_USB_CTRLEN); 408 return 0; 409 410 case BCM2835_POWER_DOMAIN_DSI0: 411 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); 412 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN); 413 return 0; 414 415 case BCM2835_POWER_DOMAIN_DSI1: 416 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); 417 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN); 418 return 0; 419 420 case BCM2835_POWER_DOMAIN_CCP2TX: 421 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); 422 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN); 423 return 0; 424 425 case BCM2835_POWER_DOMAIN_HDMI: 426 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR); 427 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN); 428 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD); 429 usleep_range(100, 200); 430 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR); 431 return 0; 432 433 default: 434 dev_err(power->dev, "Invalid domain %d\n", pd->domain); 435 return -EINVAL; 436 } 437 } 438 439 static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain) 440 { 441 struct bcm2835_power_domain *pd = 442 container_of(domain, struct bcm2835_power_domain, base); 443 struct bcm2835_power *power = pd->power; 444 445 switch (pd->domain) { 446 case BCM2835_POWER_DOMAIN_GRAFX: 447 return bcm2835_power_power_off(pd, PM_GRAFX); 448 449 case BCM2835_POWER_DOMAIN_GRAFX_V3D: 450 return bcm2835_asb_power_off(pd, PM_GRAFX, 451 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, 452 PM_V3DRSTN); 453 454 case BCM2835_POWER_DOMAIN_IMAGE: 455 return bcm2835_power_power_off(pd, PM_IMAGE); 456 457 case BCM2835_POWER_DOMAIN_IMAGE_PERI: 458 return bcm2835_asb_power_off(pd, PM_IMAGE, 459 0, 0, 460 PM_PERIRSTN); 461 462 case BCM2835_POWER_DOMAIN_IMAGE_ISP: 463 return bcm2835_asb_power_off(pd, PM_IMAGE, 464 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, 465 PM_ISPRSTN); 466 467 case BCM2835_POWER_DOMAIN_IMAGE_H264: 468 return bcm2835_asb_power_off(pd, PM_IMAGE, 469 ASB_H264_M_CTRL, ASB_H264_S_CTRL, 470 PM_H264RSTN); 471 472 case BCM2835_POWER_DOMAIN_USB: 473 PM_WRITE(PM_USB, 0); 474 return 0; 475 476 case BCM2835_POWER_DOMAIN_DSI0: 477 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); 478 PM_WRITE(PM_DSI0, 0); 479 return 0; 480 481 case BCM2835_POWER_DOMAIN_DSI1: 482 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); 483 PM_WRITE(PM_DSI1, 0); 484 return 0; 485 486 case BCM2835_POWER_DOMAIN_CCP2TX: 487 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); 488 PM_WRITE(PM_CCP2TX, 0); 489 return 0; 490 491 case BCM2835_POWER_DOMAIN_HDMI: 492 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD); 493 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN); 494 return 0; 495 496 default: 497 dev_err(power->dev, "Invalid domain %d\n", pd->domain); 498 return -EINVAL; 499 } 500 } 501 502 static int 503 bcm2835_init_power_domain(struct bcm2835_power *power, 504 int pd_xlate_index, const char *name) 505 { 506 struct device *dev = power->dev; 507 struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index]; 508 509 dom->clk = devm_clk_get(dev->parent, name); 510 if (IS_ERR(dom->clk)) { 511 int ret = PTR_ERR(dom->clk); 512 513 if (ret == -EPROBE_DEFER) 514 return ret; 515 516 /* Some domains don't have a clk, so make sure that we 517 * don't deref an error pointer later. 518 */ 519 dom->clk = NULL; 520 } 521 522 dom->base.name = name; 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 id = readl(power->asb + ASB_AXI_BRDG_ID); 646 if (id != BCM2835_BRDG_ID /* "BRDG" */) { 647 dev_err(dev, "ASB register ID returned 0x%08x\n", id); 648 return -ENODEV; 649 } 650 651 if (power->rpivid_asb) { 652 id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID); 653 if (id != BCM2835_BRDG_ID /* "BRDG" */) { 654 dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n", 655 id); 656 return -ENODEV; 657 } 658 } 659 660 power->pd_xlate.domains = devm_kcalloc(dev, 661 ARRAY_SIZE(power_domain_names), 662 sizeof(*power->pd_xlate.domains), 663 GFP_KERNEL); 664 if (!power->pd_xlate.domains) 665 return -ENOMEM; 666 667 power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names); 668 669 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { 670 ret = bcm2835_init_power_domain(power, i, power_domain_names[i]); 671 if (ret) 672 goto fail; 673 } 674 675 for (i = 0; i < ARRAY_SIZE(domain_deps); i++) { 676 pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base, 677 &power->domains[domain_deps[i].child].base); 678 } 679 680 power->reset.owner = THIS_MODULE; 681 power->reset.nr_resets = BCM2835_RESET_COUNT; 682 power->reset.ops = &bcm2835_reset_ops; 683 power->reset.of_node = dev->parent->of_node; 684 685 ret = devm_reset_controller_register(dev, &power->reset); 686 if (ret) 687 goto fail; 688 689 of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate); 690 691 dev_info(dev, "Broadcom BCM2835 power domains driver"); 692 return 0; 693 694 fail: 695 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { 696 struct generic_pm_domain *dom = &power->domains[i].base; 697 698 if (dom->name) 699 pm_genpd_remove(dom); 700 } 701 return ret; 702 } 703 704 static struct platform_driver bcm2835_power_driver = { 705 .probe = bcm2835_power_probe, 706 .driver = { 707 .name = "bcm2835-power", 708 }, 709 }; 710 module_platform_driver(bcm2835_power_driver); 711 712 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); 713 MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset"); 714