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