2 * linux/arch/arm/plat-omap/dmtimer.c
4 * OMAP Dual-Mode Timers
6 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
7 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
8 * Thara Gopinath <thara@ti.com>
10 * dmtimer adaptation to platform_driver.
12 * Copyright (C) 2005 Nokia Corporation
13 * OMAP2 support by Juha Yrjola
14 * API improvements and OMAP2 clock framework support by Timo Teras
16 * Copyright (C) 2009 Texas Instruments
17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License as published by the
21 * Free Software Foundation; either version 2 of the License, or (at your
22 * option) any later version.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
27 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * You should have received a copy of the GNU General Public License along
34 * with this program; if not, write to the Free Software Foundation, Inc.,
35 * 675 Mass Ave, Cambridge, MA 02139, USA.
39 #include <linux/slab.h>
40 #include <linux/err.h>
41 #include <linux/pm_runtime.h>
43 #include <plat/dmtimer.h>
45 static LIST_HEAD(omap_timer_list);
46 static DEFINE_SPINLOCK(dm_timer_lock);
49 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
50 * @timer: timer pointer over which read operation to perform
51 * @reg: lowest byte holds the register offset
53 * The posted mode bit is encoded in reg. Note that in posted mode write
54 * pending bit must be checked. Otherwise a read of a non completed write
55 * will produce an error.
57 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
59 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
60 return __omap_dm_timer_read(timer, reg, timer->posted);
64 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
65 * @timer: timer pointer over which write operation is to perform
66 * @reg: lowest byte holds the register offset
67 * @value: data to write into the register
69 * The posted mode bit is encoded in reg. Note that in posted mode the write
70 * pending bit must be checked. Otherwise a write on a register which has a
71 * pending write will be lost.
73 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
76 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
77 __omap_dm_timer_write(timer, reg, value, timer->posted);
80 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
88 while (!(__raw_readl(timer->sys_stat) & 1)) {
91 printk(KERN_ERR "Timer failed to reset\n");
97 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
99 if (timer->pdev->id != 1) {
100 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
101 omap_dm_timer_wait_for_reset(timer);
104 __omap_dm_timer_reset(timer, 0, 0);
108 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
110 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
113 timer->fclk = clk_get(&timer->pdev->dev, "fck");
114 if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
116 dev_err(&timer->pdev->dev, ": No fclk handle.\n");
120 omap_dm_timer_enable(timer);
122 if (pdata->needs_manual_reset)
123 omap_dm_timer_reset(timer);
125 ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
131 struct omap_dm_timer *omap_dm_timer_request(void)
133 struct omap_dm_timer *timer = NULL, *t;
137 spin_lock_irqsave(&dm_timer_lock, flags);
138 list_for_each_entry(t, &omap_timer_list, node) {
148 ret = omap_dm_timer_prepare(timer);
154 spin_unlock_irqrestore(&dm_timer_lock, flags);
157 pr_debug("%s: timer request failed!\n", __func__);
161 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
163 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
165 struct omap_dm_timer *timer = NULL, *t;
169 spin_lock_irqsave(&dm_timer_lock, flags);
170 list_for_each_entry(t, &omap_timer_list, node) {
171 if (t->pdev->id == id && !t->reserved) {
179 ret = omap_dm_timer_prepare(timer);
185 spin_unlock_irqrestore(&dm_timer_lock, flags);
188 pr_debug("%s: timer%d request failed!\n", __func__, id);
192 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
194 void omap_dm_timer_free(struct omap_dm_timer *timer)
196 omap_dm_timer_disable(timer);
197 clk_put(timer->fclk);
199 WARN_ON(!timer->reserved);
202 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
204 void omap_dm_timer_enable(struct omap_dm_timer *timer)
206 pm_runtime_get_sync(&timer->pdev->dev);
208 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
210 void omap_dm_timer_disable(struct omap_dm_timer *timer)
212 pm_runtime_put(&timer->pdev->dev);
214 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
216 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
220 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
222 #if defined(CONFIG_ARCH_OMAP1)
225 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
226 * @inputmask: current value of idlect mask
228 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
231 struct omap_dm_timer *timer = NULL;
234 /* If ARMXOR cannot be idled this function call is unnecessary */
235 if (!(inputmask & (1 << 1)))
238 /* If any active timer is using ARMXOR return modified mask */
239 spin_lock_irqsave(&dm_timer_lock, flags);
240 list_for_each_entry(timer, &omap_timer_list, node) {
243 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
244 if (l & OMAP_TIMER_CTRL_ST) {
245 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
246 inputmask &= ~(1 << 1);
248 inputmask &= ~(1 << 2);
252 spin_unlock_irqrestore(&dm_timer_lock, flags);
256 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
260 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
264 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
266 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
272 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
276 void omap_dm_timer_trigger(struct omap_dm_timer *timer)
278 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
280 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
282 void omap_dm_timer_start(struct omap_dm_timer *timer)
286 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
287 if (!(l & OMAP_TIMER_CTRL_ST)) {
288 l |= OMAP_TIMER_CTRL_ST;
289 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
292 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
294 void omap_dm_timer_stop(struct omap_dm_timer *timer)
296 unsigned long rate = 0;
297 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
299 if (!pdata->needs_manual_reset)
300 rate = clk_get_rate(timer->fclk);
302 __omap_dm_timer_stop(timer, timer->posted, rate);
304 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
306 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
309 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
311 if (source < 0 || source >= 3)
314 omap_dm_timer_disable(timer);
315 ret = pdata->set_timer_src(timer->pdev, source);
316 omap_dm_timer_enable(timer);
320 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
322 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
327 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
329 l |= OMAP_TIMER_CTRL_AR;
331 l &= ~OMAP_TIMER_CTRL_AR;
332 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
333 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
335 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
337 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
339 /* Optimized set_load which removes costly spin wait in timer_start */
340 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
345 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
347 l |= OMAP_TIMER_CTRL_AR;
348 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
350 l &= ~OMAP_TIMER_CTRL_AR;
352 l |= OMAP_TIMER_CTRL_ST;
354 __omap_dm_timer_load_start(timer, l, load, timer->posted);
356 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
358 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
363 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
365 l |= OMAP_TIMER_CTRL_CE;
367 l &= ~OMAP_TIMER_CTRL_CE;
368 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
369 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
371 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
373 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
374 int toggle, int trigger)
378 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
379 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
380 OMAP_TIMER_CTRL_PT | (0x03 << 10));
382 l |= OMAP_TIMER_CTRL_SCPWM;
384 l |= OMAP_TIMER_CTRL_PT;
386 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
388 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
390 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
394 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
395 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
396 if (prescaler >= 0x00 && prescaler <= 0x07) {
397 l |= OMAP_TIMER_CTRL_PRE;
400 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
402 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
404 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
407 __omap_dm_timer_int_enable(timer, value);
409 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
411 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
415 l = __raw_readl(timer->irq_stat);
419 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
421 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
423 __omap_dm_timer_write_status(timer, value);
425 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
427 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
429 return __omap_dm_timer_read_counter(timer, timer->posted);
431 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
433 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
435 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
437 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
439 int omap_dm_timers_active(void)
441 struct omap_dm_timer *timer;
443 list_for_each_entry(timer, &omap_timer_list, node) {
444 if (!timer->reserved)
447 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
448 OMAP_TIMER_CTRL_ST) {
454 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
457 * omap_dm_timer_probe - probe function called for every registered device
458 * @pdev: pointer to current timer platform device
460 * Called by driver framework at the end of device registration for all
463 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
467 struct omap_dm_timer *timer;
468 struct resource *mem, *irq, *ioarea;
469 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
472 dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
476 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
477 if (unlikely(!irq)) {
478 dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
482 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
483 if (unlikely(!mem)) {
484 dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
488 ioarea = request_mem_region(mem->start, resource_size(mem),
491 dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
495 timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
497 dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
500 goto err_free_ioregion;
503 timer->io_base = ioremap(mem->start, resource_size(mem));
504 if (!timer->io_base) {
505 dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
510 timer->id = pdev->id;
511 timer->irq = irq->start;
514 /* Skip pm_runtime_enable for OMAP1 */
515 if (!pdata->needs_manual_reset) {
516 pm_runtime_enable(&pdev->dev);
517 pm_runtime_irq_safe(&pdev->dev);
520 /* add the timer element to the list */
521 spin_lock_irqsave(&dm_timer_lock, flags);
522 list_add_tail(&timer->node, &omap_timer_list);
523 spin_unlock_irqrestore(&dm_timer_lock, flags);
525 dev_dbg(&pdev->dev, "Device Probed.\n");
533 release_mem_region(mem->start, resource_size(mem));
539 * omap_dm_timer_remove - cleanup a registered timer device
540 * @pdev: pointer to current timer platform device
542 * Called by driver framework whenever a timer device is unregistered.
543 * In addition to freeing platform resources it also deletes the timer
544 * entry from the local list.
546 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
548 struct omap_dm_timer *timer;
552 spin_lock_irqsave(&dm_timer_lock, flags);
553 list_for_each_entry(timer, &omap_timer_list, node)
554 if (timer->pdev->id == pdev->id) {
555 list_del(&timer->node);
560 spin_unlock_irqrestore(&dm_timer_lock, flags);
565 static struct platform_driver omap_dm_timer_driver = {
566 .probe = omap_dm_timer_probe,
567 .remove = omap_dm_timer_remove,
569 .name = "omap_timer",
573 static int __init omap_dm_timer_driver_init(void)
575 return platform_driver_register(&omap_dm_timer_driver);
578 static void __exit omap_dm_timer_driver_exit(void)
580 platform_driver_unregister(&omap_dm_timer_driver);
583 early_platform_init("earlytimer", &omap_dm_timer_driver);
584 module_init(omap_dm_timer_driver_init);
585 module_exit(omap_dm_timer_driver_exit);
587 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
588 MODULE_LICENSE("GPL");
589 MODULE_ALIAS("platform:" DRIVER_NAME);
590 MODULE_AUTHOR("Texas Instruments Inc");