1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * OMAP3xxx PRM module functions |
4 | * |
5 | * Copyright (C) 2010-2012 Texas Instruments, Inc. |
6 | * Copyright (C) 2010 Nokia Corporation |
7 | * BenoƮt Cousson |
8 | * Paul Walmsley |
9 | * Rajendra Nayak <rnayak@ti.com> |
10 | */ |
11 | |
12 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> |
14 | #include <linux/err.h> |
15 | #include <linux/io.h> |
16 | #include <linux/irq.h> |
17 | #include <linux/of_irq.h> |
18 | |
19 | #include "soc.h" |
20 | #include "common.h" |
21 | #include "vp.h" |
22 | #include "powerdomain.h" |
23 | #include "prm3xxx.h" |
24 | #include "prm2xxx_3xxx.h" |
25 | #include "cm2xxx_3xxx.h" |
26 | #include "prm-regbits-34xx.h" |
27 | #include "cm3xxx.h" |
28 | #include "cm-regbits-34xx.h" |
29 | #include "clock.h" |
30 | |
31 | static void omap3xxx_prm_read_pending_irqs(unsigned long *events); |
32 | static void omap3xxx_prm_ocp_barrier(void); |
33 | static void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask); |
34 | static void omap3xxx_prm_restore_irqen(u32 *saved_mask); |
35 | static void omap3xxx_prm_iva_idle(void); |
36 | |
37 | static const struct omap_prcm_irq omap3_prcm_irqs[] = { |
38 | OMAP_PRCM_IRQ("wkup" , 0, 0), |
39 | OMAP_PRCM_IRQ("io" , 9, 1), |
40 | }; |
41 | |
42 | static struct omap_prcm_irq_setup omap3_prcm_irq_setup = { |
43 | .ack = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, |
44 | .mask = OMAP3_PRM_IRQENABLE_MPU_OFFSET, |
45 | .nr_regs = 1, |
46 | .irqs = omap3_prcm_irqs, |
47 | .nr_irqs = ARRAY_SIZE(omap3_prcm_irqs), |
48 | .irq = 11 + OMAP_INTC_START, |
49 | .read_pending_irqs = &omap3xxx_prm_read_pending_irqs, |
50 | .ocp_barrier = &omap3xxx_prm_ocp_barrier, |
51 | .save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen, |
52 | .restore_irqen = &omap3xxx_prm_restore_irqen, |
53 | .reconfigure_io_chain = NULL, |
54 | }; |
55 | |
56 | /* |
57 | * omap3_prm_reset_src_map - map from bits in the PRM_RSTST hardware |
58 | * register (which are specific to OMAP3xxx SoCs) to reset source ID |
59 | * bit shifts (which is an OMAP SoC-independent enumeration) |
60 | */ |
61 | static struct prm_reset_src_map omap3xxx_prm_reset_src_map[] = { |
62 | { OMAP3430_GLOBAL_COLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT }, |
63 | { OMAP3430_GLOBAL_SW_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT }, |
64 | { OMAP3430_SECURITY_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT }, |
65 | { OMAP3430_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT }, |
66 | { OMAP3430_SECURE_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT }, |
67 | { OMAP3430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT }, |
68 | { OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT, |
69 | OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT }, |
70 | { OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT, |
71 | OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT }, |
72 | { OMAP3430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT }, |
73 | { OMAP3430_ICECRUSHER_RST_SHIFT, OMAP_ICECRUSHER_RST_SRC_ID_SHIFT }, |
74 | { -1, -1 }, |
75 | }; |
76 | |
77 | /* PRM VP */ |
78 | |
79 | /* |
80 | * struct omap3_vp - OMAP3 VP register access description. |
81 | * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg |
82 | */ |
83 | struct omap3_vp { |
84 | u32 tranxdone_status; |
85 | }; |
86 | |
87 | static struct omap3_vp omap3_vp[] = { |
88 | [OMAP3_VP_VDD_MPU_ID] = { |
89 | .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK, |
90 | }, |
91 | [OMAP3_VP_VDD_CORE_ID] = { |
92 | .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK, |
93 | }, |
94 | }; |
95 | |
96 | #define MAX_VP_ID ARRAY_SIZE(omap3_vp); |
97 | |
98 | static u32 omap3_prm_vp_check_txdone(u8 vp_id) |
99 | { |
100 | struct omap3_vp *vp = &omap3_vp[vp_id]; |
101 | u32 irqstatus; |
102 | |
103 | irqstatus = omap2_prm_read_mod_reg(OCP_MOD, |
104 | OMAP3_PRM_IRQSTATUS_MPU_OFFSET); |
105 | return irqstatus & vp->tranxdone_status; |
106 | } |
107 | |
108 | static void omap3_prm_vp_clear_txdone(u8 vp_id) |
109 | { |
110 | struct omap3_vp *vp = &omap3_vp[vp_id]; |
111 | |
112 | omap2_prm_write_mod_reg(val: vp->tranxdone_status, |
113 | OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); |
114 | } |
115 | |
116 | u32 omap3_prm_vcvp_read(u8 offset) |
117 | { |
118 | return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, idx: offset); |
119 | } |
120 | |
121 | void omap3_prm_vcvp_write(u32 val, u8 offset) |
122 | { |
123 | omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, idx: offset); |
124 | } |
125 | |
126 | u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) |
127 | { |
128 | return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, idx: offset); |
129 | } |
130 | |
131 | /** |
132 | * omap3xxx_prm_dpll3_reset - use DPLL3 reset to reboot the OMAP SoC |
133 | * |
134 | * Set the DPLL3 reset bit, which should reboot the SoC. This is the |
135 | * recommended way to restart the SoC, considering Errata i520. No |
136 | * return value. |
137 | */ |
138 | static void omap3xxx_prm_dpll3_reset(void) |
139 | { |
140 | omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, OMAP3430_GR_MOD, |
141 | OMAP2_RM_RSTCTRL); |
142 | /* OCP barrier */ |
143 | omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP2_RM_RSTCTRL); |
144 | } |
145 | |
146 | /** |
147 | * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events |
148 | * @events: ptr to a u32, preallocated by caller |
149 | * |
150 | * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM |
151 | * MPU IRQs, and store the result into the u32 pointed to by @events. |
152 | * No return value. |
153 | */ |
154 | static void omap3xxx_prm_read_pending_irqs(unsigned long *events) |
155 | { |
156 | u32 mask, st; |
157 | |
158 | /* XXX Can the mask read be avoided (e.g., can it come from RAM?) */ |
159 | mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); |
160 | st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); |
161 | |
162 | events[0] = mask & st; |
163 | } |
164 | |
165 | /** |
166 | * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete |
167 | * |
168 | * Force any buffered writes to the PRM IP block to complete. Needed |
169 | * by the PRM IRQ handler, which reads and writes directly to the IP |
170 | * block, to avoid race conditions after acknowledging or clearing IRQ |
171 | * bits. No return value. |
172 | */ |
173 | static void omap3xxx_prm_ocp_barrier(void) |
174 | { |
175 | omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); |
176 | } |
177 | |
178 | /** |
179 | * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg |
180 | * @saved_mask: ptr to a u32 array to save IRQENABLE bits |
181 | * |
182 | * Save the PRM_IRQENABLE_MPU register to @saved_mask. @saved_mask |
183 | * must be allocated by the caller. Intended to be used in the PRM |
184 | * interrupt handler suspend callback. The OCP barrier is needed to |
185 | * ensure the write to disable PRM interrupts reaches the PRM before |
186 | * returning; otherwise, spurious interrupts might occur. No return |
187 | * value. |
188 | */ |
189 | static void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask) |
190 | { |
191 | saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD, |
192 | OMAP3_PRM_IRQENABLE_MPU_OFFSET); |
193 | omap2_prm_write_mod_reg(val: 0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); |
194 | |
195 | /* OCP barrier */ |
196 | omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); |
197 | } |
198 | |
199 | /** |
200 | * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args |
201 | * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously |
202 | * |
203 | * Restore the PRM_IRQENABLE_MPU register from @saved_mask. Intended |
204 | * to be used in the PRM interrupt handler resume callback to restore |
205 | * values saved by omap3xxx_prm_save_and_clear_irqen(). No OCP |
206 | * barrier should be needed here; any pending PRM interrupts will fire |
207 | * once the writes reach the PRM. No return value. |
208 | */ |
209 | static void omap3xxx_prm_restore_irqen(u32 *saved_mask) |
210 | { |
211 | omap2_prm_write_mod_reg(val: saved_mask[0], OCP_MOD, |
212 | OMAP3_PRM_IRQENABLE_MPU_OFFSET); |
213 | } |
214 | |
215 | /** |
216 | * omap3xxx_prm_clear_mod_irqs - clear wake-up events from PRCM interrupt |
217 | * @module: PRM module to clear wakeups from |
218 | * @regs: register set to clear, 1 or 3 |
219 | * @wkst_mask: wkst bits to clear |
220 | * |
221 | * The purpose of this function is to clear any wake-up events latched |
222 | * in the PRCM PM_WKST_x registers. It is possible that a wake-up event |
223 | * may occur whilst attempting to clear a PM_WKST_x register and thus |
224 | * set another bit in this register. A while loop is used to ensure |
225 | * that any peripheral wake-up events occurring while attempting to |
226 | * clear the PM_WKST_x are detected and cleared. |
227 | */ |
228 | static int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask) |
229 | { |
230 | u32 wkst, fclk, iclk, clken; |
231 | u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; |
232 | u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1; |
233 | u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; |
234 | u16 grpsel_off = (regs == 3) ? |
235 | OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; |
236 | int c = 0; |
237 | |
238 | wkst = omap2_prm_read_mod_reg(module, idx: wkst_off); |
239 | wkst &= omap2_prm_read_mod_reg(module, idx: grpsel_off); |
240 | wkst &= wkst_mask; |
241 | if (wkst) { |
242 | iclk = omap2_cm_read_mod_reg(module, idx: iclk_off); |
243 | fclk = omap2_cm_read_mod_reg(module, idx: fclk_off); |
244 | while (wkst) { |
245 | clken = wkst; |
246 | omap2_cm_set_mod_reg_bits(bits: clken, module, idx: iclk_off); |
247 | /* |
248 | * For USBHOST, we don't know whether HOST1 or |
249 | * HOST2 woke us up, so enable both f-clocks |
250 | */ |
251 | if (module == OMAP3430ES2_USBHOST_MOD) |
252 | clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT; |
253 | omap2_cm_set_mod_reg_bits(bits: clken, module, idx: fclk_off); |
254 | omap2_prm_write_mod_reg(val: wkst, module, idx: wkst_off); |
255 | wkst = omap2_prm_read_mod_reg(module, idx: wkst_off); |
256 | wkst &= wkst_mask; |
257 | c++; |
258 | } |
259 | omap2_cm_write_mod_reg(val: iclk, module, idx: iclk_off); |
260 | omap2_cm_write_mod_reg(val: fclk, module, idx: fclk_off); |
261 | } |
262 | |
263 | return c; |
264 | } |
265 | |
266 | /** |
267 | * omap3_prm_reset_modem - toggle reset signal for modem |
268 | * |
269 | * Toggles the reset signal to modem IP block. Required to allow |
270 | * OMAP3430 without stacked modem to idle properly. |
271 | */ |
272 | static void __init omap3_prm_reset_modem(void) |
273 | { |
274 | omap2_prm_write_mod_reg( |
275 | OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK | |
276 | OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK, |
277 | CORE_MOD, OMAP2_RM_RSTCTRL); |
278 | omap2_prm_write_mod_reg(val: 0, CORE_MOD, OMAP2_RM_RSTCTRL); |
279 | } |
280 | |
281 | /** |
282 | * omap3_prm_init_pm - initialize PM related registers for PRM |
283 | * @has_uart4: SoC has UART4 |
284 | * @has_iva: SoC has IVA |
285 | * |
286 | * Initializes PRM registers for PM use. Called from PM init. |
287 | */ |
288 | void __init omap3_prm_init_pm(bool has_uart4, bool has_iva) |
289 | { |
290 | u32 en_uart4_mask; |
291 | u32 grpsel_uart4_mask; |
292 | |
293 | /* |
294 | * Enable control of expternal oscillator through |
295 | * sys_clkreq. In the long run clock framework should |
296 | * take care of this. |
297 | */ |
298 | omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, |
299 | bits: 1 << OMAP_AUTOEXTCLKMODE_SHIFT, |
300 | OMAP3430_GR_MOD, |
301 | OMAP3_PRM_CLKSRC_CTRL_OFFSET); |
302 | |
303 | /* setup wakup source */ |
304 | omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK | |
305 | OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK, |
306 | WKUP_MOD, PM_WKEN); |
307 | /* No need to write EN_IO, that is always enabled */ |
308 | omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK | |
309 | OMAP3430_GRPSEL_GPT1_MASK | |
310 | OMAP3430_GRPSEL_GPT12_MASK, |
311 | WKUP_MOD, OMAP3430_PM_MPUGRPSEL); |
312 | |
313 | /* Enable PM_WKEN to support DSS LPR */ |
314 | omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK, |
315 | OMAP3430_DSS_MOD, PM_WKEN); |
316 | |
317 | if (has_uart4) { |
318 | en_uart4_mask = OMAP3630_EN_UART4_MASK; |
319 | grpsel_uart4_mask = OMAP3630_GRPSEL_UART4_MASK; |
320 | } else { |
321 | en_uart4_mask = 0; |
322 | grpsel_uart4_mask = 0; |
323 | } |
324 | |
325 | /* Enable wakeups in PER */ |
326 | omap2_prm_write_mod_reg(val: en_uart4_mask | |
327 | OMAP3430_EN_GPIO2_MASK | |
328 | OMAP3430_EN_GPIO3_MASK | |
329 | OMAP3430_EN_GPIO4_MASK | |
330 | OMAP3430_EN_GPIO5_MASK | |
331 | OMAP3430_EN_GPIO6_MASK | |
332 | OMAP3430_EN_UART3_MASK | |
333 | OMAP3430_EN_MCBSP2_MASK | |
334 | OMAP3430_EN_MCBSP3_MASK | |
335 | OMAP3430_EN_MCBSP4_MASK, |
336 | OMAP3430_PER_MOD, PM_WKEN); |
337 | |
338 | /* and allow them to wake up MPU */ |
339 | omap2_prm_write_mod_reg(val: grpsel_uart4_mask | |
340 | OMAP3430_GRPSEL_GPIO2_MASK | |
341 | OMAP3430_GRPSEL_GPIO3_MASK | |
342 | OMAP3430_GRPSEL_GPIO4_MASK | |
343 | OMAP3430_GRPSEL_GPIO5_MASK | |
344 | OMAP3430_GRPSEL_GPIO6_MASK | |
345 | OMAP3430_GRPSEL_UART3_MASK | |
346 | OMAP3430_GRPSEL_MCBSP2_MASK | |
347 | OMAP3430_GRPSEL_MCBSP3_MASK | |
348 | OMAP3430_GRPSEL_MCBSP4_MASK, |
349 | OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); |
350 | |
351 | /* Don't attach IVA interrupts */ |
352 | if (has_iva) { |
353 | omap2_prm_write_mod_reg(val: 0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); |
354 | omap2_prm_write_mod_reg(val: 0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); |
355 | omap2_prm_write_mod_reg(val: 0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3); |
356 | omap2_prm_write_mod_reg(val: 0, OMAP3430_PER_MOD, |
357 | OMAP3430_PM_IVAGRPSEL); |
358 | } |
359 | |
360 | /* Clear any pending 'reset' flags */ |
361 | omap2_prm_write_mod_reg(val: 0xffffffff, MPU_MOD, OMAP2_RM_RSTST); |
362 | omap2_prm_write_mod_reg(val: 0xffffffff, CORE_MOD, OMAP2_RM_RSTST); |
363 | omap2_prm_write_mod_reg(val: 0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST); |
364 | omap2_prm_write_mod_reg(val: 0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST); |
365 | omap2_prm_write_mod_reg(val: 0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST); |
366 | omap2_prm_write_mod_reg(val: 0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST); |
367 | omap2_prm_write_mod_reg(val: 0xffffffff, OMAP3430ES2_USBHOST_MOD, |
368 | OMAP2_RM_RSTST); |
369 | |
370 | /* Clear any pending PRCM interrupts */ |
371 | omap2_prm_write_mod_reg(val: 0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); |
372 | |
373 | /* We need to idle iva2_pwrdm even on am3703 with no iva2. */ |
374 | omap3xxx_prm_iva_idle(); |
375 | |
376 | omap3_prm_reset_modem(); |
377 | } |
378 | |
379 | /** |
380 | * omap3430_pre_es3_1_reconfigure_io_chain - restart wake-up daisy chain |
381 | * |
382 | * The ST_IO_CHAIN bit does not exist in 3430 before es3.1. The only |
383 | * thing we can do is toggle EN_IO bit for earlier omaps. |
384 | */ |
385 | static void omap3430_pre_es3_1_reconfigure_io_chain(void) |
386 | { |
387 | omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, |
388 | PM_WKEN); |
389 | omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, |
390 | PM_WKEN); |
391 | omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); |
392 | } |
393 | |
394 | /** |
395 | * omap3_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain |
396 | * |
397 | * Clear any previously-latched I/O wakeup events and ensure that the |
398 | * I/O wakeup gates are aligned with the current mux settings. Works |
399 | * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then |
400 | * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No |
401 | * return value. These registers are only available in 3430 es3.1 and later. |
402 | */ |
403 | static void omap3_prm_reconfigure_io_chain(void) |
404 | { |
405 | int i = 0; |
406 | |
407 | omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, |
408 | PM_WKEN); |
409 | |
410 | omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) & |
411 | OMAP3430_ST_IO_CHAIN_MASK, |
412 | MAX_IOPAD_LATCH_TIME, i); |
413 | if (i == MAX_IOPAD_LATCH_TIME) |
414 | pr_warn("PRM: I/O chain clock line assertion timed out\n" ); |
415 | |
416 | omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, |
417 | PM_WKEN); |
418 | |
419 | omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD, |
420 | PM_WKST); |
421 | |
422 | omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST); |
423 | } |
424 | |
425 | /** |
426 | * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches |
427 | * |
428 | * Activates the I/O wakeup event latches and allows events logged by |
429 | * those latches to signal a wakeup event to the PRCM. For I/O |
430 | * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux |
431 | * registers, and omap3xxx_prm_reconfigure_io_chain() must be called. |
432 | * No return value. |
433 | */ |
434 | static void omap3xxx_prm_enable_io_wakeup(void) |
435 | { |
436 | if (prm_features & PRM_HAS_IO_WAKEUP) |
437 | omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, |
438 | PM_WKEN); |
439 | } |
440 | |
441 | /** |
442 | * omap3xxx_prm_read_reset_sources - return the last SoC reset source |
443 | * |
444 | * Return a u32 representing the last reset sources of the SoC. The |
445 | * returned reset source bits are standardized across OMAP SoCs. |
446 | */ |
447 | static u32 omap3xxx_prm_read_reset_sources(void) |
448 | { |
449 | struct prm_reset_src_map *p; |
450 | u32 r = 0; |
451 | u32 v; |
452 | |
453 | v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST); |
454 | |
455 | p = omap3xxx_prm_reset_src_map; |
456 | while (p->reg_shift >= 0 && p->std_shift >= 0) { |
457 | if (v & (1 << p->reg_shift)) |
458 | r |= 1 << p->std_shift; |
459 | p++; |
460 | } |
461 | |
462 | return r; |
463 | } |
464 | |
465 | /** |
466 | * omap3xxx_prm_iva_idle - ensure IVA is in idle so it can be put into retention |
467 | * |
468 | * In cases where IVA2 is activated by bootcode, it may prevent |
469 | * full-chip retention or off-mode because it is not idle. This |
470 | * function forces the IVA2 into idle state so it can go |
471 | * into retention/off and thus allow full-chip retention/off. |
472 | */ |
473 | static void omap3xxx_prm_iva_idle(void) |
474 | { |
475 | /* ensure IVA2 clock is disabled */ |
476 | omap2_cm_write_mod_reg(val: 0, OMAP3430_IVA2_MOD, CM_FCLKEN); |
477 | |
478 | /* if no clock activity, nothing else to do */ |
479 | if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) & |
480 | OMAP3430_CLKACTIVITY_IVA2_MASK)) |
481 | return; |
482 | |
483 | /* Reset IVA2 */ |
484 | omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK | |
485 | OMAP3430_RST2_IVA2_MASK | |
486 | OMAP3430_RST3_IVA2_MASK, |
487 | OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); |
488 | |
489 | /* Enable IVA2 clock */ |
490 | omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK, |
491 | OMAP3430_IVA2_MOD, CM_FCLKEN); |
492 | |
493 | /* Un-reset IVA2 */ |
494 | omap2_prm_write_mod_reg(val: 0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); |
495 | |
496 | /* Disable IVA2 clock */ |
497 | omap2_cm_write_mod_reg(val: 0, OMAP3430_IVA2_MOD, CM_FCLKEN); |
498 | |
499 | /* Reset IVA2 */ |
500 | omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK | |
501 | OMAP3430_RST2_IVA2_MASK | |
502 | OMAP3430_RST3_IVA2_MASK, |
503 | OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); |
504 | } |
505 | |
506 | /** |
507 | * omap3xxx_prm_clear_global_cold_reset - checks the global cold reset status |
508 | * and clears it if asserted |
509 | * |
510 | * Checks if cold-reset has occurred and clears the status bit if yes. Returns |
511 | * 1 if cold-reset has occurred, 0 otherwise. |
512 | */ |
513 | int omap3xxx_prm_clear_global_cold_reset(void) |
514 | { |
515 | if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) & |
516 | OMAP3430_GLOBAL_COLD_RST_MASK) { |
517 | omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK, |
518 | OMAP3430_GR_MOD, |
519 | OMAP3_PRM_RSTST_OFFSET); |
520 | return 1; |
521 | } |
522 | |
523 | return 0; |
524 | } |
525 | |
526 | void omap3_prm_save_scratchpad_contents(u32 *ptr) |
527 | { |
528 | *ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD, |
529 | OMAP3_PRM_CLKSRC_CTRL_OFFSET); |
530 | |
531 | *ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD, |
532 | OMAP3_PRM_CLKSEL_OFFSET); |
533 | } |
534 | |
535 | /* Powerdomain low-level functions */ |
536 | |
537 | static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) |
538 | { |
539 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, |
540 | bits: (pwrst << OMAP_POWERSTATE_SHIFT), |
541 | module: pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); |
542 | return 0; |
543 | } |
544 | |
545 | static int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) |
546 | { |
547 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
548 | OMAP2_PM_PWSTCTRL, |
549 | OMAP_POWERSTATE_MASK); |
550 | } |
551 | |
552 | static int omap3_pwrdm_read_pwrst(struct powerdomain *pwrdm) |
553 | { |
554 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
555 | OMAP2_PM_PWSTST, |
556 | OMAP_POWERSTATEST_MASK); |
557 | } |
558 | |
559 | /* Applicable only for OMAP3. Not supported on OMAP2 */ |
560 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) |
561 | { |
562 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
563 | OMAP3430_PM_PREPWSTST, |
564 | OMAP3430_LASTPOWERSTATEENTERED_MASK); |
565 | } |
566 | |
567 | static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
568 | { |
569 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
570 | OMAP2_PM_PWSTST, |
571 | OMAP3430_LOGICSTATEST_MASK); |
572 | } |
573 | |
574 | static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm) |
575 | { |
576 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
577 | OMAP2_PM_PWSTCTRL, |
578 | OMAP3430_LOGICSTATEST_MASK); |
579 | } |
580 | |
581 | static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) |
582 | { |
583 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
584 | OMAP3430_PM_PREPWSTST, |
585 | OMAP3430_LASTLOGICSTATEENTERED_MASK); |
586 | } |
587 | |
588 | static int omap3_get_mem_bank_lastmemst_mask(u8 bank) |
589 | { |
590 | switch (bank) { |
591 | case 0: |
592 | return OMAP3430_LASTMEM1STATEENTERED_MASK; |
593 | case 1: |
594 | return OMAP3430_LASTMEM2STATEENTERED_MASK; |
595 | case 2: |
596 | return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; |
597 | case 3: |
598 | return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; |
599 | default: |
600 | WARN_ON(1); /* should never happen */ |
601 | return -EEXIST; |
602 | } |
603 | return 0; |
604 | } |
605 | |
606 | static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
607 | { |
608 | u32 m; |
609 | |
610 | m = omap3_get_mem_bank_lastmemst_mask(bank); |
611 | |
612 | return omap2_prm_read_mod_bits_shift(domain: pwrdm->prcm_offs, |
613 | OMAP3430_PM_PREPWSTST, mask: m); |
614 | } |
615 | |
616 | static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) |
617 | { |
618 | omap2_prm_write_mod_reg(val: 0, module: pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); |
619 | return 0; |
620 | } |
621 | |
622 | static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) |
623 | { |
624 | return omap2_prm_rmw_mod_reg_bits(mask: 0, |
625 | bits: 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, |
626 | module: pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); |
627 | } |
628 | |
629 | static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) |
630 | { |
631 | return omap2_prm_rmw_mod_reg_bits(mask: 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, |
632 | bits: 0, module: pwrdm->prcm_offs, |
633 | OMAP2_PM_PWSTCTRL); |
634 | } |
635 | |
636 | struct pwrdm_ops omap3_pwrdm_operations = { |
637 | .pwrdm_set_next_pwrst = omap3_pwrdm_set_next_pwrst, |
638 | .pwrdm_read_next_pwrst = omap3_pwrdm_read_next_pwrst, |
639 | .pwrdm_read_pwrst = omap3_pwrdm_read_pwrst, |
640 | .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst, |
641 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, |
642 | .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst, |
643 | .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst, |
644 | .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst, |
645 | .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst, |
646 | .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst, |
647 | .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst, |
648 | .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, |
649 | .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst, |
650 | .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst, |
651 | .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar, |
652 | .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar, |
653 | .pwrdm_wait_transition = omap2_pwrdm_wait_transition, |
654 | }; |
655 | |
656 | /* |
657 | * |
658 | */ |
659 | |
660 | static int omap3xxx_prm_late_init(void); |
661 | |
662 | static struct prm_ll_data omap3xxx_prm_ll_data = { |
663 | .read_reset_sources = &omap3xxx_prm_read_reset_sources, |
664 | .late_init = &omap3xxx_prm_late_init, |
665 | .assert_hardreset = &omap2_prm_assert_hardreset, |
666 | .deassert_hardreset = &omap2_prm_deassert_hardreset, |
667 | .is_hardreset_asserted = &omap2_prm_is_hardreset_asserted, |
668 | .reset_system = &omap3xxx_prm_dpll3_reset, |
669 | .clear_mod_irqs = &omap3xxx_prm_clear_mod_irqs, |
670 | .vp_check_txdone = &omap3_prm_vp_check_txdone, |
671 | .vp_clear_txdone = &omap3_prm_vp_clear_txdone, |
672 | }; |
673 | |
674 | int __init omap3xxx_prm_init(const struct omap_prcm_init_data *data) |
675 | { |
676 | omap2_clk_legacy_provider_init(index: TI_CLKM_PRM, |
677 | mem: prm_base.va + OMAP3430_IVA2_MOD); |
678 | if (omap3_has_io_wakeup()) |
679 | prm_features |= PRM_HAS_IO_WAKEUP; |
680 | |
681 | return prm_register(pld: &omap3xxx_prm_ll_data); |
682 | } |
683 | |
684 | static const struct of_device_id omap3_prm_dt_match_table[] = { |
685 | { .compatible = "ti,omap3-prm" }, |
686 | { } |
687 | }; |
688 | |
689 | static int omap3xxx_prm_late_init(void) |
690 | { |
691 | struct device_node *np; |
692 | int irq_num; |
693 | |
694 | if (!(prm_features & PRM_HAS_IO_WAKEUP)) |
695 | return 0; |
696 | |
697 | if (omap3_has_io_chain_ctrl()) |
698 | omap3_prcm_irq_setup.reconfigure_io_chain = |
699 | omap3_prm_reconfigure_io_chain; |
700 | else |
701 | omap3_prcm_irq_setup.reconfigure_io_chain = |
702 | omap3430_pre_es3_1_reconfigure_io_chain; |
703 | |
704 | np = of_find_matching_node(NULL, matches: omap3_prm_dt_match_table); |
705 | if (!np) { |
706 | pr_err("PRM: no device tree node for interrupt?\n" ); |
707 | |
708 | return -ENODEV; |
709 | } |
710 | |
711 | irq_num = of_irq_get(dev: np, index: 0); |
712 | of_node_put(node: np); |
713 | if (irq_num == -EPROBE_DEFER) |
714 | return irq_num; |
715 | |
716 | omap3_prcm_irq_setup.irq = irq_num; |
717 | |
718 | omap3xxx_prm_enable_io_wakeup(); |
719 | |
720 | return omap_prcm_register_chain_handler(irq_setup: &omap3_prcm_irq_setup); |
721 | } |
722 | |
723 | static void __exit omap3xxx_prm_exit(void) |
724 | { |
725 | prm_unregister(pld: &omap3xxx_prm_ll_data); |
726 | } |
727 | __exitcall(omap3xxx_prm_exit); |
728 | |