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