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