~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-omap2/cm3xxx.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * OMAP3xxx CM module functions
  4  *
  5  * Copyright (C) 2009 Nokia Corporation
  6  * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
  7  * Paul Walmsley
  8  * Rajendra Nayak <rnayak@ti.com>
  9  */
 10 
 11 #include <linux/kernel.h>
 12 #include <linux/types.h>
 13 #include <linux/delay.h>
 14 #include <linux/errno.h>
 15 #include <linux/err.h>
 16 #include <linux/io.h>
 17 
 18 #include "prm2xxx_3xxx.h"
 19 #include "cm.h"
 20 #include "cm3xxx.h"
 21 #include "cm-regbits-34xx.h"
 22 #include "clockdomain.h"
 23 
 24 static const u8 omap3xxx_cm_idlest_offs[] = {
 25         CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
 26 };
 27 
 28 /*
 29  *
 30  */
 31 
 32 static void _write_clktrctrl(u8 c, s16 module, u32 mask)
 33 {
 34         u32 v;
 35 
 36         v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
 37         v &= ~mask;
 38         v |= c << __ffs(mask);
 39         omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
 40 }
 41 
 42 static bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
 43 {
 44         u32 v;
 45 
 46         v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
 47         v &= mask;
 48         v >>= __ffs(mask);
 49 
 50         return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
 51 }
 52 
 53 static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
 54 {
 55         _write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
 56 }
 57 
 58 static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
 59 {
 60         _write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
 61 }
 62 
 63 static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
 64 {
 65         _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
 66 }
 67 
 68 static void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
 69 {
 70         _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
 71 }
 72 
 73 /*
 74  *
 75  */
 76 
 77 /**
 78  * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
 79  * @part: PRCM partition, ignored for OMAP3
 80  * @prcm_mod: PRCM module offset
 81  * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
 82  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
 83  *
 84  * Wait for the PRCM to indicate that the module identified by
 85  * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
 86  * success or -EBUSY if the module doesn't enable in time.
 87  */
 88 static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
 89                                          u8 idlest_shift)
 90 {
 91         int ena = 0, i = 0;
 92         u8 cm_idlest_reg;
 93         u32 mask;
 94 
 95         if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
 96                 return -EINVAL;
 97 
 98         cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
 99 
100         mask = 1 << idlest_shift;
101         ena = 0;
102 
103         omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
104                             mask) == ena), MAX_MODULE_READY_TIME, i);
105 
106         return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
107 }
108 
109 /**
110  * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
111  * @idlest_reg: CM_IDLEST* virtual address
112  * @prcm_inst: pointer to an s16 to return the PRCM instance offset
113  * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
114  *
115  * XXX This function is only needed until absolute register addresses are
116  * removed from the OMAP struct clk records.
117  */
118 static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
119                                         s16 *prcm_inst,
120                                         u8 *idlest_reg_id)
121 {
122         unsigned long offs;
123         u8 idlest_offs;
124         int i;
125 
126         idlest_offs = idlest_reg->offset & 0xff;
127         for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
128                 if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
129                         *idlest_reg_id = i + 1;
130                         break;
131                 }
132         }
133 
134         if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
135                 return -EINVAL;
136 
137         offs = idlest_reg->offset;
138         offs &= 0xff00;
139         *prcm_inst = offs;
140 
141         return 0;
142 }
143 
144 /* Clockdomain low-level operations */
145 
146 static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
147                                        struct clockdomain *clkdm2)
148 {
149         omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
150                                   clkdm1->pwrdm.ptr->prcm_offs,
151                                   OMAP3430_CM_SLEEPDEP);
152         return 0;
153 }
154 
155 static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1,
156                                        struct clockdomain *clkdm2)
157 {
158         omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
159                                     clkdm1->pwrdm.ptr->prcm_offs,
160                                     OMAP3430_CM_SLEEPDEP);
161         return 0;
162 }
163 
164 static int omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
165                                         struct clockdomain *clkdm2)
166 {
167         return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
168                                             OMAP3430_CM_SLEEPDEP,
169                                             (1 << clkdm2->dep_bit));
170 }
171 
172 static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
173 {
174         struct clkdm_dep *cd;
175         u32 mask = 0;
176 
177         for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
178                 if (!cd->clkdm)
179                         continue; /* only happens if data is erroneous */
180 
181                 mask |= 1 << cd->clkdm->dep_bit;
182                 cd->sleepdep_usecount = 0;
183         }
184         omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
185                                     OMAP3430_CM_SLEEPDEP);
186         return 0;
187 }
188 
189 static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
190 {
191         omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
192                                       clkdm->clktrctrl_mask);
193         return 0;
194 }
195 
196 static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
197 {
198         omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
199                                        clkdm->clktrctrl_mask);
200         return 0;
201 }
202 
203 static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
204 {
205         if (clkdm->usecount > 0)
206                 clkdm_add_autodeps(clkdm);
207 
208         omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
209                                        clkdm->clktrctrl_mask);
210 }
211 
212 static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
213 {
214         omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
215                                         clkdm->clktrctrl_mask);
216 
217         if (clkdm->usecount > 0)
218                 clkdm_del_autodeps(clkdm);
219 }
220 
221 static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
222 {
223         bool hwsup = false;
224 
225         if (!clkdm->clktrctrl_mask)
226                 return 0;
227 
228         /*
229          * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
230          * more details on the unpleasant problem this is working
231          * around
232          */
233         if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
234             (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
235                 omap3xxx_clkdm_wakeup(clkdm);
236                 return 0;
237         }
238 
239         hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
240                                               clkdm->clktrctrl_mask);
241 
242         if (hwsup) {
243                 /* Disable HW transitions when we are changing deps */
244                 omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
245                                                 clkdm->clktrctrl_mask);
246                 clkdm_add_autodeps(clkdm);
247                 omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
248                                                clkdm->clktrctrl_mask);
249         } else {
250                 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
251                         omap3xxx_clkdm_wakeup(clkdm);
252         }
253 
254         return 0;
255 }
256 
257 static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
258 {
259         bool hwsup = false;
260 
261         if (!clkdm->clktrctrl_mask)
262                 return 0;
263 
264         /*
265          * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
266          * more details on the unpleasant problem this is working
267          * around
268          */
269         if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
270             !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
271                 omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
272                                                clkdm->clktrctrl_mask);
273                 return 0;
274         }
275 
276         hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
277                                               clkdm->clktrctrl_mask);
278 
279         if (hwsup) {
280                 /* Disable HW transitions when we are changing deps */
281                 omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
282                                                 clkdm->clktrctrl_mask);
283                 clkdm_del_autodeps(clkdm);
284                 omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
285                                                clkdm->clktrctrl_mask);
286         } else {
287                 if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
288                         omap3xxx_clkdm_sleep(clkdm);
289         }
290 
291         return 0;
292 }
293 
294 struct clkdm_ops omap3_clkdm_operations = {
295         .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
296         .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
297         .clkdm_read_wkdep       = omap2_clkdm_read_wkdep,
298         .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
299         .clkdm_add_sleepdep     = omap3xxx_clkdm_add_sleepdep,
300         .clkdm_del_sleepdep     = omap3xxx_clkdm_del_sleepdep,
301         .clkdm_read_sleepdep    = omap3xxx_clkdm_read_sleepdep,
302         .clkdm_clear_all_sleepdeps      = omap3xxx_clkdm_clear_all_sleepdeps,
303         .clkdm_sleep            = omap3xxx_clkdm_sleep,
304         .clkdm_wakeup           = omap3xxx_clkdm_wakeup,
305         .clkdm_allow_idle       = omap3xxx_clkdm_allow_idle,
306         .clkdm_deny_idle        = omap3xxx_clkdm_deny_idle,
307         .clkdm_clk_enable       = omap3xxx_clkdm_clk_enable,
308         .clkdm_clk_disable      = omap3xxx_clkdm_clk_disable,
309 };
310 
311 /*
312  * Context save/restore code - OMAP3 only
313  */
314 struct omap3_cm_regs {
315         u32 iva2_cm_clksel1;
316         u32 iva2_cm_clksel2;
317         u32 cm_sysconfig;
318         u32 sgx_cm_clksel;
319         u32 dss_cm_clksel;
320         u32 cam_cm_clksel;
321         u32 per_cm_clksel;
322         u32 emu_cm_clksel;
323         u32 emu_cm_clkstctrl;
324         u32 pll_cm_autoidle;
325         u32 pll_cm_autoidle2;
326         u32 pll_cm_clksel4;
327         u32 pll_cm_clksel5;
328         u32 pll_cm_clken2;
329         u32 cm_polctrl;
330         u32 iva2_cm_fclken;
331         u32 iva2_cm_clken_pll;
332         u32 core_cm_fclken1;
333         u32 core_cm_fclken3;
334         u32 sgx_cm_fclken;
335         u32 wkup_cm_fclken;
336         u32 dss_cm_fclken;
337         u32 cam_cm_fclken;
338         u32 per_cm_fclken;
339         u32 usbhost_cm_fclken;
340         u32 core_cm_iclken1;
341         u32 core_cm_iclken2;
342         u32 core_cm_iclken3;
343         u32 sgx_cm_iclken;
344         u32 wkup_cm_iclken;
345         u32 dss_cm_iclken;
346         u32 cam_cm_iclken;
347         u32 per_cm_iclken;
348         u32 usbhost_cm_iclken;
349         u32 iva2_cm_autoidle2;
350         u32 mpu_cm_autoidle2;
351         u32 iva2_cm_clkstctrl;
352         u32 mpu_cm_clkstctrl;
353         u32 core_cm_clkstctrl;
354         u32 sgx_cm_clkstctrl;
355         u32 dss_cm_clkstctrl;
356         u32 cam_cm_clkstctrl;
357         u32 per_cm_clkstctrl;
358         u32 neon_cm_clkstctrl;
359         u32 usbhost_cm_clkstctrl;
360         u32 core_cm_autoidle1;
361         u32 core_cm_autoidle2;
362         u32 core_cm_autoidle3;
363         u32 wkup_cm_autoidle;
364         u32 dss_cm_autoidle;
365         u32 cam_cm_autoidle;
366         u32 per_cm_autoidle;
367         u32 usbhost_cm_autoidle;
368         u32 sgx_cm_sleepdep;
369         u32 dss_cm_sleepdep;
370         u32 cam_cm_sleepdep;
371         u32 per_cm_sleepdep;
372         u32 usbhost_cm_sleepdep;
373         u32 cm_clkout_ctrl;
374 };
375 
376 static struct omap3_cm_regs cm_context;
377 
378 void omap3_cm_save_context(void)
379 {
380         cm_context.iva2_cm_clksel1 =
381                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
382         cm_context.iva2_cm_clksel2 =
383                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
384         cm_context.cm_sysconfig =
385                 omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_SYSCONFIG);
386         cm_context.sgx_cm_clksel =
387                 omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
388         cm_context.dss_cm_clksel =
389                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
390         cm_context.cam_cm_clksel =
391                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
392         cm_context.per_cm_clksel =
393                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
394         cm_context.emu_cm_clksel =
395                 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
396         cm_context.emu_cm_clkstctrl =
397                 omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
398         /*
399          * As per erratum i671, ROM code does not respect the PER DPLL
400          * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
401          * In this case, even though this register has been saved in
402          * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
403          * by ourselves. So, we need to save it anyway.
404          */
405         cm_context.pll_cm_autoidle =
406                 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
407         cm_context.pll_cm_autoidle2 =
408                 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
409         cm_context.pll_cm_clksel4 =
410                 omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
411         cm_context.pll_cm_clksel5 =
412                 omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
413         cm_context.pll_cm_clken2 =
414                 omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
415         cm_context.cm_polctrl =
416                 omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_POLCTRL);
417         cm_context.iva2_cm_fclken =
418                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
419         cm_context.iva2_cm_clken_pll =
420                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
421         cm_context.core_cm_fclken1 =
422                 omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
423         cm_context.core_cm_fclken3 =
424                 omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
425         cm_context.sgx_cm_fclken =
426                 omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
427         cm_context.wkup_cm_fclken =
428                 omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
429         cm_context.dss_cm_fclken =
430                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
431         cm_context.cam_cm_fclken =
432                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
433         cm_context.per_cm_fclken =
434                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
435         cm_context.usbhost_cm_fclken =
436                 omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
437         cm_context.core_cm_iclken1 =
438                 omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
439         cm_context.core_cm_iclken2 =
440                 omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
441         cm_context.core_cm_iclken3 =
442                 omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
443         cm_context.sgx_cm_iclken =
444                 omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
445         cm_context.wkup_cm_iclken =
446                 omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
447         cm_context.dss_cm_iclken =
448                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
449         cm_context.cam_cm_iclken =
450                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
451         cm_context.per_cm_iclken =
452                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
453         cm_context.usbhost_cm_iclken =
454                 omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
455         cm_context.iva2_cm_autoidle2 =
456                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
457         cm_context.mpu_cm_autoidle2 =
458                 omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
459         cm_context.iva2_cm_clkstctrl =
460                 omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
461         cm_context.mpu_cm_clkstctrl =
462                 omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
463         cm_context.core_cm_clkstctrl =
464                 omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
465         cm_context.sgx_cm_clkstctrl =
466                 omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
467         cm_context.dss_cm_clkstctrl =
468                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
469         cm_context.cam_cm_clkstctrl =
470                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
471         cm_context.per_cm_clkstctrl =
472                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
473         cm_context.neon_cm_clkstctrl =
474                 omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
475         cm_context.usbhost_cm_clkstctrl =
476                 omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
477                                       OMAP2_CM_CLKSTCTRL);
478         cm_context.core_cm_autoidle1 =
479                 omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
480         cm_context.core_cm_autoidle2 =
481                 omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
482         cm_context.core_cm_autoidle3 =
483                 omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
484         cm_context.wkup_cm_autoidle =
485                 omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
486         cm_context.dss_cm_autoidle =
487                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
488         cm_context.cam_cm_autoidle =
489                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
490         cm_context.per_cm_autoidle =
491                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
492         cm_context.usbhost_cm_autoidle =
493                 omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
494         cm_context.sgx_cm_sleepdep =
495                 omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
496                                       OMAP3430_CM_SLEEPDEP);
497         cm_context.dss_cm_sleepdep =
498                 omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
499         cm_context.cam_cm_sleepdep =
500                 omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
501         cm_context.per_cm_sleepdep =
502                 omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
503         cm_context.usbhost_cm_sleepdep =
504                 omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
505                                       OMAP3430_CM_SLEEPDEP);
506         cm_context.cm_clkout_ctrl =
507                 omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
508                                       OMAP3_CM_CLKOUT_CTRL_OFFSET);
509 }
510 
511 void omap3_cm_restore_context(void)
512 {
513         omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
514                                CM_CLKSEL1);
515         omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
516                                CM_CLKSEL2);
517         omap2_cm_write_mod_reg(cm_context.cm_sysconfig, OCP_MOD,
518                                OMAP3430_CM_SYSCONFIG);
519         omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
520                                CM_CLKSEL);
521         omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
522                                CM_CLKSEL);
523         omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
524                                CM_CLKSEL);
525         omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
526                                CM_CLKSEL);
527         omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
528                                CM_CLKSEL1);
529         omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
530                                OMAP2_CM_CLKSTCTRL);
531         /*
532          * As per erratum i671, ROM code does not respect the PER DPLL
533          * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
534          * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
535          */
536         omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
537                                CM_AUTOIDLE);
538         omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
539                                CM_AUTOIDLE2);
540         omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
541                                OMAP3430ES2_CM_CLKSEL4);
542         omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
543                                OMAP3430ES2_CM_CLKSEL5);
544         omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
545                                OMAP3430ES2_CM_CLKEN2);
546         omap2_cm_write_mod_reg(cm_context.cm_polctrl, OCP_MOD,
547                                OMAP3430_CM_POLCTRL);
548         omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
549                                CM_FCLKEN);
550         omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
551                                OMAP3430_CM_CLKEN_PLL);
552         omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
553                                CM_FCLKEN1);
554         omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
555                                OMAP3430ES2_CM_FCLKEN3);
556         omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
557                                CM_FCLKEN);
558         omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
559         omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
560                                CM_FCLKEN);
561         omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
562                                CM_FCLKEN);
563         omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
564                                CM_FCLKEN);
565         omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
566                                OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
567         omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
568                                CM_ICLKEN1);
569         omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
570                                CM_ICLKEN2);
571         omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
572                                CM_ICLKEN3);
573         omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
574                                CM_ICLKEN);
575         omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
576         omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
577                                CM_ICLKEN);
578         omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
579                                CM_ICLKEN);
580         omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
581                                CM_ICLKEN);
582         omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
583                                OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
584         omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
585                                CM_AUTOIDLE2);
586         omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
587                                CM_AUTOIDLE2);
588         omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
589                                OMAP2_CM_CLKSTCTRL);
590         omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
591                                OMAP2_CM_CLKSTCTRL);
592         omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
593                                OMAP2_CM_CLKSTCTRL);
594         omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
595                                OMAP2_CM_CLKSTCTRL);
596         omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
597                                OMAP2_CM_CLKSTCTRL);
598         omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
599                                OMAP2_CM_CLKSTCTRL);
600         omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
601                                OMAP2_CM_CLKSTCTRL);
602         omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
603                                OMAP2_CM_CLKSTCTRL);
604         omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
605                                OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
606         omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
607                                CM_AUTOIDLE1);
608         omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
609                                CM_AUTOIDLE2);
610         omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
611                                CM_AUTOIDLE3);
612         omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
613                                CM_AUTOIDLE);
614         omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
615                                CM_AUTOIDLE);
616         omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
617                                CM_AUTOIDLE);
618         omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
619                                CM_AUTOIDLE);
620         omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
621                                OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
622         omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
623                                OMAP3430_CM_SLEEPDEP);
624         omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
625                                OMAP3430_CM_SLEEPDEP);
626         omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
627                                OMAP3430_CM_SLEEPDEP);
628         omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
629                                OMAP3430_CM_SLEEPDEP);
630         omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
631                                OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
632         omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
633                                OMAP3_CM_CLKOUT_CTRL_OFFSET);
634 }
635 
636 void omap3_cm_save_scratchpad_contents(u32 *ptr)
637 {
638         *ptr++ = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
639         *ptr++ = omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
640         *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
641 
642         /*
643          * As per erratum i671, ROM code does not respect the PER DPLL
644          * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
645          * Then,  in any case, clear these bits to avoid extra latencies.
646          */
647         *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
648                 ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
649         *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
650         *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
651         *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
652         *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
653         *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
654         *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
655         *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
656 }
657 
658 /*
659  *
660  */
661 
662 static const struct cm_ll_data omap3xxx_cm_ll_data = {
663         .split_idlest_reg       = &omap3xxx_cm_split_idlest_reg,
664         .wait_module_ready      = &omap3xxx_cm_wait_module_ready,
665 };
666 
667 int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
668 {
669         omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base.va +
670                                        OMAP3430_IVA2_MOD);
671         return cm_register(&omap3xxx_cm_ll_data);
672 }
673 
674 static void __exit omap3xxx_cm_exit(void)
675 {
676         cm_unregister(&omap3xxx_cm_ll_data);
677 }
678 __exitcall(omap3xxx_cm_exit);
679 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php