pm_domains.c (34548B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Rockchip Generic power domain support. 4 * 5 * Copyright (c) 2015 ROCKCHIP, Co. Ltd. 6 */ 7 8#include <linux/io.h> 9#include <linux/iopoll.h> 10#include <linux/err.h> 11#include <linux/mutex.h> 12#include <linux/pm_clock.h> 13#include <linux/pm_domain.h> 14#include <linux/of_address.h> 15#include <linux/of_clk.h> 16#include <linux/of_platform.h> 17#include <linux/clk.h> 18#include <linux/regmap.h> 19#include <linux/mfd/syscon.h> 20#include <soc/rockchip/pm_domains.h> 21#include <dt-bindings/power/px30-power.h> 22#include <dt-bindings/power/rk3036-power.h> 23#include <dt-bindings/power/rk3066-power.h> 24#include <dt-bindings/power/rk3128-power.h> 25#include <dt-bindings/power/rk3188-power.h> 26#include <dt-bindings/power/rk3228-power.h> 27#include <dt-bindings/power/rk3288-power.h> 28#include <dt-bindings/power/rk3328-power.h> 29#include <dt-bindings/power/rk3366-power.h> 30#include <dt-bindings/power/rk3368-power.h> 31#include <dt-bindings/power/rk3399-power.h> 32#include <dt-bindings/power/rk3568-power.h> 33 34struct rockchip_domain_info { 35 const char *name; 36 int pwr_mask; 37 int status_mask; 38 int req_mask; 39 int idle_mask; 40 int ack_mask; 41 bool active_wakeup; 42 int pwr_w_mask; 43 int req_w_mask; 44}; 45 46struct rockchip_pmu_info { 47 u32 pwr_offset; 48 u32 status_offset; 49 u32 req_offset; 50 u32 idle_offset; 51 u32 ack_offset; 52 53 u32 core_pwrcnt_offset; 54 u32 gpu_pwrcnt_offset; 55 56 unsigned int core_power_transition_time; 57 unsigned int gpu_power_transition_time; 58 59 int num_domains; 60 const struct rockchip_domain_info *domain_info; 61}; 62 63#define MAX_QOS_REGS_NUM 5 64#define QOS_PRIORITY 0x08 65#define QOS_MODE 0x0c 66#define QOS_BANDWIDTH 0x10 67#define QOS_SATURATION 0x14 68#define QOS_EXTCONTROL 0x18 69 70struct rockchip_pm_domain { 71 struct generic_pm_domain genpd; 72 const struct rockchip_domain_info *info; 73 struct rockchip_pmu *pmu; 74 int num_qos; 75 struct regmap **qos_regmap; 76 u32 *qos_save_regs[MAX_QOS_REGS_NUM]; 77 int num_clks; 78 struct clk_bulk_data *clks; 79}; 80 81struct rockchip_pmu { 82 struct device *dev; 83 struct regmap *regmap; 84 const struct rockchip_pmu_info *info; 85 struct mutex mutex; /* mutex lock for pmu */ 86 struct genpd_onecell_data genpd_data; 87 struct generic_pm_domain *domains[]; 88}; 89 90#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) 91 92#define DOMAIN(_name, pwr, status, req, idle, ack, wakeup) \ 93{ \ 94 .name = _name, \ 95 .pwr_mask = (pwr), \ 96 .status_mask = (status), \ 97 .req_mask = (req), \ 98 .idle_mask = (idle), \ 99 .ack_mask = (ack), \ 100 .active_wakeup = (wakeup), \ 101} 102 103#define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup) \ 104{ \ 105 .name = _name, \ 106 .pwr_w_mask = (pwr) << 16, \ 107 .pwr_mask = (pwr), \ 108 .status_mask = (status), \ 109 .req_w_mask = (req) << 16, \ 110 .req_mask = (req), \ 111 .idle_mask = (idle), \ 112 .ack_mask = (ack), \ 113 .active_wakeup = wakeup, \ 114} 115 116#define DOMAIN_RK3036(_name, req, ack, idle, wakeup) \ 117{ \ 118 .name = _name, \ 119 .req_mask = (req), \ 120 .req_w_mask = (req) << 16, \ 121 .ack_mask = (ack), \ 122 .idle_mask = (idle), \ 123 .active_wakeup = wakeup, \ 124} 125 126#define DOMAIN_PX30(name, pwr, status, req, wakeup) \ 127 DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup) 128 129#define DOMAIN_RK3288(name, pwr, status, req, wakeup) \ 130 DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup) 131 132#define DOMAIN_RK3328(name, pwr, status, req, wakeup) \ 133 DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup) 134 135#define DOMAIN_RK3368(name, pwr, status, req, wakeup) \ 136 DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup) 137 138#define DOMAIN_RK3399(name, pwr, status, req, wakeup) \ 139 DOMAIN(name, pwr, status, req, req, req, wakeup) 140 141#define DOMAIN_RK3568(name, pwr, req, wakeup) \ 142 DOMAIN_M(name, pwr, pwr, req, req, req, wakeup) 143 144/* 145 * Dynamic Memory Controller may need to coordinate with us -- see 146 * rockchip_pmu_block(). 147 * 148 * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to 149 * block() while we're initializing the PMU. 150 */ 151static DEFINE_MUTEX(dmc_pmu_mutex); 152static struct rockchip_pmu *dmc_pmu; 153 154/* 155 * Block PMU transitions and make sure they don't interfere with ARM Trusted 156 * Firmware operations. There are two conflicts, noted in the comments below. 157 * 158 * Caller must unblock PMU transitions via rockchip_pmu_unblock(). 159 */ 160int rockchip_pmu_block(void) 161{ 162 struct rockchip_pmu *pmu; 163 struct generic_pm_domain *genpd; 164 struct rockchip_pm_domain *pd; 165 int i, ret; 166 167 mutex_lock(&dmc_pmu_mutex); 168 169 /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */ 170 if (!dmc_pmu) 171 return 0; 172 pmu = dmc_pmu; 173 174 /* 175 * mutex blocks all idle transitions: we can't touch the 176 * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted 177 * Firmware might be using it. 178 */ 179 mutex_lock(&pmu->mutex); 180 181 /* 182 * Power domain clocks: Per Rockchip, we *must* keep certain clocks 183 * enabled for the duration of power-domain transitions. Most 184 * transitions are handled by this driver, but some cases (in 185 * particular, DRAM DVFS / memory-controller idle) must be handled by 186 * firmware. Firmware can handle most clock management via a special 187 * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this 188 * doesn't handle PLLs. We can assist this transition by doing the 189 * clock management on behalf of firmware. 190 */ 191 for (i = 0; i < pmu->genpd_data.num_domains; i++) { 192 genpd = pmu->genpd_data.domains[i]; 193 if (genpd) { 194 pd = to_rockchip_pd(genpd); 195 ret = clk_bulk_enable(pd->num_clks, pd->clks); 196 if (ret < 0) { 197 dev_err(pmu->dev, 198 "failed to enable clks for domain '%s': %d\n", 199 genpd->name, ret); 200 goto err; 201 } 202 } 203 } 204 205 return 0; 206 207err: 208 for (i = i - 1; i >= 0; i--) { 209 genpd = pmu->genpd_data.domains[i]; 210 if (genpd) { 211 pd = to_rockchip_pd(genpd); 212 clk_bulk_disable(pd->num_clks, pd->clks); 213 } 214 } 215 mutex_unlock(&pmu->mutex); 216 mutex_unlock(&dmc_pmu_mutex); 217 218 return ret; 219} 220EXPORT_SYMBOL_GPL(rockchip_pmu_block); 221 222/* Unblock PMU transitions. */ 223void rockchip_pmu_unblock(void) 224{ 225 struct rockchip_pmu *pmu; 226 struct generic_pm_domain *genpd; 227 struct rockchip_pm_domain *pd; 228 int i; 229 230 if (dmc_pmu) { 231 pmu = dmc_pmu; 232 for (i = 0; i < pmu->genpd_data.num_domains; i++) { 233 genpd = pmu->genpd_data.domains[i]; 234 if (genpd) { 235 pd = to_rockchip_pd(genpd); 236 clk_bulk_disable(pd->num_clks, pd->clks); 237 } 238 } 239 240 mutex_unlock(&pmu->mutex); 241 } 242 243 mutex_unlock(&dmc_pmu_mutex); 244} 245EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); 246 247static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) 248{ 249 struct rockchip_pmu *pmu = pd->pmu; 250 const struct rockchip_domain_info *pd_info = pd->info; 251 unsigned int val; 252 253 regmap_read(pmu->regmap, pmu->info->idle_offset, &val); 254 return (val & pd_info->idle_mask) == pd_info->idle_mask; 255} 256 257static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu) 258{ 259 unsigned int val; 260 261 regmap_read(pmu->regmap, pmu->info->ack_offset, &val); 262 return val; 263} 264 265static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, 266 bool idle) 267{ 268 const struct rockchip_domain_info *pd_info = pd->info; 269 struct generic_pm_domain *genpd = &pd->genpd; 270 struct rockchip_pmu *pmu = pd->pmu; 271 unsigned int target_ack; 272 unsigned int val; 273 bool is_idle; 274 int ret; 275 276 if (pd_info->req_mask == 0) 277 return 0; 278 else if (pd_info->req_w_mask) 279 regmap_write(pmu->regmap, pmu->info->req_offset, 280 idle ? (pd_info->req_mask | pd_info->req_w_mask) : 281 pd_info->req_w_mask); 282 else 283 regmap_update_bits(pmu->regmap, pmu->info->req_offset, 284 pd_info->req_mask, idle ? -1U : 0); 285 286 wmb(); 287 288 /* Wait util idle_ack = 1 */ 289 target_ack = idle ? pd_info->ack_mask : 0; 290 ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val, 291 (val & pd_info->ack_mask) == target_ack, 292 0, 10000); 293 if (ret) { 294 dev_err(pmu->dev, 295 "failed to get ack on domain '%s', val=0x%x\n", 296 genpd->name, val); 297 return ret; 298 } 299 300 ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd, 301 is_idle, is_idle == idle, 0, 10000); 302 if (ret) { 303 dev_err(pmu->dev, 304 "failed to set idle on domain '%s', val=%d\n", 305 genpd->name, is_idle); 306 return ret; 307 } 308 309 return 0; 310} 311 312static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) 313{ 314 int i; 315 316 for (i = 0; i < pd->num_qos; i++) { 317 regmap_read(pd->qos_regmap[i], 318 QOS_PRIORITY, 319 &pd->qos_save_regs[0][i]); 320 regmap_read(pd->qos_regmap[i], 321 QOS_MODE, 322 &pd->qos_save_regs[1][i]); 323 regmap_read(pd->qos_regmap[i], 324 QOS_BANDWIDTH, 325 &pd->qos_save_regs[2][i]); 326 regmap_read(pd->qos_regmap[i], 327 QOS_SATURATION, 328 &pd->qos_save_regs[3][i]); 329 regmap_read(pd->qos_regmap[i], 330 QOS_EXTCONTROL, 331 &pd->qos_save_regs[4][i]); 332 } 333 return 0; 334} 335 336static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd) 337{ 338 int i; 339 340 for (i = 0; i < pd->num_qos; i++) { 341 regmap_write(pd->qos_regmap[i], 342 QOS_PRIORITY, 343 pd->qos_save_regs[0][i]); 344 regmap_write(pd->qos_regmap[i], 345 QOS_MODE, 346 pd->qos_save_regs[1][i]); 347 regmap_write(pd->qos_regmap[i], 348 QOS_BANDWIDTH, 349 pd->qos_save_regs[2][i]); 350 regmap_write(pd->qos_regmap[i], 351 QOS_SATURATION, 352 pd->qos_save_regs[3][i]); 353 regmap_write(pd->qos_regmap[i], 354 QOS_EXTCONTROL, 355 pd->qos_save_regs[4][i]); 356 } 357 358 return 0; 359} 360 361static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) 362{ 363 struct rockchip_pmu *pmu = pd->pmu; 364 unsigned int val; 365 366 /* check idle status for idle-only domains */ 367 if (pd->info->status_mask == 0) 368 return !rockchip_pmu_domain_is_idle(pd); 369 370 regmap_read(pmu->regmap, pmu->info->status_offset, &val); 371 372 /* 1'b0: power on, 1'b1: power off */ 373 return !(val & pd->info->status_mask); 374} 375 376static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, 377 bool on) 378{ 379 struct rockchip_pmu *pmu = pd->pmu; 380 struct generic_pm_domain *genpd = &pd->genpd; 381 bool is_on; 382 383 if (pd->info->pwr_mask == 0) 384 return; 385 else if (pd->info->pwr_w_mask) 386 regmap_write(pmu->regmap, pmu->info->pwr_offset, 387 on ? pd->info->pwr_w_mask : 388 (pd->info->pwr_mask | pd->info->pwr_w_mask)); 389 else 390 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, 391 pd->info->pwr_mask, on ? 0 : -1U); 392 393 wmb(); 394 395 if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, 396 is_on == on, 0, 10000)) { 397 dev_err(pmu->dev, 398 "failed to set domain '%s', val=%d\n", 399 genpd->name, is_on); 400 return; 401 } 402} 403 404static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) 405{ 406 struct rockchip_pmu *pmu = pd->pmu; 407 int ret; 408 409 mutex_lock(&pmu->mutex); 410 411 if (rockchip_pmu_domain_is_on(pd) != power_on) { 412 ret = clk_bulk_enable(pd->num_clks, pd->clks); 413 if (ret < 0) { 414 dev_err(pmu->dev, "failed to enable clocks\n"); 415 mutex_unlock(&pmu->mutex); 416 return ret; 417 } 418 419 if (!power_on) { 420 rockchip_pmu_save_qos(pd); 421 422 /* if powering down, idle request to NIU first */ 423 rockchip_pmu_set_idle_request(pd, true); 424 } 425 426 rockchip_do_pmu_set_power_domain(pd, power_on); 427 428 if (power_on) { 429 /* if powering up, leave idle mode */ 430 rockchip_pmu_set_idle_request(pd, false); 431 432 rockchip_pmu_restore_qos(pd); 433 } 434 435 clk_bulk_disable(pd->num_clks, pd->clks); 436 } 437 438 mutex_unlock(&pmu->mutex); 439 return 0; 440} 441 442static int rockchip_pd_power_on(struct generic_pm_domain *domain) 443{ 444 struct rockchip_pm_domain *pd = to_rockchip_pd(domain); 445 446 return rockchip_pd_power(pd, true); 447} 448 449static int rockchip_pd_power_off(struct generic_pm_domain *domain) 450{ 451 struct rockchip_pm_domain *pd = to_rockchip_pd(domain); 452 453 return rockchip_pd_power(pd, false); 454} 455 456static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd, 457 struct device *dev) 458{ 459 struct clk *clk; 460 int i; 461 int error; 462 463 dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name); 464 465 error = pm_clk_create(dev); 466 if (error) { 467 dev_err(dev, "pm_clk_create failed %d\n", error); 468 return error; 469 } 470 471 i = 0; 472 while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) { 473 dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk); 474 error = pm_clk_add_clk(dev, clk); 475 if (error) { 476 dev_err(dev, "pm_clk_add_clk failed %d\n", error); 477 clk_put(clk); 478 pm_clk_destroy(dev); 479 return error; 480 } 481 } 482 483 return 0; 484} 485 486static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd, 487 struct device *dev) 488{ 489 dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name); 490 491 pm_clk_destroy(dev); 492} 493 494static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, 495 struct device_node *node) 496{ 497 const struct rockchip_domain_info *pd_info; 498 struct rockchip_pm_domain *pd; 499 struct device_node *qos_node; 500 int i, j; 501 u32 id; 502 int error; 503 504 error = of_property_read_u32(node, "reg", &id); 505 if (error) { 506 dev_err(pmu->dev, 507 "%pOFn: failed to retrieve domain id (reg): %d\n", 508 node, error); 509 return -EINVAL; 510 } 511 512 if (id >= pmu->info->num_domains) { 513 dev_err(pmu->dev, "%pOFn: invalid domain id %d\n", 514 node, id); 515 return -EINVAL; 516 } 517 518 pd_info = &pmu->info->domain_info[id]; 519 if (!pd_info) { 520 dev_err(pmu->dev, "%pOFn: undefined domain id %d\n", 521 node, id); 522 return -EINVAL; 523 } 524 525 pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL); 526 if (!pd) 527 return -ENOMEM; 528 529 pd->info = pd_info; 530 pd->pmu = pmu; 531 532 pd->num_clks = of_clk_get_parent_count(node); 533 if (pd->num_clks > 0) { 534 pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, 535 sizeof(*pd->clks), GFP_KERNEL); 536 if (!pd->clks) 537 return -ENOMEM; 538 } else { 539 dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n", 540 node, pd->num_clks); 541 pd->num_clks = 0; 542 } 543 544 for (i = 0; i < pd->num_clks; i++) { 545 pd->clks[i].clk = of_clk_get(node, i); 546 if (IS_ERR(pd->clks[i].clk)) { 547 error = PTR_ERR(pd->clks[i].clk); 548 dev_err(pmu->dev, 549 "%pOFn: failed to get clk at index %d: %d\n", 550 node, i, error); 551 return error; 552 } 553 } 554 555 error = clk_bulk_prepare(pd->num_clks, pd->clks); 556 if (error) 557 goto err_put_clocks; 558 559 pd->num_qos = of_count_phandle_with_args(node, "pm_qos", 560 NULL); 561 562 if (pd->num_qos > 0) { 563 pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, 564 sizeof(*pd->qos_regmap), 565 GFP_KERNEL); 566 if (!pd->qos_regmap) { 567 error = -ENOMEM; 568 goto err_unprepare_clocks; 569 } 570 571 for (j = 0; j < MAX_QOS_REGS_NUM; j++) { 572 pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, 573 pd->num_qos, 574 sizeof(u32), 575 GFP_KERNEL); 576 if (!pd->qos_save_regs[j]) { 577 error = -ENOMEM; 578 goto err_unprepare_clocks; 579 } 580 } 581 582 for (j = 0; j < pd->num_qos; j++) { 583 qos_node = of_parse_phandle(node, "pm_qos", j); 584 if (!qos_node) { 585 error = -ENODEV; 586 goto err_unprepare_clocks; 587 } 588 pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); 589 if (IS_ERR(pd->qos_regmap[j])) { 590 error = -ENODEV; 591 of_node_put(qos_node); 592 goto err_unprepare_clocks; 593 } 594 of_node_put(qos_node); 595 } 596 } 597 598 error = rockchip_pd_power(pd, true); 599 if (error) { 600 dev_err(pmu->dev, 601 "failed to power on domain '%pOFn': %d\n", 602 node, error); 603 goto err_unprepare_clocks; 604 } 605 606 if (pd->info->name) 607 pd->genpd.name = pd->info->name; 608 else 609 pd->genpd.name = kbasename(node->full_name); 610 pd->genpd.power_off = rockchip_pd_power_off; 611 pd->genpd.power_on = rockchip_pd_power_on; 612 pd->genpd.attach_dev = rockchip_pd_attach_dev; 613 pd->genpd.detach_dev = rockchip_pd_detach_dev; 614 pd->genpd.flags = GENPD_FLAG_PM_CLK; 615 if (pd_info->active_wakeup) 616 pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; 617 pm_genpd_init(&pd->genpd, NULL, false); 618 619 pmu->genpd_data.domains[id] = &pd->genpd; 620 return 0; 621 622err_unprepare_clocks: 623 clk_bulk_unprepare(pd->num_clks, pd->clks); 624err_put_clocks: 625 clk_bulk_put(pd->num_clks, pd->clks); 626 return error; 627} 628 629static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) 630{ 631 int ret; 632 633 /* 634 * We're in the error cleanup already, so we only complain, 635 * but won't emit another error on top of the original one. 636 */ 637 ret = pm_genpd_remove(&pd->genpd); 638 if (ret < 0) 639 dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n", 640 pd->genpd.name, ret); 641 642 clk_bulk_unprepare(pd->num_clks, pd->clks); 643 clk_bulk_put(pd->num_clks, pd->clks); 644 645 /* protect the zeroing of pm->num_clks */ 646 mutex_lock(&pd->pmu->mutex); 647 pd->num_clks = 0; 648 mutex_unlock(&pd->pmu->mutex); 649 650 /* devm will free our memory */ 651} 652 653static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu) 654{ 655 struct generic_pm_domain *genpd; 656 struct rockchip_pm_domain *pd; 657 int i; 658 659 for (i = 0; i < pmu->genpd_data.num_domains; i++) { 660 genpd = pmu->genpd_data.domains[i]; 661 if (genpd) { 662 pd = to_rockchip_pd(genpd); 663 rockchip_pm_remove_one_domain(pd); 664 } 665 } 666 667 /* devm will free our memory */ 668} 669 670static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu, 671 u32 domain_reg_offset, 672 unsigned int count) 673{ 674 /* First configure domain power down transition count ... */ 675 regmap_write(pmu->regmap, domain_reg_offset, count); 676 /* ... and then power up count. */ 677 regmap_write(pmu->regmap, domain_reg_offset + 4, count); 678} 679 680static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, 681 struct device_node *parent) 682{ 683 struct device_node *np; 684 struct generic_pm_domain *child_domain, *parent_domain; 685 int error; 686 687 for_each_child_of_node(parent, np) { 688 u32 idx; 689 690 error = of_property_read_u32(parent, "reg", &idx); 691 if (error) { 692 dev_err(pmu->dev, 693 "%pOFn: failed to retrieve domain id (reg): %d\n", 694 parent, error); 695 goto err_out; 696 } 697 parent_domain = pmu->genpd_data.domains[idx]; 698 699 error = rockchip_pm_add_one_domain(pmu, np); 700 if (error) { 701 dev_err(pmu->dev, "failed to handle node %pOFn: %d\n", 702 np, error); 703 goto err_out; 704 } 705 706 error = of_property_read_u32(np, "reg", &idx); 707 if (error) { 708 dev_err(pmu->dev, 709 "%pOFn: failed to retrieve domain id (reg): %d\n", 710 np, error); 711 goto err_out; 712 } 713 child_domain = pmu->genpd_data.domains[idx]; 714 715 error = pm_genpd_add_subdomain(parent_domain, child_domain); 716 if (error) { 717 dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n", 718 parent_domain->name, child_domain->name, error); 719 goto err_out; 720 } else { 721 dev_dbg(pmu->dev, "%s add subdomain: %s\n", 722 parent_domain->name, child_domain->name); 723 } 724 725 rockchip_pm_add_subdomain(pmu, np); 726 } 727 728 return 0; 729 730err_out: 731 of_node_put(np); 732 return error; 733} 734 735static int rockchip_pm_domain_probe(struct platform_device *pdev) 736{ 737 struct device *dev = &pdev->dev; 738 struct device_node *np = dev->of_node; 739 struct device_node *node; 740 struct device *parent; 741 struct rockchip_pmu *pmu; 742 const struct of_device_id *match; 743 const struct rockchip_pmu_info *pmu_info; 744 int error; 745 746 if (!np) { 747 dev_err(dev, "device tree node not found\n"); 748 return -ENODEV; 749 } 750 751 match = of_match_device(dev->driver->of_match_table, dev); 752 if (!match || !match->data) { 753 dev_err(dev, "missing pmu data\n"); 754 return -EINVAL; 755 } 756 757 pmu_info = match->data; 758 759 pmu = devm_kzalloc(dev, 760 struct_size(pmu, domains, pmu_info->num_domains), 761 GFP_KERNEL); 762 if (!pmu) 763 return -ENOMEM; 764 765 pmu->dev = &pdev->dev; 766 mutex_init(&pmu->mutex); 767 768 pmu->info = pmu_info; 769 770 pmu->genpd_data.domains = pmu->domains; 771 pmu->genpd_data.num_domains = pmu_info->num_domains; 772 773 parent = dev->parent; 774 if (!parent) { 775 dev_err(dev, "no parent for syscon devices\n"); 776 return -ENODEV; 777 } 778 779 pmu->regmap = syscon_node_to_regmap(parent->of_node); 780 if (IS_ERR(pmu->regmap)) { 781 dev_err(dev, "no regmap available\n"); 782 return PTR_ERR(pmu->regmap); 783 } 784 785 /* 786 * Configure power up and down transition delays for CORE 787 * and GPU domains. 788 */ 789 if (pmu_info->core_power_transition_time) 790 rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset, 791 pmu_info->core_power_transition_time); 792 if (pmu_info->gpu_pwrcnt_offset) 793 rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset, 794 pmu_info->gpu_power_transition_time); 795 796 error = -ENODEV; 797 798 /* 799 * Prevent any rockchip_pmu_block() from racing with the remainder of 800 * setup (clocks, register initialization). 801 */ 802 mutex_lock(&dmc_pmu_mutex); 803 804 for_each_available_child_of_node(np, node) { 805 error = rockchip_pm_add_one_domain(pmu, node); 806 if (error) { 807 dev_err(dev, "failed to handle node %pOFn: %d\n", 808 node, error); 809 of_node_put(node); 810 goto err_out; 811 } 812 813 error = rockchip_pm_add_subdomain(pmu, node); 814 if (error < 0) { 815 dev_err(dev, "failed to handle subdomain node %pOFn: %d\n", 816 node, error); 817 of_node_put(node); 818 goto err_out; 819 } 820 } 821 822 if (error) { 823 dev_dbg(dev, "no power domains defined\n"); 824 goto err_out; 825 } 826 827 error = of_genpd_add_provider_onecell(np, &pmu->genpd_data); 828 if (error) { 829 dev_err(dev, "failed to add provider: %d\n", error); 830 goto err_out; 831 } 832 833 /* We only expect one PMU. */ 834 if (!WARN_ON_ONCE(dmc_pmu)) 835 dmc_pmu = pmu; 836 837 mutex_unlock(&dmc_pmu_mutex); 838 839 return 0; 840 841err_out: 842 rockchip_pm_domain_cleanup(pmu); 843 mutex_unlock(&dmc_pmu_mutex); 844 return error; 845} 846 847static const struct rockchip_domain_info px30_pm_domains[] = { 848 [PX30_PD_USB] = DOMAIN_PX30("usb", BIT(5), BIT(5), BIT(10), false), 849 [PX30_PD_SDCARD] = DOMAIN_PX30("sdcard", BIT(8), BIT(8), BIT(9), false), 850 [PX30_PD_GMAC] = DOMAIN_PX30("gmac", BIT(10), BIT(10), BIT(6), false), 851 [PX30_PD_MMC_NAND] = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5), false), 852 [PX30_PD_VPU] = DOMAIN_PX30("vpu", BIT(12), BIT(12), BIT(14), false), 853 [PX30_PD_VO] = DOMAIN_PX30("vo", BIT(13), BIT(13), BIT(7), false), 854 [PX30_PD_VI] = DOMAIN_PX30("vi", BIT(14), BIT(14), BIT(8), false), 855 [PX30_PD_GPU] = DOMAIN_PX30("gpu", BIT(15), BIT(15), BIT(2), false), 856}; 857 858static const struct rockchip_domain_info rk3036_pm_domains[] = { 859 [RK3036_PD_MSCH] = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true), 860 [RK3036_PD_CORE] = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false), 861 [RK3036_PD_PERI] = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false), 862 [RK3036_PD_VIO] = DOMAIN_RK3036("vio", BIT(11), BIT(19), BIT(26), false), 863 [RK3036_PD_VPU] = DOMAIN_RK3036("vpu", BIT(10), BIT(20), BIT(27), false), 864 [RK3036_PD_GPU] = DOMAIN_RK3036("gpu", BIT(9), BIT(21), BIT(28), false), 865 [RK3036_PD_SYS] = DOMAIN_RK3036("sys", BIT(8), BIT(22), BIT(29), false), 866}; 867 868static const struct rockchip_domain_info rk3066_pm_domains[] = { 869 [RK3066_PD_GPU] = DOMAIN("gpu", BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), 870 [RK3066_PD_VIDEO] = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), 871 [RK3066_PD_VIO] = DOMAIN("vio", BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), 872 [RK3066_PD_PERI] = DOMAIN("peri", BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), 873 [RK3066_PD_CPU] = DOMAIN("cpu", 0, BIT(5), BIT(1), BIT(26), BIT(31), false), 874}; 875 876static const struct rockchip_domain_info rk3128_pm_domains[] = { 877 [RK3128_PD_CORE] = DOMAIN_RK3288("core", BIT(0), BIT(0), BIT(4), false), 878 [RK3128_PD_MSCH] = DOMAIN_RK3288("msch", 0, 0, BIT(6), true), 879 [RK3128_PD_VIO] = DOMAIN_RK3288("vio", BIT(3), BIT(3), BIT(2), false), 880 [RK3128_PD_VIDEO] = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false), 881 [RK3128_PD_GPU] = DOMAIN_RK3288("gpu", BIT(1), BIT(1), BIT(3), false), 882}; 883 884static const struct rockchip_domain_info rk3188_pm_domains[] = { 885 [RK3188_PD_GPU] = DOMAIN("gpu", BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), 886 [RK3188_PD_VIDEO] = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), 887 [RK3188_PD_VIO] = DOMAIN("vio", BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), 888 [RK3188_PD_PERI] = DOMAIN("peri", BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), 889 [RK3188_PD_CPU] = DOMAIN("cpu", BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false), 890}; 891 892static const struct rockchip_domain_info rk3228_pm_domains[] = { 893 [RK3228_PD_CORE] = DOMAIN_RK3036("core", BIT(0), BIT(0), BIT(16), true), 894 [RK3228_PD_MSCH] = DOMAIN_RK3036("msch", BIT(1), BIT(1), BIT(17), true), 895 [RK3228_PD_BUS] = DOMAIN_RK3036("bus", BIT(2), BIT(2), BIT(18), true), 896 [RK3228_PD_SYS] = DOMAIN_RK3036("sys", BIT(3), BIT(3), BIT(19), true), 897 [RK3228_PD_VIO] = DOMAIN_RK3036("vio", BIT(4), BIT(4), BIT(20), false), 898 [RK3228_PD_VOP] = DOMAIN_RK3036("vop", BIT(5), BIT(5), BIT(21), false), 899 [RK3228_PD_VPU] = DOMAIN_RK3036("vpu", BIT(6), BIT(6), BIT(22), false), 900 [RK3228_PD_RKVDEC] = DOMAIN_RK3036("vdec", BIT(7), BIT(7), BIT(23), false), 901 [RK3228_PD_GPU] = DOMAIN_RK3036("gpu", BIT(8), BIT(8), BIT(24), false), 902 [RK3228_PD_PERI] = DOMAIN_RK3036("peri", BIT(9), BIT(9), BIT(25), true), 903 [RK3228_PD_GMAC] = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false), 904}; 905 906static const struct rockchip_domain_info rk3288_pm_domains[] = { 907 [RK3288_PD_VIO] = DOMAIN_RK3288("vio", BIT(7), BIT(7), BIT(4), false), 908 [RK3288_PD_HEVC] = DOMAIN_RK3288("hevc", BIT(14), BIT(10), BIT(9), false), 909 [RK3288_PD_VIDEO] = DOMAIN_RK3288("video", BIT(8), BIT(8), BIT(3), false), 910 [RK3288_PD_GPU] = DOMAIN_RK3288("gpu", BIT(9), BIT(9), BIT(2), false), 911}; 912 913static const struct rockchip_domain_info rk3328_pm_domains[] = { 914 [RK3328_PD_CORE] = DOMAIN_RK3328("core", 0, BIT(0), BIT(0), false), 915 [RK3328_PD_GPU] = DOMAIN_RK3328("gpu", 0, BIT(1), BIT(1), false), 916 [RK3328_PD_BUS] = DOMAIN_RK3328("bus", 0, BIT(2), BIT(2), true), 917 [RK3328_PD_MSCH] = DOMAIN_RK3328("msch", 0, BIT(3), BIT(3), true), 918 [RK3328_PD_PERI] = DOMAIN_RK3328("peri", 0, BIT(4), BIT(4), true), 919 [RK3328_PD_VIDEO] = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false), 920 [RK3328_PD_HEVC] = DOMAIN_RK3328("hevc", 0, BIT(6), BIT(6), false), 921 [RK3328_PD_VIO] = DOMAIN_RK3328("vio", 0, BIT(8), BIT(8), false), 922 [RK3328_PD_VPU] = DOMAIN_RK3328("vpu", 0, BIT(9), BIT(9), false), 923}; 924 925static const struct rockchip_domain_info rk3366_pm_domains[] = { 926 [RK3366_PD_PERI] = DOMAIN_RK3368("peri", BIT(10), BIT(10), BIT(6), true), 927 [RK3366_PD_VIO] = DOMAIN_RK3368("vio", BIT(14), BIT(14), BIT(8), false), 928 [RK3366_PD_VIDEO] = DOMAIN_RK3368("video", BIT(13), BIT(13), BIT(7), false), 929 [RK3366_PD_RKVDEC] = DOMAIN_RK3368("vdec", BIT(11), BIT(11), BIT(7), false), 930 [RK3366_PD_WIFIBT] = DOMAIN_RK3368("wifibt", BIT(8), BIT(8), BIT(9), false), 931 [RK3366_PD_VPU] = DOMAIN_RK3368("vpu", BIT(12), BIT(12), BIT(7), false), 932 [RK3366_PD_GPU] = DOMAIN_RK3368("gpu", BIT(15), BIT(15), BIT(2), false), 933}; 934 935static const struct rockchip_domain_info rk3368_pm_domains[] = { 936 [RK3368_PD_PERI] = DOMAIN_RK3368("peri", BIT(13), BIT(12), BIT(6), true), 937 [RK3368_PD_VIO] = DOMAIN_RK3368("vio", BIT(15), BIT(14), BIT(8), false), 938 [RK3368_PD_VIDEO] = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false), 939 [RK3368_PD_GPU_0] = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false), 940 [RK3368_PD_GPU_1] = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false), 941}; 942 943static const struct rockchip_domain_info rk3399_pm_domains[] = { 944 [RK3399_PD_TCPD0] = DOMAIN_RK3399("tcpd0", BIT(8), BIT(8), 0, false), 945 [RK3399_PD_TCPD1] = DOMAIN_RK3399("tcpd1", BIT(9), BIT(9), 0, false), 946 [RK3399_PD_CCI] = DOMAIN_RK3399("cci", BIT(10), BIT(10), 0, true), 947 [RK3399_PD_CCI0] = DOMAIN_RK3399("cci0", 0, 0, BIT(15), true), 948 [RK3399_PD_CCI1] = DOMAIN_RK3399("cci1", 0, 0, BIT(16), true), 949 [RK3399_PD_PERILP] = DOMAIN_RK3399("perilp", BIT(11), BIT(11), BIT(1), true), 950 [RK3399_PD_PERIHP] = DOMAIN_RK3399("perihp", BIT(12), BIT(12), BIT(2), true), 951 [RK3399_PD_CENTER] = DOMAIN_RK3399("center", BIT(13), BIT(13), BIT(14), true), 952 [RK3399_PD_VIO] = DOMAIN_RK3399("vio", BIT(14), BIT(14), BIT(17), false), 953 [RK3399_PD_GPU] = DOMAIN_RK3399("gpu", BIT(15), BIT(15), BIT(0), false), 954 [RK3399_PD_VCODEC] = DOMAIN_RK3399("vcodec", BIT(16), BIT(16), BIT(3), false), 955 [RK3399_PD_VDU] = DOMAIN_RK3399("vdu", BIT(17), BIT(17), BIT(4), false), 956 [RK3399_PD_RGA] = DOMAIN_RK3399("rga", BIT(18), BIT(18), BIT(5), false), 957 [RK3399_PD_IEP] = DOMAIN_RK3399("iep", BIT(19), BIT(19), BIT(6), false), 958 [RK3399_PD_VO] = DOMAIN_RK3399("vo", BIT(20), BIT(20), 0, false), 959 [RK3399_PD_VOPB] = DOMAIN_RK3399("vopb", 0, 0, BIT(7), false), 960 [RK3399_PD_VOPL] = DOMAIN_RK3399("vopl", 0, 0, BIT(8), false), 961 [RK3399_PD_ISP0] = DOMAIN_RK3399("isp0", BIT(22), BIT(22), BIT(9), false), 962 [RK3399_PD_ISP1] = DOMAIN_RK3399("isp1", BIT(23), BIT(23), BIT(10), false), 963 [RK3399_PD_HDCP] = DOMAIN_RK3399("hdcp", BIT(24), BIT(24), BIT(11), false), 964 [RK3399_PD_GMAC] = DOMAIN_RK3399("gmac", BIT(25), BIT(25), BIT(23), true), 965 [RK3399_PD_EMMC] = DOMAIN_RK3399("emmc", BIT(26), BIT(26), BIT(24), true), 966 [RK3399_PD_USB3] = DOMAIN_RK3399("usb3", BIT(27), BIT(27), BIT(12), true), 967 [RK3399_PD_EDP] = DOMAIN_RK3399("edp", BIT(28), BIT(28), BIT(22), false), 968 [RK3399_PD_GIC] = DOMAIN_RK3399("gic", BIT(29), BIT(29), BIT(27), true), 969 [RK3399_PD_SD] = DOMAIN_RK3399("sd", BIT(30), BIT(30), BIT(28), true), 970 [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true), 971}; 972 973static const struct rockchip_domain_info rk3568_pm_domains[] = { 974 [RK3568_PD_NPU] = DOMAIN_RK3568("npu", BIT(1), BIT(2), false), 975 [RK3568_PD_GPU] = DOMAIN_RK3568("gpu", BIT(0), BIT(1), false), 976 [RK3568_PD_VI] = DOMAIN_RK3568("vi", BIT(6), BIT(3), false), 977 [RK3568_PD_VO] = DOMAIN_RK3568("vo", BIT(7), BIT(4), false), 978 [RK3568_PD_RGA] = DOMAIN_RK3568("rga", BIT(5), BIT(5), false), 979 [RK3568_PD_VPU] = DOMAIN_RK3568("vpu", BIT(2), BIT(6), false), 980 [RK3568_PD_RKVDEC] = DOMAIN_RK3568("vdec", BIT(4), BIT(8), false), 981 [RK3568_PD_RKVENC] = DOMAIN_RK3568("venc", BIT(3), BIT(7), false), 982 [RK3568_PD_PIPE] = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false), 983}; 984 985static const struct rockchip_pmu_info px30_pmu = { 986 .pwr_offset = 0x18, 987 .status_offset = 0x20, 988 .req_offset = 0x64, 989 .idle_offset = 0x6c, 990 .ack_offset = 0x6c, 991 992 .num_domains = ARRAY_SIZE(px30_pm_domains), 993 .domain_info = px30_pm_domains, 994}; 995 996static const struct rockchip_pmu_info rk3036_pmu = { 997 .req_offset = 0x148, 998 .idle_offset = 0x14c, 999 .ack_offset = 0x14c, 1000 1001 .num_domains = ARRAY_SIZE(rk3036_pm_domains), 1002 .domain_info = rk3036_pm_domains, 1003}; 1004 1005static const struct rockchip_pmu_info rk3066_pmu = { 1006 .pwr_offset = 0x08, 1007 .status_offset = 0x0c, 1008 .req_offset = 0x38, /* PMU_MISC_CON1 */ 1009 .idle_offset = 0x0c, 1010 .ack_offset = 0x0c, 1011 1012 .num_domains = ARRAY_SIZE(rk3066_pm_domains), 1013 .domain_info = rk3066_pm_domains, 1014}; 1015 1016static const struct rockchip_pmu_info rk3128_pmu = { 1017 .pwr_offset = 0x04, 1018 .status_offset = 0x08, 1019 .req_offset = 0x0c, 1020 .idle_offset = 0x10, 1021 .ack_offset = 0x10, 1022 1023 .num_domains = ARRAY_SIZE(rk3128_pm_domains), 1024 .domain_info = rk3128_pm_domains, 1025}; 1026 1027static const struct rockchip_pmu_info rk3188_pmu = { 1028 .pwr_offset = 0x08, 1029 .status_offset = 0x0c, 1030 .req_offset = 0x38, /* PMU_MISC_CON1 */ 1031 .idle_offset = 0x0c, 1032 .ack_offset = 0x0c, 1033 1034 .num_domains = ARRAY_SIZE(rk3188_pm_domains), 1035 .domain_info = rk3188_pm_domains, 1036}; 1037 1038static const struct rockchip_pmu_info rk3228_pmu = { 1039 .req_offset = 0x40c, 1040 .idle_offset = 0x488, 1041 .ack_offset = 0x488, 1042 1043 .num_domains = ARRAY_SIZE(rk3228_pm_domains), 1044 .domain_info = rk3228_pm_domains, 1045}; 1046 1047static const struct rockchip_pmu_info rk3288_pmu = { 1048 .pwr_offset = 0x08, 1049 .status_offset = 0x0c, 1050 .req_offset = 0x10, 1051 .idle_offset = 0x14, 1052 .ack_offset = 0x14, 1053 1054 .core_pwrcnt_offset = 0x34, 1055 .gpu_pwrcnt_offset = 0x3c, 1056 1057 .core_power_transition_time = 24, /* 1us */ 1058 .gpu_power_transition_time = 24, /* 1us */ 1059 1060 .num_domains = ARRAY_SIZE(rk3288_pm_domains), 1061 .domain_info = rk3288_pm_domains, 1062}; 1063 1064static const struct rockchip_pmu_info rk3328_pmu = { 1065 .req_offset = 0x414, 1066 .idle_offset = 0x484, 1067 .ack_offset = 0x484, 1068 1069 .num_domains = ARRAY_SIZE(rk3328_pm_domains), 1070 .domain_info = rk3328_pm_domains, 1071}; 1072 1073static const struct rockchip_pmu_info rk3366_pmu = { 1074 .pwr_offset = 0x0c, 1075 .status_offset = 0x10, 1076 .req_offset = 0x3c, 1077 .idle_offset = 0x40, 1078 .ack_offset = 0x40, 1079 1080 .core_pwrcnt_offset = 0x48, 1081 .gpu_pwrcnt_offset = 0x50, 1082 1083 .core_power_transition_time = 24, 1084 .gpu_power_transition_time = 24, 1085 1086 .num_domains = ARRAY_SIZE(rk3366_pm_domains), 1087 .domain_info = rk3366_pm_domains, 1088}; 1089 1090static const struct rockchip_pmu_info rk3368_pmu = { 1091 .pwr_offset = 0x0c, 1092 .status_offset = 0x10, 1093 .req_offset = 0x3c, 1094 .idle_offset = 0x40, 1095 .ack_offset = 0x40, 1096 1097 .core_pwrcnt_offset = 0x48, 1098 .gpu_pwrcnt_offset = 0x50, 1099 1100 .core_power_transition_time = 24, 1101 .gpu_power_transition_time = 24, 1102 1103 .num_domains = ARRAY_SIZE(rk3368_pm_domains), 1104 .domain_info = rk3368_pm_domains, 1105}; 1106 1107static const struct rockchip_pmu_info rk3399_pmu = { 1108 .pwr_offset = 0x14, 1109 .status_offset = 0x18, 1110 .req_offset = 0x60, 1111 .idle_offset = 0x64, 1112 .ack_offset = 0x68, 1113 1114 /* ARM Trusted Firmware manages power transition times */ 1115 1116 .num_domains = ARRAY_SIZE(rk3399_pm_domains), 1117 .domain_info = rk3399_pm_domains, 1118}; 1119 1120static const struct rockchip_pmu_info rk3568_pmu = { 1121 .pwr_offset = 0xa0, 1122 .status_offset = 0x98, 1123 .req_offset = 0x50, 1124 .idle_offset = 0x68, 1125 .ack_offset = 0x60, 1126 1127 .num_domains = ARRAY_SIZE(rk3568_pm_domains), 1128 .domain_info = rk3568_pm_domains, 1129}; 1130 1131static const struct of_device_id rockchip_pm_domain_dt_match[] = { 1132 { 1133 .compatible = "rockchip,px30-power-controller", 1134 .data = (void *)&px30_pmu, 1135 }, 1136 { 1137 .compatible = "rockchip,rk3036-power-controller", 1138 .data = (void *)&rk3036_pmu, 1139 }, 1140 { 1141 .compatible = "rockchip,rk3066-power-controller", 1142 .data = (void *)&rk3066_pmu, 1143 }, 1144 { 1145 .compatible = "rockchip,rk3128-power-controller", 1146 .data = (void *)&rk3128_pmu, 1147 }, 1148 { 1149 .compatible = "rockchip,rk3188-power-controller", 1150 .data = (void *)&rk3188_pmu, 1151 }, 1152 { 1153 .compatible = "rockchip,rk3228-power-controller", 1154 .data = (void *)&rk3228_pmu, 1155 }, 1156 { 1157 .compatible = "rockchip,rk3288-power-controller", 1158 .data = (void *)&rk3288_pmu, 1159 }, 1160 { 1161 .compatible = "rockchip,rk3328-power-controller", 1162 .data = (void *)&rk3328_pmu, 1163 }, 1164 { 1165 .compatible = "rockchip,rk3366-power-controller", 1166 .data = (void *)&rk3366_pmu, 1167 }, 1168 { 1169 .compatible = "rockchip,rk3368-power-controller", 1170 .data = (void *)&rk3368_pmu, 1171 }, 1172 { 1173 .compatible = "rockchip,rk3399-power-controller", 1174 .data = (void *)&rk3399_pmu, 1175 }, 1176 { 1177 .compatible = "rockchip,rk3568-power-controller", 1178 .data = (void *)&rk3568_pmu, 1179 }, 1180 { /* sentinel */ }, 1181}; 1182 1183static struct platform_driver rockchip_pm_domain_driver = { 1184 .probe = rockchip_pm_domain_probe, 1185 .driver = { 1186 .name = "rockchip-pm-domain", 1187 .of_match_table = rockchip_pm_domain_dt_match, 1188 /* 1189 * We can't forcibly eject devices from the power 1190 * domain, so we can't really remove power domains 1191 * once they were added. 1192 */ 1193 .suppress_bind_attrs = true, 1194 }, 1195}; 1196 1197static int __init rockchip_pm_domain_drv_register(void) 1198{ 1199 return platform_driver_register(&rockchip_pm_domain_driver); 1200} 1201postcore_initcall(rockchip_pm_domain_drv_register);