diff options
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 346 |
1 files changed, 101 insertions, 245 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 92d5aff9b2e9..601920860597 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -36,120 +36,22 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | #include <linux/module.h> | ||
40 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
41 | #include <mach/hardware.h> | 40 | #include <linux/err.h> |
42 | #include <plat/dmtimer.h> | ||
43 | #include <mach/irqs.h> | ||
44 | |||
45 | static int dm_timer_count; | ||
46 | |||
47 | #ifdef CONFIG_ARCH_OMAP2 | ||
48 | static struct omap_dm_timer omap2_dm_timers[] = { | ||
49 | { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, | ||
50 | { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, | ||
51 | { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 }, | ||
52 | { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 }, | ||
53 | { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 }, | ||
54 | { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 }, | ||
55 | { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 }, | ||
56 | { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 }, | ||
57 | { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 }, | ||
58 | { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 }, | ||
59 | { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 }, | ||
60 | { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 }, | ||
61 | }; | ||
62 | |||
63 | static const char *omap2_dm_source_names[] __initdata = { | ||
64 | "sys_ck", | ||
65 | "func_32k_ck", | ||
66 | "alt_ck", | ||
67 | NULL | ||
68 | }; | ||
69 | |||
70 | static struct clk *omap2_dm_source_clocks[3]; | ||
71 | static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers); | ||
72 | |||
73 | #else | ||
74 | #define omap2_dm_timers NULL | ||
75 | #define omap2_dm_timer_count 0 | ||
76 | #define omap2_dm_source_names NULL | ||
77 | #define omap2_dm_source_clocks NULL | ||
78 | #endif /* CONFIG_ARCH_OMAP2 */ | ||
79 | |||
80 | #ifdef CONFIG_ARCH_OMAP3 | ||
81 | static struct omap_dm_timer omap3_dm_timers[] = { | ||
82 | { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 }, | ||
83 | { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 }, | ||
84 | { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 }, | ||
85 | { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 }, | ||
86 | { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 }, | ||
87 | { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 }, | ||
88 | { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 }, | ||
89 | { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 }, | ||
90 | { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 }, | ||
91 | { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 }, | ||
92 | { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 }, | ||
93 | { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ }, | ||
94 | }; | ||
95 | |||
96 | static const char *omap3_dm_source_names[] __initdata = { | ||
97 | "sys_ck", | ||
98 | "omap_32k_fck", | ||
99 | NULL | ||
100 | }; | ||
101 | |||
102 | static struct clk *omap3_dm_source_clocks[2]; | ||
103 | static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers); | ||
104 | |||
105 | #else | ||
106 | #define omap3_dm_timers NULL | ||
107 | #define omap3_dm_timer_count 0 | ||
108 | #define omap3_dm_source_names NULL | ||
109 | #define omap3_dm_source_clocks NULL | ||
110 | #endif /* CONFIG_ARCH_OMAP3 */ | ||
111 | |||
112 | #ifdef CONFIG_ARCH_OMAP4 | ||
113 | static struct omap_dm_timer omap4_dm_timers[] = { | ||
114 | { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 }, | ||
115 | { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 }, | ||
116 | { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 }, | ||
117 | { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 }, | ||
118 | { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 }, | ||
119 | { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 }, | ||
120 | { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 }, | ||
121 | { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 }, | ||
122 | { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 }, | ||
123 | { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 }, | ||
124 | { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 }, | ||
125 | { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 }, | ||
126 | }; | ||
127 | static const char *omap4_dm_source_names[] __initdata = { | ||
128 | "sys_clkin_ck", | ||
129 | "sys_32k_ck", | ||
130 | NULL | ||
131 | }; | ||
132 | static struct clk *omap4_dm_source_clocks[2]; | ||
133 | static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers); | ||
134 | 41 | ||
135 | #else | 42 | #include <plat/dmtimer.h> |
136 | #define omap4_dm_timers NULL | ||
137 | #define omap4_dm_timer_count 0 | ||
138 | #define omap4_dm_source_names NULL | ||
139 | #define omap4_dm_source_clocks NULL | ||
140 | #endif /* CONFIG_ARCH_OMAP4 */ | ||
141 | |||
142 | static struct omap_dm_timer *dm_timers; | ||
143 | static const char **dm_source_names; | ||
144 | static struct clk **dm_source_clocks; | ||
145 | 43 | ||
146 | static spinlock_t dm_timer_lock; | ||
147 | static LIST_HEAD(omap_timer_list); | 44 | static LIST_HEAD(omap_timer_list); |
45 | static DEFINE_SPINLOCK(dm_timer_lock); | ||
148 | 46 | ||
149 | /* | 47 | /** |
150 | * Reads timer registers in posted and non-posted mode. The posted mode bit | 48 | * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode |
151 | * is encoded in reg. Note that in posted mode write pending bit must be | 49 | * @timer: timer pointer over which read operation to perform |
152 | * checked. Otherwise a read of a non completed write will produce an error. | 50 | * @reg: lowest byte holds the register offset |
51 | * | ||
52 | * The posted mode bit is encoded in reg. Note that in posted mode write | ||
53 | * pending bit must be checked. Otherwise a read of a non completed write | ||
54 | * will produce an error. | ||
153 | */ | 55 | */ |
154 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) | 56 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) |
155 | { | 57 | { |
@@ -157,11 +59,15 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) | |||
157 | return __omap_dm_timer_read(timer, reg, timer->posted); | 59 | return __omap_dm_timer_read(timer, reg, timer->posted); |
158 | } | 60 | } |
159 | 61 | ||
160 | /* | 62 | /** |
161 | * Writes timer registers in posted and non-posted mode. The posted mode bit | 63 | * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode |
162 | * is encoded in reg. Note that in posted mode the write pending bit must be | 64 | * @timer: timer pointer over which write operation is to perform |
163 | * checked. Otherwise a write on a register which has a pending write will be | 65 | * @reg: lowest byte holds the register offset |
164 | * lost. | 66 | * @value: data to write into the register |
67 | * | ||
68 | * The posted mode bit is encoded in reg. Note that in posted mode the write | ||
69 | * pending bit must be checked. Otherwise a write on a register which has a | ||
70 | * pending write will be lost. | ||
165 | */ | 71 | */ |
166 | static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, | 72 | static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, |
167 | u32 value) | 73 | u32 value) |
@@ -189,53 +95,65 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | |||
189 | 95 | ||
190 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) | 96 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) |
191 | { | 97 | { |
192 | int autoidle = 0, wakeup = 0; | 98 | if (timer->pdev->id != 1) { |
193 | |||
194 | if (!cpu_class_is_omap2() || timer != &dm_timers[0]) { | ||
195 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); | 99 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); |
196 | omap_dm_timer_wait_for_reset(timer); | 100 | omap_dm_timer_wait_for_reset(timer); |
197 | } | 101 | } |
198 | omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); | ||
199 | |||
200 | /* Enable autoidle on OMAP2+ */ | ||
201 | if (cpu_class_is_omap2()) | ||
202 | autoidle = 1; | ||
203 | |||
204 | /* | ||
205 | * Enable wake-up on OMAP2 CPUs. | ||
206 | */ | ||
207 | if (cpu_class_is_omap2()) | ||
208 | wakeup = 1; | ||
209 | 102 | ||
210 | __omap_dm_timer_reset(timer, autoidle, wakeup); | 103 | __omap_dm_timer_reset(timer, 0, 0); |
211 | timer->posted = 1; | 104 | timer->posted = 1; |
212 | } | 105 | } |
213 | 106 | ||
214 | void omap_dm_timer_prepare(struct omap_dm_timer *timer) | 107 | int omap_dm_timer_prepare(struct omap_dm_timer *timer) |
215 | { | 108 | { |
109 | struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; | ||
110 | int ret; | ||
111 | |||
112 | timer->fclk = clk_get(&timer->pdev->dev, "fck"); | ||
113 | if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) { | ||
114 | timer->fclk = NULL; | ||
115 | dev_err(&timer->pdev->dev, ": No fclk handle.\n"); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
216 | omap_dm_timer_enable(timer); | 119 | omap_dm_timer_enable(timer); |
217 | omap_dm_timer_reset(timer); | 120 | |
121 | if (pdata->needs_manual_reset) | ||
122 | omap_dm_timer_reset(timer); | ||
123 | |||
124 | ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); | ||
125 | |||
126 | timer->posted = 1; | ||
127 | return ret; | ||
218 | } | 128 | } |
219 | 129 | ||
220 | struct omap_dm_timer *omap_dm_timer_request(void) | 130 | struct omap_dm_timer *omap_dm_timer_request(void) |
221 | { | 131 | { |
222 | struct omap_dm_timer *timer = NULL; | 132 | struct omap_dm_timer *timer = NULL, *t; |
223 | unsigned long flags; | 133 | unsigned long flags; |
224 | int i; | 134 | int ret = 0; |
225 | 135 | ||
226 | spin_lock_irqsave(&dm_timer_lock, flags); | 136 | spin_lock_irqsave(&dm_timer_lock, flags); |
227 | for (i = 0; i < dm_timer_count; i++) { | 137 | list_for_each_entry(t, &omap_timer_list, node) { |
228 | if (dm_timers[i].reserved) | 138 | if (t->reserved) |
229 | continue; | 139 | continue; |
230 | 140 | ||
231 | timer = &dm_timers[i]; | 141 | timer = t; |
232 | timer->reserved = 1; | 142 | timer->reserved = 1; |
233 | break; | 143 | break; |
234 | } | 144 | } |
145 | |||
146 | if (timer) { | ||
147 | ret = omap_dm_timer_prepare(timer); | ||
148 | if (ret) { | ||
149 | timer->reserved = 0; | ||
150 | timer = NULL; | ||
151 | } | ||
152 | } | ||
235 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 153 | spin_unlock_irqrestore(&dm_timer_lock, flags); |
236 | 154 | ||
237 | if (timer != NULL) | 155 | if (!timer) |
238 | omap_dm_timer_prepare(timer); | 156 | pr_debug("%s: timer request failed!\n", __func__); |
239 | 157 | ||
240 | return timer; | 158 | return timer; |
241 | } | 159 | } |
@@ -243,23 +161,30 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request); | |||
243 | 161 | ||
244 | struct omap_dm_timer *omap_dm_timer_request_specific(int id) | 162 | struct omap_dm_timer *omap_dm_timer_request_specific(int id) |
245 | { | 163 | { |
246 | struct omap_dm_timer *timer; | 164 | struct omap_dm_timer *timer = NULL, *t; |
247 | unsigned long flags; | 165 | unsigned long flags; |
166 | int ret = 0; | ||
248 | 167 | ||
249 | spin_lock_irqsave(&dm_timer_lock, flags); | 168 | spin_lock_irqsave(&dm_timer_lock, flags); |
250 | if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) { | 169 | list_for_each_entry(t, &omap_timer_list, node) { |
251 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 170 | if (t->pdev->id == id && !t->reserved) { |
252 | printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n", | 171 | timer = t; |
253 | __FILE__, __LINE__, __func__, id); | 172 | timer->reserved = 1; |
254 | dump_stack(); | 173 | break; |
255 | return NULL; | 174 | } |
256 | } | 175 | } |
257 | 176 | ||
258 | timer = &dm_timers[id-1]; | 177 | if (timer) { |
259 | timer->reserved = 1; | 178 | ret = omap_dm_timer_prepare(timer); |
179 | if (ret) { | ||
180 | timer->reserved = 0; | ||
181 | timer = NULL; | ||
182 | } | ||
183 | } | ||
260 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 184 | spin_unlock_irqrestore(&dm_timer_lock, flags); |
261 | 185 | ||
262 | omap_dm_timer_prepare(timer); | 186 | if (!timer) |
187 | pr_debug("%s: timer%d request failed!\n", __func__, id); | ||
263 | 188 | ||
264 | return timer; | 189 | return timer; |
265 | } | 190 | } |
@@ -267,9 +192,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); | |||
267 | 192 | ||
268 | void omap_dm_timer_free(struct omap_dm_timer *timer) | 193 | void omap_dm_timer_free(struct omap_dm_timer *timer) |
269 | { | 194 | { |
270 | omap_dm_timer_enable(timer); | ||
271 | omap_dm_timer_reset(timer); | ||
272 | omap_dm_timer_disable(timer); | 195 | omap_dm_timer_disable(timer); |
196 | clk_put(timer->fclk); | ||
273 | 197 | ||
274 | WARN_ON(!timer->reserved); | 198 | WARN_ON(!timer->reserved); |
275 | timer->reserved = 0; | 199 | timer->reserved = 0; |
@@ -278,15 +202,15 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free); | |||
278 | 202 | ||
279 | void omap_dm_timer_enable(struct omap_dm_timer *timer) | 203 | void omap_dm_timer_enable(struct omap_dm_timer *timer) |
280 | { | 204 | { |
205 | struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; | ||
206 | |||
281 | if (timer->enabled) | 207 | if (timer->enabled) |
282 | return; | 208 | return; |
283 | 209 | ||
284 | #ifdef CONFIG_ARCH_OMAP2PLUS | 210 | if (!pdata->needs_manual_reset) { |
285 | if (cpu_class_is_omap2()) { | ||
286 | clk_enable(timer->fclk); | 211 | clk_enable(timer->fclk); |
287 | clk_enable(timer->iclk); | 212 | clk_enable(timer->iclk); |
288 | } | 213 | } |
289 | #endif | ||
290 | 214 | ||
291 | timer->enabled = 1; | 215 | timer->enabled = 1; |
292 | } | 216 | } |
@@ -294,15 +218,15 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable); | |||
294 | 218 | ||
295 | void omap_dm_timer_disable(struct omap_dm_timer *timer) | 219 | void omap_dm_timer_disable(struct omap_dm_timer *timer) |
296 | { | 220 | { |
221 | struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; | ||
222 | |||
297 | if (!timer->enabled) | 223 | if (!timer->enabled) |
298 | return; | 224 | return; |
299 | 225 | ||
300 | #ifdef CONFIG_ARCH_OMAP2PLUS | 226 | if (!pdata->needs_manual_reset) { |
301 | if (cpu_class_is_omap2()) { | ||
302 | clk_disable(timer->iclk); | 227 | clk_disable(timer->iclk); |
303 | clk_disable(timer->fclk); | 228 | clk_disable(timer->fclk); |
304 | } | 229 | } |
305 | #endif | ||
306 | 230 | ||
307 | timer->enabled = 0; | 231 | timer->enabled = 0; |
308 | } | 232 | } |
@@ -322,24 +246,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq); | |||
322 | */ | 246 | */ |
323 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | 247 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) |
324 | { | 248 | { |
325 | int i; | 249 | int i = 0; |
250 | struct omap_dm_timer *timer = NULL; | ||
251 | unsigned long flags; | ||
326 | 252 | ||
327 | /* If ARMXOR cannot be idled this function call is unnecessary */ | 253 | /* If ARMXOR cannot be idled this function call is unnecessary */ |
328 | if (!(inputmask & (1 << 1))) | 254 | if (!(inputmask & (1 << 1))) |
329 | return inputmask; | 255 | return inputmask; |
330 | 256 | ||
331 | /* If any active timer is using ARMXOR return modified mask */ | 257 | /* If any active timer is using ARMXOR return modified mask */ |
332 | for (i = 0; i < dm_timer_count; i++) { | 258 | spin_lock_irqsave(&dm_timer_lock, flags); |
259 | list_for_each_entry(timer, &omap_timer_list, node) { | ||
333 | u32 l; | 260 | u32 l; |
334 | 261 | ||
335 | l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG); | 262 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
336 | if (l & OMAP_TIMER_CTRL_ST) { | 263 | if (l & OMAP_TIMER_CTRL_ST) { |
337 | if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0) | 264 | if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0) |
338 | inputmask &= ~(1 << 1); | 265 | inputmask &= ~(1 << 1); |
339 | else | 266 | else |
340 | inputmask &= ~(1 << 2); | 267 | inputmask &= ~(1 << 2); |
341 | } | 268 | } |
269 | i++; | ||
342 | } | 270 | } |
271 | spin_unlock_irqrestore(&dm_timer_lock, flags); | ||
343 | 272 | ||
344 | return inputmask; | 273 | return inputmask; |
345 | } | 274 | } |
@@ -384,10 +313,10 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start); | |||
384 | void omap_dm_timer_stop(struct omap_dm_timer *timer) | 313 | void omap_dm_timer_stop(struct omap_dm_timer *timer) |
385 | { | 314 | { |
386 | unsigned long rate = 0; | 315 | unsigned long rate = 0; |
316 | struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; | ||
387 | 317 | ||
388 | #ifdef CONFIG_ARCH_OMAP2PLUS | 318 | if (!pdata->needs_manual_reset) |
389 | rate = clk_get_rate(timer->fclk); | 319 | rate = clk_get_rate(timer->fclk); |
390 | #endif | ||
391 | 320 | ||
392 | __omap_dm_timer_stop(timer, timer->posted, rate); | 321 | __omap_dm_timer_stop(timer, timer->posted, rate); |
393 | } | 322 | } |
@@ -395,15 +324,17 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop); | |||
395 | 324 | ||
396 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 325 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) |
397 | { | 326 | { |
327 | int ret; | ||
328 | struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; | ||
329 | |||
398 | if (source < 0 || source >= 3) | 330 | if (source < 0 || source >= 3) |
399 | return -EINVAL; | 331 | return -EINVAL; |
400 | 332 | ||
401 | #ifdef CONFIG_ARCH_OMAP2PLUS | 333 | omap_dm_timer_disable(timer); |
402 | return __omap_dm_timer_set_source(timer->fclk, | 334 | ret = pdata->set_timer_src(timer->pdev, source); |
403 | dm_source_clocks[source]); | 335 | omap_dm_timer_enable(timer); |
404 | #else | 336 | |
405 | return 0; | 337 | return ret; |
406 | #endif | ||
407 | } | 338 | } |
408 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); | 339 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); |
409 | 340 | ||
@@ -526,13 +457,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); | |||
526 | 457 | ||
527 | int omap_dm_timers_active(void) | 458 | int omap_dm_timers_active(void) |
528 | { | 459 | { |
529 | int i; | 460 | struct omap_dm_timer *timer; |
530 | |||
531 | for (i = 0; i < dm_timer_count; i++) { | ||
532 | struct omap_dm_timer *timer; | ||
533 | |||
534 | timer = &dm_timers[i]; | ||
535 | 461 | ||
462 | list_for_each_entry(timer, &omap_timer_list, node) { | ||
536 | if (!timer->enabled) | 463 | if (!timer->enabled) |
537 | continue; | 464 | continue; |
538 | 465 | ||
@@ -602,7 +529,6 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) | |||
602 | timer->id = pdev->id; | 529 | timer->id = pdev->id; |
603 | timer->irq = irq->start; | 530 | timer->irq = irq->start; |
604 | timer->pdev = pdev; | 531 | timer->pdev = pdev; |
605 | __omap_dm_timer_init_regs(timer); | ||
606 | 532 | ||
607 | /* add the timer element to the list */ | 533 | /* add the timer element to the list */ |
608 | spin_lock_irqsave(&dm_timer_lock, flags); | 534 | spin_lock_irqsave(&dm_timer_lock, flags); |
@@ -675,73 +601,3 @@ MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); | |||
675 | MODULE_LICENSE("GPL"); | 601 | MODULE_LICENSE("GPL"); |
676 | MODULE_ALIAS("platform:" DRIVER_NAME); | 602 | MODULE_ALIAS("platform:" DRIVER_NAME); |
677 | MODULE_AUTHOR("Texas Instruments Inc"); | 603 | MODULE_AUTHOR("Texas Instruments Inc"); |
678 | |||
679 | static int __init omap_dm_timer_init(void) | ||
680 | { | ||
681 | struct omap_dm_timer *timer; | ||
682 | int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ | ||
683 | |||
684 | if (!cpu_class_is_omap2()) | ||
685 | return -ENODEV; | ||
686 | |||
687 | spin_lock_init(&dm_timer_lock); | ||
688 | |||
689 | if (cpu_is_omap24xx()) { | ||
690 | dm_timers = omap2_dm_timers; | ||
691 | dm_timer_count = omap2_dm_timer_count; | ||
692 | dm_source_names = omap2_dm_source_names; | ||
693 | dm_source_clocks = omap2_dm_source_clocks; | ||
694 | } else if (cpu_is_omap34xx()) { | ||
695 | dm_timers = omap3_dm_timers; | ||
696 | dm_timer_count = omap3_dm_timer_count; | ||
697 | dm_source_names = omap3_dm_source_names; | ||
698 | dm_source_clocks = omap3_dm_source_clocks; | ||
699 | } else if (cpu_is_omap44xx()) { | ||
700 | dm_timers = omap4_dm_timers; | ||
701 | dm_timer_count = omap4_dm_timer_count; | ||
702 | dm_source_names = omap4_dm_source_names; | ||
703 | dm_source_clocks = omap4_dm_source_clocks; | ||
704 | |||
705 | pr_err("dmtimers disabled for omap4 until hwmod conversion\n"); | ||
706 | return -ENODEV; | ||
707 | } | ||
708 | |||
709 | if (cpu_class_is_omap2()) | ||
710 | for (i = 0; dm_source_names[i] != NULL; i++) | ||
711 | dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]); | ||
712 | |||
713 | if (cpu_is_omap243x()) | ||
714 | dm_timers[0].phys_base = 0x49018000; | ||
715 | |||
716 | for (i = 0; i < dm_timer_count; i++) { | ||
717 | timer = &dm_timers[i]; | ||
718 | |||
719 | /* Static mapping, never released */ | ||
720 | timer->io_base = ioremap(timer->phys_base, map_size); | ||
721 | BUG_ON(!timer->io_base); | ||
722 | |||
723 | #ifdef CONFIG_ARCH_OMAP2PLUS | ||
724 | if (cpu_class_is_omap2()) { | ||
725 | char clk_name[16]; | ||
726 | sprintf(clk_name, "gpt%d_ick", i + 1); | ||
727 | timer->iclk = clk_get(NULL, clk_name); | ||
728 | sprintf(clk_name, "gpt%d_fck", i + 1); | ||
729 | timer->fclk = clk_get(NULL, clk_name); | ||
730 | } | ||
731 | |||
732 | /* One or two timers may be set up early for sys_timer */ | ||
733 | if (sys_timer_reserved & (1 << i)) { | ||
734 | timer->reserved = 1; | ||
735 | timer->posted = 1; | ||
736 | continue; | ||
737 | } | ||
738 | #endif | ||
739 | omap_dm_timer_enable(timer); | ||
740 | __omap_dm_timer_init_regs(timer); | ||
741 | omap_dm_timer_disable(timer); | ||
742 | } | ||
743 | |||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | arch_initcall(omap_dm_timer_init); | ||