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