1 /* 2 * OMAP powerdomain control 3 * 4 * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc. 5 * Copyright (C) 2007-2011 Nokia Corporation 6 * 7 * Written by Paul Walmsley 8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> 9 * State counting code by Tero Kristo <tero.kristo@nokia.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 #undef DEBUG 16 17 #include <linux/kernel.h> 18 #include <linux/types.h> 19 #include <linux/list.h> 20 #include <linux/errno.h> 21 #include <linux/string.h> 22 #include <trace/events/power.h> 23 24 #include "cm2xxx_3xxx.h" 25 #include "prcm44xx.h" 26 #include "cm44xx.h" 27 #include "prm2xxx_3xxx.h" 28 #include "prm44xx.h" 29 30 #include <asm/cpu.h> 31 #include <plat/cpu.h> 32 #include "powerdomain.h" 33 #include "clockdomain.h" 34 #include <plat/prcm.h> 35 36 #include "pm.h" 37 38 #define PWRDM_TRACE_STATES_FLAG (1<<31) 39 40 enum { 41 PWRDM_STATE_NOW = 0, 42 PWRDM_STATE_PREV, 43 }; 44 45 46 /* pwrdm_list contains all registered struct powerdomains */ 47 static LIST_HEAD(pwrdm_list); 48 49 static struct pwrdm_ops *arch_pwrdm; 50 51 /* Private functions */ 52 53 static struct powerdomain *_pwrdm_lookup(const char *name) 54 { 55 struct powerdomain *pwrdm, *temp_pwrdm; 56 57 pwrdm = NULL; 58 59 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { 60 if (!strcmp(name, temp_pwrdm->name)) { 61 pwrdm = temp_pwrdm; 62 break; 63 } 64 } 65 66 return pwrdm; 67 } 68 69 /** 70 * _pwrdm_register - register a powerdomain 71 * @pwrdm: struct powerdomain * to register 72 * 73 * Adds a powerdomain to the internal powerdomain list. Returns 74 * -EINVAL if given a null pointer, -EEXIST if a powerdomain is 75 * already registered by the provided name, or 0 upon success. 76 */ 77 static int _pwrdm_register(struct powerdomain *pwrdm) 78 { 79 int i; 80 struct voltagedomain *voltdm; 81 82 if (!pwrdm || !pwrdm->name) 83 return -EINVAL; 84 85 if (cpu_is_omap44xx() && 86 pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) { 87 pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n", 88 pwrdm->name); 89 return -EINVAL; 90 } 91 92 if (_pwrdm_lookup(pwrdm->name)) 93 return -EEXIST; 94 95 voltdm = voltdm_lookup(pwrdm->voltdm.name); 96 if (!voltdm) { 97 pr_err("powerdomain: %s: voltagedomain %s does not exist\n", 98 pwrdm->name, pwrdm->voltdm.name); 99 return -EINVAL; 100 } 101 pwrdm->voltdm.ptr = voltdm; 102 INIT_LIST_HEAD(&pwrdm->voltdm_node); 103 voltdm_add_pwrdm(voltdm, pwrdm); 104 105 list_add(&pwrdm->node, &pwrdm_list); 106 107 /* Initialize the powerdomain's state counter */ 108 for (i = 0; i < PWRDM_MAX_PWRSTS; i++) 109 pwrdm->state_counter[i] = 0; 110 111 pwrdm->ret_logic_off_counter = 0; 112 for (i = 0; i < pwrdm->banks; i++) 113 pwrdm->ret_mem_off_counter[i] = 0; 114 115 pwrdm_wait_transition(pwrdm); 116 pwrdm->state = pwrdm_read_pwrst(pwrdm); 117 pwrdm->state_counter[pwrdm->state] = 1; 118 119 pr_debug("powerdomain: registered %s\n", pwrdm->name); 120 121 return 0; 122 } 123 124 static void _update_logic_membank_counters(struct powerdomain *pwrdm) 125 { 126 int i; 127 u8 prev_logic_pwrst, prev_mem_pwrst; 128 129 prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm); 130 if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) && 131 (prev_logic_pwrst == PWRDM_POWER_OFF)) 132 pwrdm->ret_logic_off_counter++; 133 134 for (i = 0; i < pwrdm->banks; i++) { 135 prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i); 136 137 if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) && 138 (prev_mem_pwrst == PWRDM_POWER_OFF)) 139 pwrdm->ret_mem_off_counter[i]++; 140 } 141 } 142 143 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) 144 { 145 146 int prev, state, trace_state = 0; 147 148 if (pwrdm == NULL) 149 return -EINVAL; 150 151 state = pwrdm_read_pwrst(pwrdm); 152 153 switch (flag) { 154 case PWRDM_STATE_NOW: 155 prev = pwrdm->state; 156 break; 157 case PWRDM_STATE_PREV: 158 prev = pwrdm_read_prev_pwrst(pwrdm); 159 if (pwrdm->state != prev) 160 pwrdm->state_counter[prev]++; 161 if (prev == PWRDM_POWER_RET) 162 _update_logic_membank_counters(pwrdm); 163 /* 164 * If the power domain did not hit the desired state, 165 * generate a trace event with both the desired and hit states 166 */ 167 if (state != prev) { 168 trace_state = (PWRDM_TRACE_STATES_FLAG | 169 ((state & OMAP_POWERSTATE_MASK) << 8) | 170 ((prev & OMAP_POWERSTATE_MASK) << 0)); 171 trace_power_domain_target(pwrdm->name, trace_state, 172 smp_processor_id()); 173 } 174 break; 175 default: 176 return -EINVAL; 177 } 178 179 if (state != prev) 180 pwrdm->state_counter[state]++; 181 182 pm_dbg_update_time(pwrdm, prev); 183 184 pwrdm->state = state; 185 186 return 0; 187 } 188 189 static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused) 190 { 191 pwrdm_clear_all_prev_pwrst(pwrdm); 192 _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); 193 return 0; 194 } 195 196 static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) 197 { 198 _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV); 199 return 0; 200 } 201 202 /* Public functions */ 203 204 /** 205 * pwrdm_register_platform_funcs - register powerdomain implementation fns 206 * @po: func pointers for arch specific implementations 207 * 208 * Register the list of function pointers used to implement the 209 * powerdomain functions on different OMAP SoCs. Should be called 210 * before any other pwrdm_register*() function. Returns -EINVAL if 211 * @po is null, -EEXIST if platform functions have already been 212 * registered, or 0 upon success. 213 */ 214 int pwrdm_register_platform_funcs(struct pwrdm_ops *po) 215 { 216 if (!po) 217 return -EINVAL; 218 219 if (arch_pwrdm) 220 return -EEXIST; 221 222 arch_pwrdm = po; 223 224 return 0; 225 } 226 227 /** 228 * pwrdm_register_pwrdms - register SoC powerdomains 229 * @ps: pointer to an array of struct powerdomain to register 230 * 231 * Register the powerdomains available on a particular OMAP SoC. Must 232 * be called after pwrdm_register_platform_funcs(). May be called 233 * multiple times. Returns -EACCES if called before 234 * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is 235 * null; or 0 upon success. 236 */ 237 int pwrdm_register_pwrdms(struct powerdomain **ps) 238 { 239 struct powerdomain **p = NULL; 240 241 if (!arch_pwrdm) 242 return -EEXIST; 243 244 if (!ps) 245 return -EINVAL; 246 247 for (p = ps; *p; p++) 248 _pwrdm_register(*p); 249 250 return 0; 251 } 252 253 /** 254 * pwrdm_complete_init - set up the powerdomain layer 255 * 256 * Do whatever is necessary to initialize registered powerdomains and 257 * powerdomain code. Currently, this programs the next power state 258 * for each powerdomain to ON. This prevents powerdomains from 259 * unexpectedly losing context or entering high wakeup latency modes 260 * with non-power-management-enabled kernels. Must be called after 261 * pwrdm_register_pwrdms(). Returns -EACCES if called before 262 * pwrdm_register_pwrdms(), or 0 upon success. 263 */ 264 int pwrdm_complete_init(void) 265 { 266 struct powerdomain *temp_p; 267 268 if (list_empty(&pwrdm_list)) 269 return -EACCES; 270 271 list_for_each_entry(temp_p, &pwrdm_list, node) 272 pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON); 273 274 return 0; 275 } 276 277 /** 278 * pwrdm_lookup - look up a powerdomain by name, return a pointer 279 * @name: name of powerdomain 280 * 281 * Find a registered powerdomain by its name @name. Returns a pointer 282 * to the struct powerdomain if found, or NULL otherwise. 283 */ 284 struct powerdomain *pwrdm_lookup(const char *name) 285 { 286 struct powerdomain *pwrdm; 287 288 if (!name) 289 return NULL; 290 291 pwrdm = _pwrdm_lookup(name); 292 293 return pwrdm; 294 } 295 296 /** 297 * pwrdm_for_each - call function on each registered clockdomain 298 * @fn: callback function * 299 * 300 * Call the supplied function @fn for each registered powerdomain. 301 * The callback function @fn can return anything but 0 to bail out 302 * early from the iterator. Returns the last return value of the 303 * callback function, which should be 0 for success or anything else 304 * to indicate failure; or -EINVAL if the function pointer is null. 305 */ 306 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), 307 void *user) 308 { 309 struct powerdomain *temp_pwrdm; 310 int ret = 0; 311 312 if (!fn) 313 return -EINVAL; 314 315 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { 316 ret = (*fn)(temp_pwrdm, user); 317 if (ret) 318 break; 319 } 320 321 return ret; 322 } 323 324 /** 325 * pwrdm_add_clkdm - add a clockdomain to a powerdomain 326 * @pwrdm: struct powerdomain * to add the clockdomain to 327 * @clkdm: struct clockdomain * to associate with a powerdomain 328 * 329 * Associate the clockdomain @clkdm with a powerdomain @pwrdm. This 330 * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if 331 * presented with invalid pointers; -ENOMEM if memory could not be allocated; 332 * or 0 upon success. 333 */ 334 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) 335 { 336 int i; 337 int ret = -EINVAL; 338 339 if (!pwrdm || !clkdm) 340 return -EINVAL; 341 342 pr_debug("powerdomain: associating clockdomain %s with powerdomain " 343 "%s\n", clkdm->name, pwrdm->name); 344 345 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) { 346 if (!pwrdm->pwrdm_clkdms[i]) 347 break; 348 #ifdef DEBUG 349 if (pwrdm->pwrdm_clkdms[i] == clkdm) { 350 ret = -EINVAL; 351 goto pac_exit; 352 } 353 #endif 354 } 355 356 if (i == PWRDM_MAX_CLKDMS) { 357 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for " 358 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name); 359 WARN_ON(1); 360 ret = -ENOMEM; 361 goto pac_exit; 362 } 363 364 pwrdm->pwrdm_clkdms[i] = clkdm; 365 366 ret = 0; 367 368 pac_exit: 369 return ret; 370 } 371 372 /** 373 * pwrdm_del_clkdm - remove a clockdomain from a powerdomain 374 * @pwrdm: struct powerdomain * to add the clockdomain to 375 * @clkdm: struct clockdomain * to associate with a powerdomain 376 * 377 * Dissociate the clockdomain @clkdm from the powerdomain 378 * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT 379 * if @clkdm was not associated with the powerdomain, or 0 upon 380 * success. 381 */ 382 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) 383 { 384 int ret = -EINVAL; 385 int i; 386 387 if (!pwrdm || !clkdm) 388 return -EINVAL; 389 390 pr_debug("powerdomain: dissociating clockdomain %s from powerdomain " 391 "%s\n", clkdm->name, pwrdm->name); 392 393 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) 394 if (pwrdm->pwrdm_clkdms[i] == clkdm) 395 break; 396 397 if (i == PWRDM_MAX_CLKDMS) { 398 pr_debug("powerdomain: clkdm %s not associated with pwrdm " 399 "%s ?!\n", clkdm->name, pwrdm->name); 400 ret = -ENOENT; 401 goto pdc_exit; 402 } 403 404 pwrdm->pwrdm_clkdms[i] = NULL; 405 406 ret = 0; 407 408 pdc_exit: 409 return ret; 410 } 411 412 /** 413 * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm 414 * @pwrdm: struct powerdomain * to iterate over 415 * @fn: callback function * 416 * 417 * Call the supplied function @fn for each clockdomain in the powerdomain 418 * @pwrdm. The callback function can return anything but 0 to bail 419 * out early from the iterator. Returns -EINVAL if presented with 420 * invalid pointers; or passes along the last return value of the 421 * callback function, which should be 0 for success or anything else 422 * to indicate failure. 423 */ 424 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, 425 int (*fn)(struct powerdomain *pwrdm, 426 struct clockdomain *clkdm)) 427 { 428 int ret = 0; 429 int i; 430 431 if (!fn) 432 return -EINVAL; 433 434 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++) 435 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]); 436 437 return ret; 438 } 439 440 /** 441 * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in 442 * @pwrdm: struct powerdomain * 443 * 444 * Return a pointer to the struct voltageomain that the specified powerdomain 445 * @pwrdm exists in. 446 */ 447 struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm) 448 { 449 return pwrdm->voltdm.ptr; 450 } 451 452 /** 453 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain 454 * @pwrdm: struct powerdomain * 455 * 456 * Return the number of controllable memory banks in powerdomain @pwrdm, 457 * starting with 1. Returns -EINVAL if the powerdomain pointer is null. 458 */ 459 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) 460 { 461 if (!pwrdm) 462 return -EINVAL; 463 464 return pwrdm->banks; 465 } 466 467 /** 468 * pwrdm_set_next_pwrst - set next powerdomain power state 469 * @pwrdm: struct powerdomain * to set 470 * @pwrst: one of the PWRDM_POWER_* macros 471 * 472 * Set the powerdomain @pwrdm's next power state to @pwrst. The powerdomain 473 * may not enter this state immediately if the preconditions for this state 474 * have not been satisfied. Returns -EINVAL if the powerdomain pointer is 475 * null or if the power state is invalid for the powerdomin, or returns 0 476 * upon success. 477 */ 478 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 479 { 480 int ret = -EINVAL; 481 482 if (!pwrdm) 483 return -EINVAL; 484 485 if (!(pwrdm->pwrsts & (1 << pwrst))) 486 return -EINVAL; 487 488 pr_debug("powerdomain: setting next powerstate for %s to %0x\n", 489 pwrdm->name, pwrst); 490 491 if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) { 492 /* Trace the pwrdm desired target state */ 493 trace_power_domain_target(pwrdm->name, pwrst, 494 smp_processor_id()); 495 /* Program the pwrdm desired target state */ 496 ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); 497 } 498 499 return ret; 500 } 501 502 /** 503 * pwrdm_read_next_pwrst - get next powerdomain power state 504 * @pwrdm: struct powerdomain * to get power state 505 * 506 * Return the powerdomain @pwrdm's next power state. Returns -EINVAL 507 * if the powerdomain pointer is null or returns the next power state 508 * upon success. 509 */ 510 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) 511 { 512 int ret = -EINVAL; 513 514 if (!pwrdm) 515 return -EINVAL; 516 517 if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst) 518 ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm); 519 520 return ret; 521 } 522 523 /** 524 * pwrdm_read_pwrst - get current powerdomain power state 525 * @pwrdm: struct powerdomain * to get power state 526 * 527 * Return the powerdomain @pwrdm's current power state. Returns -EINVAL 528 * if the powerdomain pointer is null or returns the current power state 529 * upon success. 530 */ 531 int pwrdm_read_pwrst(struct powerdomain *pwrdm) 532 { 533 int ret = -EINVAL; 534 535 if (!pwrdm) 536 return -EINVAL; 537 538 if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst) 539 ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm); 540 541 return ret; 542 } 543 544 /** 545 * pwrdm_read_prev_pwrst - get previous powerdomain power state 546 * @pwrdm: struct powerdomain * to get previous power state 547 * 548 * Return the powerdomain @pwrdm's previous power state. Returns -EINVAL 549 * if the powerdomain pointer is null or returns the previous power state 550 * upon success. 551 */ 552 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 553 { 554 int ret = -EINVAL; 555 556 if (!pwrdm) 557 return -EINVAL; 558 559 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst) 560 ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm); 561 562 return ret; 563 } 564 565 /** 566 * pwrdm_set_logic_retst - set powerdomain logic power state upon retention 567 * @pwrdm: struct powerdomain * to set 568 * @pwrst: one of the PWRDM_POWER_* macros 569 * 570 * Set the next power state @pwrst that the logic portion of the 571 * powerdomain @pwrdm will enter when the powerdomain enters retention. 572 * This will be either RETENTION or OFF, if supported. Returns 573 * -EINVAL if the powerdomain pointer is null or the target power 574 * state is not not supported, or returns 0 upon success. 575 */ 576 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 577 { 578 int ret = -EINVAL; 579 580 if (!pwrdm) 581 return -EINVAL; 582 583 if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst))) 584 return -EINVAL; 585 586 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", 587 pwrdm->name, pwrst); 588 589 if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst) 590 ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst); 591 592 return ret; 593 } 594 595 /** 596 * pwrdm_set_mem_onst - set memory power state while powerdomain ON 597 * @pwrdm: struct powerdomain * to set 598 * @bank: memory bank number to set (0-3) 599 * @pwrst: one of the PWRDM_POWER_* macros 600 * 601 * Set the next power state @pwrst that memory bank @bank of the 602 * powerdomain @pwrdm will enter when the powerdomain enters the ON 603 * state. @bank will be a number from 0 to 3, and represents different 604 * types of memory, depending on the powerdomain. Returns -EINVAL if 605 * the powerdomain pointer is null or the target power state is not 606 * not supported for this memory bank, -EEXIST if the target memory 607 * bank does not exist or is not controllable, or returns 0 upon 608 * success. 609 */ 610 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 611 { 612 int ret = -EINVAL; 613 614 if (!pwrdm) 615 return -EINVAL; 616 617 if (pwrdm->banks < (bank + 1)) 618 return -EEXIST; 619 620 if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst))) 621 return -EINVAL; 622 623 pr_debug("powerdomain: setting next memory powerstate for domain %s " 624 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); 625 626 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst) 627 ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst); 628 629 return ret; 630 } 631 632 /** 633 * pwrdm_set_mem_retst - set memory power state while powerdomain in RET 634 * @pwrdm: struct powerdomain * to set 635 * @bank: memory bank number to set (0-3) 636 * @pwrst: one of the PWRDM_POWER_* macros 637 * 638 * Set the next power state @pwrst that memory bank @bank of the 639 * powerdomain @pwrdm will enter when the powerdomain enters the 640 * RETENTION state. Bank will be a number from 0 to 3, and represents 641 * different types of memory, depending on the powerdomain. @pwrst 642 * will be either RETENTION or OFF, if supported. Returns -EINVAL if 643 * the powerdomain pointer is null or the target power state is not 644 * not supported for this memory bank, -EEXIST if the target memory 645 * bank does not exist or is not controllable, or returns 0 upon 646 * success. 647 */ 648 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 649 { 650 int ret = -EINVAL; 651 652 if (!pwrdm) 653 return -EINVAL; 654 655 if (pwrdm->banks < (bank + 1)) 656 return -EEXIST; 657 658 if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst))) 659 return -EINVAL; 660 661 pr_debug("powerdomain: setting next memory powerstate for domain %s " 662 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); 663 664 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst) 665 ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst); 666 667 return ret; 668 } 669 670 /** 671 * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state 672 * @pwrdm: struct powerdomain * to get current logic retention power state 673 * 674 * Return the power state that the logic portion of powerdomain @pwrdm 675 * will enter when the powerdomain enters retention. Returns -EINVAL 676 * if the powerdomain pointer is null or returns the logic retention 677 * power state upon success. 678 */ 679 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 680 { 681 int ret = -EINVAL; 682 683 if (!pwrdm) 684 return -EINVAL; 685 686 if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst) 687 ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm); 688 689 return ret; 690 } 691 692 /** 693 * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state 694 * @pwrdm: struct powerdomain * to get previous logic power state 695 * 696 * Return the powerdomain @pwrdm's previous logic power state. Returns 697 * -EINVAL if the powerdomain pointer is null or returns the previous 698 * logic power state upon success. 699 */ 700 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) 701 { 702 int ret = -EINVAL; 703 704 if (!pwrdm) 705 return -EINVAL; 706 707 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst) 708 ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm); 709 710 return ret; 711 } 712 713 /** 714 * pwrdm_read_logic_retst - get next powerdomain logic power state 715 * @pwrdm: struct powerdomain * to get next logic power state 716 * 717 * Return the powerdomain pwrdm's logic power state. Returns -EINVAL 718 * if the powerdomain pointer is null or returns the next logic 719 * power state upon success. 720 */ 721 int pwrdm_read_logic_retst(struct powerdomain *pwrdm) 722 { 723 int ret = -EINVAL; 724 725 if (!pwrdm) 726 return -EINVAL; 727 728 if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst) 729 ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm); 730 731 return ret; 732 } 733 734 /** 735 * pwrdm_read_mem_pwrst - get current memory bank power state 736 * @pwrdm: struct powerdomain * to get current memory bank power state 737 * @bank: memory bank number (0-3) 738 * 739 * Return the powerdomain @pwrdm's current memory power state for bank 740 * @bank. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if 741 * the target memory bank does not exist or is not controllable, or 742 * returns the current memory power state upon success. 743 */ 744 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 745 { 746 int ret = -EINVAL; 747 748 if (!pwrdm) 749 return ret; 750 751 if (pwrdm->banks < (bank + 1)) 752 return ret; 753 754 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 755 bank = 1; 756 757 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst) 758 ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank); 759 760 return ret; 761 } 762 763 /** 764 * pwrdm_read_prev_mem_pwrst - get previous memory bank power state 765 * @pwrdm: struct powerdomain * to get previous memory bank power state 766 * @bank: memory bank number (0-3) 767 * 768 * Return the powerdomain @pwrdm's previous memory power state for 769 * bank @bank. Returns -EINVAL if the powerdomain pointer is null, 770 * -EEXIST if the target memory bank does not exist or is not 771 * controllable, or returns the previous memory power state upon 772 * success. 773 */ 774 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 775 { 776 int ret = -EINVAL; 777 778 if (!pwrdm) 779 return ret; 780 781 if (pwrdm->banks < (bank + 1)) 782 return ret; 783 784 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 785 bank = 1; 786 787 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst) 788 ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank); 789 790 return ret; 791 } 792 793 /** 794 * pwrdm_read_mem_retst - get next memory bank power state 795 * @pwrdm: struct powerdomain * to get mext memory bank power state 796 * @bank: memory bank number (0-3) 797 * 798 * Return the powerdomain pwrdm's next memory power state for bank 799 * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if 800 * the target memory bank does not exist or is not controllable, or 801 * returns the next memory power state upon success. 802 */ 803 int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) 804 { 805 int ret = -EINVAL; 806 807 if (!pwrdm) 808 return ret; 809 810 if (pwrdm->banks < (bank + 1)) 811 return ret; 812 813 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst) 814 ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank); 815 816 return ret; 817 } 818 819 /** 820 * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm 821 * @pwrdm: struct powerdomain * to clear 822 * 823 * Clear the powerdomain's previous power state register @pwrdm. 824 * Clears the entire register, including logic and memory bank 825 * previous power states. Returns -EINVAL if the powerdomain pointer 826 * is null, or returns 0 upon success. 827 */ 828 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 829 { 830 int ret = -EINVAL; 831 832 if (!pwrdm) 833 return ret; 834 835 /* 836 * XXX should get the powerdomain's current state here; 837 * warn & fail if it is not ON. 838 */ 839 840 pr_debug("powerdomain: clearing previous power state reg for %s\n", 841 pwrdm->name); 842 843 if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst) 844 ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm); 845 846 return ret; 847 } 848 849 /** 850 * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm 851 * @pwrdm: struct powerdomain * 852 * 853 * Enable automatic context save-and-restore upon power state change 854 * for some devices in the powerdomain @pwrdm. Warning: this only 855 * affects a subset of devices in a powerdomain; check the TRM 856 * closely. Returns -EINVAL if the powerdomain pointer is null or if 857 * the powerdomain does not support automatic save-and-restore, or 858 * returns 0 upon success. 859 */ 860 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) 861 { 862 int ret = -EINVAL; 863 864 if (!pwrdm) 865 return ret; 866 867 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 868 return ret; 869 870 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", 871 pwrdm->name); 872 873 if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar) 874 ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm); 875 876 return ret; 877 } 878 879 /** 880 * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm 881 * @pwrdm: struct powerdomain * 882 * 883 * Disable automatic context save-and-restore upon power state change 884 * for some devices in the powerdomain @pwrdm. Warning: this only 885 * affects a subset of devices in a powerdomain; check the TRM 886 * closely. Returns -EINVAL if the powerdomain pointer is null or if 887 * the powerdomain does not support automatic save-and-restore, or 888 * returns 0 upon success. 889 */ 890 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) 891 { 892 int ret = -EINVAL; 893 894 if (!pwrdm) 895 return ret; 896 897 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 898 return ret; 899 900 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", 901 pwrdm->name); 902 903 if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar) 904 ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm); 905 906 return ret; 907 } 908 909 /** 910 * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR 911 * @pwrdm: struct powerdomain * 912 * 913 * Returns 1 if powerdomain @pwrdm supports hardware save-and-restore 914 * for some devices, or 0 if it does not. 915 */ 916 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) 917 { 918 return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0; 919 } 920 921 /** 922 * pwrdm_set_lowpwrstchange - Request a low power state change 923 * @pwrdm: struct powerdomain * 924 * 925 * Allows a powerdomain to transtion to a lower power sleep state 926 * from an existing sleep state without waking up the powerdomain. 927 * Returns -EINVAL if the powerdomain pointer is null or if the 928 * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0 929 * upon success. 930 */ 931 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) 932 { 933 int ret = -EINVAL; 934 935 if (!pwrdm) 936 return -EINVAL; 937 938 if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) 939 return -EINVAL; 940 941 pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", 942 pwrdm->name); 943 944 if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange) 945 ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); 946 947 return ret; 948 } 949 950 /** 951 * pwrdm_wait_transition - wait for powerdomain power transition to finish 952 * @pwrdm: struct powerdomain * to wait for 953 * 954 * If the powerdomain @pwrdm is in the process of a state transition, 955 * spin until it completes the power transition, or until an iteration 956 * bailout value is reached. Returns -EINVAL if the powerdomain 957 * pointer is null, -EAGAIN if the bailout value was reached, or 958 * returns 0 upon success. 959 */ 960 int pwrdm_wait_transition(struct powerdomain *pwrdm) 961 { 962 int ret = -EINVAL; 963 964 if (!pwrdm) 965 return -EINVAL; 966 967 if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition) 968 ret = arch_pwrdm->pwrdm_wait_transition(pwrdm); 969 970 return ret; 971 } 972 973 int pwrdm_state_switch(struct powerdomain *pwrdm) 974 { 975 int ret; 976 977 ret = pwrdm_wait_transition(pwrdm); 978 if (!ret) 979 ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); 980 981 return ret; 982 } 983 984 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm) 985 { 986 if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) { 987 pwrdm_wait_transition(clkdm->pwrdm.ptr); 988 return pwrdm_state_switch(clkdm->pwrdm.ptr); 989 } 990 991 return -EINVAL; 992 } 993 994 int pwrdm_pre_transition(void) 995 { 996 pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); 997 return 0; 998 } 999 1000 int pwrdm_post_transition(void) 1001 { 1002 pwrdm_for_each(_pwrdm_post_transition_cb, NULL); 1003 return 0; 1004 } 1005 1006 /** 1007 * pwrdm_get_context_loss_count - get powerdomain's context loss count 1008 * @pwrdm: struct powerdomain * to wait for 1009 * 1010 * Context loss count is the sum of powerdomain off-mode counter, the 1011 * logic off counter and the per-bank memory off counter. Returns negative 1012 * (and WARNs) upon error, otherwise, returns the context loss count. 1013 */ 1014 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm) 1015 { 1016 int i, count; 1017 1018 if (!pwrdm) { 1019 WARN(1, "powerdomain: %s: pwrdm is null\n", __func__); 1020 return -ENODEV; 1021 } 1022 1023 count = pwrdm->state_counter[PWRDM_POWER_OFF]; 1024 count += pwrdm->ret_logic_off_counter; 1025 1026 for (i = 0; i < pwrdm->banks; i++) 1027 count += pwrdm->ret_mem_off_counter[i]; 1028 1029 /* 1030 * Context loss count has to be a non-negative value. Clear the sign 1031 * bit to get a value range from 0 to INT_MAX. 1032 */ 1033 count &= INT_MAX; 1034 1035 pr_debug("powerdomain: %s: context loss count = %d\n", 1036 pwrdm->name, count); 1037 1038 return count; 1039 } 1040 1041 /** 1042 * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? 1043 * @pwrdm: struct powerdomain * 1044 * 1045 * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain 1046 * can lose either memory or logic context or if @pwrdm is invalid, or 1047 * returns 0 otherwise. This function is not concerned with how the 1048 * powerdomain registers are programmed (i.e., to go off or not); it's 1049 * concerned with whether it's ever possible for this powerdomain to 1050 * go off while some other part of the chip is active. This function 1051 * assumes that every powerdomain can go to either ON or INACTIVE. 1052 */ 1053 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) 1054 { 1055 int i; 1056 1057 if (IS_ERR_OR_NULL(pwrdm)) { 1058 pr_debug("powerdomain: %s: invalid powerdomain pointer\n", 1059 __func__); 1060 return 1; 1061 } 1062 1063 if (pwrdm->pwrsts & PWRSTS_OFF) 1064 return 1; 1065 1066 if (pwrdm->pwrsts & PWRSTS_RET) { 1067 if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) 1068 return 1; 1069 1070 for (i = 0; i < pwrdm->banks; i++) 1071 if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) 1072 return 1; 1073 } 1074 1075 for (i = 0; i < pwrdm->banks; i++) 1076 if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) 1077 return 1; 1078 1079 return 0; 1080 } 1081