• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * OMAP powerdomain control
3  *
4  * Copyright (C) 2007-2008 Texas Instruments, Inc.
5  * Copyright (C) 2007-2008 Nokia Corporation
6  *
7  * Written by Paul Walmsley
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 #ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN
14 # define DEBUG
15 #endif
16 
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/delay.h>
21 #include <linux/spinlock.h>
22 #include <linux/list.h>
23 #include <linux/errno.h>
24 #include <linux/err.h>
25 #include <linux/io.h>
26 
27 #include <asm/atomic.h>
28 
29 #include "cm.h"
30 #include "cm-regbits-34xx.h"
31 #include "prm.h"
32 #include "prm-regbits-34xx.h"
33 
34 #include <mach/cpu.h>
35 #include <mach/powerdomain.h>
36 #include <mach/clockdomain.h>
37 
38 /* pwrdm_list contains all registered struct powerdomains */
39 static LIST_HEAD(pwrdm_list);
40 
41 /*
42  * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
43  * protect pwrdm_clkdms[] during clkdm add/del ops
44  */
45 static DEFINE_RWLOCK(pwrdm_rwlock);
46 
47 
48 /* Private functions */
49 
prm_read_mod_bits_shift(s16 domain,s16 idx,u32 mask)50 static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
51 {
52 	u32 v;
53 
54 	v = prm_read_mod_reg(domain, idx);
55 	v &= mask;
56 	v >>= __ffs(mask);
57 
58 	return v;
59 }
60 
_pwrdm_lookup(const char * name)61 static struct powerdomain *_pwrdm_lookup(const char *name)
62 {
63 	struct powerdomain *pwrdm, *temp_pwrdm;
64 
65 	pwrdm = NULL;
66 
67 	list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
68 		if (!strcmp(name, temp_pwrdm->name)) {
69 			pwrdm = temp_pwrdm;
70 			break;
71 		}
72 	}
73 
74 	return pwrdm;
75 }
76 
77 /* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
_pwrdm_deps_lookup(struct powerdomain * pwrdm,struct pwrdm_dep * deps)78 static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
79 					      struct pwrdm_dep *deps)
80 {
81 	struct pwrdm_dep *pd;
82 
83 	if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
84 		return ERR_PTR(-EINVAL);
85 
86 	for (pd = deps; pd; pd++) {
87 
88 		if (!omap_chip_is(pd->omap_chip))
89 			continue;
90 
91 		if (!pd->pwrdm && pd->pwrdm_name)
92 			pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
93 
94 		if (pd->pwrdm == pwrdm)
95 			break;
96 
97 	}
98 
99 	if (!pd)
100 		return ERR_PTR(-ENOENT);
101 
102 	return pd->pwrdm;
103 }
104 
105 
106 /* Public functions */
107 
108 /**
109  * pwrdm_init - set up the powerdomain layer
110  *
111  * Loop through the list of powerdomains, registering all that are
112  * available on the current CPU. If pwrdm_list is supplied and not
113  * null, all of the referenced powerdomains will be registered.  No
114  * return value.
115  */
pwrdm_init(struct powerdomain ** pwrdm_list)116 void pwrdm_init(struct powerdomain **pwrdm_list)
117 {
118 	struct powerdomain **p = NULL;
119 
120 	if (pwrdm_list)
121 		for (p = pwrdm_list; *p; p++)
122 			pwrdm_register(*p);
123 }
124 
125 /**
126  * pwrdm_register - register a powerdomain
127  * @pwrdm: struct powerdomain * to register
128  *
129  * Adds a powerdomain to the internal powerdomain list.  Returns
130  * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
131  * already registered by the provided name, or 0 upon success.
132  */
pwrdm_register(struct powerdomain * pwrdm)133 int pwrdm_register(struct powerdomain *pwrdm)
134 {
135 	unsigned long flags;
136 	int ret = -EINVAL;
137 
138 	if (!pwrdm)
139 		return -EINVAL;
140 
141 	if (!omap_chip_is(pwrdm->omap_chip))
142 		return -EINVAL;
143 
144 	write_lock_irqsave(&pwrdm_rwlock, flags);
145 	if (_pwrdm_lookup(pwrdm->name)) {
146 		ret = -EEXIST;
147 		goto pr_unlock;
148 	}
149 
150 	list_add(&pwrdm->node, &pwrdm_list);
151 
152 	pr_debug("powerdomain: registered %s\n", pwrdm->name);
153 	ret = 0;
154 
155 pr_unlock:
156 	write_unlock_irqrestore(&pwrdm_rwlock, flags);
157 
158 	return ret;
159 }
160 
161 /**
162  * pwrdm_unregister - unregister a powerdomain
163  * @pwrdm: struct powerdomain * to unregister
164  *
165  * Removes a powerdomain from the internal powerdomain list.  Returns
166  * -EINVAL if pwrdm argument is NULL.
167  */
pwrdm_unregister(struct powerdomain * pwrdm)168 int pwrdm_unregister(struct powerdomain *pwrdm)
169 {
170 	unsigned long flags;
171 
172 	if (!pwrdm)
173 		return -EINVAL;
174 
175 	write_lock_irqsave(&pwrdm_rwlock, flags);
176 	list_del(&pwrdm->node);
177 	write_unlock_irqrestore(&pwrdm_rwlock, flags);
178 
179 	pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
180 
181 	return 0;
182 }
183 
184 /**
185  * pwrdm_lookup - look up a powerdomain by name, return a pointer
186  * @name: name of powerdomain
187  *
188  * Find a registered powerdomain by its name.  Returns a pointer to the
189  * struct powerdomain if found, or NULL otherwise.
190  */
pwrdm_lookup(const char * name)191 struct powerdomain *pwrdm_lookup(const char *name)
192 {
193 	struct powerdomain *pwrdm;
194 	unsigned long flags;
195 
196 	if (!name)
197 		return NULL;
198 
199 	read_lock_irqsave(&pwrdm_rwlock, flags);
200 	pwrdm = _pwrdm_lookup(name);
201 	read_unlock_irqrestore(&pwrdm_rwlock, flags);
202 
203 	return pwrdm;
204 }
205 
206 /**
207  * pwrdm_for_each - call function on each registered clockdomain
208  * @fn: callback function *
209  *
210  * Call the supplied function for each registered powerdomain.  The
211  * callback function can return anything but 0 to bail out early from
212  * the iterator.  The callback function is called with the pwrdm_rwlock
213  * held for reading, so no powerdomain structure manipulation
214  * functions should be called from the callback, although hardware
215  * powerdomain control functions are fine.  Returns the last return
216  * value of the callback function, which should be 0 for success or
217  * anything else to indicate failure; or -EINVAL if the function
218  * pointer is null.
219  */
pwrdm_for_each(int (* fn)(struct powerdomain * pwrdm))220 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
221 {
222 	struct powerdomain *temp_pwrdm;
223 	unsigned long flags;
224 	int ret = 0;
225 
226 	if (!fn)
227 		return -EINVAL;
228 
229 	read_lock_irqsave(&pwrdm_rwlock, flags);
230 	list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
231 		ret = (*fn)(temp_pwrdm);
232 		if (ret)
233 			break;
234 	}
235 	read_unlock_irqrestore(&pwrdm_rwlock, flags);
236 
237 	return ret;
238 }
239 
240 /**
241  * pwrdm_add_clkdm - add a clockdomain to a powerdomain
242  * @pwrdm: struct powerdomain * to add the clockdomain to
243  * @clkdm: struct clockdomain * to associate with a powerdomain
244  *
245  * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'.  This
246  * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
247  * presented with invalid pointers; -ENOMEM if memory could not be allocated;
248  * or 0 upon success.
249  */
pwrdm_add_clkdm(struct powerdomain * pwrdm,struct clockdomain * clkdm)250 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
251 {
252 	unsigned long flags;
253 	int i;
254 	int ret = -EINVAL;
255 
256 	if (!pwrdm || !clkdm)
257 		return -EINVAL;
258 
259 	pr_debug("powerdomain: associating clockdomain %s with powerdomain "
260 		 "%s\n", clkdm->name, pwrdm->name);
261 
262 	write_lock_irqsave(&pwrdm_rwlock, flags);
263 
264 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
265 		if (!pwrdm->pwrdm_clkdms[i])
266 			break;
267 #ifdef DEBUG
268 		if (pwrdm->pwrdm_clkdms[i] == clkdm) {
269 			ret = -EINVAL;
270 			goto pac_exit;
271 		}
272 #endif
273 	}
274 
275 	if (i == PWRDM_MAX_CLKDMS) {
276 		pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
277 			 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
278 		WARN_ON(1);
279 		ret = -ENOMEM;
280 		goto pac_exit;
281 	}
282 
283 	pwrdm->pwrdm_clkdms[i] = clkdm;
284 
285 	ret = 0;
286 
287 pac_exit:
288 	write_unlock_irqrestore(&pwrdm_rwlock, flags);
289 
290 	return ret;
291 }
292 
293 /**
294  * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
295  * @pwrdm: struct powerdomain * to add the clockdomain to
296  * @clkdm: struct clockdomain * to associate with a powerdomain
297  *
298  * Dissociate the clockdomain 'clkdm' from the powerdomain
299  * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
300  * -ENOENT if the clkdm was not associated with the powerdomain, or 0
301  * upon success.
302  */
pwrdm_del_clkdm(struct powerdomain * pwrdm,struct clockdomain * clkdm)303 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
304 {
305 	unsigned long flags;
306 	int ret = -EINVAL;
307 	int i;
308 
309 	if (!pwrdm || !clkdm)
310 		return -EINVAL;
311 
312 	pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
313 		 "%s\n", clkdm->name, pwrdm->name);
314 
315 	write_lock_irqsave(&pwrdm_rwlock, flags);
316 
317 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
318 		if (pwrdm->pwrdm_clkdms[i] == clkdm)
319 			break;
320 
321 	if (i == PWRDM_MAX_CLKDMS) {
322 		pr_debug("powerdomain: clkdm %s not associated with pwrdm "
323 			 "%s ?!\n", clkdm->name, pwrdm->name);
324 		ret = -ENOENT;
325 		goto pdc_exit;
326 	}
327 
328 	pwrdm->pwrdm_clkdms[i] = NULL;
329 
330 	ret = 0;
331 
332 pdc_exit:
333 	write_unlock_irqrestore(&pwrdm_rwlock, flags);
334 
335 	return ret;
336 }
337 
338 /**
339  * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
340  * @pwrdm: struct powerdomain * to iterate over
341  * @fn: callback function *
342  *
343  * Call the supplied function for each clockdomain in the powerdomain
344  * 'pwrdm'.  The callback function can return anything but 0 to bail
345  * out early from the iterator.  The callback function is called with
346  * the pwrdm_rwlock held for reading, so no powerdomain structure
347  * manipulation functions should be called from the callback, although
348  * hardware powerdomain control functions are fine.  Returns -EINVAL
349  * if presented with invalid pointers; or passes along the last return
350  * value of the callback function, which should be 0 for success or
351  * anything else to indicate failure.
352  */
pwrdm_for_each_clkdm(struct powerdomain * pwrdm,int (* fn)(struct powerdomain * pwrdm,struct clockdomain * clkdm))353 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
354 			 int (*fn)(struct powerdomain *pwrdm,
355 				   struct clockdomain *clkdm))
356 {
357 	unsigned long flags;
358 	int ret = 0;
359 	int i;
360 
361 	if (!fn)
362 		return -EINVAL;
363 
364 	read_lock_irqsave(&pwrdm_rwlock, flags);
365 
366 	for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
367 		ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
368 
369 	read_unlock_irqrestore(&pwrdm_rwlock, flags);
370 
371 	return ret;
372 }
373 
374 
375 /**
376  * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
377  * @pwrdm1: wake this struct powerdomain * up (dependent)
378  * @pwrdm2: when this struct powerdomain * wakes up (source)
379  *
380  * When the powerdomain represented by pwrdm2 wakes up (due to an
381  * interrupt), wake up pwrdm1.	Implemented in hardware on the OMAP,
382  * this feature is designed to reduce wakeup latency of the dependent
383  * powerdomain.  Returns -EINVAL if presented with invalid powerdomain
384  * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
385  * 0 upon success.
386  */
pwrdm_add_wkdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)387 int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
388 {
389 	struct powerdomain *p;
390 
391 	if (!pwrdm1)
392 		return -EINVAL;
393 
394 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
395 	if (IS_ERR(p)) {
396 		pr_debug("powerdomain: hardware cannot set/clear wake up of "
397 			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
398 		return IS_ERR(p);
399 	}
400 
401 	pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
402 		 pwrdm1->name, pwrdm2->name);
403 
404 	prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
405 			     pwrdm1->prcm_offs, PM_WKDEP);
406 
407 	return 0;
408 }
409 
410 /**
411  * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
412  * @pwrdm1: wake this struct powerdomain * up (dependent)
413  * @pwrdm2: when this struct powerdomain * wakes up (source)
414  *
415  * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
416  * wakes up.  Returns -EINVAL if presented with invalid powerdomain
417  * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
418  * 0 upon success.
419  */
pwrdm_del_wkdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)420 int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
421 {
422 	struct powerdomain *p;
423 
424 	if (!pwrdm1)
425 		return -EINVAL;
426 
427 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
428 	if (IS_ERR(p)) {
429 		pr_debug("powerdomain: hardware cannot set/clear wake up of "
430 			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
431 		return IS_ERR(p);
432 	}
433 
434 	pr_debug("powerdomain: hardware will no longer wake up %s after %s "
435 		 "wakes up\n", pwrdm1->name, pwrdm2->name);
436 
437 	prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
438 			       pwrdm1->prcm_offs, PM_WKDEP);
439 
440 	return 0;
441 }
442 
443 /**
444  * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
445  * @pwrdm1: wake this struct powerdomain * up (dependent)
446  * @pwrdm2: when this struct powerdomain * wakes up (source)
447  *
448  * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
449  * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
450  * if either powerdomain pointer is invalid; or -ENOENT if the hardware
451  * is incapable.
452  *
453  * REVISIT: Currently this function only represents software-controllable
454  * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
455  * yet handled here.
456  */
pwrdm_read_wkdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)457 int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
458 {
459 	struct powerdomain *p;
460 
461 	if (!pwrdm1)
462 		return -EINVAL;
463 
464 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
465 	if (IS_ERR(p)) {
466 		pr_debug("powerdomain: hardware cannot set/clear wake up of "
467 			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
468 		return IS_ERR(p);
469 	}
470 
471 	return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
472 					(1 << pwrdm2->dep_bit));
473 }
474 
475 /**
476  * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
477  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
478  * @pwrdm2: when this struct powerdomain * is active (source)
479  *
480  * Prevent pwrdm1 from automatically going inactive (and then to
481  * retention or off) if pwrdm2 is still active.	 Returns -EINVAL if
482  * presented with invalid powerdomain pointers or called on a machine
483  * that does not support software-configurable hardware sleep dependencies,
484  * -ENOENT if the specified dependency cannot be set in hardware, or
485  * 0 upon success.
486  */
pwrdm_add_sleepdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)487 int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
488 {
489 	struct powerdomain *p;
490 
491 	if (!pwrdm1)
492 		return -EINVAL;
493 
494 	if (!cpu_is_omap34xx())
495 		return -EINVAL;
496 
497 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
498 	if (IS_ERR(p)) {
499 		pr_debug("powerdomain: hardware cannot set/clear sleep "
500 			 "dependency affecting %s from %s\n", pwrdm1->name,
501 			 pwrdm2->name);
502 		return IS_ERR(p);
503 	}
504 
505 	pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
506 		 pwrdm1->name, pwrdm2->name);
507 
508 	cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
509 			    pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
510 
511 	return 0;
512 }
513 
514 /**
515  * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
516  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
517  * @pwrdm2: when this struct powerdomain * is active (source)
518  *
519  * Allow pwrdm1 to automatically go inactive (and then to retention or
520  * off), independent of the activity state of pwrdm2.  Returns -EINVAL
521  * if presented with invalid powerdomain pointers or called on a machine
522  * that does not support software-configurable hardware sleep dependencies,
523  * -ENOENT if the specified dependency cannot be cleared in hardware, or
524  * 0 upon success.
525  */
pwrdm_del_sleepdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)526 int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
527 {
528 	struct powerdomain *p;
529 
530 	if (!pwrdm1)
531 		return -EINVAL;
532 
533 	if (!cpu_is_omap34xx())
534 		return -EINVAL;
535 
536 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
537 	if (IS_ERR(p)) {
538 		pr_debug("powerdomain: hardware cannot set/clear sleep "
539 			 "dependency affecting %s from %s\n", pwrdm1->name,
540 			 pwrdm2->name);
541 		return IS_ERR(p);
542 	}
543 
544 	pr_debug("powerdomain: will no longer prevent %s from sleeping if "
545 		 "%s is active\n", pwrdm1->name, pwrdm2->name);
546 
547 	cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
548 			      pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
549 
550 	return 0;
551 }
552 
553 /**
554  * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
555  * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
556  * @pwrdm2: when this struct powerdomain * is active (source)
557  *
558  * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
559  * not be allowed to automatically go inactive if pwrdm2 is active;
560  * 0 if pwrdm1's automatic power state inactivity transition is independent
561  * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
562  * on a machine that does not support software-configurable hardware sleep
563  * dependencies; or -ENOENT if the hardware is incapable.
564  *
565  * REVISIT: Currently this function only represents software-controllable
566  * sleep dependencies.	Sleep dependencies fixed in hardware are not
567  * yet handled here.
568  */
pwrdm_read_sleepdep(struct powerdomain * pwrdm1,struct powerdomain * pwrdm2)569 int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
570 {
571 	struct powerdomain *p;
572 
573 	if (!pwrdm1)
574 		return -EINVAL;
575 
576 	if (!cpu_is_omap34xx())
577 		return -EINVAL;
578 
579 	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
580 	if (IS_ERR(p)) {
581 		pr_debug("powerdomain: hardware cannot set/clear sleep "
582 			 "dependency affecting %s from %s\n", pwrdm1->name,
583 			 pwrdm2->name);
584 		return IS_ERR(p);
585 	}
586 
587 	return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
588 					(1 << pwrdm2->dep_bit));
589 }
590 
591 /**
592  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
593  * @pwrdm: struct powerdomain *
594  *
595  * Return the number of controllable memory banks in powerdomain pwrdm,
596  * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
597  */
pwrdm_get_mem_bank_count(struct powerdomain * pwrdm)598 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
599 {
600 	if (!pwrdm)
601 		return -EINVAL;
602 
603 	return pwrdm->banks;
604 }
605 
606 /**
607  * pwrdm_set_next_pwrst - set next powerdomain power state
608  * @pwrdm: struct powerdomain * to set
609  * @pwrst: one of the PWRDM_POWER_* macros
610  *
611  * Set the powerdomain pwrdm's next power state to pwrst.  The powerdomain
612  * may not enter this state immediately if the preconditions for this state
613  * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
614  * null or if the power state is invalid for the powerdomin, or returns 0
615  * upon success.
616  */
pwrdm_set_next_pwrst(struct powerdomain * pwrdm,u8 pwrst)617 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
618 {
619 	if (!pwrdm)
620 		return -EINVAL;
621 
622 	if (!(pwrdm->pwrsts & (1 << pwrst)))
623 		return -EINVAL;
624 
625 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
626 		 pwrdm->name, pwrst);
627 
628 	prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
629 			     (pwrst << OMAP_POWERSTATE_SHIFT),
630 			     pwrdm->prcm_offs, PM_PWSTCTRL);
631 
632 	return 0;
633 }
634 
635 /**
636  * pwrdm_read_next_pwrst - get next powerdomain power state
637  * @pwrdm: struct powerdomain * to get power state
638  *
639  * Return the powerdomain pwrdm's next power state.  Returns -EINVAL
640  * if the powerdomain pointer is null or returns the next power state
641  * upon success.
642  */
pwrdm_read_next_pwrst(struct powerdomain * pwrdm)643 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
644 {
645 	if (!pwrdm)
646 		return -EINVAL;
647 
648 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
649 					OMAP_POWERSTATE_MASK);
650 }
651 
652 /**
653  * pwrdm_read_pwrst - get current powerdomain power state
654  * @pwrdm: struct powerdomain * to get power state
655  *
656  * Return the powerdomain pwrdm's current power state.	Returns -EINVAL
657  * if the powerdomain pointer is null or returns the current power state
658  * upon success.
659  */
pwrdm_read_pwrst(struct powerdomain * pwrdm)660 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
661 {
662 	if (!pwrdm)
663 		return -EINVAL;
664 
665 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
666 					OMAP_POWERSTATEST_MASK);
667 }
668 
669 /**
670  * pwrdm_read_prev_pwrst - get previous powerdomain power state
671  * @pwrdm: struct powerdomain * to get previous power state
672  *
673  * Return the powerdomain pwrdm's previous power state.  Returns -EINVAL
674  * if the powerdomain pointer is null or returns the previous power state
675  * upon success.
676  */
pwrdm_read_prev_pwrst(struct powerdomain * pwrdm)677 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
678 {
679 	if (!pwrdm)
680 		return -EINVAL;
681 
682 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
683 					OMAP3430_LASTPOWERSTATEENTERED_MASK);
684 }
685 
686 /**
687  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
688  * @pwrdm: struct powerdomain * to set
689  * @pwrst: one of the PWRDM_POWER_* macros
690  *
691  * Set the next power state that the logic portion of the powerdomain
692  * pwrdm will enter when the powerdomain enters retention.  This will
693  * be either RETENTION or OFF, if supported.  Returns -EINVAL if the
694  * powerdomain pointer is null or the target power state is not not
695  * supported, or returns 0 upon success.
696  */
pwrdm_set_logic_retst(struct powerdomain * pwrdm,u8 pwrst)697 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
698 {
699 	if (!pwrdm)
700 		return -EINVAL;
701 
702 	if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
703 		return -EINVAL;
704 
705 	pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
706 		 pwrdm->name, pwrst);
707 
708 	/*
709 	 * The register bit names below may not correspond to the
710 	 * actual names of the bits in each powerdomain's register,
711 	 * but the type of value returned is the same for each
712 	 * powerdomain.
713 	 */
714 	prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
715 			     (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
716 			     pwrdm->prcm_offs, PM_PWSTCTRL);
717 
718 	return 0;
719 }
720 
721 /**
722  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
723  * @pwrdm: struct powerdomain * to set
724  * @bank: memory bank number to set (0-3)
725  * @pwrst: one of the PWRDM_POWER_* macros
726  *
727  * Set the next power state that memory bank x of the powerdomain
728  * pwrdm will enter when the powerdomain enters the ON state.  Bank
729  * will be a number from 0 to 3, and represents different types of
730  * memory, depending on the powerdomain.  Returns -EINVAL if the
731  * powerdomain pointer is null or the target power state is not not
732  * supported for this memory bank, -EEXIST if the target memory bank
733  * does not exist or is not controllable, or returns 0 upon success.
734  */
pwrdm_set_mem_onst(struct powerdomain * pwrdm,u8 bank,u8 pwrst)735 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
736 {
737 	u32 m;
738 
739 	if (!pwrdm)
740 		return -EINVAL;
741 
742 	if (pwrdm->banks < (bank + 1))
743 		return -EEXIST;
744 
745 	if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
746 		return -EINVAL;
747 
748 	pr_debug("powerdomain: setting next memory powerstate for domain %s "
749 		 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
750 
751 	/*
752 	 * The register bit names below may not correspond to the
753 	 * actual names of the bits in each powerdomain's register,
754 	 * but the type of value returned is the same for each
755 	 * powerdomain.
756 	 */
757 	switch (bank) {
758 	case 0:
759 		m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
760 		break;
761 	case 1:
762 		m = OMAP3430_L1FLATMEMONSTATE_MASK;
763 		break;
764 	case 2:
765 		m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
766 		break;
767 	case 3:
768 		m = OMAP3430_L2FLATMEMONSTATE_MASK;
769 		break;
770 	default:
771 		WARN_ON(1); /* should never happen */
772 		return -EEXIST;
773 	}
774 
775 	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
776 			     pwrdm->prcm_offs, PM_PWSTCTRL);
777 
778 	return 0;
779 }
780 
781 /**
782  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
783  * @pwrdm: struct powerdomain * to set
784  * @bank: memory bank number to set (0-3)
785  * @pwrst: one of the PWRDM_POWER_* macros
786  *
787  * Set the next power state that memory bank x of the powerdomain
788  * pwrdm will enter when the powerdomain enters the RETENTION state.
789  * Bank will be a number from 0 to 3, and represents different types
790  * of memory, depending on the powerdomain.  pwrst will be either
791  * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
792  * pointer is null or the target power state is not not supported for
793  * this memory bank, -EEXIST if the target memory bank does not exist
794  * or is not controllable, or returns 0 upon success.
795  */
pwrdm_set_mem_retst(struct powerdomain * pwrdm,u8 bank,u8 pwrst)796 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
797 {
798 	u32 m;
799 
800 	if (!pwrdm)
801 		return -EINVAL;
802 
803 	if (pwrdm->banks < (bank + 1))
804 		return -EEXIST;
805 
806 	if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
807 		return -EINVAL;
808 
809 	pr_debug("powerdomain: setting next memory powerstate for domain %s "
810 		 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
811 
812 	/*
813 	 * The register bit names below may not correspond to the
814 	 * actual names of the bits in each powerdomain's register,
815 	 * but the type of value returned is the same for each
816 	 * powerdomain.
817 	 */
818 	switch (bank) {
819 	case 0:
820 		m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
821 		break;
822 	case 1:
823 		m = OMAP3430_L1FLATMEMRETSTATE;
824 		break;
825 	case 2:
826 		m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
827 		break;
828 	case 3:
829 		m = OMAP3430_L2FLATMEMRETSTATE;
830 		break;
831 	default:
832 		WARN_ON(1); /* should never happen */
833 		return -EEXIST;
834 	}
835 
836 	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
837 			     PM_PWSTCTRL);
838 
839 	return 0;
840 }
841 
842 /**
843  * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
844  * @pwrdm: struct powerdomain * to get current logic retention power state
845  *
846  * Return the current power state that the logic portion of
847  * powerdomain pwrdm will enter
848  * Returns -EINVAL if the powerdomain pointer is null or returns the
849  * current logic retention power state upon success.
850  */
pwrdm_read_logic_pwrst(struct powerdomain * pwrdm)851 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
852 {
853 	if (!pwrdm)
854 		return -EINVAL;
855 
856 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
857 					OMAP3430_LOGICSTATEST);
858 }
859 
860 /**
861  * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
862  * @pwrdm: struct powerdomain * to get previous logic power state
863  *
864  * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
865  * if the powerdomain pointer is null or returns the previous logic
866  * power state upon success.
867  */
pwrdm_read_prev_logic_pwrst(struct powerdomain * pwrdm)868 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
869 {
870 	if (!pwrdm)
871 		return -EINVAL;
872 
873 	/*
874 	 * The register bit names below may not correspond to the
875 	 * actual names of the bits in each powerdomain's register,
876 	 * but the type of value returned is the same for each
877 	 * powerdomain.
878 	 */
879 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
880 					OMAP3430_LASTLOGICSTATEENTERED);
881 }
882 
883 /**
884  * pwrdm_read_mem_pwrst - get current memory bank power state
885  * @pwrdm: struct powerdomain * to get current memory bank power state
886  * @bank: memory bank number (0-3)
887  *
888  * Return the powerdomain pwrdm's current memory power state for bank
889  * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
890  * the target memory bank does not exist or is not controllable, or
891  * returns the current memory power state upon success.
892  */
pwrdm_read_mem_pwrst(struct powerdomain * pwrdm,u8 bank)893 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
894 {
895 	u32 m;
896 
897 	if (!pwrdm)
898 		return -EINVAL;
899 
900 	if (pwrdm->banks < (bank + 1))
901 		return -EEXIST;
902 
903 	/*
904 	 * The register bit names below may not correspond to the
905 	 * actual names of the bits in each powerdomain's register,
906 	 * but the type of value returned is the same for each
907 	 * powerdomain.
908 	 */
909 	switch (bank) {
910 	case 0:
911 		m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
912 		break;
913 	case 1:
914 		m = OMAP3430_L1FLATMEMSTATEST_MASK;
915 		break;
916 	case 2:
917 		m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
918 		break;
919 	case 3:
920 		m = OMAP3430_L2FLATMEMSTATEST_MASK;
921 		break;
922 	default:
923 		WARN_ON(1); /* should never happen */
924 		return -EEXIST;
925 	}
926 
927 	return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
928 }
929 
930 /**
931  * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
932  * @pwrdm: struct powerdomain * to get previous memory bank power state
933  * @bank: memory bank number (0-3)
934  *
935  * Return the powerdomain pwrdm's previous memory power state for bank
936  * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
937  * the target memory bank does not exist or is not controllable, or
938  * returns the previous memory power state upon success.
939  */
pwrdm_read_prev_mem_pwrst(struct powerdomain * pwrdm,u8 bank)940 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
941 {
942 	u32 m;
943 
944 	if (!pwrdm)
945 		return -EINVAL;
946 
947 	if (pwrdm->banks < (bank + 1))
948 		return -EEXIST;
949 
950 	/*
951 	 * The register bit names below may not correspond to the
952 	 * actual names of the bits in each powerdomain's register,
953 	 * but the type of value returned is the same for each
954 	 * powerdomain.
955 	 */
956 	switch (bank) {
957 	case 0:
958 		m = OMAP3430_LASTMEM1STATEENTERED_MASK;
959 		break;
960 	case 1:
961 		m = OMAP3430_LASTMEM2STATEENTERED_MASK;
962 		break;
963 	case 2:
964 		m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
965 		break;
966 	case 3:
967 		m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
968 		break;
969 	default:
970 		WARN_ON(1); /* should never happen */
971 		return -EEXIST;
972 	}
973 
974 	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
975 					OMAP3430_PM_PREPWSTST, m);
976 }
977 
978 /**
979  * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
980  * @pwrdm: struct powerdomain * to clear
981  *
982  * Clear the powerdomain's previous power state register.  Clears the
983  * entire register, including logic and memory bank previous power states.
984  * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
985  * success.
986  */
pwrdm_clear_all_prev_pwrst(struct powerdomain * pwrdm)987 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
988 {
989 	if (!pwrdm)
990 		return -EINVAL;
991 
992 	/*
993 	 * XXX should get the powerdomain's current state here;
994 	 * warn & fail if it is not ON.
995 	 */
996 
997 	pr_debug("powerdomain: clearing previous power state reg for %s\n",
998 		 pwrdm->name);
999 
1000 	prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
1001 
1002 	return 0;
1003 }
1004 
1005 /**
1006  * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
1007  * @pwrdm: struct powerdomain *
1008  *
1009  * Enable automatic context save-and-restore upon power state change
1010  * for some devices in a powerdomain.  Warning: this only affects a
1011  * subset of devices in a powerdomain; check the TRM closely.  Returns
1012  * -EINVAL if the powerdomain pointer is null or if the powerdomain
1013  * does not support automatic save-and-restore, or returns 0 upon
1014  * success.
1015  */
pwrdm_enable_hdwr_sar(struct powerdomain * pwrdm)1016 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
1017 {
1018 	if (!pwrdm)
1019 		return -EINVAL;
1020 
1021 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1022 		return -EINVAL;
1023 
1024 	pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
1025 		 pwrdm->name);
1026 
1027 	prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
1028 			     pwrdm->prcm_offs, PM_PWSTCTRL);
1029 
1030 	return 0;
1031 }
1032 
1033 /**
1034  * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
1035  * @pwrdm: struct powerdomain *
1036  *
1037  * Disable automatic context save-and-restore upon power state change
1038  * for some devices in a powerdomain.  Warning: this only affects a
1039  * subset of devices in a powerdomain; check the TRM closely.  Returns
1040  * -EINVAL if the powerdomain pointer is null or if the powerdomain
1041  * does not support automatic save-and-restore, or returns 0 upon
1042  * success.
1043  */
pwrdm_disable_hdwr_sar(struct powerdomain * pwrdm)1044 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
1045 {
1046 	if (!pwrdm)
1047 		return -EINVAL;
1048 
1049 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
1050 		return -EINVAL;
1051 
1052 	pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
1053 		 pwrdm->name);
1054 
1055 	prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
1056 			     pwrdm->prcm_offs, PM_PWSTCTRL);
1057 
1058 	return 0;
1059 }
1060 
1061 /**
1062  * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
1063  * @pwrdm: struct powerdomain *
1064  *
1065  * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
1066  * for some devices, or 0 if it does not.
1067  */
pwrdm_has_hdwr_sar(struct powerdomain * pwrdm)1068 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
1069 {
1070 	return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
1071 }
1072 
1073 /**
1074  * pwrdm_wait_transition - wait for powerdomain power transition to finish
1075  * @pwrdm: struct powerdomain * to wait for
1076  *
1077  * If the powerdomain pwrdm is in the process of a state transition,
1078  * spin until it completes the power transition, or until an iteration
1079  * bailout value is reached. Returns -EINVAL if the powerdomain
1080  * pointer is null, -EAGAIN if the bailout value was reached, or
1081  * returns 0 upon success.
1082  */
pwrdm_wait_transition(struct powerdomain * pwrdm)1083 int pwrdm_wait_transition(struct powerdomain *pwrdm)
1084 {
1085 	u32 c = 0;
1086 
1087 	if (!pwrdm)
1088 		return -EINVAL;
1089 
1090 	/*
1091 	 * REVISIT: pwrdm_wait_transition() may be better implemented
1092 	 * via a callback and a periodic timer check -- how long do we expect
1093 	 * powerdomain transitions to take?
1094 	 */
1095 
1096 	/* XXX Is this udelay() value meaningful? */
1097 	while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
1098 		OMAP_INTRANSITION) &&
1099 	       (c++ < PWRDM_TRANSITION_BAILOUT))
1100 		udelay(1);
1101 
1102 	if (c >= PWRDM_TRANSITION_BAILOUT) {
1103 		printk(KERN_ERR "powerdomain: waited too long for "
1104 		       "powerdomain %s to complete transition\n", pwrdm->name);
1105 		return -EAGAIN;
1106 	}
1107 
1108 	pr_debug("powerdomain: completed transition in %d loops\n", c);
1109 
1110 	return 0;
1111 }
1112 
1113 
1114