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