diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2013-07-16 10:45:38 -0400 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2013-07-18 09:27:21 -0400 |
commit | 7e14183469d8aa2c7aa7675a6156e7846dda7748 (patch) | |
tree | 2ce43e7591f668178440cb36c89e41227e68d5ce /drivers/clocksource | |
parent | a2c49e7b553a28f10ab34e5da538ed4a45a697a7 (diff) |
clocksource: sun4i: Fix bug when switching from periodic to oneshot modes
The interval was firing at was set up at probe time, and only changed in
the set_next_event, and never changed back, which is not really what is
expected.
When enabling the periodic mode, now set an interval to tick every
jiffy.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/sun4i_timer.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 2fadb3ba59db..8ead0258740a 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) | 38 | #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) |
39 | 39 | ||
40 | static void __iomem *timer_base; | 40 | static void __iomem *timer_base; |
41 | static u32 ticks_per_jiffy; | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * When we disable a timer, we need to wait at least for 2 cycles of | 44 | * When we disable a timer, we need to wait at least for 2 cycles of |
@@ -74,7 +75,8 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic) | |||
74 | else | 75 | else |
75 | val |= TIMER_CTL_ONESHOT; | 76 | val |= TIMER_CTL_ONESHOT; |
76 | 77 | ||
77 | writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); | 78 | writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, |
79 | timer_base + TIMER_CTL_REG(timer)); | ||
78 | } | 80 | } |
79 | 81 | ||
80 | static void sun4i_clkevt_mode(enum clock_event_mode mode, | 82 | static void sun4i_clkevt_mode(enum clock_event_mode mode, |
@@ -83,6 +85,7 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, | |||
83 | switch (mode) { | 85 | switch (mode) { |
84 | case CLOCK_EVT_MODE_PERIODIC: | 86 | case CLOCK_EVT_MODE_PERIODIC: |
85 | sun4i_clkevt_time_stop(0); | 87 | sun4i_clkevt_time_stop(0); |
88 | sun4i_clkevt_time_setup(0, ticks_per_jiffy); | ||
86 | sun4i_clkevt_time_start(0, true); | 89 | sun4i_clkevt_time_start(0, true); |
87 | break; | 90 | break; |
88 | case CLOCK_EVT_MODE_ONESHOT: | 91 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -169,9 +172,9 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
169 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, | 172 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, |
170 | rate, 300, 32, clocksource_mmio_readl_down); | 173 | rate, 300, 32, clocksource_mmio_readl_down); |
171 | 174 | ||
172 | writel(rate / HZ, timer_base + TIMER_INTVAL_REG(0)); | 175 | ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); |
173 | 176 | ||
174 | writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M) | TIMER_CTL_RELOAD, | 177 | writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), |
175 | timer_base + TIMER_CTL_REG(0)); | 178 | timer_base + TIMER_CTL_REG(0)); |
176 | 179 | ||
177 | ret = setup_irq(irq, &sun4i_timer_irq); | 180 | ret = setup_irq(irq, &sun4i_timer_irq); |