diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 22:28:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 22:28:15 -0400 |
commit | 0df0914d414a504b975f3cc66ace0c16ef55b7f3 (patch) | |
tree | c97ffa357943a8b226cdec1b9632c4cede813205 /arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | |
parent | 6899608533410557e6698cb9d4ff6df553916e98 (diff) | |
parent | 05f689400ea5fa3d71af82f910c8b140f87ad1f3 (diff) |
Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6
* 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6: (258 commits)
omap: zoom: host should not pull up wl1271's irq line
arm: plat-omap: iommu: fix request_mem_region() error path
OMAP2+: Common CPU DIE ID reading code reads wrong registers for OMAP4430
omap4: mux: Remove duplicate mux modes
omap: iovmm: don't check 'da' to set IOVMF_DA_FIXED flag
omap: iovmm: disallow mapping NULL address when IOVMF_DA_ANON is set
omap2+: mux: Fix compile when CONFIG_OMAP_MUX is not selected
omap4: board-omap4panda: Initialise the serial pads
omap3: board-3430sdp: Initialise the serial pads
omap4: board-4430sdp: Initialise the serial pads
omap2+: mux: Add macro for configuring static with omap_hwmod_mux_init
omap2+: mux: Remove the use of IDLE flag
omap2+: Add separate list for dynamic pads to mux
perf: add OMAP support for the new power events
OMAP4: Add IVA OPP enteries.
OMAP4: Update Voltage Rail Values for MPU, IVA and CORE
OMAP4: Enable 800 MHz and 1 GHz MPU-OPP
OMAP3+: OPP: Replace voltage values with Macros
OMAP3: wdtimer: Fix CORE idle transition
Watchdog: omap_wdt: add fine grain runtime-pm
...
Fix up various conflicts in
- arch/arm/mach-omap2/board-omap3evm.c
- arch/arm/mach-omap2/clock3xxx_data.c
- arch/arm/mach-omap2/usb-musb.c
- arch/arm/plat-omap/include/plat/usb.h
- drivers/usb/musb/musb_core.h
Diffstat (limited to 'arch/arm/mach-omap2/clockdomain2xxx_3xxx.c')
-rw-r--r-- | arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c new file mode 100644 index 000000000000..48d0db7e6069 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * OMAP2 and OMAP3 clockdomain control | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
6 | * | ||
7 | * Derived from mach-omap2/clockdomain.c written by Paul Walmsley | ||
8 | * Rajendra Nayak <rnayak@ti.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <plat/prcm.h> | ||
17 | #include "prm.h" | ||
18 | #include "prm2xxx_3xxx.h" | ||
19 | #include "cm.h" | ||
20 | #include "cm2xxx_3xxx.h" | ||
21 | #include "cm-regbits-24xx.h" | ||
22 | #include "cm-regbits-34xx.h" | ||
23 | #include "prm-regbits-24xx.h" | ||
24 | #include "clockdomain.h" | ||
25 | |||
26 | static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, | ||
27 | struct clockdomain *clkdm2) | ||
28 | { | ||
29 | omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), | ||
30 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1, | ||
35 | struct clockdomain *clkdm2) | ||
36 | { | ||
37 | omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | ||
38 | clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, | ||
43 | struct clockdomain *clkdm2) | ||
44 | { | ||
45 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | ||
46 | PM_WKDEP, (1 << clkdm2->dep_bit)); | ||
47 | } | ||
48 | |||
49 | static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) | ||
50 | { | ||
51 | struct clkdm_dep *cd; | ||
52 | u32 mask = 0; | ||
53 | |||
54 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { | ||
55 | if (!omap_chip_is(cd->omap_chip)) | ||
56 | continue; | ||
57 | if (!cd->clkdm) | ||
58 | continue; /* only happens if data is erroneous */ | ||
59 | |||
60 | /* PRM accesses are slow, so minimize them */ | ||
61 | mask |= 1 << cd->clkdm->dep_bit; | ||
62 | atomic_set(&cd->wkdep_usecount, 0); | ||
63 | } | ||
64 | |||
65 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
66 | PM_WKDEP); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1, | ||
71 | struct clockdomain *clkdm2) | ||
72 | { | ||
73 | omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), | ||
74 | clkdm1->pwrdm.ptr->prcm_offs, | ||
75 | OMAP3430_CM_SLEEPDEP); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1, | ||
80 | struct clockdomain *clkdm2) | ||
81 | { | ||
82 | omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), | ||
83 | clkdm1->pwrdm.ptr->prcm_offs, | ||
84 | OMAP3430_CM_SLEEPDEP); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1, | ||
89 | struct clockdomain *clkdm2) | ||
90 | { | ||
91 | return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, | ||
92 | OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit)); | ||
93 | } | ||
94 | |||
95 | static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) | ||
96 | { | ||
97 | struct clkdm_dep *cd; | ||
98 | u32 mask = 0; | ||
99 | |||
100 | for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { | ||
101 | if (!omap_chip_is(cd->omap_chip)) | ||
102 | continue; | ||
103 | if (!cd->clkdm) | ||
104 | continue; /* only happens if data is erroneous */ | ||
105 | |||
106 | /* PRM accesses are slow, so minimize them */ | ||
107 | mask |= 1 << cd->clkdm->dep_bit; | ||
108 | atomic_set(&cd->sleepdep_usecount, 0); | ||
109 | } | ||
110 | omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, | ||
111 | OMAP3430_CM_SLEEPDEP); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int omap2_clkdm_sleep(struct clockdomain *clkdm) | ||
116 | { | ||
117 | omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, | ||
118 | clkdm->pwrdm.ptr->prcm_offs, | ||
119 | OMAP2_PM_PWSTCTRL); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int omap2_clkdm_wakeup(struct clockdomain *clkdm) | ||
124 | { | ||
125 | omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, | ||
126 | clkdm->pwrdm.ptr->prcm_offs, | ||
127 | OMAP2_PM_PWSTCTRL); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static void omap2_clkdm_allow_idle(struct clockdomain *clkdm) | ||
132 | { | ||
133 | if (atomic_read(&clkdm->usecount) > 0) | ||
134 | _clkdm_add_autodeps(clkdm); | ||
135 | |||
136 | omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
137 | clkdm->clktrctrl_mask); | ||
138 | } | ||
139 | |||
140 | static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | ||
141 | { | ||
142 | omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
143 | clkdm->clktrctrl_mask); | ||
144 | |||
145 | if (atomic_read(&clkdm->usecount) > 0) | ||
146 | _clkdm_del_autodeps(clkdm); | ||
147 | } | ||
148 | |||
149 | static void _enable_hwsup(struct clockdomain *clkdm) | ||
150 | { | ||
151 | if (cpu_is_omap24xx()) | ||
152 | omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
153 | clkdm->clktrctrl_mask); | ||
154 | else if (cpu_is_omap34xx()) | ||
155 | omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
156 | clkdm->clktrctrl_mask); | ||
157 | } | ||
158 | |||
159 | static void _disable_hwsup(struct clockdomain *clkdm) | ||
160 | { | ||
161 | if (cpu_is_omap24xx()) | ||
162 | omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
163 | clkdm->clktrctrl_mask); | ||
164 | else if (cpu_is_omap34xx()) | ||
165 | omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
166 | clkdm->clktrctrl_mask); | ||
167 | } | ||
168 | |||
169 | |||
170 | static int omap2_clkdm_clk_enable(struct clockdomain *clkdm) | ||
171 | { | ||
172 | bool hwsup = false; | ||
173 | |||
174 | if (!clkdm->clktrctrl_mask) | ||
175 | return 0; | ||
176 | |||
177 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
178 | clkdm->clktrctrl_mask); | ||
179 | |||
180 | if (hwsup) { | ||
181 | /* Disable HW transitions when we are changing deps */ | ||
182 | _disable_hwsup(clkdm); | ||
183 | _clkdm_add_autodeps(clkdm); | ||
184 | _enable_hwsup(clkdm); | ||
185 | } else { | ||
186 | clkdm_wakeup(clkdm); | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int omap2_clkdm_clk_disable(struct clockdomain *clkdm) | ||
193 | { | ||
194 | bool hwsup = false; | ||
195 | |||
196 | if (!clkdm->clktrctrl_mask) | ||
197 | return 0; | ||
198 | |||
199 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
200 | clkdm->clktrctrl_mask); | ||
201 | |||
202 | if (hwsup) { | ||
203 | /* Disable HW transitions when we are changing deps */ | ||
204 | _disable_hwsup(clkdm); | ||
205 | _clkdm_del_autodeps(clkdm); | ||
206 | _enable_hwsup(clkdm); | ||
207 | } else { | ||
208 | clkdm_sleep(clkdm); | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int omap3_clkdm_sleep(struct clockdomain *clkdm) | ||
215 | { | ||
216 | omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, | ||
217 | clkdm->clktrctrl_mask); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int omap3_clkdm_wakeup(struct clockdomain *clkdm) | ||
222 | { | ||
223 | omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs, | ||
224 | clkdm->clktrctrl_mask); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void omap3_clkdm_allow_idle(struct clockdomain *clkdm) | ||
229 | { | ||
230 | if (atomic_read(&clkdm->usecount) > 0) | ||
231 | _clkdm_add_autodeps(clkdm); | ||
232 | |||
233 | omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
234 | clkdm->clktrctrl_mask); | ||
235 | } | ||
236 | |||
237 | static void omap3_clkdm_deny_idle(struct clockdomain *clkdm) | ||
238 | { | ||
239 | omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
240 | clkdm->clktrctrl_mask); | ||
241 | |||
242 | if (atomic_read(&clkdm->usecount) > 0) | ||
243 | _clkdm_del_autodeps(clkdm); | ||
244 | } | ||
245 | |||
246 | struct clkdm_ops omap2_clkdm_operations = { | ||
247 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, | ||
248 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, | ||
249 | .clkdm_read_wkdep = omap2_clkdm_read_wkdep, | ||
250 | .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, | ||
251 | .clkdm_sleep = omap2_clkdm_sleep, | ||
252 | .clkdm_wakeup = omap2_clkdm_wakeup, | ||
253 | .clkdm_allow_idle = omap2_clkdm_allow_idle, | ||
254 | .clkdm_deny_idle = omap2_clkdm_deny_idle, | ||
255 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
256 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
257 | }; | ||
258 | |||
259 | struct clkdm_ops omap3_clkdm_operations = { | ||
260 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, | ||
261 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, | ||
262 | .clkdm_read_wkdep = omap2_clkdm_read_wkdep, | ||
263 | .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, | ||
264 | .clkdm_add_sleepdep = omap3_clkdm_add_sleepdep, | ||
265 | .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep, | ||
266 | .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep, | ||
267 | .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps, | ||
268 | .clkdm_sleep = omap3_clkdm_sleep, | ||
269 | .clkdm_wakeup = omap3_clkdm_wakeup, | ||
270 | .clkdm_allow_idle = omap3_clkdm_allow_idle, | ||
271 | .clkdm_deny_idle = omap3_clkdm_deny_idle, | ||
272 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
273 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
274 | }; | ||