[PATCH 2/2] plat-omap: dmtimer: Add support for capture mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Added new API function (omap_dm_timer_set_capture_mode) that
configures any timer in capture mode.
The event on which to capture is one of the following: low to high,
high to low or both edges timer pin transition.

The timer can be configured in two capture modes: single and second.
In single event mode the timer will capture on the first event and
write the current timer value in tcar1 register.
In second event mode, timer will capture on the first event and
write the curret timer value into tcar1 and on the second event will
write the timer counter value into tcar2.

If capture interrupt is enabled the timer will trigger it after a
capture was done and not update tcar1 and tcar2 until the status
of that irq is cleared. In the timer ISR the tcar1 and tcar2 are
read and stored for future use.

Added new API function (omap_dm_timer_read_counter_captures) to read
the captured timer values, tcar1 and tcar2.

Signed-off-by: Andrei Varvara <andrei.varvara@xxxxxxxx>
---
 arch/arm/plat-omap/dmtimer.c              | 81 +++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/dmtimer.h | 14 ++++++
 2 files changed, 95 insertions(+)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index b13e0d2..b0b593f 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -643,6 +643,66 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 
+int omap_dm_timer_set_capture_mode(struct omap_dm_timer *timer, int capt_mode,
+				   int transition_cap_mode)
+{
+	u32 l;
+
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
+	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
+
+	/* Set as input pin */
+	l |= OMAP_TIMER_CTRL_GPOCFG;
+
+	l &= ~OMAP_TIMER_CTRL_CAPTMODE;
+	switch (capt_mode) {
+	case OMAP_TIMER_CAPTMODE_SINGLE:
+		break;
+	case OMAP_TIMER_CAPTMODE_SECOND:
+		l |= OMAP_TIMER_CTRL_CAPTMODE;
+		break;
+	default:
+		pr_err("%s: Invalid timer capture mode %d\n",
+		       __func__, capt_mode);
+		return -EINVAL;
+	}
+
+	l &= ~OMAP_TIMER_CTRL_TCM_BOTHEDGES;
+	switch (transition_cap_mode) {
+	case OMAP_TIMER_CAPTURE_NONE:
+		break;
+	case OMAP_TIMER_CAPTURE_LOWTOHIGH:
+		l |= OMAP_TIMER_CTRL_TCM_LOWTOHIGH;
+		break;
+	case OMAP_TIMER_CAPTURE_HIGHTOLOW:
+		l |= OMAP_TIMER_CTRL_TCM_HIGHTOLOW;
+		break;
+	case OMAP_TIMER_CAPTURE_BOTHEDGES:
+		l |= OMAP_TIMER_CTRL_TCM_BOTHEDGES;
+		break;
+	default:
+		pr_err("%s: Invalid timer transition capture mode %d\n",
+		       __func__, transition_cap_mode);
+		return -EINVAL;
+	}
+
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+
+	omap_dm_timer_disable(timer);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_capture_mode);
+
 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 {
 	u32 l;
@@ -793,6 +853,27 @@ int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
+int omap_dm_timer_read_counter_captures(struct omap_dm_timer *timer, u32 *tcar1,
+					u32 *tcar2)
+{
+	unsigned long flags;
+
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
+	raw_spin_lock_irqsave(&timer->raw_lock, flags);
+
+	*tcar1 = timer->context.tcar1;
+	*tcar2 = timer->context.tcar2;
+
+	raw_spin_unlock_irqrestore(&timer->raw_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter_captures);
+
 int omap_dm_timers_active(void)
 {
 	struct omap_dm_timer *timer;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 4e7daf9..6d5fe56 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -54,6 +54,16 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
 
+/* transition capture mode on PIEVENTCAPT input pin */
+#define OMAP_TIMER_CAPTURE_NONE			0x00
+#define OMAP_TIMER_CAPTURE_LOWTOHIGH		0x01
+#define OMAP_TIMER_CAPTURE_HIGHTOLOW		0x02
+#define OMAP_TIMER_CAPTURE_BOTHEDGES		0x03
+
+/* capture mode */
+#define OMAP_TIMER_CAPTMODE_SINGLE		0x00
+#define OMAP_TIMER_CAPTMODE_SECOND		0x01
+
 /* posted mode types */
 #define OMAP_TIMER_NONPOSTED			0x00
 #define OMAP_TIMER_POSTED			0x01
@@ -170,6 +180,8 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned
 int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+int omap_dm_timer_set_capture_mode(struct omap_dm_timer *timer, int capt_mode,
+				   int trigger_out_mode);
 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
 
 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
@@ -180,6 +192,8 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_read_counter_captures(struct omap_dm_timer *timer, u32 *tcar1,
+					u32 *tcar2);
 
 int omap_dm_timers_active(void);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux