root/arch/arm/mach-omap2/powerdomain.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _pwrdm_lookup
  2. _pwrdm_register
  3. _update_logic_membank_counters
  4. _pwrdm_state_switch
  5. _pwrdm_pre_transition_cb
  6. _pwrdm_post_transition_cb
  7. _pwrdm_save_clkdm_state_and_activate
  8. _pwrdm_restore_clkdm_state
  9. pwrdm_register_platform_funcs
  10. pwrdm_register_pwrdms
  11. cpu_notifier
  12. pwrdm_complete_init
  13. pwrdm_lock
  14. pwrdm_unlock
  15. pwrdm_lookup
  16. pwrdm_for_each
  17. pwrdm_add_clkdm
  18. pwrdm_get_mem_bank_count
  19. pwrdm_set_next_pwrst
  20. pwrdm_read_next_pwrst
  21. pwrdm_read_pwrst
  22. pwrdm_read_prev_pwrst
  23. pwrdm_set_logic_retst
  24. pwrdm_set_mem_onst
  25. pwrdm_set_mem_retst
  26. pwrdm_read_logic_pwrst
  27. pwrdm_read_prev_logic_pwrst
  28. pwrdm_read_logic_retst
  29. pwrdm_read_mem_pwrst
  30. pwrdm_read_prev_mem_pwrst
  31. pwrdm_read_mem_retst
  32. pwrdm_clear_all_prev_pwrst
  33. pwrdm_enable_hdwr_sar
  34. pwrdm_disable_hdwr_sar
  35. pwrdm_has_hdwr_sar
  36. pwrdm_state_switch_nolock
  37. pwrdm_state_switch
  38. pwrdm_pre_transition
  39. pwrdm_post_transition
  40. pwrdm_get_valid_lp_state
  41. omap_set_pwrdm_state
  42. pwrdm_get_context_loss_count
  43. pwrdm_can_ever_lose_context
  44. pwrdm_save_context
  45. pwrdm_restore_context
  46. pwrdm_lost_power
  47. pwrdms_save_context
  48. pwrdms_restore_context
  49. pwrdms_lost_power

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * OMAP powerdomain control
   4  *
   5  * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
   6  * Copyright (C) 2007-2011 Nokia Corporation
   7  *
   8  * Written by Paul Walmsley
   9  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
  10  * State counting code by Tero Kristo <tero.kristo@nokia.com>
  11  */
  12 #undef DEBUG
  13 
  14 #include <linux/cpu_pm.h>
  15 #include <linux/kernel.h>
  16 #include <linux/types.h>
  17 #include <linux/list.h>
  18 #include <linux/errno.h>
  19 #include <linux/string.h>
  20 #include <linux/spinlock.h>
  21 #include <trace/events/power.h>
  22 
  23 #include "cm2xxx_3xxx.h"
  24 #include "prcm44xx.h"
  25 #include "cm44xx.h"
  26 #include "prm2xxx_3xxx.h"
  27 #include "prm44xx.h"
  28 
  29 #include <asm/cpu.h>
  30 
  31 #include "powerdomain.h"
  32 #include "clockdomain.h"
  33 #include "voltage.h"
  34 
  35 #include "soc.h"
  36 #include "pm.h"
  37 
  38 #define PWRDM_TRACE_STATES_FLAG (1<<31)
  39 
  40 void pwrdms_save_context(void);
  41 void pwrdms_restore_context(void);
  42 
  43 enum {
  44         PWRDM_STATE_NOW = 0,
  45         PWRDM_STATE_PREV,
  46 };
  47 
  48 /*
  49  * Types of sleep_switch used internally in omap_set_pwrdm_state()
  50  * and its associated static functions
  51  *
  52  * XXX Better documentation is needed here
  53  */
  54 #define ALREADYACTIVE_SWITCH            0
  55 #define FORCEWAKEUP_SWITCH              1
  56 #define LOWPOWERSTATE_SWITCH            2
  57 
  58 /* pwrdm_list contains all registered struct powerdomains */
  59 static LIST_HEAD(pwrdm_list);
  60 
  61 static struct pwrdm_ops *arch_pwrdm;
  62 
  63 /* Private functions */
  64 
  65 static struct powerdomain *_pwrdm_lookup(const char *name)
  66 {
  67         struct powerdomain *pwrdm, *temp_pwrdm;
  68 
  69         pwrdm = NULL;
  70 
  71         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
  72                 if (!strcmp(name, temp_pwrdm->name)) {
  73                         pwrdm = temp_pwrdm;
  74                         break;
  75                 }
  76         }
  77 
  78         return pwrdm;
  79 }
  80 
  81 /**
  82  * _pwrdm_register - register a powerdomain
  83  * @pwrdm: struct powerdomain * to register
  84  *
  85  * Adds a powerdomain to the internal powerdomain list.  Returns
  86  * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
  87  * already registered by the provided name, or 0 upon success.
  88  */
  89 static int _pwrdm_register(struct powerdomain *pwrdm)
  90 {
  91         int i;
  92         struct voltagedomain *voltdm;
  93 
  94         if (!pwrdm || !pwrdm->name)
  95                 return -EINVAL;
  96 
  97         if (cpu_is_omap44xx() &&
  98             pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
  99                 pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
 100                        pwrdm->name);
 101                 return -EINVAL;
 102         }
 103 
 104         if (_pwrdm_lookup(pwrdm->name))
 105                 return -EEXIST;
 106 
 107         if (arch_pwrdm && arch_pwrdm->pwrdm_has_voltdm)
 108                 if (!arch_pwrdm->pwrdm_has_voltdm())
 109                         goto skip_voltdm;
 110 
 111         voltdm = voltdm_lookup(pwrdm->voltdm.name);
 112         if (!voltdm) {
 113                 pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
 114                        pwrdm->name, pwrdm->voltdm.name);
 115                 return -EINVAL;
 116         }
 117         pwrdm->voltdm.ptr = voltdm;
 118         INIT_LIST_HEAD(&pwrdm->voltdm_node);
 119 skip_voltdm:
 120         spin_lock_init(&pwrdm->_lock);
 121 
 122         list_add(&pwrdm->node, &pwrdm_list);
 123 
 124         /* Initialize the powerdomain's state counter */
 125         for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
 126                 pwrdm->state_counter[i] = 0;
 127 
 128         pwrdm->ret_logic_off_counter = 0;
 129         for (i = 0; i < pwrdm->banks; i++)
 130                 pwrdm->ret_mem_off_counter[i] = 0;
 131 
 132         if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
 133                 arch_pwrdm->pwrdm_wait_transition(pwrdm);
 134         pwrdm->state = pwrdm_read_pwrst(pwrdm);
 135         pwrdm->state_counter[pwrdm->state] = 1;
 136 
 137         pr_debug("powerdomain: registered %s\n", pwrdm->name);
 138 
 139         return 0;
 140 }
 141 
 142 static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 143 {
 144         int i;
 145         u8 prev_logic_pwrst, prev_mem_pwrst;
 146 
 147         prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
 148         if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
 149             (prev_logic_pwrst == PWRDM_POWER_OFF))
 150                 pwrdm->ret_logic_off_counter++;
 151 
 152         for (i = 0; i < pwrdm->banks; i++) {
 153                 prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
 154 
 155                 if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
 156                     (prev_mem_pwrst == PWRDM_POWER_OFF))
 157                         pwrdm->ret_mem_off_counter[i]++;
 158         }
 159 }
 160 
 161 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 162 {
 163 
 164         int prev, next, state, trace_state = 0;
 165 
 166         if (pwrdm == NULL)
 167                 return -EINVAL;
 168 
 169         state = pwrdm_read_pwrst(pwrdm);
 170 
 171         switch (flag) {
 172         case PWRDM_STATE_NOW:
 173                 prev = pwrdm->state;
 174                 break;
 175         case PWRDM_STATE_PREV:
 176                 prev = pwrdm_read_prev_pwrst(pwrdm);
 177                 if (pwrdm->state != prev)
 178                         pwrdm->state_counter[prev]++;
 179                 if (prev == PWRDM_POWER_RET)
 180                         _update_logic_membank_counters(pwrdm);
 181                 /*
 182                  * If the power domain did not hit the desired state,
 183                  * generate a trace event with both the desired and hit states
 184                  */
 185                 next = pwrdm_read_next_pwrst(pwrdm);
 186                 if (next != prev) {
 187                         trace_state = (PWRDM_TRACE_STATES_FLAG |
 188                                        ((next & OMAP_POWERSTATE_MASK) << 8) |
 189                                        ((prev & OMAP_POWERSTATE_MASK) << 0));
 190                         trace_power_domain_target_rcuidle(pwrdm->name,
 191                                                           trace_state,
 192                                                           raw_smp_processor_id());
 193                 }
 194                 break;
 195         default:
 196                 return -EINVAL;
 197         }
 198 
 199         if (state != prev)
 200                 pwrdm->state_counter[state]++;
 201 
 202         pm_dbg_update_time(pwrdm, prev);
 203 
 204         pwrdm->state = state;
 205 
 206         return 0;
 207 }
 208 
 209 static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
 210 {
 211         pwrdm_clear_all_prev_pwrst(pwrdm);
 212         _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
 213         return 0;
 214 }
 215 
 216 static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 217 {
 218         _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
 219         return 0;
 220 }
 221 
 222 /**
 223  * _pwrdm_save_clkdm_state_and_activate - prepare for power state change
 224  * @pwrdm: struct powerdomain * to operate on
 225  * @curr_pwrst: current power state of @pwrdm
 226  * @pwrst: power state to switch to
 227  *
 228  * Determine whether the powerdomain needs to be turned on before
 229  * attempting to switch power states.  Called by
 230  * omap_set_pwrdm_state().  NOTE that if the powerdomain contains
 231  * multiple clockdomains, this code assumes that the first clockdomain
 232  * supports software-supervised wakeup mode - potentially a problem.
 233  * Returns the power state switch mode currently in use (see the
 234  * "Types of sleep_switch" comment above).
 235  */
 236 static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
 237                                                u8 curr_pwrst, u8 pwrst)
 238 {
 239         u8 sleep_switch;
 240 
 241         if (curr_pwrst < PWRDM_POWER_ON) {
 242                 if (curr_pwrst > pwrst &&
 243                     pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
 244                     arch_pwrdm->pwrdm_set_lowpwrstchange) {
 245                         sleep_switch = LOWPOWERSTATE_SWITCH;
 246                 } else {
 247                         clkdm_deny_idle_nolock(pwrdm->pwrdm_clkdms[0]);
 248                         sleep_switch = FORCEWAKEUP_SWITCH;
 249                 }
 250         } else {
 251                 sleep_switch = ALREADYACTIVE_SWITCH;
 252         }
 253 
 254         return sleep_switch;
 255 }
 256 
 257 /**
 258  * _pwrdm_restore_clkdm_state - restore the clkdm hwsup state after pwrst change
 259  * @pwrdm: struct powerdomain * to operate on
 260  * @sleep_switch: return value from _pwrdm_save_clkdm_state_and_activate()
 261  *
 262  * Restore the clockdomain state perturbed by
 263  * _pwrdm_save_clkdm_state_and_activate(), and call the power state
 264  * bookkeeping code.  Called by omap_set_pwrdm_state().  NOTE that if
 265  * the powerdomain contains multiple clockdomains, this assumes that
 266  * the first associated clockdomain supports either
 267  * hardware-supervised idle control in the register, or
 268  * software-supervised sleep.  No return value.
 269  */
 270 static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
 271                                        u8 sleep_switch)
 272 {
 273         switch (sleep_switch) {
 274         case FORCEWAKEUP_SWITCH:
 275                 clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
 276                 break;
 277         case LOWPOWERSTATE_SWITCH:
 278                 if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
 279                     arch_pwrdm->pwrdm_set_lowpwrstchange)
 280                         arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
 281                 pwrdm_state_switch_nolock(pwrdm);
 282                 break;
 283         }
 284 }
 285 
 286 /* Public functions */
 287 
 288 /**
 289  * pwrdm_register_platform_funcs - register powerdomain implementation fns
 290  * @po: func pointers for arch specific implementations
 291  *
 292  * Register the list of function pointers used to implement the
 293  * powerdomain functions on different OMAP SoCs.  Should be called
 294  * before any other pwrdm_register*() function.  Returns -EINVAL if
 295  * @po is null, -EEXIST if platform functions have already been
 296  * registered, or 0 upon success.
 297  */
 298 int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
 299 {
 300         if (!po)
 301                 return -EINVAL;
 302 
 303         if (arch_pwrdm)
 304                 return -EEXIST;
 305 
 306         arch_pwrdm = po;
 307 
 308         return 0;
 309 }
 310 
 311 /**
 312  * pwrdm_register_pwrdms - register SoC powerdomains
 313  * @ps: pointer to an array of struct powerdomain to register
 314  *
 315  * Register the powerdomains available on a particular OMAP SoC.  Must
 316  * be called after pwrdm_register_platform_funcs().  May be called
 317  * multiple times.  Returns -EACCES if called before
 318  * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
 319  * null; or 0 upon success.
 320  */
 321 int pwrdm_register_pwrdms(struct powerdomain **ps)
 322 {
 323         struct powerdomain **p = NULL;
 324 
 325         if (!arch_pwrdm)
 326                 return -EEXIST;
 327 
 328         if (!ps)
 329                 return -EINVAL;
 330 
 331         for (p = ps; *p; p++)
 332                 _pwrdm_register(*p);
 333 
 334         return 0;
 335 }
 336 
 337 static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
 338 {
 339         switch (cmd) {
 340         case CPU_CLUSTER_PM_ENTER:
 341                 if (enable_off_mode)
 342                         pwrdms_save_context();
 343                 break;
 344         case CPU_CLUSTER_PM_EXIT:
 345                 if (enable_off_mode)
 346                         pwrdms_restore_context();
 347                 break;
 348         }
 349 
 350         return NOTIFY_OK;
 351 }
 352 
 353 /**
 354  * pwrdm_complete_init - set up the powerdomain layer
 355  *
 356  * Do whatever is necessary to initialize registered powerdomains and
 357  * powerdomain code.  Currently, this programs the next power state
 358  * for each powerdomain to ON.  This prevents powerdomains from
 359  * unexpectedly losing context or entering high wakeup latency modes
 360  * with non-power-management-enabled kernels.  Must be called after
 361  * pwrdm_register_pwrdms().  Returns -EACCES if called before
 362  * pwrdm_register_pwrdms(), or 0 upon success.
 363  */
 364 int pwrdm_complete_init(void)
 365 {
 366         struct powerdomain *temp_p;
 367         static struct notifier_block nb;
 368 
 369         if (list_empty(&pwrdm_list))
 370                 return -EACCES;
 371 
 372         list_for_each_entry(temp_p, &pwrdm_list, node)
 373                 pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
 374 
 375         /* Only AM43XX can lose pwrdm context during rtc-ddr suspend */
 376         if (soc_is_am43xx()) {
 377                 nb.notifier_call = cpu_notifier;
 378                 cpu_pm_register_notifier(&nb);
 379         }
 380 
 381         return 0;
 382 }
 383 
 384 /**
 385  * pwrdm_lock - acquire a Linux spinlock on a powerdomain
 386  * @pwrdm: struct powerdomain * to lock
 387  *
 388  * Acquire the powerdomain spinlock on @pwrdm.  No return value.
 389  */
 390 void pwrdm_lock(struct powerdomain *pwrdm)
 391         __acquires(&pwrdm->_lock)
 392 {
 393         spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags);
 394 }
 395 
 396 /**
 397  * pwrdm_unlock - release a Linux spinlock on a powerdomain
 398  * @pwrdm: struct powerdomain * to unlock
 399  *
 400  * Release the powerdomain spinlock on @pwrdm.  No return value.
 401  */
 402 void pwrdm_unlock(struct powerdomain *pwrdm)
 403         __releases(&pwrdm->_lock)
 404 {
 405         spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags);
 406 }
 407 
 408 /**
 409  * pwrdm_lookup - look up a powerdomain by name, return a pointer
 410  * @name: name of powerdomain
 411  *
 412  * Find a registered powerdomain by its name @name.  Returns a pointer
 413  * to the struct powerdomain if found, or NULL otherwise.
 414  */
 415 struct powerdomain *pwrdm_lookup(const char *name)
 416 {
 417         struct powerdomain *pwrdm;
 418 
 419         if (!name)
 420                 return NULL;
 421 
 422         pwrdm = _pwrdm_lookup(name);
 423 
 424         return pwrdm;
 425 }
 426 
 427 /**
 428  * pwrdm_for_each - call function on each registered clockdomain
 429  * @fn: callback function *
 430  *
 431  * Call the supplied function @fn for each registered powerdomain.
 432  * The callback function @fn can return anything but 0 to bail out
 433  * early from the iterator.  Returns the last return value of the
 434  * callback function, which should be 0 for success or anything else
 435  * to indicate failure; or -EINVAL if the function pointer is null.
 436  */
 437 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
 438                    void *user)
 439 {
 440         struct powerdomain *temp_pwrdm;
 441         int ret = 0;
 442 
 443         if (!fn)
 444                 return -EINVAL;
 445 
 446         list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
 447                 ret = (*fn)(temp_pwrdm, user);
 448                 if (ret)
 449                         break;
 450         }
 451 
 452         return ret;
 453 }
 454 
 455 /**
 456  * pwrdm_add_clkdm - add a clockdomain to a powerdomain
 457  * @pwrdm: struct powerdomain * to add the clockdomain to
 458  * @clkdm: struct clockdomain * to associate with a powerdomain
 459  *
 460  * Associate the clockdomain @clkdm with a powerdomain @pwrdm.  This
 461  * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
 462  * presented with invalid pointers; -ENOMEM if memory could not be allocated;
 463  * or 0 upon success.
 464  */
 465 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 466 {
 467         int i;
 468         int ret = -EINVAL;
 469 
 470         if (!pwrdm || !clkdm)
 471                 return -EINVAL;
 472 
 473         pr_debug("powerdomain: %s: associating clockdomain %s\n",
 474                  pwrdm->name, clkdm->name);
 475 
 476         for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
 477                 if (!pwrdm->pwrdm_clkdms[i])
 478                         break;
 479 #ifdef DEBUG
 480                 if (pwrdm->pwrdm_clkdms[i] == clkdm) {
 481                         ret = -EINVAL;
 482                         goto pac_exit;
 483                 }
 484 #endif
 485         }
 486 
 487         if (i == PWRDM_MAX_CLKDMS) {
 488                 pr_debug("powerdomain: %s: increase PWRDM_MAX_CLKDMS for clkdm %s\n",
 489                          pwrdm->name, clkdm->name);
 490                 WARN_ON(1);
 491                 ret = -ENOMEM;
 492                 goto pac_exit;
 493         }
 494 
 495         pwrdm->pwrdm_clkdms[i] = clkdm;
 496 
 497         ret = 0;
 498 
 499 pac_exit:
 500         return ret;
 501 }
 502 
 503 /**
 504  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
 505  * @pwrdm: struct powerdomain *
 506  *
 507  * Return the number of controllable memory banks in powerdomain @pwrdm,
 508  * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
 509  */
 510 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 511 {
 512         if (!pwrdm)
 513                 return -EINVAL;
 514 
 515         return pwrdm->banks;
 516 }
 517 
 518 /**
 519  * pwrdm_set_next_pwrst - set next powerdomain power state
 520  * @pwrdm: struct powerdomain * to set
 521  * @pwrst: one of the PWRDM_POWER_* macros
 522  *
 523  * Set the powerdomain @pwrdm's next power state to @pwrst.  The powerdomain
 524  * may not enter this state immediately if the preconditions for this state
 525  * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
 526  * null or if the power state is invalid for the powerdomin, or returns 0
 527  * upon success.
 528  */
 529 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 530 {
 531         int ret = -EINVAL;
 532 
 533         if (!pwrdm)
 534                 return -EINVAL;
 535 
 536         if (!(pwrdm->pwrsts & (1 << pwrst)))
 537                 return -EINVAL;
 538 
 539         pr_debug("powerdomain: %s: setting next powerstate to %0x\n",
 540                  pwrdm->name, pwrst);
 541 
 542         if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
 543                 /* Trace the pwrdm desired target state */
 544                 trace_power_domain_target_rcuidle(pwrdm->name, pwrst,
 545                                                   raw_smp_processor_id());
 546                 /* Program the pwrdm desired target state */
 547                 ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
 548         }
 549 
 550         return ret;
 551 }
 552 
 553 /**
 554  * pwrdm_read_next_pwrst - get next powerdomain power state
 555  * @pwrdm: struct powerdomain * to get power state
 556  *
 557  * Return the powerdomain @pwrdm's next power state.  Returns -EINVAL
 558  * if the powerdomain pointer is null or returns the next power state
 559  * upon success.
 560  */
 561 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 562 {
 563         int ret = -EINVAL;
 564 
 565         if (!pwrdm)
 566                 return -EINVAL;
 567 
 568         if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
 569                 ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
 570 
 571         return ret;
 572 }
 573 
 574 /**
 575  * pwrdm_read_pwrst - get current powerdomain power state
 576  * @pwrdm: struct powerdomain * to get power state
 577  *
 578  * Return the powerdomain @pwrdm's current power state. Returns -EINVAL
 579  * if the powerdomain pointer is null or returns the current power state
 580  * upon success. Note that if the power domain only supports the ON state
 581  * then just return ON as the current state.
 582  */
 583 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 584 {
 585         int ret = -EINVAL;
 586 
 587         if (!pwrdm)
 588                 return -EINVAL;
 589 
 590         if (pwrdm->pwrsts == PWRSTS_ON)
 591                 return PWRDM_POWER_ON;
 592 
 593         if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst)
 594                 ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
 595 
 596         return ret;
 597 }
 598 
 599 /**
 600  * pwrdm_read_prev_pwrst - get previous powerdomain power state
 601  * @pwrdm: struct powerdomain * to get previous power state
 602  *
 603  * Return the powerdomain @pwrdm's previous power state.  Returns -EINVAL
 604  * if the powerdomain pointer is null or returns the previous power state
 605  * upon success.
 606  */
 607 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 608 {
 609         int ret = -EINVAL;
 610 
 611         if (!pwrdm)
 612                 return -EINVAL;
 613 
 614         if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst)
 615                 ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm);
 616 
 617         return ret;
 618 }
 619 
 620 /**
 621  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
 622  * @pwrdm: struct powerdomain * to set
 623  * @pwrst: one of the PWRDM_POWER_* macros
 624  *
 625  * Set the next power state @pwrst that the logic portion of the
 626  * powerdomain @pwrdm will enter when the powerdomain enters retention.
 627  * This will be either RETENTION or OFF, if supported.  Returns
 628  * -EINVAL if the powerdomain pointer is null or the target power
 629  * state is not not supported, or returns 0 upon success.
 630  */
 631 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 632 {
 633         int ret = -EINVAL;
 634 
 635         if (!pwrdm)
 636                 return -EINVAL;
 637 
 638         if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
 639                 return -EINVAL;
 640 
 641         pr_debug("powerdomain: %s: setting next logic powerstate to %0x\n",
 642                  pwrdm->name, pwrst);
 643 
 644         if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst)
 645                 ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst);
 646 
 647         return ret;
 648 }
 649 
 650 /**
 651  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
 652  * @pwrdm: struct powerdomain * to set
 653  * @bank: memory bank number to set (0-3)
 654  * @pwrst: one of the PWRDM_POWER_* macros
 655  *
 656  * Set the next power state @pwrst that memory bank @bank of the
 657  * powerdomain @pwrdm will enter when the powerdomain enters the ON
 658  * state.  @bank will be a number from 0 to 3, and represents different
 659  * types of memory, depending on the powerdomain.  Returns -EINVAL if
 660  * the powerdomain pointer is null or the target power state is not
 661  * not supported for this memory bank, -EEXIST if the target memory
 662  * bank does not exist or is not controllable, or returns 0 upon
 663  * success.
 664  */
 665 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 666 {
 667         int ret = -EINVAL;
 668 
 669         if (!pwrdm)
 670                 return -EINVAL;
 671 
 672         if (pwrdm->banks < (bank + 1))
 673                 return -EEXIST;
 674 
 675         if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
 676                 return -EINVAL;
 677 
 678         pr_debug("powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-ON to %0x\n",
 679                  pwrdm->name, bank, pwrst);
 680 
 681         if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
 682                 ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
 683 
 684         return ret;
 685 }
 686 
 687 /**
 688  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
 689  * @pwrdm: struct powerdomain * to set
 690  * @bank: memory bank number to set (0-3)
 691  * @pwrst: one of the PWRDM_POWER_* macros
 692  *
 693  * Set the next power state @pwrst that memory bank @bank of the
 694  * powerdomain @pwrdm will enter when the powerdomain enters the
 695  * RETENTION state.  Bank will be a number from 0 to 3, and represents
 696  * different types of memory, depending on the powerdomain.  @pwrst
 697  * will be either RETENTION or OFF, if supported.  Returns -EINVAL if
 698  * the powerdomain pointer is null or the target power state is not
 699  * not supported for this memory bank, -EEXIST if the target memory
 700  * bank does not exist or is not controllable, or returns 0 upon
 701  * success.
 702  */
 703 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 704 {
 705         int ret = -EINVAL;
 706 
 707         if (!pwrdm)
 708                 return -EINVAL;
 709 
 710         if (pwrdm->banks < (bank + 1))
 711                 return -EEXIST;
 712 
 713         if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
 714                 return -EINVAL;
 715 
 716         pr_debug("powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-RET to %0x\n",
 717                  pwrdm->name, bank, pwrst);
 718 
 719         if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
 720                 ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst);
 721 
 722         return ret;
 723 }
 724 
 725 /**
 726  * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
 727  * @pwrdm: struct powerdomain * to get current logic retention power state
 728  *
 729  * Return the power state that the logic portion of powerdomain @pwrdm
 730  * will enter when the powerdomain enters retention.  Returns -EINVAL
 731  * if the powerdomain pointer is null or returns the logic retention
 732  * power state upon success.
 733  */
 734 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
 735 {
 736         int ret = -EINVAL;
 737 
 738         if (!pwrdm)
 739                 return -EINVAL;
 740 
 741         if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst)
 742                 ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
 743 
 744         return ret;
 745 }
 746 
 747 /**
 748  * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
 749  * @pwrdm: struct powerdomain * to get previous logic power state
 750  *
 751  * Return the powerdomain @pwrdm's previous logic power state.  Returns
 752  * -EINVAL if the powerdomain pointer is null or returns the previous
 753  * logic power state upon success.
 754  */
 755 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
 756 {
 757         int ret = -EINVAL;
 758 
 759         if (!pwrdm)
 760                 return -EINVAL;
 761 
 762         if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst)
 763                 ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm);
 764 
 765         return ret;
 766 }
 767 
 768 /**
 769  * pwrdm_read_logic_retst - get next powerdomain logic power state
 770  * @pwrdm: struct powerdomain * to get next logic power state
 771  *
 772  * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
 773  * if the powerdomain pointer is null or returns the next logic
 774  * power state upon success.
 775  */
 776 int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
 777 {
 778         int ret = -EINVAL;
 779 
 780         if (!pwrdm)
 781                 return -EINVAL;
 782 
 783         if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst)
 784                 ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm);
 785 
 786         return ret;
 787 }
 788 
 789 /**
 790  * pwrdm_read_mem_pwrst - get current memory bank power state
 791  * @pwrdm: struct powerdomain * to get current memory bank power state
 792  * @bank: memory bank number (0-3)
 793  *
 794  * Return the powerdomain @pwrdm's current memory power state for bank
 795  * @bank.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
 796  * the target memory bank does not exist or is not controllable, or
 797  * returns the current memory power state upon success.
 798  */
 799 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 800 {
 801         int ret = -EINVAL;
 802 
 803         if (!pwrdm)
 804                 return ret;
 805 
 806         if (pwrdm->banks < (bank + 1))
 807                 return ret;
 808 
 809         if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
 810                 bank = 1;
 811 
 812         if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst)
 813                 ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank);
 814 
 815         return ret;
 816 }
 817 
 818 /**
 819  * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
 820  * @pwrdm: struct powerdomain * to get previous memory bank power state
 821  * @bank: memory bank number (0-3)
 822  *
 823  * Return the powerdomain @pwrdm's previous memory power state for
 824  * bank @bank.  Returns -EINVAL if the powerdomain pointer is null,
 825  * -EEXIST if the target memory bank does not exist or is not
 826  * controllable, or returns the previous memory power state upon
 827  * success.
 828  */
 829 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 830 {
 831         int ret = -EINVAL;
 832 
 833         if (!pwrdm)
 834                 return ret;
 835 
 836         if (pwrdm->banks < (bank + 1))
 837                 return ret;
 838 
 839         if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
 840                 bank = 1;
 841 
 842         if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst)
 843                 ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank);
 844 
 845         return ret;
 846 }
 847 
 848 /**
 849  * pwrdm_read_mem_retst - get next memory bank power state
 850  * @pwrdm: struct powerdomain * to get mext memory bank power state
 851  * @bank: memory bank number (0-3)
 852  *
 853  * Return the powerdomain pwrdm's next memory power state for bank
 854  * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
 855  * the target memory bank does not exist or is not controllable, or
 856  * returns the next memory power state upon success.
 857  */
 858 int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
 859 {
 860         int ret = -EINVAL;
 861 
 862         if (!pwrdm)
 863                 return ret;
 864 
 865         if (pwrdm->banks < (bank + 1))
 866                 return ret;
 867 
 868         if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst)
 869                 ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank);
 870 
 871         return ret;
 872 }
 873 
 874 /**
 875  * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
 876  * @pwrdm: struct powerdomain * to clear
 877  *
 878  * Clear the powerdomain's previous power state register @pwrdm.
 879  * Clears the entire register, including logic and memory bank
 880  * previous power states.  Returns -EINVAL if the powerdomain pointer
 881  * is null, or returns 0 upon success.
 882  */
 883 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
 884 {
 885         int ret = -EINVAL;
 886 
 887         if (!pwrdm)
 888                 return ret;
 889 
 890         /*
 891          * XXX should get the powerdomain's current state here;
 892          * warn & fail if it is not ON.
 893          */
 894 
 895         pr_debug("powerdomain: %s: clearing previous power state reg\n",
 896                  pwrdm->name);
 897 
 898         if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
 899                 ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm);
 900 
 901         return ret;
 902 }
 903 
 904 /**
 905  * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
 906  * @pwrdm: struct powerdomain *
 907  *
 908  * Enable automatic context save-and-restore upon power state change
 909  * for some devices in the powerdomain @pwrdm.  Warning: this only
 910  * affects a subset of devices in a powerdomain; check the TRM
 911  * closely.  Returns -EINVAL if the powerdomain pointer is null or if
 912  * the powerdomain does not support automatic save-and-restore, or
 913  * returns 0 upon success.
 914  */
 915 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
 916 {
 917         int ret = -EINVAL;
 918 
 919         if (!pwrdm)
 920                 return ret;
 921 
 922         if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 923                 return ret;
 924 
 925         pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", pwrdm->name);
 926 
 927         if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar)
 928                 ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm);
 929 
 930         return ret;
 931 }
 932 
 933 /**
 934  * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
 935  * @pwrdm: struct powerdomain *
 936  *
 937  * Disable automatic context save-and-restore upon power state change
 938  * for some devices in the powerdomain @pwrdm.  Warning: this only
 939  * affects a subset of devices in a powerdomain; check the TRM
 940  * closely.  Returns -EINVAL if the powerdomain pointer is null or if
 941  * the powerdomain does not support automatic save-and-restore, or
 942  * returns 0 upon success.
 943  */
 944 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 945 {
 946         int ret = -EINVAL;
 947 
 948         if (!pwrdm)
 949                 return ret;
 950 
 951         if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 952                 return ret;
 953 
 954         pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", pwrdm->name);
 955 
 956         if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar)
 957                 ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm);
 958 
 959         return ret;
 960 }
 961 
 962 /**
 963  * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
 964  * @pwrdm: struct powerdomain *
 965  *
 966  * Returns 1 if powerdomain @pwrdm supports hardware save-and-restore
 967  * for some devices, or 0 if it does not.
 968  */
 969 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
 970 {
 971         return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 972 }
 973 
 974 int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
 975 {
 976         int ret;
 977 
 978         if (!pwrdm || !arch_pwrdm)
 979                 return -EINVAL;
 980 
 981         ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 982         if (!ret)
 983                 ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
 984 
 985         return ret;
 986 }
 987 
 988 int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm)
 989 {
 990         int ret;
 991 
 992         pwrdm_lock(pwrdm);
 993         ret = pwrdm_state_switch_nolock(pwrdm);
 994         pwrdm_unlock(pwrdm);
 995 
 996         return ret;
 997 }
 998 
 999 int pwrdm_pre_transition(struct powerdomain *pwrdm)
