summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2013-04-23 17:46:30 +0200
committerOlof Johansson <olof@lixom.net>2013-04-28 12:17:05 -0700
commit81d4f7bfdc9417e7d8fc1133c762daa4458eec5e (patch)
treea9942c9fb2ec8d830ead2fb01517b7f95985fb80 /drivers/clocksource
parent6fe4dfd041dadbc1cc2460ed8680f2734dc3dc95 (diff)
clocksource: samsung_pwm_timer: Work around rounding errors in clockevents core
Due to rounding errors in clockevents core (in conversions between ticks and nsecs), it might happen that the set_next_event callback gets called with cycles = 0, causing the code to incorrectly program the PWM timer. This patch modifies the callback to program the timer for 1 tick, if received tick count value is 0. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/samsung_pwm_timer.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index 92b2f130ae9..0234c8d2c8f 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -176,6 +176,19 @@ static void samsung_time_start(unsigned int channel, bool periodic)
static int samsung_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
+ /*
+ * This check is needed to account for internal rounding
+ * errors inside clockevents core, which might result in
+ * passing cycles = 0, which in turn would not generate any
+ * timer interrupt and hang the system.
+ *
+ * Another solution would be to set up the clockevent device
+ * with min_delta = 2, but this would unnecessarily increase
+ * the minimum sleep period.
+ */
+ if (!cycles)
+ cycles = 1;
+
samsung_time_setup(pwm.event_id, cycles);
samsung_time_start(pwm.event_id, false);