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