1/*
2 * linux/arch/arm/plat-omap/dmtimer.c
3 *
4 * OMAP Dual-Mode Timers
5 *
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>
9 *
10 * dmtimer adaptation to platform_driver.
11 *
12 * Copyright (C) 2005 Nokia Corporation
13 * OMAP2 support by Juha Yrjola
14 * API improvements and OMAP2 clock framework support by Timo Teras
15 *
16 * Copyright (C) 2009 Texas Instruments
17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
18 *
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.
23 *
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.
32 *
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.
36 */
37
38#include <linux/clk.h>
39#include <linux/module.h>
40#include <linux/io.h>
41#include <linux/device.h>
42#include <linux/err.h>
43#include <linux/pm_runtime.h>
44#include <linux/of.h>
45#include <linux/of_device.h>
46#include <linux/platform_device.h>
47#include <linux/platform_data/dmtimer-omap.h>
48
49#include <plat/dmtimer.h>
50
51static u32 omap_reserved_systimers;
52static LIST_HEAD(omap_timer_list);
53static DEFINE_SPINLOCK(dm_timer_lock);
54
55enum {
56	REQUEST_ANY = 0,
57	REQUEST_BY_ID,
58	REQUEST_BY_CAP,
59	REQUEST_BY_NODE,
60};
61
62/**
63 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
64 * @timer:      timer pointer over which read operation to perform
65 * @reg:        lowest byte holds the register offset
66 *
67 * The posted mode bit is encoded in reg. Note that in posted mode write
68 * pending bit must be checked. Otherwise a read of a non completed write
69 * will produce an error.
70 */
71static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
72{
73	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
74	return __omap_dm_timer_read(timer, reg, timer->posted);
75}
76
77/**
78 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
79 * @timer:      timer pointer over which write operation is to perform
80 * @reg:        lowest byte holds the register offset
81 * @value:      data to write into the register
82 *
83 * The posted mode bit is encoded in reg. Note that in posted mode the write
84 * pending bit must be checked. Otherwise a write on a register which has a
85 * pending write will be lost.
86 */
87static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
88						u32 value)
89{
90	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
91	__omap_dm_timer_write(timer, reg, value, timer->posted);
92}
93
94static void omap_timer_restore_context(struct omap_dm_timer *timer)
95{
96	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
97				timer->context.twer);
98	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
99				timer->context.tcrr);
100	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
101				timer->context.tldr);
102	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
103				timer->context.tmar);
104	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
105				timer->context.tsicr);
106	writel_relaxed(timer->context.tier, timer->irq_ena);
107	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
108				timer->context.tclr);
109}
110
111static int omap_dm_timer_reset(struct omap_dm_timer *timer)
112{
113	u32 l, timeout = 100000;
114
115	if (timer->revision != 1)
116		return -EINVAL;
117
118	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
119
120	do {
121		l = __omap_dm_timer_read(timer,
122					 OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
123	} while (!l && timeout--);
124
125	if (!timeout) {
126		dev_err(&timer->pdev->dev, "Timer failed to reset\n");
127		return -ETIMEDOUT;
128	}
129
130	/* Configure timer for smart-idle mode */
131	l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
132	l |= 0x2 << 0x3;
133	__omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
134
135	timer->posted = 0;
136
137	return 0;
138}
139
140static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
141{
142	int rc;
143
144	/*
145	 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
146	 * do not call clk_get() for these devices.
147	 */
148	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
149		timer->fclk = clk_get(&timer->pdev->dev, "fck");
150		if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
151			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
152			return -EINVAL;
153		}
154	}
155
156	omap_dm_timer_enable(timer);
157
158	if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
159		rc = omap_dm_timer_reset(timer);
160		if (rc) {
161			omap_dm_timer_disable(timer);
162			return rc;
163		}
164	}
165
166	__omap_dm_timer_enable_posted(timer);
167	omap_dm_timer_disable(timer);
168
169	return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
170}
171
172static inline u32 omap_dm_timer_reserved_systimer(int id)
173{
174	return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
175}
176
177int omap_dm_timer_reserve_systimer(int id)
178{
179	if (omap_dm_timer_reserved_systimer(id))
180		return -ENODEV;
181
182	omap_reserved_systimers |= (1 << (id - 1));
183
184	return 0;
185}
186
187static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)
188{
189	struct omap_dm_timer *timer = NULL, *t;
190	struct device_node *np = NULL;
191	unsigned long flags;
192	u32 cap = 0;
193	int id = 0;
194
195	switch (req_type) {
196	case REQUEST_BY_ID:
197		id = *(int *)data;
198		break;
199	case REQUEST_BY_CAP:
200		cap = *(u32 *)data;
201		break;
202	case REQUEST_BY_NODE:
203		np = (struct device_node *)data;
204		break;
205	default:
206		/* REQUEST_ANY */
207		break;
208	}
209
210	spin_lock_irqsave(&dm_timer_lock, flags);
211	list_for_each_entry(t, &omap_timer_list, node) {
212		if (t->reserved)
213			continue;
214
215		switch (req_type) {
216		case REQUEST_BY_ID:
217			if (id == t->pdev->id) {
218				timer = t;
219				timer->reserved = 1;
220				goto found;
221			}
222			break;
223		case REQUEST_BY_CAP:
224			if (cap == (t->capability & cap)) {
225				/*
226				 * If timer is not NULL, we have already found
227				 * one timer but it was not an exact match
228				 * because it had more capabilites that what
229				 * was required. Therefore, unreserve the last
230				 * timer found and see if this one is a better
231				 * match.
232				 */
233				if (timer)
234					timer->reserved = 0;
235				timer = t;
236				timer->reserved = 1;
237
238				/* Exit loop early if we find an exact match */
239				if (t->capability == cap)
240					goto found;
241			}
242			break;
243		case REQUEST_BY_NODE:
244			if (np == t->pdev->dev.of_node) {
245				timer = t;
246				timer->reserved = 1;
247				goto found;
248			}
249			break;
250		default:
251			/* REQUEST_ANY */
252			timer = t;
253			timer->reserved = 1;
254			goto found;
255		}
256	}
257found:
258	spin_unlock_irqrestore(&dm_timer_lock, flags);
259
260	if (timer && omap_dm_timer_prepare(timer)) {
261		timer->reserved = 0;
262		timer = NULL;
263	}
264
265	if (!timer)
266		pr_debug("%s: timer request failed!\n", __func__);
267
268	return timer;
269}
270
271struct omap_dm_timer *omap_dm_timer_request(void)
272{
273	return _omap_dm_timer_request(REQUEST_ANY, NULL);
274}
275EXPORT_SYMBOL_GPL(omap_dm_timer_request);
276
277struct omap_dm_timer *omap_dm_timer_request_specific(int id)
278{
279	/* Requesting timer by ID is not supported when device tree is used */
280	if (of_have_populated_dt()) {
281		pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n",
282			__func__);
283		return NULL;
284	}
285
286	return _omap_dm_timer_request(REQUEST_BY_ID, &id);
287}
288EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
289
290/**
291 * omap_dm_timer_request_by_cap - Request a timer by capability
292 * @cap:	Bit mask of capabilities to match
293 *
294 * Find a timer based upon capabilities bit mask. Callers of this function
295 * should use the definitions found in the plat/dmtimer.h file under the
296 * comment "timer capabilities used in hwmod database". Returns pointer to
297 * timer handle on success and a NULL pointer on failure.
298 */
299struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
300{
301	return _omap_dm_timer_request(REQUEST_BY_CAP, &cap);
302}
303EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
304
305/**
306 * omap_dm_timer_request_by_node - Request a timer by device-tree node
307 * @np:		Pointer to device-tree timer node
308 *
309 * Request a timer based upon a device node pointer. Returns pointer to
310 * timer handle on success and a NULL pointer on failure.
311 */
312struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
313{
314	if (!np)
315		return NULL;
316
317	return _omap_dm_timer_request(REQUEST_BY_NODE, np);
318}
319EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node);
320
321int omap_dm_timer_free(struct omap_dm_timer *timer)
322{
323	if (unlikely(!timer))
324		return -EINVAL;
325
326	clk_put(timer->fclk);
327
328	WARN_ON(!timer->reserved);
329	timer->reserved = 0;
330	return 0;
331}
332EXPORT_SYMBOL_GPL(omap_dm_timer_free);
333
334void omap_dm_timer_enable(struct omap_dm_timer *timer)
335{
336	int c;
337
338	pm_runtime_get_sync(&timer->pdev->dev);
339
340	if (!(timer->capability & OMAP_TIMER_ALWON)) {
341		if (timer->get_context_loss_count) {
342			c = timer->get_context_loss_count(&timer->pdev->dev);
343			if (c != timer->ctx_loss_count) {
344				omap_timer_restore_context(timer);
345				timer->ctx_loss_count = c;
346			}
347		} else {
348			omap_timer_restore_context(timer);
349		}
350	}
351}
352EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
353
354void omap_dm_timer_disable(struct omap_dm_timer *timer)
355{
356	pm_runtime_put_sync(&timer->pdev->dev);
357}
358EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
359
360int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
361{
362	if (timer)
363		return timer->irq;
364	return -EINVAL;
365}
366EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
367
368#if defined(CONFIG_ARCH_OMAP1)
369#include <mach/hardware.h>
370/**
371 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
372 * @inputmask: current value of idlect mask
373 */
374__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
375{
376	int i = 0;
377	struct omap_dm_timer *timer = NULL;
378	unsigned long flags;
379
380	/* If ARMXOR cannot be idled this function call is unnecessary */
381	if (!(inputmask & (1 << 1)))
382		return inputmask;
383
384	/* If any active timer is using ARMXOR return modified mask */
385	spin_lock_irqsave(&dm_timer_lock, flags);
386	list_for_each_entry(timer, &omap_timer_list, node) {
387		u32 l;
388
389		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
390		if (l & OMAP_TIMER_CTRL_ST) {
391			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
392				inputmask &= ~(1 << 1);
393			else
394				inputmask &= ~(1 << 2);
395		}
396		i++;
397	}
398	spin_unlock_irqrestore(&dm_timer_lock, flags);
399
400	return inputmask;
401}
402EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
403
404#else
405
406struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
407{
408	if (timer && !IS_ERR(timer->fclk))
409		return timer->fclk;
410	return NULL;
411}
412EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
413
414__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
415{
416	BUG();
417
418	return 0;
419}
420EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
421
422#endif
423
424int omap_dm_timer_trigger(struct omap_dm_timer *timer)
425{
426	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
427		pr_err("%s: timer not available or enabled.\n", __func__);
428		return -EINVAL;
429	}
430
431	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
432	return 0;
433}
434EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
435
436int omap_dm_timer_start(struct omap_dm_timer *timer)
437{
438	u32 l;
439
440	if (unlikely(!timer))
441		return -EINVAL;
442
443	omap_dm_timer_enable(timer);
444
445	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
446	if (!(l & OMAP_TIMER_CTRL_ST)) {
447		l |= OMAP_TIMER_CTRL_ST;
448		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
449	}
450
451	/* Save the context */
452	timer->context.tclr = l;
453	return 0;
454}
455EXPORT_SYMBOL_GPL(omap_dm_timer_start);
456
457int omap_dm_timer_stop(struct omap_dm_timer *timer)
458{
459	unsigned long rate = 0;
460
461	if (unlikely(!timer))
462		return -EINVAL;
463
464	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
465		rate = clk_get_rate(timer->fclk);
466
467	__omap_dm_timer_stop(timer, timer->posted, rate);
468
469	/*
470	 * Since the register values are computed and written within
471	 * __omap_dm_timer_stop, we need to use read to retrieve the
472	 * context.
473	 */
474	timer->context.tclr =
475			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
476	omap_dm_timer_disable(timer);
477	return 0;
478}
479EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
480
481int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
482{
483	int ret;
484	char *parent_name = NULL;
485	struct clk *parent;
486	struct dmtimer_platform_data *pdata;
487
488	if (unlikely(!timer))
489		return -EINVAL;
490
491	pdata = timer->pdev->dev.platform_data;
492
493	if (source < 0 || source >= 3)
494		return -EINVAL;
495
496	/*
497	 * FIXME: Used for OMAP1 devices only because they do not currently
498	 * use the clock framework to set the parent clock. To be removed
499	 * once OMAP1 migrated to using clock framework for dmtimers
500	 */
501	if (pdata && pdata->set_timer_src)
502		return pdata->set_timer_src(timer->pdev, source);
503
504	if (IS_ERR(timer->fclk))
505		return -EINVAL;
506
507	switch (source) {
508	case OMAP_TIMER_SRC_SYS_CLK:
509		parent_name = "timer_sys_ck";
510		break;
511
512	case OMAP_TIMER_SRC_32_KHZ:
513		parent_name = "timer_32k_ck";
514		break;
515
516	case OMAP_TIMER_SRC_EXT_CLK:
517		parent_name = "timer_ext_ck";
518		break;
519	}
520
521	parent = clk_get(&timer->pdev->dev, parent_name);
522	if (IS_ERR(parent)) {
523		pr_err("%s: %s not found\n", __func__, parent_name);
524		return -EINVAL;
525	}
526
527	ret = clk_set_parent(timer->fclk, parent);
528	if (ret < 0)
529		pr_err("%s: failed to set %s as parent\n", __func__,
530			parent_name);
531
532	clk_put(parent);
533
534	return ret;
535}
536EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
537
538int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
539			    unsigned int load)
540{
541	u32 l;
542
543	if (unlikely(!timer))
544		return -EINVAL;
545
546	omap_dm_timer_enable(timer);
547	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
548	if (autoreload)
549		l |= OMAP_TIMER_CTRL_AR;
550	else
551		l &= ~OMAP_TIMER_CTRL_AR;
552	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
553	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
554
555	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
556	/* Save the context */
557	timer->context.tclr = l;
558	timer->context.tldr = load;
559	omap_dm_timer_disable(timer);
560	return 0;
561}
562EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
563
564/* Optimized set_load which removes costly spin wait in timer_start */
565int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
566                            unsigned int load)
567{
568	u32 l;
569
570	if (unlikely(!timer))
571		return -EINVAL;
572
573	omap_dm_timer_enable(timer);
574
575	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
576	if (autoreload) {
577		l |= OMAP_TIMER_CTRL_AR;
578		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
579	} else {
580		l &= ~OMAP_TIMER_CTRL_AR;
581	}
582	l |= OMAP_TIMER_CTRL_ST;
583
584	__omap_dm_timer_load_start(timer, l, load, timer->posted);
585
586	/* Save the context */
587	timer->context.tclr = l;
588	timer->context.tldr = load;
589	timer->context.tcrr = load;
590	return 0;
591}
592EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
593
594int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
595			     unsigned int match)
596{
597	u32 l;
598
599	if (unlikely(!timer))
600		return -EINVAL;
601
602	omap_dm_timer_enable(timer);
603	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
604	if (enable)
605		l |= OMAP_TIMER_CTRL_CE;
606	else
607		l &= ~OMAP_TIMER_CTRL_CE;
608	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
609	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
610
611	/* Save the context */
612	timer->context.tclr = l;
613	timer->context.tmar = match;
614	omap_dm_timer_disable(timer);
615	return 0;
616}
617EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
618
619int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
620			   int toggle, int trigger)
621{
622	u32 l;
623
624	if (unlikely(!timer))
625		return -EINVAL;
626
627	omap_dm_timer_enable(timer);
628	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
629	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
630	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
631	if (def_on)
632		l |= OMAP_TIMER_CTRL_SCPWM;
633	if (toggle)
634		l |= OMAP_TIMER_CTRL_PT;
635	l |= trigger << 10;
636	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
637
638	/* Save the context */
639	timer->context.tclr = l;
640	omap_dm_timer_disable(timer);
641	return 0;
642}
643EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
644
645int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
646{
647	u32 l;
648
649	if (unlikely(!timer))
650		return -EINVAL;
651
652	omap_dm_timer_enable(timer);
653	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
654	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
655	if (prescaler >= 0x00 && prescaler <= 0x07) {
656		l |= OMAP_TIMER_CTRL_PRE;
657		l |= prescaler << 2;
658	}
659	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
660
661	/* Save the context */
662	timer->context.tclr = l;
663	omap_dm_timer_disable(timer);
664	return 0;
665}
666EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
667
668int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
669				  unsigned int value)
670{
671	if (unlikely(!timer))
672		return -EINVAL;
673
674	omap_dm_timer_enable(timer);
675	__omap_dm_timer_int_enable(timer, value);
676
677	/* Save the context */
678	timer->context.tier = value;
679	timer->context.twer = value;
680	omap_dm_timer_disable(timer);
681	return 0;
682}
683EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
684
685/**
686 * omap_dm_timer_set_int_disable - disable timer interrupts
687 * @timer:	pointer to timer handle
688 * @mask:	bit mask of interrupts to be disabled
689 *
690 * Disables the specified timer interrupts for a timer.
691 */
692int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
693{
694	u32 l = mask;
695
696	if (unlikely(!timer))
697		return -EINVAL;
698
699	omap_dm_timer_enable(timer);
700
701	if (timer->revision == 1)
702		l = readl_relaxed(timer->irq_ena) & ~mask;
703
704	writel_relaxed(l, timer->irq_dis);
705	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
706	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
707
708	/* Save the context */
709	timer->context.tier &= ~mask;
710	timer->context.twer &= ~mask;
711	omap_dm_timer_disable(timer);
712	return 0;
713}
714EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
715
716unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
717{
718	unsigned int l;
719
720	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
721		pr_err("%s: timer not available or enabled.\n", __func__);
722		return 0;
723	}
724
725	l = readl_relaxed(timer->irq_stat);
726
727	return l;
728}
729EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
730
731int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
732{
733	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
734		return -EINVAL;
735
736	__omap_dm_timer_write_status(timer, value);
737
738	return 0;
739}
740EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
741
742unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
743{
744	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
745		pr_err("%s: timer not iavailable or enabled.\n", __func__);
746		return 0;
747	}
748
749	return __omap_dm_timer_read_counter(timer, timer->posted);
750}
751EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
752
753int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
754{
755	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
756		pr_err("%s: timer not available or enabled.\n", __func__);
757		return -EINVAL;
758	}
759
760	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
761
762	/* Save the context */
763	timer->context.tcrr = value;
764	return 0;
765}
766EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
767
768int omap_dm_timers_active(void)
769{
770	struct omap_dm_timer *timer;
771
772	list_for_each_entry(timer, &omap_timer_list, node) {
773		if (!timer->reserved)
774			continue;
775
776		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
777		    OMAP_TIMER_CTRL_ST) {
778			return 1;
779		}
780	}
781	return 0;
782}
783EXPORT_SYMBOL_GPL(omap_dm_timers_active);
784
785static const struct of_device_id omap_timer_match[];
786
787/**
788 * omap_dm_timer_probe - probe function called for every registered device
789 * @pdev:	pointer to current timer platform device
790 *
791 * Called by driver framework at the end of device registration for all
792 * timer devices.
793 */
794static int omap_dm_timer_probe(struct platform_device *pdev)
795{
796	unsigned long flags;
797	struct omap_dm_timer *timer;
798	struct resource *mem, *irq;
799	struct device *dev = &pdev->dev;
800	const struct of_device_id *match;
801	const struct dmtimer_platform_data *pdata;
802	int ret;
803
804	match = of_match_device(of_match_ptr(omap_timer_match), dev);
805	pdata = match ? match->data : dev->platform_data;
806
807	if (!pdata && !dev->of_node) {
808		dev_err(dev, "%s: no platform data.\n", __func__);
809		return -ENODEV;
810	}
811
812	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
813	if (unlikely(!irq)) {
814		dev_err(dev, "%s: no IRQ resource.\n", __func__);
815		return -ENODEV;
816	}
817
818	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
819	if (unlikely(!mem)) {
820		dev_err(dev, "%s: no memory resource.\n", __func__);
821		return -ENODEV;
822	}
823
824	timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
825	if (!timer) {
826		dev_err(dev, "%s: memory alloc failed!\n", __func__);
827		return  -ENOMEM;
828	}
829
830	timer->fclk = ERR_PTR(-ENODEV);
831	timer->io_base = devm_ioremap_resource(dev, mem);
832	if (IS_ERR(timer->io_base))
833		return PTR_ERR(timer->io_base);
834
835	if (dev->of_node) {
836		if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
837			timer->capability |= OMAP_TIMER_ALWON;
838		if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
839			timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
840		if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
841			timer->capability |= OMAP_TIMER_HAS_PWM;
842		if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
843			timer->capability |= OMAP_TIMER_SECURE;
844	} else {
845		timer->id = pdev->id;
846		timer->capability = pdata->timer_capability;
847		timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
848		timer->get_context_loss_count = pdata->get_context_loss_count;
849	}
850
851	if (pdata)
852		timer->errata = pdata->timer_errata;
853
854	timer->irq = irq->start;
855	timer->pdev = pdev;
856
857	/* Skip pm_runtime_enable for OMAP1 */
858	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
859		pm_runtime_enable(dev);
860		pm_runtime_irq_safe(dev);
861	}
862
863	if (!timer->reserved) {
864		ret = pm_runtime_get_sync(dev);
865		if (ret < 0) {
866			dev_err(dev, "%s: pm_runtime_get_sync failed!\n",
867				__func__);
868			goto err_get_sync;
869		}
870		__omap_dm_timer_init_regs(timer);
871		pm_runtime_put(dev);
872	}
873
874	/* add the timer element to the list */
875	spin_lock_irqsave(&dm_timer_lock, flags);
876	list_add_tail(&timer->node, &omap_timer_list);
877	spin_unlock_irqrestore(&dm_timer_lock, flags);
878
879	dev_dbg(dev, "Device Probed.\n");
880
881	return 0;
882
883err_get_sync:
884	pm_runtime_put_noidle(dev);
885	pm_runtime_disable(dev);
886	return ret;
887}
888
889/**
890 * omap_dm_timer_remove - cleanup a registered timer device
891 * @pdev:	pointer to current timer platform device
892 *
893 * Called by driver framework whenever a timer device is unregistered.
894 * In addition to freeing platform resources it also deletes the timer
895 * entry from the local list.
896 */
897static int omap_dm_timer_remove(struct platform_device *pdev)
898{
899	struct omap_dm_timer *timer;
900	unsigned long flags;
901	int ret = -EINVAL;
902
903	spin_lock_irqsave(&dm_timer_lock, flags);
904	list_for_each_entry(timer, &omap_timer_list, node)
905		if (!strcmp(dev_name(&timer->pdev->dev),
906			    dev_name(&pdev->dev))) {
907			list_del(&timer->node);
908			ret = 0;
909			break;
910		}
911	spin_unlock_irqrestore(&dm_timer_lock, flags);
912
913	pm_runtime_disable(&pdev->dev);
914
915	return ret;
916}
917
918static const struct dmtimer_platform_data omap3plus_pdata = {
919	.timer_errata = OMAP_TIMER_ERRATA_I103_I767,
920};
921
922static const struct of_device_id omap_timer_match[] = {
923	{
924		.compatible = "ti,omap2420-timer",
925	},
926	{
927		.compatible = "ti,omap3430-timer",
928		.data = &omap3plus_pdata,
929	},
930	{
931		.compatible = "ti,omap4430-timer",
932		.data = &omap3plus_pdata,
933	},
934	{
935		.compatible = "ti,omap5430-timer",
936		.data = &omap3plus_pdata,
937	},
938	{
939		.compatible = "ti,am335x-timer",
940		.data = &omap3plus_pdata,
941	},
942	{
943		.compatible = "ti,am335x-timer-1ms",
944		.data = &omap3plus_pdata,
945	},
946	{},
947};
948MODULE_DEVICE_TABLE(of, omap_timer_match);
949
950static struct platform_driver omap_dm_timer_driver = {
951	.probe  = omap_dm_timer_probe,
952	.remove = omap_dm_timer_remove,
953	.driver = {
954		.name   = "omap_timer",
955		.of_match_table = of_match_ptr(omap_timer_match),
956	},
957};
958
959early_platform_init("earlytimer", &omap_dm_timer_driver);
960module_platform_driver(omap_dm_timer_driver);
961
962MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
963MODULE_LICENSE("GPL");
964MODULE_ALIAS("platform:" DRIVER_NAME);
965MODULE_AUTHOR("Texas Instruments Inc");
966