Commit | Line | Data |
---|---|---|
b824efae TL |
1 | /* |
2 | * linux/arch/arm/mach-omap2/prcm.c | |
3 | * | |
4 | * OMAP 24xx Power Reset and Clock Management (PRCM) functions | |
5 | * | |
6 | * Copyright (C) 2005 Nokia Corporation | |
7 | * | |
8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | |
9 | * | |
10 | * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc. | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License version 2 as | |
14 | * published by the Free Software Foundation. | |
15 | */ | |
b824efae TL |
16 | #include <linux/module.h> |
17 | #include <linux/init.h> | |
18 | #include <linux/clk.h> | |
a58caad1 | 19 | #include <linux/io.h> |
72350b29 | 20 | #include <linux/delay.h> |
b824efae | 21 | |
a09e64fb RK |
22 | #include <mach/common.h> |
23 | #include <mach/prcm.h> | |
44595982 | 24 | |
a58caad1 | 25 | #include "clock.h" |
44595982 PW |
26 | #include "prm.h" |
27 | #include "prm-regbits-24xx.h" | |
b824efae | 28 | |
a58caad1 TL |
29 | static void __iomem *prm_base; |
30 | static void __iomem *cm_base; | |
31 | ||
72350b29 PW |
32 | #define MAX_MODULE_ENABLE_WAIT 100000 |
33 | ||
b824efae TL |
34 | u32 omap_prcm_get_reset_sources(void) |
35 | { | |
ff00fcc9 | 36 | /* XXX This presumably needs modification for 34XX */ |
44595982 | 37 | return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f; |
b824efae TL |
38 | } |
39 | EXPORT_SYMBOL(omap_prcm_get_reset_sources); | |
40 | ||
41 | /* Resets clock rates and reboots the system. Only called from system.h */ | |
42 | void omap_prcm_arch_reset(char mode) | |
43 | { | |
ff00fcc9 | 44 | s16 prcm_offs; |
ae78dcf7 | 45 | omap2_clk_prepare_for_reboot(); |
44595982 | 46 | |
ff00fcc9 TL |
47 | if (cpu_is_omap24xx()) |
48 | prcm_offs = WKUP_MOD; | |
49 | else if (cpu_is_omap34xx()) | |
50 | prcm_offs = OMAP3430_GR_MOD; | |
51 | else | |
52 | WARN_ON(1); | |
53 | ||
54 | prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL); | |
b824efae | 55 | } |
a58caad1 TL |
56 | |
57 | static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg) | |
58 | { | |
59 | BUG_ON(!base); | |
60 | return __raw_readl(base + module + reg); | |
61 | } | |
62 | ||
63 | static inline void __omap_prcm_write(u32 value, void __iomem *base, | |
64 | s16 module, u16 reg) | |
65 | { | |
66 | BUG_ON(!base); | |
67 | __raw_writel(value, base + module + reg); | |
68 | } | |
69 | ||
70 | /* Read a register in a PRM module */ | |
71 | u32 prm_read_mod_reg(s16 module, u16 idx) | |
72 | { | |
73 | return __omap_prcm_read(prm_base, module, idx); | |
74 | } | |
75 | EXPORT_SYMBOL(prm_read_mod_reg); | |
76 | ||
77 | /* Write into a register in a PRM module */ | |
78 | void prm_write_mod_reg(u32 val, s16 module, u16 idx) | |
79 | { | |
80 | __omap_prcm_write(val, prm_base, module, idx); | |
81 | } | |
82 | EXPORT_SYMBOL(prm_write_mod_reg); | |
83 | ||
ff00fcc9 TL |
84 | /* Read-modify-write a register in a PRM module. Caller must lock */ |
85 | u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) | |
86 | { | |
87 | u32 v; | |
88 | ||
89 | v = prm_read_mod_reg(module, idx); | |
90 | v &= ~mask; | |
91 | v |= bits; | |
92 | prm_write_mod_reg(v, module, idx); | |
93 | ||
94 | return v; | |
95 | } | |
96 | EXPORT_SYMBOL(prm_rmw_mod_reg_bits); | |
97 | ||
a58caad1 TL |
98 | /* Read a register in a CM module */ |
99 | u32 cm_read_mod_reg(s16 module, u16 idx) | |
100 | { | |
101 | return __omap_prcm_read(cm_base, module, idx); | |
102 | } | |
103 | EXPORT_SYMBOL(cm_read_mod_reg); | |
104 | ||
105 | /* Write into a register in a CM module */ | |
106 | void cm_write_mod_reg(u32 val, s16 module, u16 idx) | |
107 | { | |
108 | __omap_prcm_write(val, cm_base, module, idx); | |
109 | } | |
110 | EXPORT_SYMBOL(cm_write_mod_reg); | |
111 | ||
ff00fcc9 TL |
112 | /* Read-modify-write a register in a CM module. Caller must lock */ |
113 | u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) | |
114 | { | |
115 | u32 v; | |
116 | ||
117 | v = cm_read_mod_reg(module, idx); | |
118 | v &= ~mask; | |
119 | v |= bits; | |
120 | cm_write_mod_reg(v, module, idx); | |
121 | ||
122 | return v; | |
123 | } | |
124 | EXPORT_SYMBOL(cm_rmw_mod_reg_bits); | |
125 | ||
72350b29 PW |
126 | /** |
127 | * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness | |
128 | * @reg: physical address of module IDLEST register | |
129 | * @mask: value to mask against to determine if the module is active | |
130 | * @name: name of the clock (for printk) | |
131 | * | |
132 | * Returns 1 if the module indicated readiness in time, or 0 if it | |
133 | * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds. | |
134 | */ | |
135 | int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name) | |
136 | { | |
137 | int i = 0; | |
138 | int ena = 0; | |
139 | ||
140 | /* | |
141 | * 24xx uses 0 to indicate not ready, and 1 to indicate ready. | |
142 | * 34xx reverses this, just to keep us on our toes | |
143 | */ | |
144 | if (cpu_is_omap24xx()) | |
145 | ena = mask; | |
146 | else if (cpu_is_omap34xx()) | |
147 | ena = 0; | |
148 | else | |
149 | BUG(); | |
150 | ||
151 | /* Wait for lock */ | |
152 | while (((__raw_readl(reg) & mask) != ena) && | |
153 | (i++ < MAX_MODULE_ENABLE_WAIT)) | |
154 | udelay(1); | |
155 | ||
156 | if (i < MAX_MODULE_ENABLE_WAIT) | |
157 | pr_debug("cm: Module associated with clock %s ready after %d " | |
158 | "loops\n", name, i); | |
159 | else | |
160 | pr_err("cm: Module associated with clock %s didn't enable in " | |
161 | "%d tries\n", name, MAX_MODULE_ENABLE_WAIT); | |
162 | ||
163 | return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0; | |
164 | }; | |
165 | ||
a58caad1 TL |
166 | void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals) |
167 | { | |
168 | prm_base = omap2_globals->prm; | |
169 | cm_base = omap2_globals->cm; | |
170 | } |