1000 {
1001         if (pwrdm)
1002                 _pwrdm_pre_transition_cb(pwrdm, NULL);
1003         else
1004                 pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
1005 
1006         return 0;
1007 }
1008 
1009 int pwrdm_post_transition(struct powerdomain *pwrdm)
1010 {
1011         if (pwrdm)
1012                 _pwrdm_post_transition_cb(pwrdm, NULL);
1013         else
1014                 pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
1015 
1016         return 0;
1017 }
1018 
1019 /**
1020  * pwrdm_get_valid_lp_state() - Find best match deep power state
1021  * @pwrdm:      power domain for which we want to find best match
1022  * @is_logic_state: Are we looking for logic state match here? Should
1023  *                  be one of PWRDM_xxx macro values
1024  * @req_state:  requested power state
1025  *
1026  * Returns: closest match for requested power state. default fallback
1027  * is RET for logic state and ON for power state.
1028  *
1029  * This does a search from the power domain data looking for the
1030  * closest valid power domain state that the hardware can achieve.
1031  * PRCM definitions for PWRSTCTRL allows us to program whatever
1032  * configuration we'd like, and PRCM will actually attempt such
1033  * a transition, however if the powerdomain does not actually support it,
1034  * we endup with a hung system. The valid power domain states are already
1035  * available in our powerdomain data files. So this function tries to do
1036  * the following:
1037  * a) find if we have an exact match to the request - no issues.
1038  * b) else find if a deeper power state is possible.
1039  * c) failing which, it tries to find closest higher power state for the
1040  * request.
1041  */
1042 u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
1043                             bool is_logic_state, u8 req_state)
1044 {
1045         u8 pwrdm_states = is_logic_state ? pwrdm->pwrsts_logic_ret :
1046                         pwrdm->pwrsts;
1047         /* For logic, ret is highest and others, ON is highest */
1048         u8 default_pwrst = is_logic_state ? PWRDM_POWER_RET : PWRDM_POWER_ON;
1049         u8 new_pwrst;
1050         bool found;
1051 
1052         /* If it is already supported, nothing to search */
1053         if (pwrdm_states & BIT(req_state))
1054                 return req_state;
1055 
1056         if (!req_state)
1057                 goto up_search;
1058 
1059         /*
1060          * So, we dont have a exact match
1061          * Can we get a deeper power state match?
1062          */
1063         new_pwrst = req_state - 1;
1064         found = true;
1065         while (!(pwrdm_states & BIT(new_pwrst))) {
1066                 /* No match even at OFF? Not available */
1067                 if (new_pwrst == PWRDM_POWER_OFF) {
1068                         found = false;
1069                         break;
1070                 }
1071                 new_pwrst--;
1072         }
1073 
1074         if (found)
1075                 goto done;
1076 
1077 up_search:
1078         /* OK, no deeper ones, can we get a higher match? */
1079         new_pwrst = req_state + 1;
1080         while (!(pwrdm_states & BIT(new_pwrst))) {
1081                 if (new_pwrst > PWRDM_POWER_ON) {
1082                         WARN(1, "powerdomain: %s: Fix max powerstate to ON\n",
1083                              pwrdm->name);
1084                         return PWRDM_POWER_ON;
1085                 }
1086 
1087                 if (new_pwrst == default_pwrst)
1088                         break;
1089                 new_pwrst++;
1090         }
1091 done:
1092         return new_pwrst;
1093 }
1094 
1095 /**
1096  * omap_set_pwrdm_state - change a powerdomain's current power state
1097  * @pwrdm: struct powerdomain * to change the power state of
1098  * @pwrst: power state to change to
1099  *
1100  * Change the current hardware power state of the powerdomain
1101  * represented by @pwrdm to the power state represented by @pwrst.
1102  * Returns -EINVAL if @pwrdm is null or invalid or if the
1103  * powerdomain's current power state could not be read, or returns 0
1104  * upon success or if @pwrdm does not support @pwrst or any
1105  * lower-power state.  XXX Should not return 0 if the @pwrdm does not
1106  * support @pwrst or any lower-power state: this should be an error.
1107  */
1108 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
1109 {
1110         u8 next_pwrst, sleep_switch;
1111         int curr_pwrst;
1112         int ret = 0;
1113 
1114         if (!pwrdm || IS_ERR(pwrdm))
1115                 return -EINVAL;
1116 
1117         while (!(pwrdm->pwrsts & (1 << pwrst))) {
1118                 if (pwrst == PWRDM_POWER_OFF)
1119                         return ret;
1120                 pwrst--;
1121         }
1122 
1123         pwrdm_lock(pwrdm);
1124 
1125         curr_pwrst = pwrdm_read_pwrst(pwrdm);
1126         if (curr_pwrst < 0) {
1127                 ret = -EINVAL;
1128                 goto osps_out;
1129         }
1130 
1131         next_pwrst = pwrdm_read_next_pwrst(pwrdm);
1132         if (curr_pwrst == pwrst && next_pwrst == pwrst)
1133                 goto osps_out;
1134 
1135         sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
1136                                                             pwrst);
1137 
1138         ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
1139         if (ret)
1140                 pr_err("%s: unable to set power state of powerdomain: %s\n",
1141                        __func__, pwrdm->name);
1142 
1143         _pwrdm_restore_clkdm_state(pwrdm, sleep_switch);
1144 
1145 osps_out:
1146         pwrdm_unlock(pwrdm);
1147 
1148         return ret;
1149 }
1150 
1151 /**
1152  * pwrdm_get_context_loss_count - get powerdomain's context loss count
1153  * @pwrdm: struct powerdomain * to wait for
1154  *
1155  * Context loss count is the sum of powerdomain off-mode counter, the
1156  * logic off counter and the per-bank memory off counter.  Returns negative
1157  * (and WARNs) upon error, otherwise, returns the context loss count.
1158  */
1159 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
1160 {
1161         int i, count;
1162 
1163         if (!pwrdm) {
1164                 WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
1165                 return -ENODEV;
1166         }
1167 
1168         count = pwrdm->state_counter[PWRDM_POWER_OFF];
1169         count += pwrdm->ret_logic_off_counter;
1170 
1171         for (i = 0; i < pwrdm->banks; i++)
1172                 count += pwrdm->ret_mem_off_counter[i];
1173 
1174         /*
1175          * Context loss count has to be a non-negative value. Clear the sign
1176          * bit to get a value range from 0 to INT_MAX.
1177          */
1178         count &= INT_MAX;
1179 
1180         pr_debug("powerdomain: %s: context loss count = %d\n",
1181                  pwrdm->name, count);
1182 
1183         return count;
1184 }
1185 
1186 /**
1187  * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
1188  * @pwrdm: struct powerdomain *
1189  *
1190  * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
1191  * can lose either memory or logic context or if @pwrdm is invalid, or
1192  * returns 0 otherwise.  This function is not concerned with how the
1193  * powerdomain registers are programmed (i.e., to go off or not); it's
1194  * concerned with whether it's ever possible for this powerdomain to
1195  * go off while some other part of the chip is active.  This function
1196  * assumes that every powerdomain can go to either ON or INACTIVE.
1197  */
1198 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
1199 {
1200         int i;
1201 
1202         if (!pwrdm) {
1203                 pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
1204                          __func__);
1205                 return 1;
1206         }
1207 
1208         if (pwrdm->pwrsts & PWRSTS_OFF)
1209                 return 1;
1210 
1211         if (pwrdm->pwrsts & PWRSTS_RET) {
1212                 if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
1213                         return 1;
1214 
1215                 for (i = 0; i < pwrdm->banks; i++)
1216                         if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
1217                                 return 1;
1218         }
1219 
1220         for (i = 0; i < pwrdm->banks; i++)
1221                 if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
1222                         return 1;
1223 
1224         return 0;
1225 }
1226 
1227 /**
1228  * pwrdm_save_context - save powerdomain registers
1229  *
1230  * Register state is going to be lost due to a suspend or hibernate
1231  * event. Save the powerdomain registers.
1232  */
1233 static int pwrdm_save_context(struct powerdomain *pwrdm, void *unused)
1234 {
1235         if (arch_pwrdm && arch_pwrdm->pwrdm_save_context)
1236                 arch_pwrdm->pwrdm_save_context(pwrdm);
1237         return 0;
1238 }
1239 
1240 /**
1241  * pwrdm_save_context - restore powerdomain registers
1242  *
1243  * Restore powerdomain control registers after a suspend or resume
1244  * event.
1245  */
1246 static int pwrdm_restore_context(struct powerdomain *pwrdm, void *unused)
1247 {
1248         if (arch_pwrdm && arch_pwrdm->pwrdm_restore_context)
1249                 arch_pwrdm->pwrdm_restore_context(pwrdm);
1250         return 0;
1251 }
1252 
1253 static int pwrdm_lost_power(struct powerdomain *pwrdm, void *unused)
1254 {
1255         int state;
1256 
1257         /*
1258          * Power has been lost across all powerdomains, increment the
1259          * counter.
1260          */
1261 
1262         state = pwrdm_read_pwrst(pwrdm);
1263         if (state != PWRDM_POWER_OFF) {
1264                 pwrdm->state_counter[state]++;
1265                 pwrdm->state_counter[PWRDM_POWER_OFF]++;
1266         }
1267         pwrdm->state = state;
1268 
1269         return 0;
1270 }
1271 
1272 void pwrdms_save_context(void)
1273 {
1274         pwrdm_for_each(pwrdm_save_context, NULL);
1275 }
1276 
1277 void pwrdms_restore_context(void)
1278 {
1279         pwrdm_for_each(pwrdm_restore_context, NULL);
1280 }
1281 
1282 void pwrdms_lost_power(void)
1283 {
1284         pwrdm_for_each(pwrdm_lost_power, NULL);
1285 }

/* [<][>][^][v][top][bottom][index][help] */