diff options
80 files changed, 1575 insertions, 1681 deletions
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 643a9dcdf093..5b6202a825ff 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c | |||
@@ -93,7 +93,7 @@ rtc_timer_interrupt(int irq, void *dev) | |||
93 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | 93 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); |
94 | 94 | ||
95 | /* Don't run the hook for UNUSED or SHUTDOWN. */ | 95 | /* Don't run the hook for UNUSED or SHUTDOWN. */ |
96 | if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC)) | 96 | if (likely(clockevent_state_periodic(ce))) |
97 | ce->event_handler(ce); | 97 | ce->event_handler(ce); |
98 | 98 | ||
99 | if (test_irq_work_pending()) { | 99 | if (test_irq_work_pending()) { |
@@ -104,13 +104,6 @@ rtc_timer_interrupt(int irq, void *dev) | |||
104 | return IRQ_HANDLED; | 104 | return IRQ_HANDLED; |
105 | } | 105 | } |
106 | 106 | ||
107 | static void | ||
108 | rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) | ||
109 | { | ||
110 | /* The mode member of CE is updated in generic code. | ||
111 | Since we only support periodic events, nothing to do. */ | ||
112 | } | ||
113 | |||
114 | static int | 107 | static int |
115 | rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | 108 | rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) |
116 | { | 109 | { |
@@ -129,7 +122,6 @@ init_rtc_clockevent(void) | |||
129 | .features = CLOCK_EVT_FEAT_PERIODIC, | 122 | .features = CLOCK_EVT_FEAT_PERIODIC, |
130 | .rating = 100, | 123 | .rating = 100, |
131 | .cpumask = cpumask_of(cpu), | 124 | .cpumask = cpumask_of(cpu), |
132 | .set_mode = rtc_ce_set_mode, | ||
133 | .set_next_event = rtc_ce_set_next_event, | 125 | .set_next_event = rtc_ce_set_next_event, |
134 | }; | 126 | }; |
135 | 127 | ||
@@ -161,12 +153,12 @@ static struct clocksource qemu_cs = { | |||
161 | * The QEMU alarm as a clock_event_device primitive. | 153 | * The QEMU alarm as a clock_event_device primitive. |
162 | */ | 154 | */ |
163 | 155 | ||
164 | static void | 156 | static int qemu_ce_shutdown(struct clock_event_device *ce) |
165 | qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) | ||
166 | { | 157 | { |
167 | /* The mode member of CE is updated for us in generic code. | 158 | /* The mode member of CE is updated for us in generic code. |
168 | Just make sure that the event is disabled. */ | 159 | Just make sure that the event is disabled. */ |
169 | qemu_set_alarm_abs(0); | 160 | qemu_set_alarm_abs(0); |
161 | return 0; | ||
170 | } | 162 | } |
171 | 163 | ||
172 | static int | 164 | static int |
@@ -197,7 +189,9 @@ init_qemu_clockevent(void) | |||
197 | .features = CLOCK_EVT_FEAT_ONESHOT, | 189 | .features = CLOCK_EVT_FEAT_ONESHOT, |
198 | .rating = 400, | 190 | .rating = 400, |
199 | .cpumask = cpumask_of(cpu), | 191 | .cpumask = cpumask_of(cpu), |
200 | .set_mode = qemu_ce_set_mode, | 192 | .set_state_shutdown = qemu_ce_shutdown, |
193 | .set_state_oneshot = qemu_ce_shutdown, | ||
194 | .tick_resume = qemu_ce_shutdown, | ||
201 | .set_next_event = qemu_ce_set_next_event, | 195 | .set_next_event = qemu_ce_set_next_event, |
202 | }; | 196 | }; |
203 | 197 | ||
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index cb0a4845339e..fb9e95f1b719 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c | |||
@@ -136,44 +136,44 @@ static int bfin_gptmr0_set_next_event(unsigned long cycles, | |||
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | static void bfin_gptmr0_set_mode(enum clock_event_mode mode, | 139 | static int bfin_gptmr0_set_periodic(struct clock_event_device *evt) |
140 | struct clock_event_device *evt) | ||
141 | { | 140 | { |
142 | switch (mode) { | ||
143 | case CLOCK_EVT_MODE_PERIODIC: { | ||
144 | #ifndef CONFIG_BF60x | 141 | #ifndef CONFIG_BF60x |
145 | set_gptimer_config(TIMER0_id, \ | 142 | set_gptimer_config(TIMER0_id, |
146 | TIMER_OUT_DIS | TIMER_IRQ_ENA | \ | 143 | TIMER_OUT_DIS | TIMER_IRQ_ENA | |
147 | TIMER_PERIOD_CNT | TIMER_MODE_PWM); | 144 | TIMER_PERIOD_CNT | TIMER_MODE_PWM); |
148 | #else | 145 | #else |
149 | set_gptimer_config(TIMER0_id, TIMER_OUT_DIS | 146 | set_gptimer_config(TIMER0_id, |
150 | | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER); | 147 | TIMER_OUT_DIS | TIMER_MODE_PWM_CONT | |
148 | TIMER_PULSE_HI | TIMER_IRQ_PER); | ||
151 | #endif | 149 | #endif |
152 | 150 | ||
153 | set_gptimer_period(TIMER0_id, get_sclk() / HZ); | 151 | set_gptimer_period(TIMER0_id, get_sclk() / HZ); |
154 | set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); | 152 | set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); |
155 | enable_gptimers(TIMER0bit); | 153 | enable_gptimers(TIMER0bit); |
156 | break; | 154 | return 0; |
157 | } | 155 | } |
158 | case CLOCK_EVT_MODE_ONESHOT: | 156 | |
159 | disable_gptimers(TIMER0bit); | 157 | static int bfin_gptmr0_set_oneshot(struct clock_event_device *evt) |
158 | { | ||
159 | disable_gptimers(TIMER0bit); | ||
160 | #ifndef CONFIG_BF60x | 160 | #ifndef CONFIG_BF60x |
161 | set_gptimer_config(TIMER0_id, \ | 161 | set_gptimer_config(TIMER0_id, |
162 | TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); | 162 | TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); |
163 | #else | 163 | #else |
164 | set_gptimer_config(TIMER0_id, TIMER_OUT_DIS | TIMER_MODE_PWM | 164 | set_gptimer_config(TIMER0_id, |
165 | | TIMER_PULSE_HI | TIMER_IRQ_WID_DLY); | 165 | TIMER_OUT_DIS | TIMER_MODE_PWM | TIMER_PULSE_HI | |
166 | TIMER_IRQ_WID_DLY); | ||
166 | #endif | 167 | #endif |
167 | 168 | ||
168 | set_gptimer_period(TIMER0_id, 0); | 169 | set_gptimer_period(TIMER0_id, 0); |
169 | break; | 170 | return 0; |
170 | case CLOCK_EVT_MODE_UNUSED: | 171 | } |
171 | case CLOCK_EVT_MODE_SHUTDOWN: | 172 | |
172 | disable_gptimers(TIMER0bit); | 173 | static int bfin_gptmr0_shutdown(struct clock_event_device *evt) |
173 | break; | 174 | { |
174 | case CLOCK_EVT_MODE_RESUME: | 175 | disable_gptimers(TIMER0bit); |
175 | break; | 176 | return 0; |
176 | } | ||
177 | } | 177 | } |
178 | 178 | ||
179 | static void bfin_gptmr0_ack(void) | 179 | static void bfin_gptmr0_ack(void) |
@@ -211,13 +211,16 @@ static struct irqaction gptmr0_irq = { | |||
211 | }; | 211 | }; |
212 | 212 | ||
213 | static struct clock_event_device clockevent_gptmr0 = { | 213 | static struct clock_event_device clockevent_gptmr0 = { |
214 | .name = "bfin_gptimer0", | 214 | .name = "bfin_gptimer0", |
215 | .rating = 300, | 215 | .rating = 300, |
216 | .irq = IRQ_TIMER0, | 216 | .irq = IRQ_TIMER0, |
217 | .shift = 32, | 217 | .shift = 32, |
218 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 218 | .features = CLOCK_EVT_FEAT_PERIODIC | |
219 | .set_next_event = bfin_gptmr0_set_next_event, | 219 | CLOCK_EVT_FEAT_ONESHOT, |
220 | .set_mode = bfin_gptmr0_set_mode, | 220 | .set_next_event = bfin_gptmr0_set_next_event, |
221 | .set_state_shutdown = bfin_gptmr0_shutdown, | ||
222 | .set_state_periodic = bfin_gptmr0_set_periodic, | ||
223 | .set_state_oneshot = bfin_gptmr0_set_oneshot, | ||
221 | }; | 224 | }; |
222 | 225 | ||
223 | static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) | 226 | static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) |
@@ -250,36 +253,35 @@ static int bfin_coretmr_set_next_event(unsigned long cycles, | |||
250 | return 0; | 253 | return 0; |
251 | } | 254 | } |
252 | 255 | ||
253 | static void bfin_coretmr_set_mode(enum clock_event_mode mode, | 256 | static int bfin_coretmr_set_periodic(struct clock_event_device *evt) |
254 | struct clock_event_device *evt) | ||
255 | { | 257 | { |
256 | switch (mode) { | 258 | unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); |
257 | case CLOCK_EVT_MODE_PERIODIC: { | 259 | |
258 | unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); | 260 | bfin_write_TCNTL(TMPWR); |
259 | bfin_write_TCNTL(TMPWR); | 261 | CSYNC(); |
260 | CSYNC(); | 262 | bfin_write_TSCALE(TIME_SCALE - 1); |
261 | bfin_write_TSCALE(TIME_SCALE - 1); | 263 | bfin_write_TPERIOD(tcount); |
262 | bfin_write_TPERIOD(tcount); | 264 | bfin_write_TCOUNT(tcount); |
263 | bfin_write_TCOUNT(tcount); | 265 | CSYNC(); |
264 | CSYNC(); | 266 | bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); |
265 | bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); | 267 | return 0; |
266 | break; | 268 | } |
267 | } | 269 | |
268 | case CLOCK_EVT_MODE_ONESHOT: | 270 | static int bfin_coretmr_set_oneshot(struct clock_event_device *evt) |
269 | bfin_write_TCNTL(TMPWR); | 271 | { |
270 | CSYNC(); | 272 | bfin_write_TCNTL(TMPWR); |
271 | bfin_write_TSCALE(TIME_SCALE - 1); | 273 | CSYNC(); |
272 | bfin_write_TPERIOD(0); | 274 | bfin_write_TSCALE(TIME_SCALE - 1); |
273 | bfin_write_TCOUNT(0); | 275 | bfin_write_TPERIOD(0); |
274 | break; | 276 | bfin_write_TCOUNT(0); |
275 | case CLOCK_EVT_MODE_UNUSED: | 277 | return 0; |
276 | case CLOCK_EVT_MODE_SHUTDOWN: | 278 | } |
277 | bfin_write_TCNTL(0); | 279 | |
278 | CSYNC(); | 280 | static int bfin_coretmr_shutdown(struct clock_event_device *evt) |
279 | break; | 281 | { |
280 | case CLOCK_EVT_MODE_RESUME: | 282 | bfin_write_TCNTL(0); |
281 | break; | 283 | CSYNC(); |
282 | } | 284 | return 0; |
283 | } | 285 | } |
284 | 286 | ||
285 | void bfin_coretmr_init(void) | 287 | void bfin_coretmr_init(void) |
@@ -335,7 +337,9 @@ void bfin_coretmr_clockevent_init(void) | |||
335 | evt->shift = 32; | 337 | evt->shift = 32; |
336 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 338 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
337 | evt->set_next_event = bfin_coretmr_set_next_event; | 339 | evt->set_next_event = bfin_coretmr_set_next_event; |
338 | evt->set_mode = bfin_coretmr_set_mode; | 340 | evt->set_state_shutdown = bfin_coretmr_shutdown; |
341 | evt->set_state_periodic = bfin_coretmr_set_periodic; | ||
342 | evt->set_state_oneshot = bfin_coretmr_set_oneshot; | ||
339 | 343 | ||
340 | clock_tick = get_cclk() / TIME_SCALE; | 344 | clock_tick = get_cclk() / TIME_SCALE; |
341 | evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); | 345 | evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); |
diff --git a/arch/c6x/platforms/timer64.c b/arch/c6x/platforms/timer64.c index 3c73d74a4674..c19901e5f055 100644 --- a/arch/c6x/platforms/timer64.c +++ b/arch/c6x/platforms/timer64.c | |||
@@ -126,35 +126,37 @@ static int next_event(unsigned long delta, | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static void set_clock_mode(enum clock_event_mode mode, | 129 | static int set_periodic(struct clock_event_device *evt) |
130 | struct clock_event_device *evt) | ||
131 | { | 130 | { |
132 | switch (mode) { | 131 | timer64_enable(); |
133 | case CLOCK_EVT_MODE_PERIODIC: | 132 | timer64_mode = TIMER64_MODE_PERIODIC; |
134 | timer64_enable(); | 133 | timer64_config(TIMER64_RATE / HZ); |
135 | timer64_mode = TIMER64_MODE_PERIODIC; | 134 | return 0; |
136 | timer64_config(TIMER64_RATE / HZ); | 135 | } |
137 | break; | 136 | |
138 | case CLOCK_EVT_MODE_ONESHOT: | 137 | static int set_oneshot(struct clock_event_device *evt) |
139 | timer64_enable(); | 138 | { |
140 | timer64_mode = TIMER64_MODE_ONE_SHOT; | 139 | timer64_enable(); |
141 | break; | 140 | timer64_mode = TIMER64_MODE_ONE_SHOT; |
142 | case CLOCK_EVT_MODE_UNUSED: | 141 | return 0; |
143 | case CLOCK_EVT_MODE_SHUTDOWN: | 142 | } |
144 | timer64_mode = TIMER64_MODE_DISABLED; | 143 | |
145 | timer64_disable(); | 144 | static int shutdown(struct clock_event_device *evt) |
146 | break; | 145 | { |
147 | case CLOCK_EVT_MODE_RESUME: | 146 | timer64_mode = TIMER64_MODE_DISABLED; |
148 | break; | 147 | timer64_disable(); |
149 | } | 148 | return 0; |
150 | } | 149 | } |
151 | 150 | ||
152 | static struct clock_event_device t64_clockevent_device = { | 151 | static struct clock_event_device t64_clockevent_device = { |
153 | .name = "TIMER64_EVT32_TIMER", | 152 | .name = "TIMER64_EVT32_TIMER", |
154 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 153 | .features = CLOCK_EVT_FEAT_ONESHOT | |
155 | .rating = 200, | 154 | CLOCK_EVT_FEAT_PERIODIC, |
156 | .set_mode = set_clock_mode, | 155 | .rating = 200, |
157 | .set_next_event = next_event, | 156 | .set_state_shutdown = shutdown, |
157 | .set_state_periodic = set_periodic, | ||
158 | .set_state_oneshot = set_oneshot, | ||
159 | .set_next_event = next_event, | ||
158 | }; | 160 | }; |
159 | 161 | ||
160 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 162 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c index 4fce9f1f7cc0..d2a84407654a 100644 --- a/arch/cris/arch-v32/kernel/time.c +++ b/arch/cris/arch-v32/kernel/time.c | |||
@@ -172,8 +172,7 @@ void handle_watchdog_bite(struct pt_regs *regs) | |||
172 | extern void cris_profile_sample(struct pt_regs *regs); | 172 | extern void cris_profile_sample(struct pt_regs *regs); |
173 | static void __iomem *timer_base; | 173 | static void __iomem *timer_base; |
174 | 174 | ||
175 | static void crisv32_clkevt_mode(enum clock_event_mode mode, | 175 | static int crisv32_clkevt_switch_state(struct clock_event_device *dev) |
176 | struct clock_event_device *dev) | ||
177 | { | 176 | { |
178 | reg_timer_rw_tmr0_ctrl ctrl = { | 177 | reg_timer_rw_tmr0_ctrl ctrl = { |
179 | .op = regk_timer_hold, | 178 | .op = regk_timer_hold, |
@@ -181,6 +180,7 @@ static void crisv32_clkevt_mode(enum clock_event_mode mode, | |||
181 | }; | 180 | }; |
182 | 181 | ||
183 | REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); | 182 | REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); |
183 | return 0; | ||
184 | } | 184 | } |
185 | 185 | ||
186 | static int crisv32_clkevt_next_event(unsigned long evt, | 186 | static int crisv32_clkevt_next_event(unsigned long evt, |
@@ -231,7 +231,9 @@ static struct clock_event_device crisv32_clockevent = { | |||
231 | .name = "crisv32-timer", | 231 | .name = "crisv32-timer", |
232 | .rating = 300, | 232 | .rating = 300, |
233 | .features = CLOCK_EVT_FEAT_ONESHOT, | 233 | .features = CLOCK_EVT_FEAT_ONESHOT, |
234 | .set_mode = crisv32_clkevt_mode, | 234 | .set_state_oneshot = crisv32_clkevt_switch_state, |
235 | .set_state_shutdown = crisv32_clkevt_switch_state, | ||
236 | .tick_resume = crisv32_clkevt_switch_state, | ||
235 | .set_next_event = crisv32_clkevt_next_event, | 237 | .set_next_event = crisv32_clkevt_next_event, |
236 | }; | 238 | }; |
237 | 239 | ||
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index c8977450e28c..67e2ef48d2d0 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
@@ -122,37 +122,29 @@ static int xilinx_timer_set_next_event(unsigned long delta, | |||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | 124 | ||
125 | static void xilinx_timer_set_mode(enum clock_event_mode mode, | 125 | static int xilinx_timer_shutdown(struct clock_event_device *evt) |
126 | struct clock_event_device *evt) | ||
127 | { | 126 | { |
128 | switch (mode) { | 127 | pr_info("%s\n", __func__); |
129 | case CLOCK_EVT_MODE_PERIODIC: | 128 | xilinx_timer0_stop(); |
130 | pr_info("%s: periodic\n", __func__); | 129 | return 0; |
131 | xilinx_timer0_start_periodic(freq_div_hz); | 130 | } |
132 | break; | 131 | |
133 | case CLOCK_EVT_MODE_ONESHOT: | 132 | static int xilinx_timer_set_periodic(struct clock_event_device *evt) |
134 | pr_info("%s: oneshot\n", __func__); | 133 | { |
135 | break; | 134 | pr_info("%s\n", __func__); |
136 | case CLOCK_EVT_MODE_UNUSED: | 135 | xilinx_timer0_start_periodic(freq_div_hz); |
137 | pr_info("%s: unused\n", __func__); | 136 | return 0; |
138 | break; | ||
139 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
140 | pr_info("%s: shutdown\n", __func__); | ||
141 | xilinx_timer0_stop(); | ||
142 | break; | ||
143 | case CLOCK_EVT_MODE_RESUME: | ||
144 | pr_info("%s: resume\n", __func__); | ||
145 | break; | ||
146 | } | ||
147 | } | 137 | } |
148 | 138 | ||
149 | static struct clock_event_device clockevent_xilinx_timer = { | 139 | static struct clock_event_device clockevent_xilinx_timer = { |
150 | .name = "xilinx_clockevent", | 140 | .name = "xilinx_clockevent", |
151 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 141 | .features = CLOCK_EVT_FEAT_ONESHOT | |
152 | .shift = 8, | 142 | CLOCK_EVT_FEAT_PERIODIC, |
153 | .rating = 300, | 143 | .shift = 8, |
154 | .set_next_event = xilinx_timer_set_next_event, | 144 | .rating = 300, |
155 | .set_mode = xilinx_timer_set_mode, | 145 | .set_next_event = xilinx_timer_set_next_event, |
146 | .set_state_shutdown = xilinx_timer_shutdown, | ||
147 | .set_state_periodic = xilinx_timer_set_periodic, | ||
156 | }; | 148 | }; |
157 | 149 | ||
158 | static inline void timer_ack(void) | 150 | static inline void timer_ack(void) |
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index 60f64ca1752a..3aae9f5a98aa 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c | |||
@@ -41,12 +41,6 @@ static int next_event(unsigned long delta, | |||
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static void set_clock_mode(enum clock_event_mode mode, | ||
45 | struct clock_event_device *evt) | ||
46 | { | ||
47 | /* Nothing to do ... */ | ||
48 | } | ||
49 | |||
50 | static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device); | 44 | static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device); |
51 | static DEFINE_PER_CPU(struct irqaction, timer_irq); | 45 | static DEFINE_PER_CPU(struct irqaction, timer_irq); |
52 | 46 | ||
@@ -108,7 +102,6 @@ int __init init_clockevents(void) | |||
108 | 102 | ||
109 | cd->rating = 200; | 103 | cd->rating = 200; |
110 | cd->cpumask = cpumask_of(smp_processor_id()); | 104 | cd->cpumask = cpumask_of(smp_processor_id()); |
111 | cd->set_mode = set_clock_mode; | ||
112 | cd->event_handler = event_handler; | 105 | cd->event_handler = event_handler; |
113 | cd->set_next_event = next_event; | 106 | cd->set_next_event = next_event; |
114 | 107 | ||
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c index 7c52e9494a8d..50e970183dcd 100644 --- a/arch/openrisc/kernel/time.c +++ b/arch/openrisc/kernel/time.c | |||
@@ -48,29 +48,6 @@ static int openrisc_timer_set_next_event(unsigned long delta, | |||
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static void openrisc_timer_set_mode(enum clock_event_mode mode, | ||
52 | struct clock_event_device *evt) | ||
53 | { | ||
54 | switch (mode) { | ||
55 | case CLOCK_EVT_MODE_PERIODIC: | ||
56 | pr_debug(KERN_INFO "%s: periodic\n", __func__); | ||
57 | BUG(); | ||
58 | break; | ||
59 | case CLOCK_EVT_MODE_ONESHOT: | ||
60 | pr_debug(KERN_INFO "%s: oneshot\n", __func__); | ||
61 | break; | ||
62 | case CLOCK_EVT_MODE_UNUSED: | ||
63 | pr_debug(KERN_INFO "%s: unused\n", __func__); | ||
64 | break; | ||
65 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
66 | pr_debug(KERN_INFO "%s: shutdown\n", __func__); | ||
67 | break; | ||
68 | case CLOCK_EVT_MODE_RESUME: | ||
69 | pr_debug(KERN_INFO "%s: resume\n", __func__); | ||
70 | break; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /* This is the clock event device based on the OR1K tick timer. | 51 | /* This is the clock event device based on the OR1K tick timer. |
75 | * As the timer is being used as a continuous clock-source (required for HR | 52 | * As the timer is being used as a continuous clock-source (required for HR |
76 | * timers) we cannot enable the PERIODIC feature. The tick timer can run using | 53 | * timers) we cannot enable the PERIODIC feature. The tick timer can run using |
@@ -82,7 +59,6 @@ static struct clock_event_device clockevent_openrisc_timer = { | |||
82 | .features = CLOCK_EVT_FEAT_ONESHOT, | 59 | .features = CLOCK_EVT_FEAT_ONESHOT, |
83 | .rating = 300, | 60 | .rating = 300, |
84 | .set_next_event = openrisc_timer_set_next_event, | 61 | .set_next_event = openrisc_timer_set_next_event, |
85 | .set_mode = openrisc_timer_set_mode, | ||
86 | }; | 62 | }; |
87 | 63 | ||
88 | static inline void timer_ack(void) | 64 | static inline void timer_ack(void) |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 43922509a483..1be1092c7204 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -99,16 +99,17 @@ static struct clocksource clocksource_timebase = { | |||
99 | 99 | ||
100 | static int decrementer_set_next_event(unsigned long evt, | 100 | static int decrementer_set_next_event(unsigned long evt, |
101 | struct clock_event_device *dev); | 101 | struct clock_event_device *dev); |
102 | static void decrementer_set_mode(enum clock_event_mode mode, | 102 | static int decrementer_shutdown(struct clock_event_device *evt); |
103 | struct clock_event_device *dev); | ||
104 | 103 | ||
105 | struct clock_event_device decrementer_clockevent = { | 104 | struct clock_event_device decrementer_clockevent = { |
106 | .name = "decrementer", | 105 | .name = "decrementer", |
107 | .rating = 200, | 106 | .rating = 200, |
108 | .irq = 0, | 107 | .irq = 0, |
109 | .set_next_event = decrementer_set_next_event, | 108 | .set_next_event = decrementer_set_next_event, |
110 | .set_mode = decrementer_set_mode, | 109 | .set_state_shutdown = decrementer_shutdown, |
111 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP, | 110 | .tick_resume = decrementer_shutdown, |
111 | .features = CLOCK_EVT_FEAT_ONESHOT | | ||
112 | CLOCK_EVT_FEAT_C3STOP, | ||
112 | }; | 113 | }; |
113 | EXPORT_SYMBOL(decrementer_clockevent); | 114 | EXPORT_SYMBOL(decrementer_clockevent); |
114 | 115 | ||
@@ -862,11 +863,10 @@ static int decrementer_set_next_event(unsigned long evt, | |||
862 | return 0; | 863 | return 0; |
863 | } | 864 | } |
864 | 865 | ||
865 | static void decrementer_set_mode(enum clock_event_mode mode, | 866 | static int decrementer_shutdown(struct clock_event_device *dev) |
866 | struct clock_event_device *dev) | ||
867 | { | 867 | { |
868 | if (mode != CLOCK_EVT_MODE_ONESHOT) | 868 | decrementer_set_next_event(DECREMENTER_MAX, dev); |
869 | decrementer_set_next_event(DECREMENTER_MAX, dev); | 869 | return 0; |
870 | } | 870 | } |
871 | 871 | ||
872 | /* Interrupt handler for the timer broadcast IPI */ | 872 | /* Interrupt handler for the timer broadcast IPI */ |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 627887b075a7..52524b9083c3 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -120,11 +120,6 @@ static int s390_next_event(unsigned long delta, | |||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void s390_set_mode(enum clock_event_mode mode, | ||
124 | struct clock_event_device *evt) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | /* | 123 | /* |
129 | * Set up lowcore and control register of the current cpu to | 124 | * Set up lowcore and control register of the current cpu to |
130 | * enable TOD clock and clock comparator interrupts. | 125 | * enable TOD clock and clock comparator interrupts. |
@@ -148,7 +143,6 @@ void init_cpu_timer(void) | |||
148 | cd->rating = 400; | 143 | cd->rating = 400; |
149 | cd->cpumask = cpumask_of(cpu); | 144 | cd->cpumask = cpumask_of(cpu); |
150 | cd->set_next_event = s390_next_event; | 145 | cd->set_next_event = s390_next_event; |
151 | cd->set_mode = s390_set_mode; | ||
152 | 146 | ||
153 | clockevents_register_device(cd); | 147 | clockevents_register_device(cd); |
154 | 148 | ||
diff --git a/arch/score/kernel/time.c b/arch/score/kernel/time.c index 24770cd9b473..679b8d7b0350 100644 --- a/arch/score/kernel/time.c +++ b/arch/score/kernel/time.c | |||
@@ -55,31 +55,20 @@ static int score_timer_set_next_event(unsigned long delta, | |||
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | static void score_timer_set_mode(enum clock_event_mode mode, | 58 | static int score_timer_set_periodic(struct clock_event_device *evt) |
59 | struct clock_event_device *evdev) | ||
60 | { | 59 | { |
61 | switch (mode) { | 60 | outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL); |
62 | case CLOCK_EVT_MODE_PERIODIC: | 61 | outl(SYSTEM_CLOCK / HZ, P_TIMER0_PRELOAD); |
63 | outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL); | 62 | outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL); |
64 | outl(SYSTEM_CLOCK/HZ, P_TIMER0_PRELOAD); | 63 | return 0; |
65 | outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL); | ||
66 | break; | ||
67 | case CLOCK_EVT_MODE_ONESHOT: | ||
68 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
69 | case CLOCK_EVT_MODE_RESUME: | ||
70 | case CLOCK_EVT_MODE_UNUSED: | ||
71 | break; | ||
72 | default: | ||
73 | BUG(); | ||
74 | } | ||
75 | } | 64 | } |
76 | 65 | ||
77 | static struct clock_event_device score_clockevent = { | 66 | static struct clock_event_device score_clockevent = { |
78 | .name = "score_clockevent", | 67 | .name = "score_clockevent", |
79 | .features = CLOCK_EVT_FEAT_PERIODIC, | 68 | .features = CLOCK_EVT_FEAT_PERIODIC, |
80 | .shift = 16, | 69 | .shift = 16, |
81 | .set_next_event = score_timer_set_next_event, | 70 | .set_next_event = score_timer_set_next_event, |
82 | .set_mode = score_timer_set_mode, | 71 | .set_state_periodic = score_timer_set_periodic, |
83 | }; | 72 | }; |
84 | 73 | ||
85 | void __init time_init(void) | 74 | void __init time_init(void) |
diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c index b880a7e2ace7..cbb7d4636ec0 100644 --- a/arch/sh/kernel/localtimer.c +++ b/arch/sh/kernel/localtimer.c | |||
@@ -39,11 +39,6 @@ void local_timer_interrupt(void) | |||
39 | irq_exit(); | 39 | irq_exit(); |
40 | } | 40 | } |
41 | 41 | ||
42 | static void dummy_timer_set_mode(enum clock_event_mode mode, | ||
43 | struct clock_event_device *clk) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | void local_timer_setup(unsigned int cpu) | 42 | void local_timer_setup(unsigned int cpu) |
48 | { | 43 | { |
49 | struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); | 44 | struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); |
@@ -54,7 +49,6 @@ void local_timer_setup(unsigned int cpu) | |||
54 | CLOCK_EVT_FEAT_DUMMY; | 49 | CLOCK_EVT_FEAT_DUMMY; |
55 | clk->rating = 400; | 50 | clk->rating = 400; |
56 | clk->mult = 1; | 51 | clk->mult = 1; |
57 | clk->set_mode = dummy_timer_set_mode; | ||
58 | clk->broadcast = smp_timer_broadcast; | 52 | clk->broadcast = smp_timer_broadcast; |
59 | clk->cpumask = cpumask_of(cpu); | 53 | clk->cpumask = cpumask_of(cpu); |
60 | 54 | ||
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index d3408e72d20c..278c40abce82 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
@@ -247,7 +247,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
247 | 247 | ||
248 | ce = &per_cpu(sparc32_clockevent, cpu); | 248 | ce = &per_cpu(sparc32_clockevent, cpu); |
249 | 249 | ||
250 | if (ce->mode & CLOCK_EVT_MODE_PERIODIC) | 250 | if (clockevent_state_periodic(ce)) |
251 | sun4m_clear_profile_irq(cpu); | 251 | sun4m_clear_profile_irq(cpu); |
252 | else | 252 | else |
253 | sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */ | 253 | sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */ |
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index c9692f387cee..1affabc96b08 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c | |||
@@ -101,21 +101,18 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id) | |||
101 | return IRQ_HANDLED; | 101 | return IRQ_HANDLED; |
102 | } | 102 | } |
103 | 103 | ||
104 | static void timer_ce_set_mode(enum clock_event_mode mode, | 104 | static int timer_ce_shutdown(struct clock_event_device *evt) |
105 | struct clock_event_device *evt) | ||
106 | { | 105 | { |
107 | switch (mode) { | 106 | timer_ce_enabled = 0; |
108 | case CLOCK_EVT_MODE_PERIODIC: | 107 | smp_mb(); |
109 | case CLOCK_EVT_MODE_RESUME: | 108 | return 0; |
110 | timer_ce_enabled = 1; | 109 | } |
111 | break; | 110 | |
112 | case CLOCK_EVT_MODE_SHUTDOWN: | 111 | static int timer_ce_set_periodic(struct clock_event_device *evt) |
113 | timer_ce_enabled = 0; | 112 | { |
114 | break; | 113 | timer_ce_enabled = 1; |
115 | default: | ||
116 | break; | ||
117 | } | ||
118 | smp_mb(); | 114 | smp_mb(); |
115 | return 0; | ||
119 | } | 116 | } |
120 | 117 | ||
121 | static __init void setup_timer_ce(void) | 118 | static __init void setup_timer_ce(void) |
@@ -127,7 +124,9 @@ static __init void setup_timer_ce(void) | |||
127 | ce->name = "timer_ce"; | 124 | ce->name = "timer_ce"; |
128 | ce->rating = 100; | 125 | ce->rating = 100; |
129 | ce->features = CLOCK_EVT_FEAT_PERIODIC; | 126 | ce->features = CLOCK_EVT_FEAT_PERIODIC; |
130 | ce->set_mode = timer_ce_set_mode; | 127 | ce->set_state_shutdown = timer_ce_shutdown; |
128 | ce->set_state_periodic = timer_ce_set_periodic; | ||
129 | ce->tick_resume = timer_ce_set_periodic; | ||
131 | ce->cpumask = cpu_possible_mask; | 130 | ce->cpumask = cpu_possible_mask; |
132 | ce->shift = 32; | 131 | ce->shift = 32; |
133 | ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, | 132 | ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, |
@@ -183,24 +182,20 @@ static __init int setup_timer_cs(void) | |||
183 | } | 182 | } |
184 | 183 | ||
185 | #ifdef CONFIG_SMP | 184 | #ifdef CONFIG_SMP |
186 | static void percpu_ce_setup(enum clock_event_mode mode, | 185 | static int percpu_ce_shutdown(struct clock_event_device *evt) |
187 | struct clock_event_device *evt) | ||
188 | { | 186 | { |
189 | int cpu = cpumask_first(evt->cpumask); | 187 | int cpu = cpumask_first(evt->cpumask); |
190 | 188 | ||
191 | switch (mode) { | 189 | sparc_config.load_profile_irq(cpu, 0); |
192 | case CLOCK_EVT_MODE_PERIODIC: | 190 | return 0; |
193 | sparc_config.load_profile_irq(cpu, | 191 | } |
194 | SBUS_CLOCK_RATE / HZ); | 192 | |
195 | break; | 193 | static int percpu_ce_set_periodic(struct clock_event_device *evt) |
196 | case CLOCK_EVT_MODE_ONESHOT: | 194 | { |
197 | case CLOCK_EVT_MODE_SHUTDOWN: | 195 | int cpu = cpumask_first(evt->cpumask); |
198 | case CLOCK_EVT_MODE_UNUSED: | 196 | |
199 | sparc_config.load_profile_irq(cpu, 0); | 197 | sparc_config.load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ); |
200 | break; | 198 | return 0; |
201 | default: | ||
202 | break; | ||
203 | } | ||
204 | } | 199 | } |
205 | 200 | ||
206 | static int percpu_ce_set_next_event(unsigned long delta, | 201 | static int percpu_ce_set_next_event(unsigned long delta, |
@@ -224,7 +219,9 @@ void register_percpu_ce(int cpu) | |||
224 | ce->name = "percpu_ce"; | 219 | ce->name = "percpu_ce"; |
225 | ce->rating = 200; | 220 | ce->rating = 200; |
226 | ce->features = features; | 221 | ce->features = features; |
227 | ce->set_mode = percpu_ce_setup; | 222 | ce->set_state_shutdown = percpu_ce_shutdown; |
223 | ce->set_state_periodic = percpu_ce_set_periodic; | ||
224 | ce->set_state_oneshot = percpu_ce_shutdown; | ||
228 | ce->set_next_event = percpu_ce_set_next_event; | 225 | ce->set_next_event = percpu_ce_set_next_event; |
229 | ce->cpumask = cpumask_of(cpu); | 226 | ce->cpumask = cpumask_of(cpu); |
230 | ce->shift = 32; | 227 | ce->shift = 32; |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 2e6035c0a8ca..c69b21e51efc 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -674,32 +674,19 @@ static int sparc64_next_event(unsigned long delta, | |||
674 | return tick_ops->add_compare(delta) ? -ETIME : 0; | 674 | return tick_ops->add_compare(delta) ? -ETIME : 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | static void sparc64_timer_setup(enum clock_event_mode mode, | 677 | static int sparc64_timer_shutdown(struct clock_event_device *evt) |
678 | struct clock_event_device *evt) | 678 | { |
679 | { | 679 | tick_ops->disable_irq(); |
680 | switch (mode) { | 680 | return 0; |
681 | case CLOCK_EVT_MODE_ONESHOT: | ||
682 | case CLOCK_EVT_MODE_RESUME: | ||
683 | break; | ||
684 | |||
685 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
686 | tick_ops->disable_irq(); | ||
687 | break; | ||
688 | |||
689 | case CLOCK_EVT_MODE_PERIODIC: | ||
690 | case CLOCK_EVT_MODE_UNUSED: | ||
691 | WARN_ON(1); | ||
692 | break; | ||
693 | } | ||
694 | } | 681 | } |
695 | 682 | ||
696 | static struct clock_event_device sparc64_clockevent = { | 683 | static struct clock_event_device sparc64_clockevent = { |
697 | .features = CLOCK_EVT_FEAT_ONESHOT, | 684 | .features = CLOCK_EVT_FEAT_ONESHOT, |
698 | .set_mode = sparc64_timer_setup, | 685 | .set_state_shutdown = sparc64_timer_shutdown, |
699 | .set_next_event = sparc64_next_event, | 686 | .set_next_event = sparc64_next_event, |
700 | .rating = 100, | 687 | .rating = 100, |
701 | .shift = 30, | 688 | .shift = 30, |
702 | .irq = -1, | 689 | .irq = -1, |
703 | }; | 690 | }; |
704 | static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); | 691 | static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); |
705 | 692 | ||
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 117568d4f64a..5af441efb377 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -22,23 +22,16 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | |||
22 | local_irq_restore(flags); | 22 | local_irq_restore(flags); |
23 | } | 23 | } |
24 | 24 | ||
25 | static void itimer_set_mode(enum clock_event_mode mode, | 25 | static int itimer_shutdown(struct clock_event_device *evt) |
26 | struct clock_event_device *evt) | ||
27 | { | 26 | { |
28 | switch (mode) { | 27 | disable_timer(); |
29 | case CLOCK_EVT_MODE_PERIODIC: | 28 | return 0; |
30 | set_interval(); | 29 | } |
31 | break; | 30 | |
32 | 31 | static int itimer_set_periodic(struct clock_event_device *evt) | |
33 | case CLOCK_EVT_MODE_SHUTDOWN: | 32 | { |
34 | case CLOCK_EVT_MODE_UNUSED: | 33 | set_interval(); |
35 | case CLOCK_EVT_MODE_ONESHOT: | 34 | return 0; |
36 | disable_timer(); | ||
37 | break; | ||
38 | |||
39 | case CLOCK_EVT_MODE_RESUME: | ||
40 | break; | ||
41 | } | ||
42 | } | 35 | } |
43 | 36 | ||
44 | static int itimer_next_event(unsigned long delta, | 37 | static int itimer_next_event(unsigned long delta, |
@@ -48,14 +41,17 @@ static int itimer_next_event(unsigned long delta, | |||
48 | } | 41 | } |
49 | 42 | ||
50 | static struct clock_event_device itimer_clockevent = { | 43 | static struct clock_event_device itimer_clockevent = { |
51 | .name = "itimer", | 44 | .name = "itimer", |
52 | .rating = 250, | 45 | .rating = 250, |
53 | .cpumask = cpu_all_mask, | 46 | .cpumask = cpu_all_mask, |
54 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 47 | .features = CLOCK_EVT_FEAT_PERIODIC | |
55 | .set_mode = itimer_set_mode, | 48 | CLOCK_EVT_FEAT_ONESHOT, |
56 | .set_next_event = itimer_next_event, | 49 | .set_state_shutdown = itimer_shutdown, |
57 | .shift = 32, | 50 | .set_state_periodic = itimer_set_periodic, |
58 | .irq = 0, | 51 | .set_state_oneshot = itimer_shutdown, |
52 | .set_next_event = itimer_next_event, | ||
53 | .shift = 32, | ||
54 | .irq = 0, | ||
59 | }; | 55 | }; |
60 | 56 | ||
61 | static irqreturn_t um_timer(int irq, void *dev) | 57 | static irqreturn_t um_timer(int irq, void *dev) |
diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c index d3824b2ff644..ac4c5449bb88 100644 --- a/arch/unicore32/kernel/time.c +++ b/arch/unicore32/kernel/time.c | |||
@@ -46,29 +46,20 @@ puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) | |||
46 | return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; | 46 | return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static void | 49 | static int puv3_osmr0_shutdown(struct clock_event_device *evt) |
50 | puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) | ||
51 | { | 50 | { |
52 | switch (mode) { | 51 | writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER); |
53 | case CLOCK_EVT_MODE_ONESHOT: | 52 | writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR); |
54 | case CLOCK_EVT_MODE_UNUSED: | 53 | return 0; |
55 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
56 | writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER); | ||
57 | writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR); | ||
58 | break; | ||
59 | |||
60 | case CLOCK_EVT_MODE_RESUME: | ||
61 | case CLOCK_EVT_MODE_PERIODIC: | ||
62 | break; | ||
63 | } | ||
64 | } | 54 | } |
65 | 55 | ||
66 | static struct clock_event_device ckevt_puv3_osmr0 = { | 56 | static struct clock_event_device ckevt_puv3_osmr0 = { |
67 | .name = "osmr0", | 57 | .name = "osmr0", |
68 | .features = CLOCK_EVT_FEAT_ONESHOT, | 58 | .features = CLOCK_EVT_FEAT_ONESHOT, |
69 | .rating = 200, | 59 | .rating = 200, |
70 | .set_next_event = puv3_osmr0_set_next_event, | 60 | .set_next_event = puv3_osmr0_set_next_event, |
71 | .set_mode = puv3_osmr0_set_mode, | 61 | .set_state_shutdown = puv3_osmr0_shutdown, |
62 | .set_state_oneshot = puv3_osmr0_shutdown, | ||
72 | }; | 63 | }; |
73 | 64 | ||
74 | static cycle_t puv3_read_oscr(struct clocksource *cs) | 65 | static cycle_t puv3_read_oscr(struct clocksource *cs) |
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index f2b96de3c7c1..efb82f07b29c 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c | |||
@@ -34,7 +34,7 @@ static int __init init_pit_clocksource(void) | |||
34 | * - when local APIC timer is active (PIT is switched off) | 34 | * - when local APIC timer is active (PIT is switched off) |
35 | */ | 35 | */ |
36 | if (num_possible_cpus() > 1 || is_hpet_enabled() || | 36 | if (num_possible_cpus() > 1 || is_hpet_enabled() || |
37 | i8253_clockevent.mode != CLOCK_EVT_MODE_PERIODIC) | 37 | !clockevent_state_periodic(&i8253_clockevent)) |
38 | return 0; | 38 | return 0; |
39 | 39 | ||
40 | return clocksource_i8253_init(); | 40 | return clocksource_i8253_init(); |
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 2a1823de69cc..b97767dbc7c8 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -52,8 +52,6 @@ static struct clocksource ccount_clocksource = { | |||
52 | 52 | ||
53 | static int ccount_timer_set_next_event(unsigned long delta, | 53 | static int ccount_timer_set_next_event(unsigned long delta, |
54 | struct clock_event_device *dev); | 54 | struct clock_event_device *dev); |
55 | static void ccount_timer_set_mode(enum clock_event_mode mode, | ||
56 | struct clock_event_device *evt); | ||
57 | struct ccount_timer { | 55 | struct ccount_timer { |
58 | struct clock_event_device evt; | 56 | struct clock_event_device evt; |
59 | int irq_enabled; | 57 | int irq_enabled; |
@@ -77,35 +75,34 @@ static int ccount_timer_set_next_event(unsigned long delta, | |||
77 | return ret; | 75 | return ret; |
78 | } | 76 | } |
79 | 77 | ||
80 | static void ccount_timer_set_mode(enum clock_event_mode mode, | 78 | /* |
81 | struct clock_event_device *evt) | 79 | * There is no way to disable the timer interrupt at the device level, |
80 | * only at the intenable register itself. Since enable_irq/disable_irq | ||
81 | * calls are nested, we need to make sure that these calls are | ||
82 | * balanced. | ||
83 | */ | ||
84 | static int ccount_timer_shutdown(struct clock_event_device *evt) | ||
85 | { | ||
86 | struct ccount_timer *timer = | ||
87 | container_of(evt, struct ccount_timer, evt); | ||
88 | |||
89 | if (timer->irq_enabled) { | ||
90 | disable_irq(evt->irq); | ||
91 | timer->irq_enabled = 0; | ||
92 | } | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int ccount_timer_set_oneshot(struct clock_event_device *evt) | ||
82 | { | 97 | { |
83 | struct ccount_timer *timer = | 98 | struct ccount_timer *timer = |
84 | container_of(evt, struct ccount_timer, evt); | 99 | container_of(evt, struct ccount_timer, evt); |
85 | 100 | ||
86 | /* | 101 | if (!timer->irq_enabled) { |
87 | * There is no way to disable the timer interrupt at the device level, | 102 | enable_irq(evt->irq); |
88 | * only at the intenable register itself. Since enable_irq/disable_irq | 103 | timer->irq_enabled = 1; |
89 | * calls are nested, we need to make sure that these calls are | ||
90 | * balanced. | ||
91 | */ | ||
92 | switch (mode) { | ||
93 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
94 | case CLOCK_EVT_MODE_UNUSED: | ||
95 | if (timer->irq_enabled) { | ||
96 | disable_irq(evt->irq); | ||
97 | timer->irq_enabled = 0; | ||
98 | } | ||
99 | break; | ||
100 | case CLOCK_EVT_MODE_RESUME: | ||
101 | case CLOCK_EVT_MODE_ONESHOT: | ||
102 | if (!timer->irq_enabled) { | ||
103 | enable_irq(evt->irq); | ||
104 | timer->irq_enabled = 1; | ||
105 | } | ||
106 | default: | ||
107 | break; | ||
108 | } | 104 | } |
105 | return 0; | ||
109 | } | 106 | } |
110 | 107 | ||
111 | static irqreturn_t timer_interrupt(int irq, void *dev_id); | 108 | static irqreturn_t timer_interrupt(int irq, void *dev_id); |
@@ -126,7 +123,9 @@ void local_timer_setup(unsigned cpu) | |||
126 | clockevent->features = CLOCK_EVT_FEAT_ONESHOT; | 123 | clockevent->features = CLOCK_EVT_FEAT_ONESHOT; |
127 | clockevent->rating = 300; | 124 | clockevent->rating = 300; |
128 | clockevent->set_next_event = ccount_timer_set_next_event; | 125 | clockevent->set_next_event = ccount_timer_set_next_event; |
129 | clockevent->set_mode = ccount_timer_set_mode; | 126 | clockevent->set_state_shutdown = ccount_timer_shutdown; |
127 | clockevent->set_state_oneshot = ccount_timer_set_oneshot; | ||
128 | clockevent->tick_resume = ccount_timer_set_oneshot; | ||
130 | clockevent->cpumask = cpumask_of(cpu); | 129 | clockevent->cpumask = cpumask_of(cpu); |
131 | clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); | 130 | clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); |
132 | if (WARN(!clockevent->irq, "error: can't map timer irq")) | 131 | if (WARN(!clockevent->irq, "error: can't map timer irq")) |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 4e57730e0be4..c03f04d82c6a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -277,7 +277,7 @@ config CLKSRC_MIPS_GIC | |||
277 | 277 | ||
278 | config CLKSRC_PXA | 278 | config CLKSRC_PXA |
279 | def_bool y if ARCH_PXA || ARCH_SA1100 | 279 | def_bool y if ARCH_PXA || ARCH_SA1100 |
280 | select CLKSRC_OF if USE_OF | 280 | select CLKSRC_OF if OF |
281 | help | 281 | help |
282 | This enables OST0 support available on PXA and SA-11x0 | 282 | This enables OST0 support available on PXA and SA-11x0 |
283 | platforms. | 283 | platforms. |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 0aa135ddbf80..d6e3e49399dd 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -181,44 +181,36 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) | |||
181 | return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); | 181 | return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); |
182 | } | 182 | } |
183 | 183 | ||
184 | static __always_inline void timer_set_mode(const int access, int mode, | 184 | static __always_inline int timer_shutdown(const int access, |
185 | struct clock_event_device *clk) | 185 | struct clock_event_device *clk) |
186 | { | 186 | { |
187 | unsigned long ctrl; | 187 | unsigned long ctrl; |
188 | switch (mode) { | 188 | |
189 | case CLOCK_EVT_MODE_UNUSED: | 189 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); |
190 | case CLOCK_EVT_MODE_SHUTDOWN: | 190 | ctrl &= ~ARCH_TIMER_CTRL_ENABLE; |
191 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); | 191 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); |
192 | ctrl &= ~ARCH_TIMER_CTRL_ENABLE; | 192 | |
193 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); | 193 | return 0; |
194 | break; | ||
195 | default: | ||
196 | break; | ||
197 | } | ||
198 | } | 194 | } |
199 | 195 | ||
200 | static void arch_timer_set_mode_virt(enum clock_event_mode mode, | 196 | static int arch_timer_shutdown_virt(struct clock_event_device *clk) |
201 | struct clock_event_device *clk) | ||
202 | { | 197 | { |
203 | timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); | 198 | return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); |
204 | } | 199 | } |
205 | 200 | ||
206 | static void arch_timer_set_mode_phys(enum clock_event_mode mode, | 201 | static int arch_timer_shutdown_phys(struct clock_event_device *clk) |
207 | struct clock_event_device *clk) | ||
208 | { | 202 | { |
209 | timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); | 203 | return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); |
210 | } | 204 | } |
211 | 205 | ||
212 | static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode, | 206 | static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk) |
213 | struct clock_event_device *clk) | ||
214 | { | 207 | { |
215 | timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); | 208 | return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); |
216 | } | 209 | } |
217 | 210 | ||
218 | static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode, | 211 | static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk) |
219 | struct clock_event_device *clk) | ||
220 | { | 212 | { |
221 | timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); | 213 | return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); |
222 | } | 214 | } |
223 | 215 | ||
224 | static __always_inline void set_next_event(const int access, unsigned long evt, | 216 | static __always_inline void set_next_event(const int access, unsigned long evt, |
@@ -273,11 +265,11 @@ static void __arch_timer_setup(unsigned type, | |||
273 | clk->cpumask = cpumask_of(smp_processor_id()); | 265 | clk->cpumask = cpumask_of(smp_processor_id()); |
274 | if (arch_timer_use_virtual) { | 266 | if (arch_timer_use_virtual) { |
275 | clk->irq = arch_timer_ppi[VIRT_PPI]; | 267 | clk->irq = arch_timer_ppi[VIRT_PPI]; |
276 | clk->set_mode = arch_timer_set_mode_virt; | 268 | clk->set_state_shutdown = arch_timer_shutdown_virt; |
277 | clk->set_next_event = arch_timer_set_next_event_virt; | 269 | clk->set_next_event = arch_timer_set_next_event_virt; |
278 | } else { | 270 | } else { |
279 | clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; | 271 | clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; |
280 | clk->set_mode = arch_timer_set_mode_phys; | 272 | clk->set_state_shutdown = arch_timer_shutdown_phys; |
281 | clk->set_next_event = arch_timer_set_next_event_phys; | 273 | clk->set_next_event = arch_timer_set_next_event_phys; |
282 | } | 274 | } |
283 | } else { | 275 | } else { |
@@ -286,17 +278,17 @@ static void __arch_timer_setup(unsigned type, | |||
286 | clk->rating = 400; | 278 | clk->rating = 400; |
287 | clk->cpumask = cpu_all_mask; | 279 | clk->cpumask = cpu_all_mask; |
288 | if (arch_timer_mem_use_virtual) { | 280 | if (arch_timer_mem_use_virtual) { |
289 | clk->set_mode = arch_timer_set_mode_virt_mem; | 281 | clk->set_state_shutdown = arch_timer_shutdown_virt_mem; |
290 | clk->set_next_event = | 282 | clk->set_next_event = |
291 | arch_timer_set_next_event_virt_mem; | 283 | arch_timer_set_next_event_virt_mem; |
292 | } else { | 284 | } else { |
293 | clk->set_mode = arch_timer_set_mode_phys_mem; | 285 | clk->set_state_shutdown = arch_timer_shutdown_phys_mem; |
294 | clk->set_next_event = | 286 | clk->set_next_event = |
295 | arch_timer_set_next_event_phys_mem; | 287 | arch_timer_set_next_event_phys_mem; |
296 | } | 288 | } |
297 | } | 289 | } |
298 | 290 | ||
299 | clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); | 291 | clk->set_state_shutdown(clk); |
300 | 292 | ||
301 | clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); | 293 | clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); |
302 | } | 294 | } |
@@ -506,7 +498,7 @@ static void arch_timer_stop(struct clock_event_device *clk) | |||
506 | disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); | 498 | disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); |
507 | } | 499 | } |
508 | 500 | ||
509 | clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); | 501 | clk->set_state_shutdown(clk); |
510 | } | 502 | } |
511 | 503 | ||
512 | static int arch_timer_cpu_notify(struct notifier_block *self, | 504 | static int arch_timer_cpu_notify(struct notifier_block *self, |
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index e6833771a716..29ea50ac366a 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c | |||
@@ -107,26 +107,21 @@ static void gt_compare_set(unsigned long delta, int periodic) | |||
107 | writel(ctrl, gt_base + GT_CONTROL); | 107 | writel(ctrl, gt_base + GT_CONTROL); |
108 | } | 108 | } |
109 | 109 | ||
110 | static void gt_clockevent_set_mode(enum clock_event_mode mode, | 110 | static int gt_clockevent_shutdown(struct clock_event_device *evt) |
111 | struct clock_event_device *clk) | ||
112 | { | 111 | { |
113 | unsigned long ctrl; | 112 | unsigned long ctrl; |
114 | 113 | ||
115 | switch (mode) { | 114 | ctrl = readl(gt_base + GT_CONTROL); |
116 | case CLOCK_EVT_MODE_PERIODIC: | 115 | ctrl &= ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE | |
117 | gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1); | 116 | GT_CONTROL_AUTO_INC); |
118 | break; | 117 | writel(ctrl, gt_base + GT_CONTROL); |
119 | case CLOCK_EVT_MODE_ONESHOT: | 118 | return 0; |
120 | case CLOCK_EVT_MODE_UNUSED: | 119 | } |
121 | case CLOCK_EVT_MODE_SHUTDOWN: | 120 | |
122 | ctrl = readl(gt_base + GT_CONTROL); | 121 | static int gt_clockevent_set_periodic(struct clock_event_device *evt) |
123 | ctrl &= ~(GT_CONTROL_COMP_ENABLE | | 122 | { |
124 | GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC); | 123 | gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1); |
125 | writel(ctrl, gt_base + GT_CONTROL); | 124 | return 0; |
126 | break; | ||
127 | default: | ||
128 | break; | ||
129 | } | ||
130 | } | 125 | } |
131 | 126 | ||
132 | static int gt_clockevent_set_next_event(unsigned long evt, | 127 | static int gt_clockevent_set_next_event(unsigned long evt, |
@@ -155,7 +150,7 @@ static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) | |||
155 | * the Global Timer flag _after_ having incremented | 150 | * the Global Timer flag _after_ having incremented |
156 | * the Comparator register value to a higher value. | 151 | * the Comparator register value to a higher value. |
157 | */ | 152 | */ |
158 | if (evt->mode == CLOCK_EVT_MODE_ONESHOT) | 153 | if (clockevent_state_oneshot(evt)) |
159 | gt_compare_set(ULONG_MAX, 0); | 154 | gt_compare_set(ULONG_MAX, 0); |
160 | 155 | ||
161 | writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS); | 156 | writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS); |
@@ -171,7 +166,9 @@ static int gt_clockevents_init(struct clock_event_device *clk) | |||
171 | clk->name = "arm_global_timer"; | 166 | clk->name = "arm_global_timer"; |
172 | clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | | 167 | clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | |
173 | CLOCK_EVT_FEAT_PERCPU; | 168 | CLOCK_EVT_FEAT_PERCPU; |
174 | clk->set_mode = gt_clockevent_set_mode; | 169 | clk->set_state_shutdown = gt_clockevent_shutdown; |
170 | clk->set_state_periodic = gt_clockevent_set_periodic; | ||
171 | clk->set_state_oneshot = gt_clockevent_shutdown; | ||
175 | clk->set_next_event = gt_clockevent_set_next_event; | 172 | clk->set_next_event = gt_clockevent_set_next_event; |
176 | clk->cpumask = cpumask_of(cpu); | 173 | clk->cpumask = cpumask_of(cpu); |
177 | clk->rating = 300; | 174 | clk->rating = 300; |
@@ -184,7 +181,7 @@ static int gt_clockevents_init(struct clock_event_device *clk) | |||
184 | 181 | ||
185 | static void gt_clockevents_stop(struct clock_event_device *clk) | 182 | static void gt_clockevents_stop(struct clock_event_device *clk) |
186 | { | 183 | { |
187 | gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk); | 184 | gt_clockevent_shutdown(clk); |
188 | disable_percpu_irq(clk->irq); | 185 | disable_percpu_irq(clk->irq); |
189 | } | 186 | } |
190 | 187 | ||
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index 4c2ba59897e8..217438d39eb3 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c | |||
@@ -120,38 +120,52 @@ static int asm9260_timer_set_next_event(unsigned long delta, | |||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void asm9260_timer_set_mode(enum clock_event_mode mode, | 123 | static inline void __asm9260_timer_shutdown(struct clock_event_device *evt) |
124 | struct clock_event_device *evt) | ||
125 | { | 124 | { |
126 | /* stop timer0 */ | 125 | /* stop timer0 */ |
127 | writel_relaxed(BM_C0_EN, priv.base + HW_TCR + CLR_REG); | 126 | writel_relaxed(BM_C0_EN, priv.base + HW_TCR + CLR_REG); |
127 | } | ||
128 | |||
129 | static int asm9260_timer_shutdown(struct clock_event_device *evt) | ||
130 | { | ||
131 | __asm9260_timer_shutdown(evt); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int asm9260_timer_set_oneshot(struct clock_event_device *evt) | ||
136 | { | ||
137 | __asm9260_timer_shutdown(evt); | ||
138 | |||
139 | /* enable reset and stop on match */ | ||
140 | writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), | ||
141 | priv.base + HW_MCR + SET_REG); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int asm9260_timer_set_periodic(struct clock_event_device *evt) | ||
146 | { | ||
147 | __asm9260_timer_shutdown(evt); | ||
128 | 148 | ||
129 | switch (mode) { | 149 | /* disable reset and stop on match */ |
130 | case CLOCK_EVT_MODE_PERIODIC: | 150 | writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), |
131 | /* disable reset and stop on match */ | 151 | priv.base + HW_MCR + CLR_REG); |
132 | writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), | 152 | /* configure match count for TC0 */ |
133 | priv.base + HW_MCR + CLR_REG); | 153 | writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0); |
134 | /* configure match count for TC0 */ | 154 | /* enable TC0 */ |
135 | writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0); | 155 | writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG); |
136 | /* enable TC0 */ | 156 | return 0; |
137 | writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG); | ||
138 | break; | ||
139 | case CLOCK_EVT_MODE_ONESHOT: | ||
140 | /* enable reset and stop on match */ | ||
141 | writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), | ||
142 | priv.base + HW_MCR + SET_REG); | ||
143 | break; | ||
144 | default: | ||
145 | break; | ||
146 | } | ||
147 | } | 157 | } |
148 | 158 | ||
149 | static struct clock_event_device event_dev = { | 159 | static struct clock_event_device event_dev = { |
150 | .name = DRIVER_NAME, | 160 | .name = DRIVER_NAME, |
151 | .rating = 200, | 161 | .rating = 200, |
152 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 162 | .features = CLOCK_EVT_FEAT_PERIODIC | |
153 | .set_next_event = asm9260_timer_set_next_event, | 163 | CLOCK_EVT_FEAT_ONESHOT, |
154 | .set_mode = asm9260_timer_set_mode, | 164 | .set_next_event = asm9260_timer_set_next_event, |
165 | .set_state_shutdown = asm9260_timer_shutdown, | ||
166 | .set_state_periodic = asm9260_timer_set_periodic, | ||
167 | .set_state_oneshot = asm9260_timer_set_oneshot, | ||
168 | .tick_resume = asm9260_timer_shutdown, | ||
155 | }; | 169 | }; |
156 | 170 | ||
157 | static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id) | 171 | static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id) |
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 26ed331b1aad..6f2822928963 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c | |||
@@ -54,21 +54,6 @@ static u64 notrace bcm2835_sched_read(void) | |||
54 | return readl_relaxed(system_clock); | 54 | return readl_relaxed(system_clock); |
55 | } | 55 | } |
56 | 56 | ||
57 | static void bcm2835_time_set_mode(enum clock_event_mode mode, | ||
58 | struct clock_event_device *evt_dev) | ||
59 | { | ||
60 | switch (mode) { | ||
61 | case CLOCK_EVT_MODE_ONESHOT: | ||
62 | case CLOCK_EVT_MODE_UNUSED: | ||
63 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
64 | case CLOCK_EVT_MODE_RESUME: | ||
65 | break; | ||
66 | default: | ||
67 | WARN(1, "%s: unhandled event mode %d\n", __func__, mode); | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static int bcm2835_time_set_next_event(unsigned long event, | 57 | static int bcm2835_time_set_next_event(unsigned long event, |
73 | struct clock_event_device *evt_dev) | 58 | struct clock_event_device *evt_dev) |
74 | { | 59 | { |
@@ -129,7 +114,6 @@ static void __init bcm2835_timer_init(struct device_node *node) | |||
129 | timer->evt.name = node->name; | 114 | timer->evt.name = node->name; |
130 | timer->evt.rating = 300; | 115 | timer->evt.rating = 300; |
131 | timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; | 116 | timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; |
132 | timer->evt.set_mode = bcm2835_time_set_mode; | ||
133 | timer->evt.set_next_event = bcm2835_time_set_next_event; | 117 | timer->evt.set_next_event = bcm2835_time_set_next_event; |
134 | timer->evt.cpumask = cpumask_of(0); | 118 | timer->evt.cpumask = cpumask_of(0); |
135 | timer->act.name = node->name; | 119 | timer->act.name = node->name; |
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index f1e33d08dd83..e717e87df9bc 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c | |||
@@ -127,25 +127,18 @@ static int kona_timer_set_next_event(unsigned long clc, | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static void kona_timer_set_mode(enum clock_event_mode mode, | 130 | static int kona_timer_shutdown(struct clock_event_device *evt) |
131 | struct clock_event_device *unused) | ||
132 | { | 131 | { |
133 | switch (mode) { | 132 | kona_timer_disable_and_clear(timers.tmr_regs); |
134 | case CLOCK_EVT_MODE_ONESHOT: | 133 | return 0; |
135 | /* by default mode is one shot don't do any thing */ | ||
136 | break; | ||
137 | case CLOCK_EVT_MODE_UNUSED: | ||
138 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
139 | default: | ||
140 | kona_timer_disable_and_clear(timers.tmr_regs); | ||
141 | } | ||
142 | } | 134 | } |
143 | 135 | ||
144 | static struct clock_event_device kona_clockevent_timer = { | 136 | static struct clock_event_device kona_clockevent_timer = { |
145 | .name = "timer 1", | 137 | .name = "timer 1", |
146 | .features = CLOCK_EVT_FEAT_ONESHOT, | 138 | .features = CLOCK_EVT_FEAT_ONESHOT, |
147 | .set_next_event = kona_timer_set_next_event, | 139 | .set_next_event = kona_timer_set_next_event, |
148 | .set_mode = kona_timer_set_mode | 140 | .set_state_shutdown = kona_timer_shutdown, |
141 | .tick_resume = kona_timer_shutdown, | ||
149 | }; | 142 | }; |
150 | 143 | ||
151 | static void __init kona_timer_clockevents_init(void) | 144 | static void __init kona_timer_clockevents_init(void) |
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 5ea91e3818d0..9be6018bd2b8 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
@@ -190,40 +190,42 @@ static int ttc_set_next_event(unsigned long cycles, | |||
190 | } | 190 | } |
191 | 191 | ||
192 | /** | 192 | /** |
193 | * ttc_set_mode - Sets the mode of timer | 193 | * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer |
194 | * | 194 | * |
195 | * @mode: Mode to be set | ||
196 | * @evt: Address of clock event instance | 195 | * @evt: Address of clock event instance |
197 | **/ | 196 | **/ |
198 | static void ttc_set_mode(enum clock_event_mode mode, | 197 | static int ttc_shutdown(struct clock_event_device *evt) |
199 | struct clock_event_device *evt) | ||
200 | { | 198 | { |
201 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); | 199 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); |
202 | struct ttc_timer *timer = &ttce->ttc; | 200 | struct ttc_timer *timer = &ttce->ttc; |
203 | u32 ctrl_reg; | 201 | u32 ctrl_reg; |
204 | 202 | ||
205 | switch (mode) { | 203 | ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); |
206 | case CLOCK_EVT_MODE_PERIODIC: | 204 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; |
207 | ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq, | 205 | writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); |
208 | PRESCALE * HZ)); | 206 | return 0; |
209 | break; | 207 | } |
210 | case CLOCK_EVT_MODE_ONESHOT: | 208 | |
211 | case CLOCK_EVT_MODE_UNUSED: | 209 | static int ttc_set_periodic(struct clock_event_device *evt) |
212 | case CLOCK_EVT_MODE_SHUTDOWN: | 210 | { |
213 | ctrl_reg = readl_relaxed(timer->base_addr + | 211 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); |
214 | TTC_CNT_CNTRL_OFFSET); | 212 | struct ttc_timer *timer = &ttce->ttc; |
215 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; | 213 | |
216 | writel_relaxed(ctrl_reg, | 214 | ttc_set_interval(timer, |
217 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | 215 | DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); |
218 | break; | 216 | return 0; |
219 | case CLOCK_EVT_MODE_RESUME: | 217 | } |
220 | ctrl_reg = readl_relaxed(timer->base_addr + | 218 | |
221 | TTC_CNT_CNTRL_OFFSET); | 219 | static int ttc_resume(struct clock_event_device *evt) |
222 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | 220 | { |
223 | writel_relaxed(ctrl_reg, | 221 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); |
224 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | 222 | struct ttc_timer *timer = &ttce->ttc; |
225 | break; | 223 | u32 ctrl_reg; |
226 | } | 224 | |
225 | ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
226 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | ||
227 | writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
228 | return 0; | ||
227 | } | 229 | } |
228 | 230 | ||
229 | static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, | 231 | static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, |
@@ -429,7 +431,10 @@ static void __init ttc_setup_clockevent(struct clk *clk, | |||
429 | ttcce->ce.name = "ttc_clockevent"; | 431 | ttcce->ce.name = "ttc_clockevent"; |
430 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 432 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
431 | ttcce->ce.set_next_event = ttc_set_next_event; | 433 | ttcce->ce.set_next_event = ttc_set_next_event; |
432 | ttcce->ce.set_mode = ttc_set_mode; | 434 | ttcce->ce.set_state_shutdown = ttc_shutdown; |
435 | ttcce->ce.set_state_periodic = ttc_set_periodic; | ||
436 | ttcce->ce.set_state_oneshot = ttc_shutdown; | ||
437 | ttcce->ce.tick_resume = ttc_resume; | ||
433 | ttcce->ce.rating = 200; | 438 | ttcce->ce.rating = 200; |
434 | ttcce->ce.irq = irq; | 439 | ttcce->ce.irq = irq; |
435 | ttcce->ce.cpumask = cpu_possible_mask; | 440 | ttcce->ce.cpumask = cpu_possible_mask; |
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c index d83ec1f2fddc..cdd86e3525bb 100644 --- a/drivers/clocksource/clps711x-timer.c +++ b/drivers/clocksource/clps711x-timer.c | |||
@@ -61,11 +61,6 @@ static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id) | |||
61 | return IRQ_HANDLED; | 61 | return IRQ_HANDLED; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void clps711x_clockevent_set_mode(enum clock_event_mode mode, | ||
65 | struct clock_event_device *evt) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base, | 64 | static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base, |
70 | unsigned int irq) | 65 | unsigned int irq) |
71 | { | 66 | { |
@@ -91,7 +86,6 @@ static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base, | |||
91 | clkevt->name = "clps711x-clockevent"; | 86 | clkevt->name = "clps711x-clockevent"; |
92 | clkevt->rating = 300; | 87 | clkevt->rating = 300; |
93 | clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP; | 88 | clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP; |
94 | clkevt->set_mode = clps711x_clockevent_set_mode; | ||
95 | clkevt->cpumask = cpumask_of(0); | 89 | clkevt->cpumask = cpumask_of(0); |
96 | clockevents_config_and_register(clkevt, HZ, 0, 0); | 90 | clockevents_config_and_register(clkevt, HZ, 0, 0); |
97 | 91 | ||
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index db2105290898..9a7e37cf56b0 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c | |||
@@ -42,7 +42,6 @@ MODULE_PARM_DESC(irq, "Which IRQ to use for the clock source MFGPT ticks."); | |||
42 | * 256 128 .125 512.000 | 42 | * 256 128 .125 512.000 |
43 | */ | 43 | */ |
44 | 44 | ||
45 | static unsigned int cs5535_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | ||
46 | static struct cs5535_mfgpt_timer *cs5535_event_clock; | 45 | static struct cs5535_mfgpt_timer *cs5535_event_clock; |
47 | 46 | ||
48 | /* Selected from the table above */ | 47 | /* Selected from the table above */ |
@@ -77,15 +76,17 @@ static void start_timer(struct cs5535_mfgpt_timer *timer, uint16_t delta) | |||
77 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | 76 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); |
78 | } | 77 | } |
79 | 78 | ||
80 | static void mfgpt_set_mode(enum clock_event_mode mode, | 79 | static int mfgpt_shutdown(struct clock_event_device *evt) |
81 | struct clock_event_device *evt) | ||
82 | { | 80 | { |
83 | disable_timer(cs5535_event_clock); | 81 | disable_timer(cs5535_event_clock); |
82 | return 0; | ||
83 | } | ||
84 | 84 | ||
85 | if (mode == CLOCK_EVT_MODE_PERIODIC) | 85 | static int mfgpt_set_periodic(struct clock_event_device *evt) |
86 | start_timer(cs5535_event_clock, MFGPT_PERIODIC); | 86 | { |
87 | 87 | disable_timer(cs5535_event_clock); | |
88 | cs5535_tick_mode = mode; | 88 | start_timer(cs5535_event_clock, MFGPT_PERIODIC); |
89 | return 0; | ||
89 | } | 90 | } |
90 | 91 | ||
91 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | 92 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) |
@@ -97,7 +98,10 @@ static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | |||
97 | static struct clock_event_device cs5535_clockevent = { | 98 | static struct clock_event_device cs5535_clockevent = { |
98 | .name = DRV_NAME, | 99 | .name = DRV_NAME, |
99 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 100 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
100 | .set_mode = mfgpt_set_mode, | 101 | .set_state_shutdown = mfgpt_shutdown, |
102 | .set_state_periodic = mfgpt_set_periodic, | ||
103 | .set_state_oneshot = mfgpt_shutdown, | ||
104 | .tick_resume = mfgpt_shutdown, | ||
101 | .set_next_event = mfgpt_next_event, | 105 | .set_next_event = mfgpt_next_event, |
102 | .rating = 250, | 106 | .rating = 250, |
103 | }; | 107 | }; |
@@ -113,7 +117,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) | |||
113 | /* Turn off the clock (and clear the event) */ | 117 | /* Turn off the clock (and clear the event) */ |
114 | disable_timer(cs5535_event_clock); | 118 | disable_timer(cs5535_event_clock); |
115 | 119 | ||
116 | if (cs5535_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | 120 | if (clockevent_state_shutdown(&cs5535_clockevent)) |
117 | return IRQ_HANDLED; | 121 | return IRQ_HANDLED; |
118 | 122 | ||
119 | /* Clear the counter */ | 123 | /* Clear the counter */ |
@@ -121,7 +125,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) | |||
121 | 125 | ||
122 | /* Restart the clock in periodic mode */ | 126 | /* Restart the clock in periodic mode */ |
123 | 127 | ||
124 | if (cs5535_tick_mode == CLOCK_EVT_MODE_PERIODIC) | 128 | if (clockevent_state_periodic(&cs5535_clockevent)) |
125 | cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, | 129 | cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, |
126 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | 130 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); |
127 | 131 | ||
diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c index 31990600fcff..776b6c86dcd5 100644 --- a/drivers/clocksource/dummy_timer.c +++ b/drivers/clocksource/dummy_timer.c | |||
@@ -16,15 +16,6 @@ | |||
16 | 16 | ||
17 | static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt); | 17 | static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt); |
18 | 18 | ||
19 | static void dummy_timer_set_mode(enum clock_event_mode mode, | ||
20 | struct clock_event_device *evt) | ||
21 | { | ||
22 | /* | ||
23 | * Core clockevents code will call this when exchanging timer devices. | ||
24 | * We don't need to do anything here. | ||
25 | */ | ||
26 | } | ||
27 | |||
28 | static void dummy_timer_setup(void) | 19 | static void dummy_timer_setup(void) |
29 | { | 20 | { |
30 | int cpu = smp_processor_id(); | 21 | int cpu = smp_processor_id(); |
@@ -35,7 +26,6 @@ static void dummy_timer_setup(void) | |||
35 | CLOCK_EVT_FEAT_ONESHOT | | 26 | CLOCK_EVT_FEAT_ONESHOT | |
36 | CLOCK_EVT_FEAT_DUMMY; | 27 | CLOCK_EVT_FEAT_DUMMY; |
37 | evt->rating = 100; | 28 | evt->rating = 100; |
38 | evt->set_mode = dummy_timer_set_mode; | ||
39 | evt->cpumask = cpumask_of(cpu); | 29 | evt->cpumask = cpumask_of(cpu); |
40 | 30 | ||
41 | clockevents_register_device(evt); | 31 | clockevents_register_device(evt); |
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 35a88097af3c..c76c75006ea6 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c | |||
@@ -110,71 +110,87 @@ static void apbt_enable_int(struct dw_apb_timer *timer) | |||
110 | apbt_writel(timer, ctrl, APBTMR_N_CONTROL); | 110 | apbt_writel(timer, ctrl, APBTMR_N_CONTROL); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void apbt_set_mode(enum clock_event_mode mode, | 113 | static int apbt_shutdown(struct clock_event_device *evt) |
114 | struct clock_event_device *evt) | ||
115 | { | 114 | { |
115 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | ||
116 | unsigned long ctrl; | 116 | unsigned long ctrl; |
117 | unsigned long period; | 117 | |
118 | pr_debug("%s CPU %d state=shutdown\n", __func__, | ||
119 | cpumask_first(evt->cpumask)); | ||
120 | |||
121 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | ||
122 | ctrl &= ~APBTMR_CONTROL_ENABLE; | ||
123 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int apbt_set_oneshot(struct clock_event_device *evt) | ||
128 | { | ||
118 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | 129 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
130 | unsigned long ctrl; | ||
119 | 131 | ||
120 | pr_debug("%s CPU %d mode=%d\n", __func__, | 132 | pr_debug("%s CPU %d state=oneshot\n", __func__, |
121 | cpumask_first(evt->cpumask), | 133 | cpumask_first(evt->cpumask)); |
122 | mode); | 134 | |
123 | 135 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | |
124 | switch (mode) { | 136 | /* |
125 | case CLOCK_EVT_MODE_PERIODIC: | 137 | * set free running mode, this mode will let timer reload max |
126 | period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); | 138 | * timeout which will give time (3min on 25MHz clock) to rearm |
127 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | 139 | * the next event, therefore emulate the one-shot mode. |
128 | ctrl |= APBTMR_CONTROL_MODE_PERIODIC; | 140 | */ |
129 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 141 | ctrl &= ~APBTMR_CONTROL_ENABLE; |
130 | /* | 142 | ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; |
131 | * DW APB p. 46, have to disable timer before load counter, | 143 | |
132 | * may cause sync problem. | 144 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
133 | */ | 145 | /* write again to set free running mode */ |
134 | ctrl &= ~APBTMR_CONTROL_ENABLE; | 146 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
135 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 147 | |
136 | udelay(1); | 148 | /* |
137 | pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); | 149 | * DW APB p. 46, load counter with all 1s before starting free |
138 | apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); | 150 | * running mode. |
139 | ctrl |= APBTMR_CONTROL_ENABLE; | 151 | */ |
140 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 152 | apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); |
141 | break; | 153 | ctrl &= ~APBTMR_CONTROL_INT; |
142 | 154 | ctrl |= APBTMR_CONTROL_ENABLE; | |
143 | case CLOCK_EVT_MODE_ONESHOT: | 155 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
144 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | 156 | return 0; |
145 | /* | 157 | } |
146 | * set free running mode, this mode will let timer reload max | 158 | |
147 | * timeout which will give time (3min on 25MHz clock) to rearm | 159 | static int apbt_set_periodic(struct clock_event_device *evt) |
148 | * the next event, therefore emulate the one-shot mode. | 160 | { |
149 | */ | 161 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
150 | ctrl &= ~APBTMR_CONTROL_ENABLE; | 162 | unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); |
151 | ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; | 163 | unsigned long ctrl; |
152 | 164 | ||
153 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 165 | pr_debug("%s CPU %d state=periodic\n", __func__, |
154 | /* write again to set free running mode */ | 166 | cpumask_first(evt->cpumask)); |
155 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 167 | |
156 | 168 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | |
157 | /* | 169 | ctrl |= APBTMR_CONTROL_MODE_PERIODIC; |
158 | * DW APB p. 46, load counter with all 1s before starting free | 170 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
159 | * running mode. | 171 | /* |
160 | */ | 172 | * DW APB p. 46, have to disable timer before load counter, |
161 | apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); | 173 | * may cause sync problem. |
162 | ctrl &= ~APBTMR_CONTROL_INT; | 174 | */ |
163 | ctrl |= APBTMR_CONTROL_ENABLE; | 175 | ctrl &= ~APBTMR_CONTROL_ENABLE; |
164 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 176 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
165 | break; | 177 | udelay(1); |
166 | 178 | pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); | |
167 | case CLOCK_EVT_MODE_UNUSED: | 179 | apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); |
168 | case CLOCK_EVT_MODE_SHUTDOWN: | 180 | ctrl |= APBTMR_CONTROL_ENABLE; |
169 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | 181 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
170 | ctrl &= ~APBTMR_CONTROL_ENABLE; | 182 | return 0; |
171 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 183 | } |
172 | break; | 184 | |
173 | 185 | static int apbt_resume(struct clock_event_device *evt) | |
174 | case CLOCK_EVT_MODE_RESUME: | 186 | { |
175 | apbt_enable_int(&dw_ced->timer); | 187 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
176 | break; | 188 | |
177 | } | 189 | pr_debug("%s CPU %d state=resume\n", __func__, |
190 | cpumask_first(evt->cpumask)); | ||
191 | |||
192 | apbt_enable_int(&dw_ced->timer); | ||
193 | return 0; | ||
178 | } | 194 | } |
179 | 195 | ||
180 | static int apbt_next_event(unsigned long delta, | 196 | static int apbt_next_event(unsigned long delta, |
@@ -232,8 +248,12 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, | |||
232 | &dw_ced->ced); | 248 | &dw_ced->ced); |
233 | dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); | 249 | dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); |
234 | dw_ced->ced.cpumask = cpumask_of(cpu); | 250 | dw_ced->ced.cpumask = cpumask_of(cpu); |
235 | dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 251 | dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | |
236 | dw_ced->ced.set_mode = apbt_set_mode; | 252 | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; |
253 | dw_ced->ced.set_state_shutdown = apbt_shutdown; | ||
254 | dw_ced->ced.set_state_periodic = apbt_set_periodic; | ||
255 | dw_ced->ced.set_state_oneshot = apbt_set_oneshot; | ||
256 | dw_ced->ced.tick_resume = apbt_resume; | ||
237 | dw_ced->ced.set_next_event = apbt_next_event; | 257 | dw_ced->ced.set_next_event = apbt_next_event; |
238 | dw_ced->ced.irq = dw_ced->timer.irq; | 258 | dw_ced->ced.irq = dw_ced->timer.irq; |
239 | dw_ced->ced.rating = rating; | 259 | dw_ced->ced.rating = rating; |
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index dc3c6ee04aaa..7a97a34dba70 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c | |||
@@ -251,33 +251,21 @@ static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) | |||
251 | return container_of(ced, struct em_sti_priv, ced); | 251 | return container_of(ced, struct em_sti_priv, ced); |
252 | } | 252 | } |
253 | 253 | ||
254 | static void em_sti_clock_event_mode(enum clock_event_mode mode, | 254 | static int em_sti_clock_event_shutdown(struct clock_event_device *ced) |
255 | struct clock_event_device *ced) | ||
256 | { | 255 | { |
257 | struct em_sti_priv *p = ced_to_em_sti(ced); | 256 | struct em_sti_priv *p = ced_to_em_sti(ced); |
257 | em_sti_stop(p, USER_CLOCKEVENT); | ||
258 | return 0; | ||
259 | } | ||
258 | 260 | ||
259 | /* deal with old setting first */ | 261 | static int em_sti_clock_event_set_oneshot(struct clock_event_device *ced) |
260 | switch (ced->mode) { | 262 | { |
261 | case CLOCK_EVT_MODE_ONESHOT: | 263 | struct em_sti_priv *p = ced_to_em_sti(ced); |
262 | em_sti_stop(p, USER_CLOCKEVENT); | ||
263 | break; | ||
264 | default: | ||
265 | break; | ||
266 | } | ||
267 | 264 | ||
268 | switch (mode) { | 265 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
269 | case CLOCK_EVT_MODE_ONESHOT: | 266 | em_sti_start(p, USER_CLOCKEVENT); |
270 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); | 267 | clockevents_config(&p->ced, p->rate); |
271 | em_sti_start(p, USER_CLOCKEVENT); | 268 | return 0; |
272 | clockevents_config(&p->ced, p->rate); | ||
273 | break; | ||
274 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
275 | case CLOCK_EVT_MODE_UNUSED: | ||
276 | em_sti_stop(p, USER_CLOCKEVENT); | ||
277 | break; | ||
278 | default: | ||
279 | break; | ||
280 | } | ||
281 | } | 269 | } |
282 | 270 | ||
283 | static int em_sti_clock_event_next(unsigned long delta, | 271 | static int em_sti_clock_event_next(unsigned long delta, |
@@ -303,11 +291,12 @@ static void em_sti_register_clockevent(struct em_sti_priv *p) | |||
303 | ced->rating = 200; | 291 | ced->rating = 200; |
304 | ced->cpumask = cpu_possible_mask; | 292 | ced->cpumask = cpu_possible_mask; |
305 | ced->set_next_event = em_sti_clock_event_next; | 293 | ced->set_next_event = em_sti_clock_event_next; |
306 | ced->set_mode = em_sti_clock_event_mode; | 294 | ced->set_state_shutdown = em_sti_clock_event_shutdown; |
295 | ced->set_state_oneshot = em_sti_clock_event_set_oneshot; | ||
307 | 296 | ||
308 | dev_info(&p->pdev->dev, "used for clock events\n"); | 297 | dev_info(&p->pdev->dev, "used for clock events\n"); |
309 | 298 | ||
310 | /* Register with dummy 1 Hz value, gets updated in ->set_mode() */ | 299 | /* Register with dummy 1 Hz value, gets updated in ->set_state_oneshot() */ |
311 | clockevents_config_and_register(ced, 1, 2, 0xffffffff); | 300 | clockevents_config_and_register(ced, 1, 2, 0xffffffff); |
312 | } | 301 | } |
313 | 302 | ||
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 9064ff743598..029f96ab131a 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
@@ -257,15 +257,14 @@ static void exynos4_mct_comp0_stop(void) | |||
257 | exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB); | 257 | exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB); |
258 | } | 258 | } |
259 | 259 | ||
260 | static void exynos4_mct_comp0_start(enum clock_event_mode mode, | 260 | static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles) |
261 | unsigned long cycles) | ||
262 | { | 261 | { |
263 | unsigned int tcon; | 262 | unsigned int tcon; |
264 | cycle_t comp_cycle; | 263 | cycle_t comp_cycle; |
265 | 264 | ||
266 | tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON); | 265 | tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON); |
267 | 266 | ||
268 | if (mode == CLOCK_EVT_MODE_PERIODIC) { | 267 | if (periodic) { |
269 | tcon |= MCT_G_TCON_COMP0_AUTO_INC; | 268 | tcon |= MCT_G_TCON_COMP0_AUTO_INC; |
270 | exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); | 269 | exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); |
271 | } | 270 | } |
@@ -283,38 +282,38 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode, | |||
283 | static int exynos4_comp_set_next_event(unsigned long cycles, | 282 | static int exynos4_comp_set_next_event(unsigned long cycles, |
284 | struct clock_event_device *evt) | 283 | struct clock_event_device *evt) |
285 | { | 284 | { |
286 | exynos4_mct_comp0_start(evt->mode, cycles); | 285 | exynos4_mct_comp0_start(false, cycles); |
287 | 286 | ||
288 | return 0; | 287 | return 0; |
289 | } | 288 | } |
290 | 289 | ||
291 | static void exynos4_comp_set_mode(enum clock_event_mode mode, | 290 | static int mct_set_state_shutdown(struct clock_event_device *evt) |
292 | struct clock_event_device *evt) | ||
293 | { | 291 | { |
294 | unsigned long cycles_per_jiffy; | ||
295 | exynos4_mct_comp0_stop(); | 292 | exynos4_mct_comp0_stop(); |
293 | return 0; | ||
294 | } | ||
296 | 295 | ||
297 | switch (mode) { | 296 | static int mct_set_state_periodic(struct clock_event_device *evt) |
298 | case CLOCK_EVT_MODE_PERIODIC: | 297 | { |
299 | cycles_per_jiffy = | 298 | unsigned long cycles_per_jiffy; |
300 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
301 | exynos4_mct_comp0_start(mode, cycles_per_jiffy); | ||
302 | break; | ||
303 | 299 | ||
304 | case CLOCK_EVT_MODE_ONESHOT: | 300 | cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult) |
305 | case CLOCK_EVT_MODE_UNUSED: | 301 | >> evt->shift); |
306 | case CLOCK_EVT_MODE_SHUTDOWN: | 302 | exynos4_mct_comp0_stop(); |
307 | case CLOCK_EVT_MODE_RESUME: | 303 | exynos4_mct_comp0_start(true, cycles_per_jiffy); |
308 | break; | 304 | return 0; |
309 | } | ||
310 | } | 305 | } |
311 | 306 | ||
312 | static struct clock_event_device mct_comp_device = { | 307 | static struct clock_event_device mct_comp_device = { |
313 | .name = "mct-comp", | 308 | .name = "mct-comp", |
314 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 309 | .features = CLOCK_EVT_FEAT_PERIODIC | |
315 | .rating = 250, | 310 | CLOCK_EVT_FEAT_ONESHOT, |
316 | .set_next_event = exynos4_comp_set_next_event, | 311 | .rating = 250, |
317 | .set_mode = exynos4_comp_set_mode, | 312 | .set_next_event = exynos4_comp_set_next_event, |
313 | .set_state_periodic = mct_set_state_periodic, | ||
314 | .set_state_shutdown = mct_set_state_shutdown, | ||
315 | .set_state_oneshot = mct_set_state_shutdown, | ||
316 | .tick_resume = mct_set_state_shutdown, | ||
318 | }; | 317 | }; |
319 | 318 | ||
320 | static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id) | 319 | static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id) |
@@ -390,39 +389,32 @@ static int exynos4_tick_set_next_event(unsigned long cycles, | |||
390 | return 0; | 389 | return 0; |
391 | } | 390 | } |
392 | 391 | ||
393 | static inline void exynos4_tick_set_mode(enum clock_event_mode mode, | 392 | static int set_state_shutdown(struct clock_event_device *evt) |
394 | struct clock_event_device *evt) | 393 | { |
394 | exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick)); | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int set_state_periodic(struct clock_event_device *evt) | ||
395 | { | 399 | { |
396 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); | 400 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); |
397 | unsigned long cycles_per_jiffy; | 401 | unsigned long cycles_per_jiffy; |
398 | 402 | ||
403 | cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult) | ||
404 | >> evt->shift); | ||
399 | exynos4_mct_tick_stop(mevt); | 405 | exynos4_mct_tick_stop(mevt); |
400 | 406 | exynos4_mct_tick_start(cycles_per_jiffy, mevt); | |
401 | switch (mode) { | 407 | return 0; |
402 | case CLOCK_EVT_MODE_PERIODIC: | ||
403 | cycles_per_jiffy = | ||
404 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
405 | exynos4_mct_tick_start(cycles_per_jiffy, mevt); | ||
406 | break; | ||
407 | |||
408 | case CLOCK_EVT_MODE_ONESHOT: | ||
409 | case CLOCK_EVT_MODE_UNUSED: | ||
410 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
411 | case CLOCK_EVT_MODE_RESUME: | ||
412 | break; | ||
413 | } | ||
414 | } | 408 | } |
415 | 409 | ||
416 | static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) | 410 | static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) |
417 | { | 411 | { |
418 | struct clock_event_device *evt = &mevt->evt; | ||
419 | |||
420 | /* | 412 | /* |
421 | * This is for supporting oneshot mode. | 413 | * This is for supporting oneshot mode. |
422 | * Mct would generate interrupt periodically | 414 | * Mct would generate interrupt periodically |
423 | * without explicit stopping. | 415 | * without explicit stopping. |
424 | */ | 416 | */ |
425 | if (evt->mode != CLOCK_EVT_MODE_PERIODIC) | 417 | if (!clockevent_state_periodic(&mevt->evt)) |
426 | exynos4_mct_tick_stop(mevt); | 418 | exynos4_mct_tick_stop(mevt); |
427 | 419 | ||
428 | /* Clear the MCT tick interrupt */ | 420 | /* Clear the MCT tick interrupt */ |
@@ -442,20 +434,21 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) | |||
442 | return IRQ_HANDLED; | 434 | return IRQ_HANDLED; |
443 | } | 435 | } |
444 | 436 | ||
445 | static int exynos4_local_timer_setup(struct clock_event_device *evt) | 437 | static int exynos4_local_timer_setup(struct mct_clock_event_device *mevt) |
446 | { | 438 | { |
447 | struct mct_clock_event_device *mevt; | 439 | struct clock_event_device *evt = &mevt->evt; |
448 | unsigned int cpu = smp_processor_id(); | 440 | unsigned int cpu = smp_processor_id(); |
449 | 441 | ||
450 | mevt = container_of(evt, struct mct_clock_event_device, evt); | ||
451 | |||
452 | mevt->base = EXYNOS4_MCT_L_BASE(cpu); | 442 | mevt->base = EXYNOS4_MCT_L_BASE(cpu); |
453 | snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); | 443 | snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); |
454 | 444 | ||
455 | evt->name = mevt->name; | 445 | evt->name = mevt->name; |
456 | evt->cpumask = cpumask_of(cpu); | 446 | evt->cpumask = cpumask_of(cpu); |
457 | evt->set_next_event = exynos4_tick_set_next_event; | 447 | evt->set_next_event = exynos4_tick_set_next_event; |
458 | evt->set_mode = exynos4_tick_set_mode; | 448 | evt->set_state_periodic = set_state_periodic; |
449 | evt->set_state_shutdown = set_state_shutdown; | ||
450 | evt->set_state_oneshot = set_state_shutdown; | ||
451 | evt->tick_resume = set_state_shutdown; | ||
459 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 452 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
460 | evt->rating = 450; | 453 | evt->rating = 450; |
461 | 454 | ||
@@ -477,9 +470,11 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
477 | return 0; | 470 | return 0; |
478 | } | 471 | } |
479 | 472 | ||
480 | static void exynos4_local_timer_stop(struct clock_event_device *evt) | 473 | static void exynos4_local_timer_stop(struct mct_clock_event_device *mevt) |
481 | { | 474 | { |
482 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 475 | struct clock_event_device *evt = &mevt->evt; |
476 | |||
477 | evt->set_state_shutdown(evt); | ||
483 | if (mct_int_type == MCT_INT_SPI) { | 478 | if (mct_int_type == MCT_INT_SPI) { |
484 | if (evt->irq != -1) | 479 | if (evt->irq != -1) |
485 | disable_irq_nosync(evt->irq); | 480 | disable_irq_nosync(evt->irq); |
@@ -500,11 +495,11 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self, | |||
500 | switch (action & ~CPU_TASKS_FROZEN) { | 495 | switch (action & ~CPU_TASKS_FROZEN) { |
501 | case CPU_STARTING: | 496 | case CPU_STARTING: |
502 | mevt = this_cpu_ptr(&percpu_mct_tick); | 497 | mevt = this_cpu_ptr(&percpu_mct_tick); |
503 | exynos4_local_timer_setup(&mevt->evt); | 498 | exynos4_local_timer_setup(mevt); |
504 | break; | 499 | break; |
505 | case CPU_DYING: | 500 | case CPU_DYING: |
506 | mevt = this_cpu_ptr(&percpu_mct_tick); | 501 | mevt = this_cpu_ptr(&percpu_mct_tick); |
507 | exynos4_local_timer_stop(&mevt->evt); | 502 | exynos4_local_timer_stop(mevt); |
508 | break; | 503 | break; |
509 | } | 504 | } |
510 | 505 | ||
@@ -570,7 +565,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem | |||
570 | goto out_irq; | 565 | goto out_irq; |
571 | 566 | ||
572 | /* Immediately configure the timer on the boot CPU */ | 567 | /* Immediately configure the timer on the boot CPU */ |
573 | exynos4_local_timer_setup(&mevt->evt); | 568 | exynos4_local_timer_setup(mevt); |
574 | return; | 569 | return; |
575 | 570 | ||
576 | out_irq: | 571 | out_irq: |
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c index 454227d4f895..ef434699c80a 100644 --- a/drivers/clocksource/fsl_ftm_timer.c +++ b/drivers/clocksource/fsl_ftm_timer.c | |||
@@ -153,19 +153,16 @@ static int ftm_set_next_event(unsigned long delta, | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static void ftm_set_mode(enum clock_event_mode mode, | 156 | static int ftm_set_oneshot(struct clock_event_device *evt) |
157 | struct clock_event_device *evt) | ||
158 | { | 157 | { |
159 | switch (mode) { | 158 | ftm_counter_disable(priv->clkevt_base); |
160 | case CLOCK_EVT_MODE_PERIODIC: | 159 | return 0; |
161 | ftm_set_next_event(priv->periodic_cyc, evt); | 160 | } |
162 | break; | 161 | |
163 | case CLOCK_EVT_MODE_ONESHOT: | 162 | static int ftm_set_periodic(struct clock_event_device *evt) |
164 | ftm_counter_disable(priv->clkevt_base); | 163 | { |
165 | break; | 164 | ftm_set_next_event(priv->periodic_cyc, evt); |
166 | default: | 165 | return 0; |
167 | return; | ||
168 | } | ||
169 | } | 166 | } |
170 | 167 | ||
171 | static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) | 168 | static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) |
@@ -174,7 +171,7 @@ static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) | |||
174 | 171 | ||
175 | ftm_irq_acknowledge(priv->clkevt_base); | 172 | ftm_irq_acknowledge(priv->clkevt_base); |
176 | 173 | ||
177 | if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT)) { | 174 | if (likely(clockevent_state_oneshot(evt))) { |
178 | ftm_irq_disable(priv->clkevt_base); | 175 | ftm_irq_disable(priv->clkevt_base); |
179 | ftm_counter_disable(priv->clkevt_base); | 176 | ftm_counter_disable(priv->clkevt_base); |
180 | } | 177 | } |
@@ -185,11 +182,13 @@ static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) | |||
185 | } | 182 | } |
186 | 183 | ||
187 | static struct clock_event_device ftm_clockevent = { | 184 | static struct clock_event_device ftm_clockevent = { |
188 | .name = "Freescale ftm timer", | 185 | .name = "Freescale ftm timer", |
189 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 186 | .features = CLOCK_EVT_FEAT_PERIODIC | |
190 | .set_mode = ftm_set_mode, | 187 | CLOCK_EVT_FEAT_ONESHOT, |
191 | .set_next_event = ftm_set_next_event, | 188 | .set_state_periodic = ftm_set_periodic, |
192 | .rating = 300, | 189 | .set_state_oneshot = ftm_set_oneshot, |
190 | .set_next_event = ftm_set_next_event, | ||
191 | .rating = 300, | ||
193 | }; | 192 | }; |
194 | 193 | ||
195 | static struct irqaction ftm_timer_irq = { | 194 | static struct irqaction ftm_timer_irq = { |
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 0214cb3a7f5e..f9b3b7033a97 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c | |||
@@ -81,7 +81,7 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id) | |||
81 | p->flags |= FLAG_IRQCONTEXT; | 81 | p->flags |= FLAG_IRQCONTEXT; |
82 | ctrl_outw(p->tcora, p->mapbase + TCORA); | 82 | ctrl_outw(p->tcora, p->mapbase + TCORA); |
83 | if (!(p->flags & FLAG_SKIPEVENT)) { | 83 | if (!(p->flags & FLAG_SKIPEVENT)) { |
84 | if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) | 84 | if (clockevent_state_oneshot(&p->ced)) |
85 | ctrl_outw(0x0000, p->mapbase + _8TCR); | 85 | ctrl_outw(0x0000, p->mapbase + _8TCR); |
86 | p->ced.event_handler(&p->ced); | 86 | p->ced.event_handler(&p->ced); |
87 | } | 87 | } |
@@ -169,29 +169,32 @@ static void timer8_clock_event_start(struct timer8_priv *p, int periodic) | |||
169 | timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000); | 169 | timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000); |
170 | } | 170 | } |
171 | 171 | ||
172 | static void timer8_clock_event_mode(enum clock_event_mode mode, | 172 | static int timer8_clock_event_shutdown(struct clock_event_device *ced) |
173 | struct clock_event_device *ced) | 173 | { |
174 | timer8_stop(ced_to_priv(ced)); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int timer8_clock_event_periodic(struct clock_event_device *ced) | ||
174 | { | 179 | { |
175 | struct timer8_priv *p = ced_to_priv(ced); | 180 | struct timer8_priv *p = ced_to_priv(ced); |
176 | 181 | ||
177 | switch (mode) { | 182 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
178 | case CLOCK_EVT_MODE_PERIODIC: | 183 | timer8_stop(p); |
179 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); | 184 | timer8_clock_event_start(p, PERIODIC); |
180 | timer8_stop(p); | 185 | |
181 | timer8_clock_event_start(p, PERIODIC); | 186 | return 0; |
182 | break; | 187 | } |
183 | case CLOCK_EVT_MODE_ONESHOT: | 188 | |
184 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); | 189 | static int timer8_clock_event_oneshot(struct clock_event_device *ced) |
185 | timer8_stop(p); | 190 | { |
186 | timer8_clock_event_start(p, ONESHOT); | 191 | struct timer8_priv *p = ced_to_priv(ced); |
187 | break; | 192 | |
188 | case CLOCK_EVT_MODE_SHUTDOWN: | 193 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
189 | case CLOCK_EVT_MODE_UNUSED: | 194 | timer8_stop(p); |
190 | timer8_stop(p); | 195 | timer8_clock_event_start(p, ONESHOT); |
191 | break; | 196 | |
192 | default: | 197 | return 0; |
193 | break; | ||
194 | } | ||
195 | } | 198 | } |
196 | 199 | ||
197 | static int timer8_clock_event_next(unsigned long delta, | 200 | static int timer8_clock_event_next(unsigned long delta, |
@@ -199,7 +202,7 @@ static int timer8_clock_event_next(unsigned long delta, | |||
199 | { | 202 | { |
200 | struct timer8_priv *p = ced_to_priv(ced); | 203 | struct timer8_priv *p = ced_to_priv(ced); |
201 | 204 | ||
202 | BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); | 205 | BUG_ON(!clockevent_state_oneshot(ced)); |
203 | timer8_set_next(p, delta - 1); | 206 | timer8_set_next(p, delta - 1); |
204 | 207 | ||
205 | return 0; | 208 | return 0; |
@@ -246,7 +249,9 @@ static int timer8_setup(struct timer8_priv *p, | |||
246 | p->ced.rating = 200; | 249 | p->ced.rating = 200; |
247 | p->ced.cpumask = cpumask_of(0); | 250 | p->ced.cpumask = cpumask_of(0); |
248 | p->ced.set_next_event = timer8_clock_event_next; | 251 | p->ced.set_next_event = timer8_clock_event_next; |
249 | p->ced.set_mode = timer8_clock_event_mode; | 252 | p->ced.set_state_shutdown = timer8_clock_event_shutdown; |
253 | p->ced.set_state_periodic = timer8_clock_event_periodic; | ||
254 | p->ced.set_state_oneshot = timer8_clock_event_oneshot; | ||
250 | 255 | ||
251 | ret = setup_irq(irq, &p->irqaction); | 256 | ret = setup_irq(irq, &p->irqaction); |
252 | if (ret < 0) { | 257 | if (ret < 0) { |
diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c index 14ee3efcc404..0efd36e483ab 100644 --- a/drivers/clocksource/i8253.c +++ b/drivers/clocksource/i8253.c | |||
@@ -100,44 +100,40 @@ int __init clocksource_i8253_init(void) | |||
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | #ifdef CONFIG_CLKEVT_I8253 | 102 | #ifdef CONFIG_CLKEVT_I8253 |
103 | /* | 103 | static int pit_shutdown(struct clock_event_device *evt) |
104 | * Initialize the PIT timer. | ||
105 | * | ||
106 | * This is also called after resume to bring the PIT into operation again. | ||
107 | */ | ||
108 | static void init_pit_timer(enum clock_event_mode mode, | ||
109 | struct clock_event_device *evt) | ||
110 | { | 104 | { |
105 | if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt)) | ||
106 | return 0; | ||
107 | |||
111 | raw_spin_lock(&i8253_lock); | 108 | raw_spin_lock(&i8253_lock); |
112 | 109 | ||
113 | switch (mode) { | 110 | outb_p(0x30, PIT_MODE); |
114 | case CLOCK_EVT_MODE_PERIODIC: | 111 | outb_p(0, PIT_CH0); |
115 | /* binary, mode 2, LSB/MSB, ch 0 */ | 112 | outb_p(0, PIT_CH0); |
116 | outb_p(0x34, PIT_MODE); | 113 | |
117 | outb_p(PIT_LATCH & 0xff , PIT_CH0); /* LSB */ | 114 | raw_spin_unlock(&i8253_lock); |
118 | outb_p(PIT_LATCH >> 8 , PIT_CH0); /* MSB */ | 115 | return 0; |
119 | break; | 116 | } |
120 | 117 | ||
121 | case CLOCK_EVT_MODE_SHUTDOWN: | 118 | static int pit_set_oneshot(struct clock_event_device *evt) |
122 | case CLOCK_EVT_MODE_UNUSED: | 119 | { |
123 | if (evt->mode == CLOCK_EVT_MODE_PERIODIC || | 120 | raw_spin_lock(&i8253_lock); |
124 | evt->mode == CLOCK_EVT_MODE_ONESHOT) { | 121 | outb_p(0x38, PIT_MODE); |
125 | outb_p(0x30, PIT_MODE); | 122 | raw_spin_unlock(&i8253_lock); |
126 | outb_p(0, PIT_CH0); | 123 | return 0; |
127 | outb_p(0, PIT_CH0); | 124 | } |
128 | } | 125 | |
129 | break; | 126 | static int pit_set_periodic(struct clock_event_device *evt) |
130 | 127 | { | |
131 | case CLOCK_EVT_MODE_ONESHOT: | 128 | raw_spin_lock(&i8253_lock); |
132 | /* One shot setup */ | 129 | |
133 | outb_p(0x38, PIT_MODE); | 130 | /* binary, mode 2, LSB/MSB, ch 0 */ |
134 | break; | 131 | outb_p(0x34, PIT_MODE); |
135 | 132 | outb_p(PIT_LATCH & 0xff, PIT_CH0); /* LSB */ | |
136 | case CLOCK_EVT_MODE_RESUME: | 133 | outb_p(PIT_LATCH >> 8, PIT_CH0); /* MSB */ |
137 | /* Nothing to do here */ | 134 | |
138 | break; | ||
139 | } | ||
140 | raw_spin_unlock(&i8253_lock); | 135 | raw_spin_unlock(&i8253_lock); |
136 | return 0; | ||
141 | } | 137 | } |
142 | 138 | ||
143 | /* | 139 | /* |
@@ -160,10 +156,11 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt) | |||
160 | * it can be solely used for the global tick. | 156 | * it can be solely used for the global tick. |
161 | */ | 157 | */ |
162 | struct clock_event_device i8253_clockevent = { | 158 | struct clock_event_device i8253_clockevent = { |
163 | .name = "pit", | 159 | .name = "pit", |
164 | .features = CLOCK_EVT_FEAT_PERIODIC, | 160 | .features = CLOCK_EVT_FEAT_PERIODIC, |
165 | .set_mode = init_pit_timer, | 161 | .set_state_shutdown = pit_shutdown, |
166 | .set_next_event = pit_next_event, | 162 | .set_state_periodic = pit_set_periodic, |
163 | .set_next_event = pit_next_event, | ||
167 | }; | 164 | }; |
168 | 165 | ||
169 | /* | 166 | /* |
@@ -172,8 +169,10 @@ struct clock_event_device i8253_clockevent = { | |||
172 | */ | 169 | */ |
173 | void __init clockevent_i8253_init(bool oneshot) | 170 | void __init clockevent_i8253_init(bool oneshot) |
174 | { | 171 | { |
175 | if (oneshot) | 172 | if (oneshot) { |
176 | i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT; | 173 | i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT; |
174 | i8253_clockevent.set_state_oneshot = pit_set_oneshot; | ||
175 | } | ||
177 | /* | 176 | /* |
178 | * Start pit with the boot cpu mask. x86 might make it global | 177 | * Start pit with the boot cpu mask. x86 might make it global |
179 | * when it is used as broadcast device later. | 178 | * when it is used as broadcast device later. |
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c index 5c15cba41dca..1fa22c4d2d49 100644 --- a/drivers/clocksource/meson6_timer.c +++ b/drivers/clocksource/meson6_timer.c | |||
@@ -67,25 +67,25 @@ static void meson6_clkevt_time_start(unsigned char timer, bool periodic) | |||
67 | writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); | 67 | writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); |
68 | } | 68 | } |
69 | 69 | ||
70 | static void meson6_clkevt_mode(enum clock_event_mode mode, | 70 | static int meson6_shutdown(struct clock_event_device *evt) |
71 | struct clock_event_device *clk) | ||
72 | { | 71 | { |
73 | switch (mode) { | 72 | meson6_clkevt_time_stop(CED_ID); |
74 | case CLOCK_EVT_MODE_PERIODIC: | 73 | return 0; |
75 | meson6_clkevt_time_stop(CED_ID); | 74 | } |
76 | meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC/HZ - 1); | 75 | |
77 | meson6_clkevt_time_start(CED_ID, true); | 76 | static int meson6_set_oneshot(struct clock_event_device *evt) |
78 | break; | 77 | { |
79 | case CLOCK_EVT_MODE_ONESHOT: | 78 | meson6_clkevt_time_stop(CED_ID); |
80 | meson6_clkevt_time_stop(CED_ID); | 79 | meson6_clkevt_time_start(CED_ID, false); |
81 | meson6_clkevt_time_start(CED_ID, false); | 80 | return 0; |
82 | break; | 81 | } |
83 | case CLOCK_EVT_MODE_UNUSED: | 82 | |
84 | case CLOCK_EVT_MODE_SHUTDOWN: | 83 | static int meson6_set_periodic(struct clock_event_device *evt) |
85 | default: | 84 | { |
86 | meson6_clkevt_time_stop(CED_ID); | 85 | meson6_clkevt_time_stop(CED_ID); |
87 | break; | 86 | meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC / HZ - 1); |
88 | } | 87 | meson6_clkevt_time_start(CED_ID, true); |
88 | return 0; | ||
89 | } | 89 | } |
90 | 90 | ||
91 | static int meson6_clkevt_next_event(unsigned long evt, | 91 | static int meson6_clkevt_next_event(unsigned long evt, |
@@ -99,11 +99,15 @@ static int meson6_clkevt_next_event(unsigned long evt, | |||
99 | } | 99 | } |
100 | 100 | ||
101 | static struct clock_event_device meson6_clockevent = { | 101 | static struct clock_event_device meson6_clockevent = { |
102 | .name = "meson6_tick", | 102 | .name = "meson6_tick", |
103 | .rating = 400, | 103 | .rating = 400, |
104 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 104 | .features = CLOCK_EVT_FEAT_PERIODIC | |
105 | .set_mode = meson6_clkevt_mode, | 105 | CLOCK_EVT_FEAT_ONESHOT, |
106 | .set_next_event = meson6_clkevt_next_event, | 106 | .set_state_shutdown = meson6_shutdown, |
107 | .set_state_periodic = meson6_set_periodic, | ||
108 | .set_state_oneshot = meson6_set_oneshot, | ||
109 | .tick_resume = meson6_shutdown, | ||
110 | .set_next_event = meson6_clkevt_next_event, | ||
107 | }; | 111 | }; |
108 | 112 | ||
109 | static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id) | 113 | static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id) |
diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index b7384b853e5a..bcd5c0d602a0 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c | |||
@@ -56,25 +56,6 @@ static int metag_timer_set_next_event(unsigned long delta, | |||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | static void metag_timer_set_mode(enum clock_event_mode mode, | ||
60 | struct clock_event_device *evt) | ||
61 | { | ||
62 | switch (mode) { | ||
63 | case CLOCK_EVT_MODE_ONESHOT: | ||
64 | case CLOCK_EVT_MODE_RESUME: | ||
65 | break; | ||
66 | |||
67 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
68 | /* We should disable the IRQ here */ | ||
69 | break; | ||
70 | |||
71 | case CLOCK_EVT_MODE_PERIODIC: | ||
72 | case CLOCK_EVT_MODE_UNUSED: | ||
73 | WARN_ON(1); | ||
74 | break; | ||
75 | }; | ||
76 | } | ||
77 | |||
78 | static cycle_t metag_clocksource_read(struct clocksource *cs) | 59 | static cycle_t metag_clocksource_read(struct clocksource *cs) |
79 | { | 60 | { |
80 | return __core_reg_get(TXTIMER); | 61 | return __core_reg_get(TXTIMER); |
@@ -129,7 +110,6 @@ static void arch_timer_setup(unsigned int cpu) | |||
129 | clk->rating = 200, | 110 | clk->rating = 200, |
130 | clk->shift = 12, | 111 | clk->shift = 12, |
131 | clk->irq = tbisig_map(TBID_SIGNUM_TRT), | 112 | clk->irq = tbisig_map(TBID_SIGNUM_TRT), |
132 | clk->set_mode = metag_timer_set_mode, | ||
133 | clk->set_next_event = metag_timer_set_next_event, | 113 | clk->set_next_event = metag_timer_set_next_event, |
134 | 114 | ||
135 | clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift); | 115 | clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift); |
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index b81ed1a5342d..c3810b61c815 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c | |||
@@ -33,12 +33,6 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt) | |||
33 | return res; | 33 | return res; |
34 | } | 34 | } |
35 | 35 | ||
36 | static void gic_set_clock_mode(enum clock_event_mode mode, | ||
37 | struct clock_event_device *evt) | ||
38 | { | ||
39 | /* Nothing to do ... */ | ||
40 | } | ||
41 | |||
42 | static irqreturn_t gic_compare_interrupt(int irq, void *dev_id) | 36 | static irqreturn_t gic_compare_interrupt(int irq, void *dev_id) |
43 | { | 37 | { |
44 | struct clock_event_device *cd = dev_id; | 38 | struct clock_event_device *cd = dev_id; |
@@ -67,7 +61,6 @@ static void gic_clockevent_cpu_init(struct clock_event_device *cd) | |||
67 | cd->irq = gic_timer_irq; | 61 | cd->irq = gic_timer_irq; |
68 | cd->cpumask = cpumask_of(cpu); | 62 | cd->cpumask = cpumask_of(cpu); |
69 | cd->set_next_event = gic_next_event; | 63 | cd->set_next_event = gic_next_event; |
70 | cd->set_mode = gic_set_clock_mode; | ||
71 | 64 | ||
72 | clockevents_config_and_register(cd, gic_frequency, 0x300, 0x7fffffff); | 65 | clockevents_config_and_register(cd, gic_frequency, 0x300, 0x7fffffff); |
73 | 66 | ||
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c index 5eb2c35932b1..19857af651c1 100644 --- a/drivers/clocksource/moxart_timer.c +++ b/drivers/clocksource/moxart_timer.c | |||
@@ -58,25 +58,24 @@ | |||
58 | static void __iomem *base; | 58 | static void __iomem *base; |
59 | static unsigned int clock_count_per_tick; | 59 | static unsigned int clock_count_per_tick; |
60 | 60 | ||
61 | static void moxart_clkevt_mode(enum clock_event_mode mode, | 61 | static int moxart_shutdown(struct clock_event_device *evt) |
62 | struct clock_event_device *clk) | ||
63 | { | 62 | { |
64 | switch (mode) { | 63 | writel(TIMER1_DISABLE, base + TIMER_CR); |
65 | case CLOCK_EVT_MODE_RESUME: | 64 | return 0; |
66 | case CLOCK_EVT_MODE_ONESHOT: | 65 | } |
67 | writel(TIMER1_DISABLE, base + TIMER_CR); | 66 | |
68 | writel(~0, base + TIMER1_BASE + REG_LOAD); | 67 | static int moxart_set_oneshot(struct clock_event_device *evt) |
69 | break; | 68 | { |
70 | case CLOCK_EVT_MODE_PERIODIC: | 69 | writel(TIMER1_DISABLE, base + TIMER_CR); |
71 | writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); | 70 | writel(~0, base + TIMER1_BASE + REG_LOAD); |
72 | writel(TIMER1_ENABLE, base + TIMER_CR); | 71 | return 0; |
73 | break; | 72 | } |
74 | case CLOCK_EVT_MODE_UNUSED: | 73 | |
75 | case CLOCK_EVT_MODE_SHUTDOWN: | 74 | static int moxart_set_periodic(struct clock_event_device *evt) |
76 | default: | 75 | { |
77 | writel(TIMER1_DISABLE, base + TIMER_CR); | 76 | writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); |
78 | break; | 77 | writel(TIMER1_ENABLE, base + TIMER_CR); |
79 | } | 78 | return 0; |
80 | } | 79 | } |
81 | 80 | ||
82 | static int moxart_clkevt_next_event(unsigned long cycles, | 81 | static int moxart_clkevt_next_event(unsigned long cycles, |
@@ -95,11 +94,15 @@ static int moxart_clkevt_next_event(unsigned long cycles, | |||
95 | } | 94 | } |
96 | 95 | ||
97 | static struct clock_event_device moxart_clockevent = { | 96 | static struct clock_event_device moxart_clockevent = { |
98 | .name = "moxart_timer", | 97 | .name = "moxart_timer", |
99 | .rating = 200, | 98 | .rating = 200, |
100 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 99 | .features = CLOCK_EVT_FEAT_PERIODIC | |
101 | .set_mode = moxart_clkevt_mode, | 100 | CLOCK_EVT_FEAT_ONESHOT, |
102 | .set_next_event = moxart_clkevt_next_event, | 101 | .set_state_shutdown = moxart_shutdown, |
102 | .set_state_periodic = moxart_set_periodic, | ||
103 | .set_state_oneshot = moxart_set_oneshot, | ||
104 | .tick_resume = moxart_set_oneshot, | ||
105 | .set_next_event = moxart_clkevt_next_event, | ||
103 | }; | 106 | }; |
104 | 107 | ||
105 | static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) | 108 | static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) |
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index 68ab42356d0e..50f0641c65b6 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c | |||
@@ -102,27 +102,20 @@ static void mtk_clkevt_time_start(struct mtk_clock_event_device *evt, | |||
102 | evt->gpt_base + TIMER_CTRL_REG(timer)); | 102 | evt->gpt_base + TIMER_CTRL_REG(timer)); |
103 | } | 103 | } |
104 | 104 | ||
105 | static void mtk_clkevt_mode(enum clock_event_mode mode, | 105 | static int mtk_clkevt_shutdown(struct clock_event_device *clk) |
106 | struct clock_event_device *clk) | 106 | { |
107 | mtk_clkevt_time_stop(to_mtk_clk(clk), GPT_CLK_EVT); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int mtk_clkevt_set_periodic(struct clock_event_device *clk) | ||
107 | { | 112 | { |
108 | struct mtk_clock_event_device *evt = to_mtk_clk(clk); | 113 | struct mtk_clock_event_device *evt = to_mtk_clk(clk); |
109 | 114 | ||
110 | mtk_clkevt_time_stop(evt, GPT_CLK_EVT); | 115 | mtk_clkevt_time_stop(evt, GPT_CLK_EVT); |
111 | 116 | mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT); | |
112 | switch (mode) { | 117 | mtk_clkevt_time_start(evt, true, GPT_CLK_EVT); |
113 | case CLOCK_EVT_MODE_PERIODIC: | 118 | return 0; |
114 | mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT); | ||
115 | mtk_clkevt_time_start(evt, true, GPT_CLK_EVT); | ||
116 | break; | ||
117 | case CLOCK_EVT_MODE_ONESHOT: | ||
118 | /* Timer is enabled in set_next_event */ | ||
119 | break; | ||
120 | case CLOCK_EVT_MODE_UNUSED: | ||
121 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
122 | default: | ||
123 | /* No more interrupts will occur as source is disabled */ | ||
124 | break; | ||
125 | } | ||
126 | } | 119 | } |
127 | 120 | ||
128 | static int mtk_clkevt_next_event(unsigned long event, | 121 | static int mtk_clkevt_next_event(unsigned long event, |
@@ -196,7 +189,10 @@ static void __init mtk_timer_init(struct device_node *node) | |||
196 | evt->dev.name = "mtk_tick"; | 189 | evt->dev.name = "mtk_tick"; |
197 | evt->dev.rating = 300; | 190 | evt->dev.rating = 300; |
198 | evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 191 | evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
199 | evt->dev.set_mode = mtk_clkevt_mode; | 192 | evt->dev.set_state_shutdown = mtk_clkevt_shutdown; |
193 | evt->dev.set_state_periodic = mtk_clkevt_set_periodic; | ||
194 | evt->dev.set_state_oneshot = mtk_clkevt_shutdown; | ||
195 | evt->dev.tick_resume = mtk_clkevt_shutdown; | ||
200 | evt->dev.set_next_event = mtk_clkevt_next_event; | 196 | evt->dev.set_next_event = mtk_clkevt_next_event; |
201 | evt->dev.cpumask = cpu_possible_mask; | 197 | evt->dev.cpumask = cpu_possible_mask; |
202 | 198 | ||
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index 445b68a01dc5..f5ce2961c0d6 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c | |||
@@ -77,7 +77,6 @@ | |||
77 | #define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS 0xf | 77 | #define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS 0xf |
78 | 78 | ||
79 | static struct clock_event_device mxs_clockevent_device; | 79 | static struct clock_event_device mxs_clockevent_device; |
80 | static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED; | ||
81 | 80 | ||
82 | static void __iomem *mxs_timrot_base; | 81 | static void __iomem *mxs_timrot_base; |
83 | static u32 timrot_major_version; | 82 | static u32 timrot_major_version; |
@@ -141,64 +140,49 @@ static struct irqaction mxs_timer_irq = { | |||
141 | .handler = mxs_timer_interrupt, | 140 | .handler = mxs_timer_interrupt, |
142 | }; | 141 | }; |
143 | 142 | ||
144 | #ifdef DEBUG | 143 | static void mxs_irq_clear(char *state) |
145 | static const char *clock_event_mode_label[] const = { | ||
146 | [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", | ||
147 | [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", | ||
148 | [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", | ||
149 | [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED" | ||
150 | }; | ||
151 | #endif /* DEBUG */ | ||
152 | |||
153 | static void mxs_set_mode(enum clock_event_mode mode, | ||
154 | struct clock_event_device *evt) | ||
155 | { | 144 | { |
156 | /* Disable interrupt in timer module */ | 145 | /* Disable interrupt in timer module */ |
157 | timrot_irq_disable(); | 146 | timrot_irq_disable(); |
158 | 147 | ||
159 | if (mode != mxs_clockevent_mode) { | 148 | /* Set event time into the furthest future */ |
160 | /* Set event time into the furthest future */ | 149 | if (timrot_is_v1()) |
161 | if (timrot_is_v1()) | 150 | __raw_writel(0xffff, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1)); |
162 | __raw_writel(0xffff, | 151 | else |
163 | mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1)); | 152 | __raw_writel(0xffffffff, |
164 | else | 153 | mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1)); |
165 | __raw_writel(0xffffffff, | 154 | |
166 | mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1)); | 155 | /* Clear pending interrupt */ |
167 | 156 | timrot_irq_acknowledge(); | |
168 | /* Clear pending interrupt */ | ||
169 | timrot_irq_acknowledge(); | ||
170 | } | ||
171 | 157 | ||
172 | #ifdef DEBUG | 158 | #ifdef DEBUG |
173 | pr_info("%s: changing mode from %s to %s\n", __func__, | 159 | pr_info("%s: changing mode to %s\n", __func__, state) |
174 | clock_event_mode_label[mxs_clockevent_mode], | ||
175 | clock_event_mode_label[mode]); | ||
176 | #endif /* DEBUG */ | 160 | #endif /* DEBUG */ |
161 | } | ||
177 | 162 | ||
178 | /* Remember timer mode */ | 163 | static int mxs_shutdown(struct clock_event_device *evt) |
179 | mxs_clockevent_mode = mode; | 164 | { |
180 | 165 | mxs_irq_clear("shutdown"); | |
181 | switch (mode) { | 166 | |
182 | case CLOCK_EVT_MODE_PERIODIC: | 167 | return 0; |
183 | pr_err("%s: Periodic mode is not implemented\n", __func__); | 168 | } |
184 | break; | 169 | |
185 | case CLOCK_EVT_MODE_ONESHOT: | 170 | static int mxs_set_oneshot(struct clock_event_device *evt) |
186 | timrot_irq_enable(); | 171 | { |
187 | break; | 172 | if (clockevent_state_oneshot(evt)) |
188 | case CLOCK_EVT_MODE_SHUTDOWN: | 173 | mxs_irq_clear("oneshot"); |
189 | case CLOCK_EVT_MODE_UNUSED: | 174 | timrot_irq_enable(); |
190 | case CLOCK_EVT_MODE_RESUME: | 175 | return 0; |
191 | /* Left event sources disabled, no more interrupts appear */ | ||
192 | break; | ||
193 | } | ||
194 | } | 176 | } |
195 | 177 | ||
196 | static struct clock_event_device mxs_clockevent_device = { | 178 | static struct clock_event_device mxs_clockevent_device = { |
197 | .name = "mxs_timrot", | 179 | .name = "mxs_timrot", |
198 | .features = CLOCK_EVT_FEAT_ONESHOT, | 180 | .features = CLOCK_EVT_FEAT_ONESHOT, |
199 | .set_mode = mxs_set_mode, | 181 | .set_state_shutdown = mxs_shutdown, |
200 | .set_next_event = timrotv2_set_next_event, | 182 | .set_state_oneshot = mxs_set_oneshot, |
201 | .rating = 200, | 183 | .tick_resume = mxs_shutdown, |
184 | .set_next_event = timrotv2_set_next_event, | ||
185 | .rating = 200, | ||
202 | }; | 186 | }; |
203 | 187 | ||
204 | static int __init mxs_clockevent_init(struct clk *timer_clk) | 188 | static int __init mxs_clockevent_init(struct clk *timer_clk) |
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index a709cfa49d85..bc8dd443c727 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c | |||
@@ -119,28 +119,27 @@ static void nmdk_clkevt_reset(void) | |||
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | static void nmdk_clkevt_mode(enum clock_event_mode mode, | 122 | static int nmdk_clkevt_shutdown(struct clock_event_device *evt) |
123 | struct clock_event_device *dev) | ||
124 | { | 123 | { |
125 | switch (mode) { | 124 | writel(0, mtu_base + MTU_IMSC); |
126 | case CLOCK_EVT_MODE_PERIODIC: | 125 | /* disable timer */ |
127 | clkevt_periodic = true; | 126 | writel(0, mtu_base + MTU_CR(1)); |
128 | nmdk_clkevt_reset(); | 127 | /* load some high default value */ |
129 | break; | 128 | writel(0xffffffff, mtu_base + MTU_LR(1)); |
130 | case CLOCK_EVT_MODE_ONESHOT: | 129 | return 0; |
131 | clkevt_periodic = false; | 130 | } |
132 | break; | 131 | |
133 | case CLOCK_EVT_MODE_SHUTDOWN: | 132 | static int nmdk_clkevt_set_oneshot(struct clock_event_device *evt) |
134 | case CLOCK_EVT_MODE_UNUSED: | 133 | { |
135 | writel(0, mtu_base + MTU_IMSC); | 134 | clkevt_periodic = false; |
136 | /* disable timer */ | 135 | return 0; |
137 | writel(0, mtu_base + MTU_CR(1)); | 136 | } |
138 | /* load some high default value */ | 137 | |
139 | writel(0xffffffff, mtu_base + MTU_LR(1)); | 138 | static int nmdk_clkevt_set_periodic(struct clock_event_device *evt) |
140 | break; | 139 | { |
141 | case CLOCK_EVT_MODE_RESUME: | 140 | clkevt_periodic = true; |
142 | break; | 141 | nmdk_clkevt_reset(); |
143 | } | 142 | return 0; |
144 | } | 143 | } |
145 | 144 | ||
146 | static void nmdk_clksrc_reset(void) | 145 | static void nmdk_clksrc_reset(void) |
@@ -163,13 +162,16 @@ static void nmdk_clkevt_resume(struct clock_event_device *cedev) | |||
163 | } | 162 | } |
164 | 163 | ||
165 | static struct clock_event_device nmdk_clkevt = { | 164 | static struct clock_event_device nmdk_clkevt = { |
166 | .name = "mtu_1", | 165 | .name = "mtu_1", |
167 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC | | 166 | .features = CLOCK_EVT_FEAT_ONESHOT | |
168 | CLOCK_EVT_FEAT_DYNIRQ, | 167 | CLOCK_EVT_FEAT_PERIODIC | |
169 | .rating = 200, | 168 | CLOCK_EVT_FEAT_DYNIRQ, |
170 | .set_mode = nmdk_clkevt_mode, | 169 | .rating = 200, |
171 | .set_next_event = nmdk_clkevt_next, | 170 | .set_state_shutdown = nmdk_clkevt_shutdown, |
172 | .resume = nmdk_clkevt_resume, | 171 | .set_state_periodic = nmdk_clkevt_set_periodic, |
172 | .set_state_oneshot = nmdk_clkevt_set_oneshot, | ||
173 | .set_next_event = nmdk_clkevt_next, | ||
174 | .resume = nmdk_clkevt_resume, | ||
173 | }; | 175 | }; |
174 | 176 | ||
175 | /* | 177 | /* |
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index d9438af2bbd6..45b6a4999713 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c | |||
@@ -88,26 +88,12 @@ pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) | |||
88 | return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; | 88 | return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static void | 91 | static int pxa_osmr0_shutdown(struct clock_event_device *evt) |
92 | pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) | ||
93 | { | 92 | { |
94 | switch (mode) { | 93 | /* initializing, released, or preparing for suspend */ |
95 | case CLOCK_EVT_MODE_ONESHOT: | 94 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); |
96 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); | 95 | timer_writel(OSSR_M0, OSSR); |
97 | timer_writel(OSSR_M0, OSSR); | 96 | return 0; |
98 | break; | ||
99 | |||
100 | case CLOCK_EVT_MODE_UNUSED: | ||
101 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
102 | /* initializing, released, or preparing for suspend */ | ||
103 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); | ||
104 | timer_writel(OSSR_M0, OSSR); | ||
105 | break; | ||
106 | |||
107 | case CLOCK_EVT_MODE_RESUME: | ||
108 | case CLOCK_EVT_MODE_PERIODIC: | ||
109 | break; | ||
110 | } | ||
111 | } | 97 | } |
112 | 98 | ||
113 | #ifdef CONFIG_PM | 99 | #ifdef CONFIG_PM |
@@ -147,13 +133,14 @@ static void pxa_timer_resume(struct clock_event_device *cedev) | |||
147 | #endif | 133 | #endif |
148 | 134 | ||
149 | static struct clock_event_device ckevt_pxa_osmr0 = { | 135 | static struct clock_event_device ckevt_pxa_osmr0 = { |
150 | .name = "osmr0", | 136 | .name = "osmr0", |
151 | .features = CLOCK_EVT_FEAT_ONESHOT, | 137 | .features = CLOCK_EVT_FEAT_ONESHOT, |
152 | .rating = 200, | 138 | .rating = 200, |
153 | .set_next_event = pxa_osmr0_set_next_event, | 139 | .set_next_event = pxa_osmr0_set_next_event, |
154 | .set_mode = pxa_osmr0_set_mode, | 140 | .set_state_shutdown = pxa_osmr0_shutdown, |
155 | .suspend = pxa_timer_suspend, | 141 | .set_state_oneshot = pxa_osmr0_shutdown, |
156 | .resume = pxa_timer_resume, | 142 | .suspend = pxa_timer_suspend, |
143 | .resume = pxa_timer_resume, | ||
157 | }; | 144 | }; |
158 | 145 | ||
159 | static struct irqaction pxa_ost0_irq = { | 146 | static struct irqaction pxa_ost0_irq = { |
diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c index cba2d015564c..f8e09f923651 100644 --- a/drivers/clocksource/qcom-timer.c +++ b/drivers/clocksource/qcom-timer.c | |||
@@ -47,7 +47,7 @@ static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) | |||
47 | { | 47 | { |
48 | struct clock_event_device *evt = dev_id; | 48 | struct clock_event_device *evt = dev_id; |
49 | /* Stop the timer tick */ | 49 | /* Stop the timer tick */ |
50 | if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { | 50 | if (clockevent_state_oneshot(evt)) { |
51 | u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); | 51 | u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); |
52 | ctrl &= ~TIMER_ENABLE_EN; | 52 | ctrl &= ~TIMER_ENABLE_EN; |
53 | writel_relaxed(ctrl, event_base + TIMER_ENABLE); | 53 | writel_relaxed(ctrl, event_base + TIMER_ENABLE); |
@@ -75,26 +75,14 @@ static int msm_timer_set_next_event(unsigned long cycles, | |||
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void msm_timer_set_mode(enum clock_event_mode mode, | 78 | static int msm_timer_shutdown(struct clock_event_device *evt) |
79 | struct clock_event_device *evt) | ||
80 | { | 79 | { |
81 | u32 ctrl; | 80 | u32 ctrl; |
82 | 81 | ||
83 | ctrl = readl_relaxed(event_base + TIMER_ENABLE); | 82 | ctrl = readl_relaxed(event_base + TIMER_ENABLE); |
84 | ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); | 83 | ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); |
85 | |||
86 | switch (mode) { | ||
87 | case CLOCK_EVT_MODE_RESUME: | ||
88 | case CLOCK_EVT_MODE_PERIODIC: | ||
89 | break; | ||
90 | case CLOCK_EVT_MODE_ONESHOT: | ||
91 | /* Timer is enabled in set_next_event */ | ||
92 | break; | ||
93 | case CLOCK_EVT_MODE_UNUSED: | ||
94 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
95 | break; | ||
96 | } | ||
97 | writel_relaxed(ctrl, event_base + TIMER_ENABLE); | 84 | writel_relaxed(ctrl, event_base + TIMER_ENABLE); |
85 | return 0; | ||
98 | } | 86 | } |
99 | 87 | ||
100 | static struct clock_event_device __percpu *msm_evt; | 88 | static struct clock_event_device __percpu *msm_evt; |
@@ -126,7 +114,9 @@ static int msm_local_timer_setup(struct clock_event_device *evt) | |||
126 | evt->name = "msm_timer"; | 114 | evt->name = "msm_timer"; |
127 | evt->features = CLOCK_EVT_FEAT_ONESHOT; | 115 | evt->features = CLOCK_EVT_FEAT_ONESHOT; |
128 | evt->rating = 200; | 116 | evt->rating = 200; |
129 | evt->set_mode = msm_timer_set_mode; | 117 | evt->set_state_shutdown = msm_timer_shutdown; |
118 | evt->set_state_oneshot = msm_timer_shutdown; | ||
119 | evt->tick_resume = msm_timer_shutdown; | ||
130 | evt->set_next_event = msm_timer_set_next_event; | 120 | evt->set_next_event = msm_timer_set_next_event; |
131 | evt->cpumask = cpumask_of(cpu); | 121 | evt->cpumask = cpumask_of(cpu); |
132 | 122 | ||
@@ -147,7 +137,7 @@ static int msm_local_timer_setup(struct clock_event_device *evt) | |||
147 | 137 | ||
148 | static void msm_local_timer_stop(struct clock_event_device *evt) | 138 | static void msm_local_timer_stop(struct clock_event_device *evt) |
149 | { | 139 | { |
150 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 140 | evt->set_state_shutdown(evt); |
151 | disable_percpu_irq(evt->irq); | 141 | disable_percpu_irq(evt->irq); |
152 | } | 142 | } |
153 | 143 | ||
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index a35993bafb20..bb2c2b050964 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c | |||
@@ -82,23 +82,18 @@ static inline int rk_timer_set_next_event(unsigned long cycles, | |||
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline void rk_timer_set_mode(enum clock_event_mode mode, | 85 | static int rk_timer_shutdown(struct clock_event_device *ce) |
86 | struct clock_event_device *ce) | ||
87 | { | 86 | { |
88 | switch (mode) { | 87 | rk_timer_disable(ce); |
89 | case CLOCK_EVT_MODE_PERIODIC: | 88 | return 0; |
90 | rk_timer_disable(ce); | 89 | } |
91 | rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce); | 90 | |
92 | rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING); | 91 | static int rk_timer_set_periodic(struct clock_event_device *ce) |
93 | break; | 92 | { |
94 | case CLOCK_EVT_MODE_ONESHOT: | 93 | rk_timer_disable(ce); |
95 | case CLOCK_EVT_MODE_RESUME: | 94 | rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce); |
96 | break; | 95 | rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING); |
97 | case CLOCK_EVT_MODE_UNUSED: | 96 | return 0; |
98 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
99 | rk_timer_disable(ce); | ||
100 | break; | ||
101 | } | ||
102 | } | 97 | } |
103 | 98 | ||
104 | static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) | 99 | static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) |
@@ -107,7 +102,7 @@ static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) | |||
107 | 102 | ||
108 | rk_timer_interrupt_clear(ce); | 103 | rk_timer_interrupt_clear(ce); |
109 | 104 | ||
110 | if (ce->mode == CLOCK_EVT_MODE_ONESHOT) | 105 | if (clockevent_state_oneshot(ce)) |
111 | rk_timer_disable(ce); | 106 | rk_timer_disable(ce); |
112 | 107 | ||
113 | ce->event_handler(ce); | 108 | ce->event_handler(ce); |
@@ -161,7 +156,8 @@ static void __init rk_timer_init(struct device_node *np) | |||
161 | ce->name = TIMER_NAME; | 156 | ce->name = TIMER_NAME; |
162 | ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 157 | ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
163 | ce->set_next_event = rk_timer_set_next_event; | 158 | ce->set_next_event = rk_timer_set_next_event; |
164 | ce->set_mode = rk_timer_set_mode; | 159 | ce->set_state_shutdown = rk_timer_shutdown; |
160 | ce->set_state_periodic = rk_timer_set_periodic; | ||
165 | ce->irq = irq; | 161 | ce->irq = irq; |
166 | ce->cpumask = cpumask_of(0); | 162 | ce->cpumask = cpumask_of(0); |
167 | ce->rating = 250; | 163 | ce->rating = 250; |
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 5645cfc90c41..bc90e13338cc 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c | |||
@@ -207,25 +207,18 @@ static int samsung_set_next_event(unsigned long cycles, | |||
207 | return 0; | 207 | return 0; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void samsung_set_mode(enum clock_event_mode mode, | 210 | static int samsung_shutdown(struct clock_event_device *evt) |
211 | struct clock_event_device *evt) | ||
212 | { | 211 | { |
213 | samsung_time_stop(pwm.event_id); | 212 | samsung_time_stop(pwm.event_id); |
213 | return 0; | ||
214 | } | ||
214 | 215 | ||
215 | switch (mode) { | 216 | static int samsung_set_periodic(struct clock_event_device *evt) |
216 | case CLOCK_EVT_MODE_PERIODIC: | 217 | { |
217 | samsung_time_setup(pwm.event_id, pwm.clock_count_per_tick - 1); | 218 | samsung_time_stop(pwm.event_id); |
218 | samsung_time_start(pwm.event_id, true); | 219 | samsung_time_setup(pwm.event_id, pwm.clock_count_per_tick - 1); |
219 | break; | 220 | samsung_time_start(pwm.event_id, true); |
220 | 221 | return 0; | |
221 | case CLOCK_EVT_MODE_ONESHOT: | ||
222 | break; | ||
223 | |||
224 | case CLOCK_EVT_MODE_UNUSED: | ||
225 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
226 | case CLOCK_EVT_MODE_RESUME: | ||
227 | break; | ||
228 | } | ||
229 | } | 222 | } |
230 | 223 | ||
231 | static void samsung_clockevent_resume(struct clock_event_device *cev) | 224 | static void samsung_clockevent_resume(struct clock_event_device *cev) |
@@ -240,12 +233,16 @@ static void samsung_clockevent_resume(struct clock_event_device *cev) | |||
240 | } | 233 | } |
241 | 234 | ||
242 | static struct clock_event_device time_event_device = { | 235 | static struct clock_event_device time_event_device = { |
243 | .name = "samsung_event_timer", | 236 | .name = "samsung_event_timer", |
244 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 237 | .features = CLOCK_EVT_FEAT_PERIODIC | |
245 | .rating = 200, | 238 | CLOCK_EVT_FEAT_ONESHOT, |
246 | .set_next_event = samsung_set_next_event, | 239 | .rating = 200, |
247 | .set_mode = samsung_set_mode, | 240 | .set_next_event = samsung_set_next_event, |
248 | .resume = samsung_clockevent_resume, | 241 | .set_state_shutdown = samsung_shutdown, |
242 | .set_state_periodic = samsung_set_periodic, | ||
243 | .set_state_oneshot = samsung_shutdown, | ||
244 | .tick_resume = samsung_shutdown, | ||
245 | .resume = samsung_clockevent_resume, | ||
249 | }; | 246 | }; |
250 | 247 | ||
251 | static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) | 248 | static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index c96de14036a0..ba73a6eb8d66 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -538,7 +538,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) | |||
538 | 538 | ||
539 | if (ch->flags & FLAG_CLOCKEVENT) { | 539 | if (ch->flags & FLAG_CLOCKEVENT) { |
540 | if (!(ch->flags & FLAG_SKIPEVENT)) { | 540 | if (!(ch->flags & FLAG_SKIPEVENT)) { |
541 | if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT) { | 541 | if (clockevent_state_oneshot(&ch->ced)) { |
542 | ch->next_match_value = ch->max_match_value; | 542 | ch->next_match_value = ch->max_match_value; |
543 | ch->flags |= FLAG_REPROGRAM; | 543 | ch->flags |= FLAG_REPROGRAM; |
544 | } | 544 | } |
@@ -554,7 +554,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) | |||
554 | sh_cmt_clock_event_program_verify(ch, 1); | 554 | sh_cmt_clock_event_program_verify(ch, 1); |
555 | 555 | ||
556 | if (ch->flags & FLAG_CLOCKEVENT) | 556 | if (ch->flags & FLAG_CLOCKEVENT) |
557 | if ((ch->ced.mode == CLOCK_EVT_MODE_SHUTDOWN) | 557 | if ((clockevent_state_shutdown(&ch->ced)) |
558 | || (ch->match_value == ch->next_match_value)) | 558 | || (ch->match_value == ch->next_match_value)) |
559 | ch->flags &= ~FLAG_REPROGRAM; | 559 | ch->flags &= ~FLAG_REPROGRAM; |
560 | } | 560 | } |
@@ -726,39 +726,37 @@ static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic) | |||
726 | sh_cmt_set_next(ch, ch->max_match_value); | 726 | sh_cmt_set_next(ch, ch->max_match_value); |
727 | } | 727 | } |
728 | 728 | ||
729 | static void sh_cmt_clock_event_mode(enum clock_event_mode mode, | 729 | static int sh_cmt_clock_event_shutdown(struct clock_event_device *ced) |
730 | struct clock_event_device *ced) | 730 | { |
731 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); | ||
732 | |||
733 | sh_cmt_stop(ch, FLAG_CLOCKEVENT); | ||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static int sh_cmt_clock_event_set_state(struct clock_event_device *ced, | ||
738 | int periodic) | ||
731 | { | 739 | { |
732 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); | 740 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); |
733 | 741 | ||
734 | /* deal with old setting first */ | 742 | /* deal with old setting first */ |
735 | switch (ced->mode) { | 743 | if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) |
736 | case CLOCK_EVT_MODE_PERIODIC: | ||
737 | case CLOCK_EVT_MODE_ONESHOT: | ||
738 | sh_cmt_stop(ch, FLAG_CLOCKEVENT); | 744 | sh_cmt_stop(ch, FLAG_CLOCKEVENT); |
739 | break; | ||
740 | default: | ||
741 | break; | ||
742 | } | ||
743 | 745 | ||
744 | switch (mode) { | 746 | dev_info(&ch->cmt->pdev->dev, "ch%u: used for %s clock events\n", |
745 | case CLOCK_EVT_MODE_PERIODIC: | 747 | ch->index, periodic ? "periodic" : "oneshot"); |
746 | dev_info(&ch->cmt->pdev->dev, | 748 | sh_cmt_clock_event_start(ch, periodic); |
747 | "ch%u: used for periodic clock events\n", ch->index); | 749 | return 0; |
748 | sh_cmt_clock_event_start(ch, 1); | 750 | } |
749 | break; | 751 | |
750 | case CLOCK_EVT_MODE_ONESHOT: | 752 | static int sh_cmt_clock_event_set_oneshot(struct clock_event_device *ced) |
751 | dev_info(&ch->cmt->pdev->dev, | 753 | { |
752 | "ch%u: used for oneshot clock events\n", ch->index); | 754 | return sh_cmt_clock_event_set_state(ced, 0); |
753 | sh_cmt_clock_event_start(ch, 0); | 755 | } |
754 | break; | 756 | |
755 | case CLOCK_EVT_MODE_SHUTDOWN: | 757 | static int sh_cmt_clock_event_set_periodic(struct clock_event_device *ced) |
756 | case CLOCK_EVT_MODE_UNUSED: | 758 | { |
757 | sh_cmt_stop(ch, FLAG_CLOCKEVENT); | 759 | return sh_cmt_clock_event_set_state(ced, 1); |
758 | break; | ||
759 | default: | ||
760 | break; | ||
761 | } | ||
762 | } | 760 | } |
763 | 761 | ||
764 | static int sh_cmt_clock_event_next(unsigned long delta, | 762 | static int sh_cmt_clock_event_next(unsigned long delta, |
@@ -766,7 +764,7 @@ static int sh_cmt_clock_event_next(unsigned long delta, | |||
766 | { | 764 | { |
767 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); | 765 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); |
768 | 766 | ||
769 | BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); | 767 | BUG_ON(!clockevent_state_oneshot(ced)); |
770 | if (likely(ch->flags & FLAG_IRQCONTEXT)) | 768 | if (likely(ch->flags & FLAG_IRQCONTEXT)) |
771 | ch->next_match_value = delta - 1; | 769 | ch->next_match_value = delta - 1; |
772 | else | 770 | else |
@@ -820,7 +818,9 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, | |||
820 | ced->rating = 125; | 818 | ced->rating = 125; |
821 | ced->cpumask = cpu_possible_mask; | 819 | ced->cpumask = cpu_possible_mask; |
822 | ced->set_next_event = sh_cmt_clock_event_next; | 820 | ced->set_next_event = sh_cmt_clock_event_next; |
823 | ced->set_mode = sh_cmt_clock_event_mode; | 821 | ced->set_state_shutdown = sh_cmt_clock_event_shutdown; |
822 | ced->set_state_periodic = sh_cmt_clock_event_set_periodic; | ||
823 | ced->set_state_oneshot = sh_cmt_clock_event_set_oneshot; | ||
824 | ced->suspend = sh_cmt_clock_event_suspend; | 824 | ced->suspend = sh_cmt_clock_event_suspend; |
825 | ced->resume = sh_cmt_clock_event_resume; | 825 | ced->resume = sh_cmt_clock_event_resume; |
826 | 826 | ||
@@ -935,9 +935,6 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt) | |||
935 | static const struct platform_device_id sh_cmt_id_table[] = { | 935 | static const struct platform_device_id sh_cmt_id_table[] = { |
936 | { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] }, | 936 | { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] }, |
937 | { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] }, | 937 | { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] }, |
938 | { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] }, | ||
939 | { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] }, | ||
940 | { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] }, | ||
941 | { } | 938 | { } |
942 | }; | 939 | }; |
943 | MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); | 940 | MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); |
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 3d88698cf2b8..f1985da8113f 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -276,36 +276,25 @@ static struct sh_mtu2_channel *ced_to_sh_mtu2(struct clock_event_device *ced) | |||
276 | return container_of(ced, struct sh_mtu2_channel, ced); | 276 | return container_of(ced, struct sh_mtu2_channel, ced); |
277 | } | 277 | } |
278 | 278 | ||
279 | static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, | 279 | static int sh_mtu2_clock_event_shutdown(struct clock_event_device *ced) |
280 | struct clock_event_device *ced) | ||
281 | { | 280 | { |
282 | struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced); | 281 | struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced); |
283 | int disabled = 0; | ||
284 | 282 | ||
285 | /* deal with old setting first */ | 283 | sh_mtu2_disable(ch); |
286 | switch (ced->mode) { | 284 | return 0; |
287 | case CLOCK_EVT_MODE_PERIODIC: | 285 | } |
286 | |||
287 | static int sh_mtu2_clock_event_set_periodic(struct clock_event_device *ced) | ||
288 | { | ||
289 | struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced); | ||
290 | |||
291 | if (clockevent_state_periodic(ced)) | ||
288 | sh_mtu2_disable(ch); | 292 | sh_mtu2_disable(ch); |
289 | disabled = 1; | ||
290 | break; | ||
291 | default: | ||
292 | break; | ||
293 | } | ||
294 | 293 | ||
295 | switch (mode) { | 294 | dev_info(&ch->mtu->pdev->dev, "ch%u: used for periodic clock events\n", |
296 | case CLOCK_EVT_MODE_PERIODIC: | 295 | ch->index); |
297 | dev_info(&ch->mtu->pdev->dev, | 296 | sh_mtu2_enable(ch); |
298 | "ch%u: used for periodic clock events\n", ch->index); | 297 | return 0; |
299 | sh_mtu2_enable(ch); | ||
300 | break; | ||
301 | case CLOCK_EVT_MODE_UNUSED: | ||
302 | if (!disabled) | ||
303 | sh_mtu2_disable(ch); | ||
304 | break; | ||
305 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
306 | default: | ||
307 | break; | ||
308 | } | ||
309 | } | 298 | } |
310 | 299 | ||
311 | static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced) | 300 | static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced) |
@@ -327,7 +316,8 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch, | |||
327 | ced->features = CLOCK_EVT_FEAT_PERIODIC; | 316 | ced->features = CLOCK_EVT_FEAT_PERIODIC; |
328 | ced->rating = 200; | 317 | ced->rating = 200; |
329 | ced->cpumask = cpu_possible_mask; | 318 | ced->cpumask = cpu_possible_mask; |
330 | ced->set_mode = sh_mtu2_clock_event_mode; | 319 | ced->set_state_shutdown = sh_mtu2_clock_event_shutdown; |
320 | ced->set_state_periodic = sh_mtu2_clock_event_set_periodic; | ||
331 | ced->suspend = sh_mtu2_clock_event_suspend; | 321 | ced->suspend = sh_mtu2_clock_event_suspend; |
332 | ced->resume = sh_mtu2_clock_event_resume; | 322 | ced->resume = sh_mtu2_clock_event_resume; |
333 | 323 | ||
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index b6b8fa3cd211..469e776ec17a 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -240,7 +240,7 @@ static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id) | |||
240 | struct sh_tmu_channel *ch = dev_id; | 240 | struct sh_tmu_channel *ch = dev_id; |
241 | 241 | ||
242 | /* disable or acknowledge interrupt */ | 242 | /* disable or acknowledge interrupt */ |
243 | if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT) | 243 | if (clockevent_state_oneshot(&ch->ced)) |
244 | sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); | 244 | sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); |
245 | else | 245 | else |
246 | sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4); | 246 | sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4); |
@@ -358,42 +358,38 @@ static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic) | |||
358 | } | 358 | } |
359 | } | 359 | } |
360 | 360 | ||
361 | static void sh_tmu_clock_event_mode(enum clock_event_mode mode, | 361 | static int sh_tmu_clock_event_shutdown(struct clock_event_device *ced) |
362 | struct clock_event_device *ced) | 362 | { |
363 | struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); | ||
364 | |||
365 | if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) | ||
366 | sh_tmu_disable(ch); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int sh_tmu_clock_event_set_state(struct clock_event_device *ced, | ||
371 | int periodic) | ||
363 | { | 372 | { |
364 | struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); | 373 | struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); |
365 | int disabled = 0; | ||
366 | 374 | ||
367 | /* deal with old setting first */ | 375 | /* deal with old setting first */ |
368 | switch (ced->mode) { | 376 | if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) |
369 | case CLOCK_EVT_MODE_PERIODIC: | ||
370 | case CLOCK_EVT_MODE_ONESHOT: | ||
371 | sh_tmu_disable(ch); | 377 | sh_tmu_disable(ch); |
372 | disabled = 1; | ||
373 | break; | ||
374 | default: | ||
375 | break; | ||
376 | } | ||
377 | 378 | ||
378 | switch (mode) { | 379 | dev_info(&ch->tmu->pdev->dev, "ch%u: used for %s clock events\n", |
379 | case CLOCK_EVT_MODE_PERIODIC: | 380 | ch->index, periodic ? "periodic" : "oneshot"); |
380 | dev_info(&ch->tmu->pdev->dev, | 381 | sh_tmu_clock_event_start(ch, periodic); |
381 | "ch%u: used for periodic clock events\n", ch->index); | 382 | return 0; |
382 | sh_tmu_clock_event_start(ch, 1); | 383 | } |
383 | break; | 384 | |
384 | case CLOCK_EVT_MODE_ONESHOT: | 385 | static int sh_tmu_clock_event_set_oneshot(struct clock_event_device *ced) |
385 | dev_info(&ch->tmu->pdev->dev, | 386 | { |
386 | "ch%u: used for oneshot clock events\n", ch->index); | 387 | return sh_tmu_clock_event_set_state(ced, 0); |
387 | sh_tmu_clock_event_start(ch, 0); | 388 | } |
388 | break; | 389 | |
389 | case CLOCK_EVT_MODE_UNUSED: | 390 | static int sh_tmu_clock_event_set_periodic(struct clock_event_device *ced) |
390 | if (!disabled) | 391 | { |
391 | sh_tmu_disable(ch); | 392 | return sh_tmu_clock_event_set_state(ced, 1); |
392 | break; | ||
393 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
394 | default: | ||
395 | break; | ||
396 | } | ||
397 | } | 393 | } |
398 | 394 | ||
399 | static int sh_tmu_clock_event_next(unsigned long delta, | 395 | static int sh_tmu_clock_event_next(unsigned long delta, |
@@ -401,7 +397,7 @@ static int sh_tmu_clock_event_next(unsigned long delta, | |||
401 | { | 397 | { |
402 | struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); | 398 | struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); |
403 | 399 | ||
404 | BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); | 400 | BUG_ON(!clockevent_state_oneshot(ced)); |
405 | 401 | ||
406 | /* program new delta value */ | 402 | /* program new delta value */ |
407 | sh_tmu_set_next(ch, delta, 0); | 403 | sh_tmu_set_next(ch, delta, 0); |
@@ -430,7 +426,9 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch, | |||
430 | ced->rating = 200; | 426 | ced->rating = 200; |
431 | ced->cpumask = cpu_possible_mask; | 427 | ced->cpumask = cpu_possible_mask; |
432 | ced->set_next_event = sh_tmu_clock_event_next; | 428 | ced->set_next_event = sh_tmu_clock_event_next; |
433 | ced->set_mode = sh_tmu_clock_event_mode; | 429 | ced->set_state_shutdown = sh_tmu_clock_event_shutdown; |
430 | ced->set_state_periodic = sh_tmu_clock_event_set_periodic; | ||
431 | ced->set_state_oneshot = sh_tmu_clock_event_set_oneshot; | ||
434 | ced->suspend = sh_tmu_clock_event_suspend; | 432 | ced->suspend = sh_tmu_clock_event_suspend; |
435 | ced->resume = sh_tmu_clock_event_resume; | 433 | ced->resume = sh_tmu_clock_event_resume; |
436 | 434 | ||
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 1928a8912584..6f3719d73390 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
@@ -81,25 +81,25 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic) | |||
81 | timer_base + TIMER_CTL_REG(timer)); | 81 | timer_base + TIMER_CTL_REG(timer)); |
82 | } | 82 | } |
83 | 83 | ||
84 | static void sun4i_clkevt_mode(enum clock_event_mode mode, | 84 | static int sun4i_clkevt_shutdown(struct clock_event_device *evt) |
85 | struct clock_event_device *clk) | ||
86 | { | 85 | { |
87 | switch (mode) { | 86 | sun4i_clkevt_time_stop(0); |
88 | case CLOCK_EVT_MODE_PERIODIC: | 87 | return 0; |
89 | sun4i_clkevt_time_stop(0); | 88 | } |
90 | sun4i_clkevt_time_setup(0, ticks_per_jiffy); | 89 | |
91 | sun4i_clkevt_time_start(0, true); | 90 | static int sun4i_clkevt_set_oneshot(struct clock_event_device *evt) |
92 | break; | 91 | { |
93 | case CLOCK_EVT_MODE_ONESHOT: | 92 | sun4i_clkevt_time_stop(0); |
94 | sun4i_clkevt_time_stop(0); | 93 | sun4i_clkevt_time_start(0, false); |
95 | sun4i_clkevt_time_start(0, false); | 94 | return 0; |
96 | break; | 95 | } |
97 | case CLOCK_EVT_MODE_UNUSED: | 96 | |
98 | case CLOCK_EVT_MODE_SHUTDOWN: | 97 | static int sun4i_clkevt_set_periodic(struct clock_event_device *evt) |
99 | default: | 98 | { |
100 | sun4i_clkevt_time_stop(0); | 99 | sun4i_clkevt_time_stop(0); |
101 | break; | 100 | sun4i_clkevt_time_setup(0, ticks_per_jiffy); |
102 | } | 101 | sun4i_clkevt_time_start(0, true); |
102 | return 0; | ||
103 | } | 103 | } |
104 | 104 | ||
105 | static int sun4i_clkevt_next_event(unsigned long evt, | 105 | static int sun4i_clkevt_next_event(unsigned long evt, |
@@ -116,7 +116,10 @@ static struct clock_event_device sun4i_clockevent = { | |||
116 | .name = "sun4i_tick", | 116 | .name = "sun4i_tick", |
117 | .rating = 350, | 117 | .rating = 350, |
118 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 118 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
119 | .set_mode = sun4i_clkevt_mode, | 119 | .set_state_shutdown = sun4i_clkevt_shutdown, |
120 | .set_state_periodic = sun4i_clkevt_set_periodic, | ||
121 | .set_state_oneshot = sun4i_clkevt_set_oneshot, | ||
122 | .tick_resume = sun4i_clkevt_shutdown, | ||
120 | .set_next_event = sun4i_clkevt_next_event, | 123 | .set_next_event = sun4i_clkevt_next_event, |
121 | }; | 124 | }; |
122 | 125 | ||
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 8bdbc45c6dad..d28d2fe798d5 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c | |||
@@ -91,55 +91,62 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) | |||
91 | */ | 91 | */ |
92 | static u32 timer_clock; | 92 | static u32 timer_clock; |
93 | 93 | ||
94 | static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) | 94 | static int tc_shutdown(struct clock_event_device *d) |
95 | { | 95 | { |
96 | struct tc_clkevt_device *tcd = to_tc_clkevt(d); | 96 | struct tc_clkevt_device *tcd = to_tc_clkevt(d); |
97 | void __iomem *regs = tcd->regs; | 97 | void __iomem *regs = tcd->regs; |
98 | 98 | ||
99 | if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC | 99 | __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); |
100 | || tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) { | 100 | __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); |
101 | __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); | 101 | clk_disable(tcd->clk); |
102 | __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); | ||
103 | clk_disable(tcd->clk); | ||
104 | } | ||
105 | 102 | ||
106 | switch (m) { | 103 | return 0; |
104 | } | ||
107 | 105 | ||
108 | /* By not making the gentime core emulate periodic mode on top | 106 | static int tc_set_oneshot(struct clock_event_device *d) |
109 | * of oneshot, we get lower overhead and improved accuracy. | 107 | { |
110 | */ | 108 | struct tc_clkevt_device *tcd = to_tc_clkevt(d); |
111 | case CLOCK_EVT_MODE_PERIODIC: | 109 | void __iomem *regs = tcd->regs; |
112 | clk_enable(tcd->clk); | ||
113 | 110 | ||
114 | /* slow clock, count up to RC, then irq and restart */ | 111 | if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) |
115 | __raw_writel(timer_clock | 112 | tc_shutdown(d); |
116 | | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, | ||
117 | regs + ATMEL_TC_REG(2, CMR)); | ||
118 | __raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); | ||
119 | 113 | ||
120 | /* Enable clock and interrupts on RC compare */ | 114 | clk_enable(tcd->clk); |
121 | __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); | ||
122 | 115 | ||
123 | /* go go gadget! */ | 116 | /* slow clock, count up to RC, then irq and stop */ |
124 | __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, | 117 | __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE | |
125 | regs + ATMEL_TC_REG(2, CCR)); | 118 | ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR)); |
126 | break; | 119 | __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); |
127 | 120 | ||
128 | case CLOCK_EVT_MODE_ONESHOT: | 121 | /* set_next_event() configures and starts the timer */ |
129 | clk_enable(tcd->clk); | 122 | return 0; |
123 | } | ||
130 | 124 | ||
131 | /* slow clock, count up to RC, then irq and stop */ | 125 | static int tc_set_periodic(struct clock_event_device *d) |
132 | __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | 126 | { |
133 | | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, | 127 | struct tc_clkevt_device *tcd = to_tc_clkevt(d); |
134 | regs + ATMEL_TC_REG(2, CMR)); | 128 | void __iomem *regs = tcd->regs; |
135 | __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); | ||
136 | 129 | ||
137 | /* set_next_event() configures and starts the timer */ | 130 | if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) |
138 | break; | 131 | tc_shutdown(d); |
139 | 132 | ||
140 | default: | 133 | /* By not making the gentime core emulate periodic mode on top |
141 | break; | 134 | * of oneshot, we get lower overhead and improved accuracy. |
142 | } | 135 | */ |
136 | clk_enable(tcd->clk); | ||
137 | |||
138 | /* slow clock, count up to RC, then irq and restart */ | ||
139 | __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, | ||
140 | regs + ATMEL_TC_REG(2, CMR)); | ||
141 | __raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); | ||
142 | |||
143 | /* Enable clock and interrupts on RC compare */ | ||
144 | __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); | ||
145 | |||
146 | /* go go gadget! */ | ||
147 | __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs + | ||
148 | ATMEL_TC_REG(2, CCR)); | ||
149 | return 0; | ||
143 | } | 150 | } |
144 | 151 | ||
145 | static int tc_next_event(unsigned long delta, struct clock_event_device *d) | 152 | static int tc_next_event(unsigned long delta, struct clock_event_device *d) |
@@ -154,13 +161,15 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d) | |||
154 | 161 | ||
155 | static struct tc_clkevt_device clkevt = { | 162 | static struct tc_clkevt_device clkevt = { |
156 | .clkevt = { | 163 | .clkevt = { |
157 | .name = "tc_clkevt", | 164 | .name = "tc_clkevt", |
158 | .features = CLOCK_EVT_FEAT_PERIODIC | 165 | .features = CLOCK_EVT_FEAT_PERIODIC | |
159 | | CLOCK_EVT_FEAT_ONESHOT, | 166 | CLOCK_EVT_FEAT_ONESHOT, |
160 | /* Should be lower than at91rm9200's system timer */ | 167 | /* Should be lower than at91rm9200's system timer */ |
161 | .rating = 125, | 168 | .rating = 125, |
162 | .set_next_event = tc_next_event, | 169 | .set_next_event = tc_next_event, |
163 | .set_mode = tc_mode, | 170 | .set_state_shutdown = tc_shutdown, |
171 | .set_state_periodic = tc_set_periodic, | ||
172 | .set_state_oneshot = tc_set_oneshot, | ||
164 | }, | 173 | }, |
165 | }; | 174 | }; |
166 | 175 | ||
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 5a112d72fc2d..6ebda1177e79 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -72,33 +72,36 @@ static int tegra_timer_set_next_event(unsigned long cycles, | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static void tegra_timer_set_mode(enum clock_event_mode mode, | 75 | static inline void timer_shutdown(struct clock_event_device *evt) |
76 | struct clock_event_device *evt) | ||
77 | { | 76 | { |
78 | u32 reg; | ||
79 | |||
80 | timer_writel(0, TIMER3_BASE + TIMER_PTV); | 77 | timer_writel(0, TIMER3_BASE + TIMER_PTV); |
78 | } | ||
81 | 79 | ||
82 | switch (mode) { | 80 | static int tegra_timer_shutdown(struct clock_event_device *evt) |
83 | case CLOCK_EVT_MODE_PERIODIC: | 81 | { |
84 | reg = 0xC0000000 | ((1000000/HZ)-1); | 82 | timer_shutdown(evt); |
85 | timer_writel(reg, TIMER3_BASE + TIMER_PTV); | 83 | return 0; |
86 | break; | 84 | } |
87 | case CLOCK_EVT_MODE_ONESHOT: | 85 | |
88 | break; | 86 | static int tegra_timer_set_periodic(struct clock_event_device *evt) |
89 | case CLOCK_EVT_MODE_UNUSED: | 87 | { |
90 | case CLOCK_EVT_MODE_SHUTDOWN: | 88 | u32 reg = 0xC0000000 | ((1000000 / HZ) - 1); |
91 | case CLOCK_EVT_MODE_RESUME: | 89 | |
92 | break; | 90 | timer_shutdown(evt); |
93 | } | 91 | timer_writel(reg, TIMER3_BASE + TIMER_PTV); |
92 | return 0; | ||
94 | } | 93 | } |
95 | 94 | ||
96 | static struct clock_event_device tegra_clockevent = { | 95 | static struct clock_event_device tegra_clockevent = { |
97 | .name = "timer0", | 96 | .name = "timer0", |
98 | .rating = 300, | 97 | .rating = 300, |
99 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 98 | .features = CLOCK_EVT_FEAT_ONESHOT | |
100 | .set_next_event = tegra_timer_set_next_event, | 99 | CLOCK_EVT_FEAT_PERIODIC, |
101 | .set_mode = tegra_timer_set_mode, | 100 | .set_next_event = tegra_timer_set_next_event, |
101 | .set_state_shutdown = tegra_timer_shutdown, | ||
102 | .set_state_periodic = tegra_timer_set_periodic, | ||
103 | .set_state_oneshot = tegra_timer_shutdown, | ||
104 | .tick_resume = tegra_timer_shutdown, | ||
102 | }; | 105 | }; |
103 | 106 | ||
104 | static u64 notrace tegra_read_sched_clock(void) | 107 | static u64 notrace tegra_read_sched_clock(void) |
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 0c8c5e337540..2162796fd504 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
@@ -121,33 +121,33 @@ armada_370_xp_clkevt_next_event(unsigned long delta, | |||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | 123 | ||
124 | static void | 124 | static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) |
125 | armada_370_xp_clkevt_mode(enum clock_event_mode mode, | ||
126 | struct clock_event_device *dev) | ||
127 | { | 125 | { |
128 | if (mode == CLOCK_EVT_MODE_PERIODIC) { | 126 | /* |
127 | * Disable timer. | ||
128 | */ | ||
129 | local_timer_ctrl_clrset(TIMER0_EN, 0); | ||
129 | 130 | ||
130 | /* | 131 | /* |
131 | * Setup timer to fire at 1/HZ intervals. | 132 | * ACK pending timer interrupt. |
132 | */ | 133 | */ |
133 | writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); | 134 | writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); |
134 | writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); | 135 | return 0; |
136 | } | ||
135 | 137 | ||
136 | /* | 138 | static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) |
137 | * Enable timer. | 139 | { |
138 | */ | 140 | /* |
139 | local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); | 141 | * Setup timer to fire at 1/HZ intervals. |
140 | } else { | 142 | */ |
141 | /* | 143 | writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); |
142 | * Disable timer. | 144 | writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); |
143 | */ | ||
144 | local_timer_ctrl_clrset(TIMER0_EN, 0); | ||
145 | 145 | ||
146 | /* | 146 | /* |
147 | * ACK pending timer interrupt. | 147 | * Enable timer. |
148 | */ | 148 | */ |
149 | writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); | 149 | local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); |
150 | } | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int armada_370_xp_clkevt_irq; | 153 | static int armada_370_xp_clkevt_irq; |
@@ -185,7 +185,10 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt) | |||
185 | evt->shift = 32, | 185 | evt->shift = 32, |
186 | evt->rating = 300, | 186 | evt->rating = 300, |
187 | evt->set_next_event = armada_370_xp_clkevt_next_event, | 187 | evt->set_next_event = armada_370_xp_clkevt_next_event, |
188 | evt->set_mode = armada_370_xp_clkevt_mode, | 188 | evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; |
189 | evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; | ||
190 | evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; | ||
191 | evt->tick_resume = armada_370_xp_clkevt_shutdown; | ||
189 | evt->irq = armada_370_xp_clkevt_irq; | 192 | evt->irq = armada_370_xp_clkevt_irq; |
190 | evt->cpumask = cpumask_of(cpu); | 193 | evt->cpumask = cpumask_of(cpu); |
191 | 194 | ||
@@ -197,7 +200,7 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt) | |||
197 | 200 | ||
198 | static void armada_370_xp_timer_stop(struct clock_event_device *evt) | 201 | static void armada_370_xp_timer_stop(struct clock_event_device *evt) |
199 | { | 202 | { |
200 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 203 | evt->set_state_shutdown(evt); |
201 | disable_percpu_irq(evt->irq); | 204 | disable_percpu_irq(evt->irq); |
202 | } | 205 | } |
203 | 206 | ||
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c index 5b6e3d5644c9..b06e4c2be406 100644 --- a/drivers/clocksource/time-efm32.c +++ b/drivers/clocksource/time-efm32.c | |||
@@ -48,40 +48,42 @@ struct efm32_clock_event_ddata { | |||
48 | unsigned periodic_top; | 48 | unsigned periodic_top; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static void efm32_clock_event_set_mode(enum clock_event_mode mode, | 51 | static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) |
52 | struct clock_event_device *evtdev) | ||
53 | { | 52 | { |
54 | struct efm32_clock_event_ddata *ddata = | 53 | struct efm32_clock_event_ddata *ddata = |
55 | container_of(evtdev, struct efm32_clock_event_ddata, evtdev); | 54 | container_of(evtdev, struct efm32_clock_event_ddata, evtdev); |
56 | 55 | ||
57 | switch (mode) { | 56 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); |
58 | case CLOCK_EVT_MODE_PERIODIC: | 57 | return 0; |
59 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); | 58 | } |
60 | writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); | 59 | |
61 | writel_relaxed(TIMERn_CTRL_PRESC_1024 | | 60 | static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) |
62 | TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | | 61 | { |
63 | TIMERn_CTRL_MODE_DOWN, | 62 | struct efm32_clock_event_ddata *ddata = |
64 | ddata->base + TIMERn_CTRL); | 63 | container_of(evtdev, struct efm32_clock_event_ddata, evtdev); |
65 | writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); | 64 | |
66 | break; | 65 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); |
67 | 66 | writel_relaxed(TIMERn_CTRL_PRESC_1024 | | |
68 | case CLOCK_EVT_MODE_ONESHOT: | 67 | TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | |
69 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); | 68 | TIMERn_CTRL_OSMEN | |
70 | writel_relaxed(TIMERn_CTRL_PRESC_1024 | | 69 | TIMERn_CTRL_MODE_DOWN, |
71 | TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | | 70 | ddata->base + TIMERn_CTRL); |
72 | TIMERn_CTRL_OSMEN | | 71 | return 0; |
73 | TIMERn_CTRL_MODE_DOWN, | 72 | } |
74 | ddata->base + TIMERn_CTRL); | 73 | |
75 | break; | 74 | static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) |
76 | 75 | { | |
77 | case CLOCK_EVT_MODE_UNUSED: | 76 | struct efm32_clock_event_ddata *ddata = |
78 | case CLOCK_EVT_MODE_SHUTDOWN: | 77 | container_of(evtdev, struct efm32_clock_event_ddata, evtdev); |
79 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); | 78 | |
80 | break; | 79 | writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); |
81 | 80 | writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); | |
82 | case CLOCK_EVT_MODE_RESUME: | 81 | writel_relaxed(TIMERn_CTRL_PRESC_1024 | |
83 | break; | 82 | TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | |
84 | } | 83 | TIMERn_CTRL_MODE_DOWN, |
84 | ddata->base + TIMERn_CTRL); | ||
85 | writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); | ||
86 | return 0; | ||
85 | } | 87 | } |
86 | 88 | ||
87 | static int efm32_clock_event_set_next_event(unsigned long evt, | 89 | static int efm32_clock_event_set_next_event(unsigned long evt, |
@@ -112,7 +114,9 @@ static struct efm32_clock_event_ddata clock_event_ddata = { | |||
112 | .evtdev = { | 114 | .evtdev = { |
113 | .name = "efm32 clockevent", | 115 | .name = "efm32 clockevent", |
114 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 116 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, |
115 | .set_mode = efm32_clock_event_set_mode, | 117 | .set_state_shutdown = efm32_clock_event_shutdown, |
118 | .set_state_periodic = efm32_clock_event_set_periodic, | ||
119 | .set_state_oneshot = efm32_clock_event_set_oneshot, | ||
116 | .set_next_event = efm32_clock_event_set_next_event, | 120 | .set_next_event = efm32_clock_event_set_next_event, |
117 | .rating = 200, | 121 | .rating = 200, |
118 | }, | 122 | }, |
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 0b3ce0399c51..0ece7427b497 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c | |||
@@ -60,30 +60,36 @@ static int orion_clkevt_next_event(unsigned long delta, | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | static void orion_clkevt_mode(enum clock_event_mode mode, | 63 | static int orion_clkevt_shutdown(struct clock_event_device *dev) |
64 | struct clock_event_device *dev) | ||
65 | { | 64 | { |
66 | if (mode == CLOCK_EVT_MODE_PERIODIC) { | 65 | /* disable timer */ |
67 | /* setup and enable periodic timer at 1/HZ intervals */ | 66 | atomic_io_modify(timer_base + TIMER_CTRL, |
68 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); | 67 | TIMER1_RELOAD_EN | TIMER1_EN, 0); |
69 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); | 68 | return 0; |
70 | atomic_io_modify(timer_base + TIMER_CTRL, | 69 | } |
71 | TIMER1_RELOAD_EN | TIMER1_EN, | 70 | |
72 | TIMER1_RELOAD_EN | TIMER1_EN); | 71 | static int orion_clkevt_set_periodic(struct clock_event_device *dev) |
73 | } else { | 72 | { |
74 | /* disable timer */ | 73 | /* setup and enable periodic timer at 1/HZ intervals */ |
75 | atomic_io_modify(timer_base + TIMER_CTRL, | 74 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); |
76 | TIMER1_RELOAD_EN | TIMER1_EN, 0); | 75 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); |
77 | } | 76 | atomic_io_modify(timer_base + TIMER_CTRL, |
77 | TIMER1_RELOAD_EN | TIMER1_EN, | ||
78 | TIMER1_RELOAD_EN | TIMER1_EN); | ||
79 | return 0; | ||
78 | } | 80 | } |
79 | 81 | ||
80 | static struct clock_event_device orion_clkevt = { | 82 | static struct clock_event_device orion_clkevt = { |
81 | .name = "orion_event", | 83 | .name = "orion_event", |
82 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 84 | .features = CLOCK_EVT_FEAT_ONESHOT | |
83 | .shift = 32, | 85 | CLOCK_EVT_FEAT_PERIODIC, |
84 | .rating = 300, | 86 | .shift = 32, |
85 | .set_next_event = orion_clkevt_next_event, | 87 | .rating = 300, |
86 | .set_mode = orion_clkevt_mode, | 88 | .set_next_event = orion_clkevt_next_event, |
89 | .set_state_shutdown = orion_clkevt_shutdown, | ||
90 | .set_state_periodic = orion_clkevt_set_periodic, | ||
91 | .set_state_oneshot = orion_clkevt_shutdown, | ||
92 | .tick_resume = orion_clkevt_shutdown, | ||
87 | }; | 93 | }; |
88 | 94 | ||
89 | static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) | 95 | static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) |
diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c index 60f9de3438b0..27fa13680be1 100644 --- a/drivers/clocksource/timer-atlas7.c +++ b/drivers/clocksource/timer-atlas7.c | |||
@@ -76,7 +76,7 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) | |||
76 | /* clear timer interrupt */ | 76 | /* clear timer interrupt */ |
77 | writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); | 77 | writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); |
78 | 78 | ||
79 | if (ce->mode == CLOCK_EVT_MODE_ONESHOT) | 79 | if (clockevent_state_oneshot(ce)) |
80 | sirfsoc_timer_count_disable(cpu); | 80 | sirfsoc_timer_count_disable(cpu); |
81 | 81 | ||
82 | ce->event_handler(ce); | 82 | ce->event_handler(ce); |
@@ -117,18 +117,11 @@ static int sirfsoc_timer_set_next_event(unsigned long delta, | |||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
120 | static void sirfsoc_timer_set_mode(enum clock_event_mode mode, | 120 | /* Oneshot is enabled in set_next_event */ |
121 | struct clock_event_device *ce) | 121 | static int sirfsoc_timer_shutdown(struct clock_event_device *evt) |
122 | { | 122 | { |
123 | switch (mode) { | ||
124 | case CLOCK_EVT_MODE_ONESHOT: | ||
125 | /* enable in set_next_event */ | ||
126 | break; | ||
127 | default: | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | sirfsoc_timer_count_disable(smp_processor_id()); | 123 | sirfsoc_timer_count_disable(smp_processor_id()); |
124 | return 0; | ||
132 | } | 125 | } |
133 | 126 | ||
134 | static void sirfsoc_clocksource_suspend(struct clocksource *cs) | 127 | static void sirfsoc_clocksource_suspend(struct clocksource *cs) |
@@ -193,7 +186,9 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce) | |||
193 | ce->name = "local_timer"; | 186 | ce->name = "local_timer"; |
194 | ce->features = CLOCK_EVT_FEAT_ONESHOT; | 187 | ce->features = CLOCK_EVT_FEAT_ONESHOT; |
195 | ce->rating = 200; | 188 | ce->rating = 200; |
196 | ce->set_mode = sirfsoc_timer_set_mode; | 189 | ce->set_state_shutdown = sirfsoc_timer_shutdown; |
190 | ce->set_state_oneshot = sirfsoc_timer_shutdown; | ||
191 | ce->tick_resume = sirfsoc_timer_shutdown; | ||
197 | ce->set_next_event = sirfsoc_timer_set_next_event; | 192 | ce->set_next_event = sirfsoc_timer_set_next_event; |
198 | clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60); | 193 | clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60); |
199 | ce->max_delta_ns = clockevent_delta2ns(-2, ce); | 194 | ce->max_delta_ns = clockevent_delta2ns(-2, ce); |
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index c0304ff608b0..d911c5dca8f1 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c | |||
@@ -90,33 +90,27 @@ static cycle_t read_pit_clk(struct clocksource *cs) | |||
90 | return elapsed; | 90 | return elapsed; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int pit_clkevt_shutdown(struct clock_event_device *dev) | ||
94 | { | ||
95 | struct pit_data *data = clkevt_to_pit_data(dev); | ||
96 | |||
97 | /* disable irq, leaving the clocksource active */ | ||
98 | pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
93 | /* | 102 | /* |
94 | * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) | 103 | * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) |
95 | */ | 104 | */ |
96 | static void | 105 | static int pit_clkevt_set_periodic(struct clock_event_device *dev) |
97 | pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) | ||
98 | { | 106 | { |
99 | struct pit_data *data = clkevt_to_pit_data(dev); | 107 | struct pit_data *data = clkevt_to_pit_data(dev); |
100 | 108 | ||
101 | switch (mode) { | 109 | /* update clocksource counter */ |
102 | case CLOCK_EVT_MODE_PERIODIC: | 110 | data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR)); |
103 | /* update clocksource counter */ | 111 | pit_write(data->base, AT91_PIT_MR, |
104 | data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR)); | 112 | (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN); |
105 | pit_write(data->base, AT91_PIT_MR, | 113 | return 0; |
106 | (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN); | ||
107 | break; | ||
108 | case CLOCK_EVT_MODE_ONESHOT: | ||
109 | BUG(); | ||
110 | /* FALLTHROUGH */ | ||
111 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
112 | case CLOCK_EVT_MODE_UNUSED: | ||
113 | /* disable irq, leaving the clocksource active */ | ||
114 | pit_write(data->base, AT91_PIT_MR, | ||
115 | (data->cycle - 1) | AT91_PIT_PITEN); | ||
116 | break; | ||
117 | case CLOCK_EVT_MODE_RESUME: | ||
118 | break; | ||
119 | } | ||
120 | } | 114 | } |
121 | 115 | ||
122 | static void at91sam926x_pit_suspend(struct clock_event_device *cedev) | 116 | static void at91sam926x_pit_suspend(struct clock_event_device *cedev) |
@@ -162,7 +156,7 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) | |||
162 | WARN_ON_ONCE(!irqs_disabled()); | 156 | WARN_ON_ONCE(!irqs_disabled()); |
163 | 157 | ||
164 | /* The PIT interrupt may be disabled, and is shared */ | 158 | /* The PIT interrupt may be disabled, and is shared */ |
165 | if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) && | 159 | if (clockevent_state_periodic(&data->clkevt) && |
166 | (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) { | 160 | (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) { |
167 | unsigned nr_ticks; | 161 | unsigned nr_ticks; |
168 | 162 | ||
@@ -208,8 +202,8 @@ static void __init at91sam926x_pit_common_init(struct pit_data *data) | |||
208 | data->clksrc.mask = CLOCKSOURCE_MASK(bits); | 202 | data->clksrc.mask = CLOCKSOURCE_MASK(bits); |
209 | data->clksrc.name = "pit"; | 203 | data->clksrc.name = "pit"; |
210 | data->clksrc.rating = 175; | 204 | data->clksrc.rating = 175; |
211 | data->clksrc.read = read_pit_clk, | 205 | data->clksrc.read = read_pit_clk; |
212 | data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS, | 206 | data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; |
213 | clocksource_register_hz(&data->clksrc, pit_rate); | 207 | clocksource_register_hz(&data->clksrc, pit_rate); |
214 | 208 | ||
215 | /* Set up irq handler */ | 209 | /* Set up irq handler */ |
@@ -227,7 +221,8 @@ static void __init at91sam926x_pit_common_init(struct pit_data *data) | |||
227 | data->clkevt.rating = 100; | 221 | data->clkevt.rating = 100; |
228 | data->clkevt.cpumask = cpumask_of(0); | 222 | data->clkevt.cpumask = cpumask_of(0); |
229 | 223 | ||
230 | data->clkevt.set_mode = pit_clkevt_mode; | 224 | data->clkevt.set_state_shutdown = pit_clkevt_shutdown; |
225 | data->clkevt.set_state_periodic = pit_clkevt_set_periodic; | ||
231 | data->clkevt.resume = at91sam926x_pit_resume; | 226 | data->clkevt.resume = at91sam926x_pit_resume; |
232 | data->clkevt.suspend = at91sam926x_pit_suspend; | 227 | data->clkevt.suspend = at91sam926x_pit_suspend; |
233 | clockevents_register_device(&data->clkevt); | 228 | clockevents_register_device(&data->clkevt); |
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c index 1692e17e096b..41b7b6dc1d0d 100644 --- a/drivers/clocksource/timer-atmel-st.c +++ b/drivers/clocksource/timer-atmel-st.c | |||
@@ -106,36 +106,47 @@ static struct clocksource clk32k = { | |||
106 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 106 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static void | 109 | static void clkdev32k_disable_and_flush_irq(void) |
110 | clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) | ||
111 | { | 110 | { |
112 | unsigned int val; | 111 | unsigned int val; |
113 | 112 | ||
114 | /* Disable and flush pending timer interrupts */ | 113 | /* Disable and flush pending timer interrupts */ |
115 | regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); | 114 | regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); |
116 | regmap_read(regmap_st, AT91_ST_SR, &val); | 115 | regmap_read(regmap_st, AT91_ST_SR, &val); |
117 | |||
118 | last_crtr = read_CRTR(); | 116 | last_crtr = read_CRTR(); |
119 | switch (mode) { | 117 | } |
120 | case CLOCK_EVT_MODE_PERIODIC: | 118 | |
121 | /* PIT for periodic irqs; fixed rate of 1/HZ */ | 119 | static int clkevt32k_shutdown(struct clock_event_device *evt) |
122 | irqmask = AT91_ST_PITS; | 120 | { |
123 | regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); | 121 | clkdev32k_disable_and_flush_irq(); |
124 | break; | 122 | irqmask = 0; |
125 | case CLOCK_EVT_MODE_ONESHOT: | 123 | regmap_write(regmap_st, AT91_ST_IER, irqmask); |
126 | /* ALM for oneshot irqs, set by next_event() | 124 | return 0; |
127 | * before 32 seconds have passed | 125 | } |
128 | */ | 126 | |
129 | irqmask = AT91_ST_ALMS; | 127 | static int clkevt32k_set_oneshot(struct clock_event_device *dev) |
130 | regmap_write(regmap_st, AT91_ST_RTAR, last_crtr); | 128 | { |
131 | break; | 129 | clkdev32k_disable_and_flush_irq(); |
132 | case CLOCK_EVT_MODE_SHUTDOWN: | 130 | |
133 | case CLOCK_EVT_MODE_UNUSED: | 131 | /* |
134 | case CLOCK_EVT_MODE_RESUME: | 132 | * ALM for oneshot irqs, set by next_event() |
135 | irqmask = 0; | 133 | * before 32 seconds have passed. |
136 | break; | 134 | */ |
137 | } | 135 | irqmask = AT91_ST_ALMS; |
136 | regmap_write(regmap_st, AT91_ST_RTAR, last_crtr); | ||
138 | regmap_write(regmap_st, AT91_ST_IER, irqmask); | 137 | regmap_write(regmap_st, AT91_ST_IER, irqmask); |
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int clkevt32k_set_periodic(struct clock_event_device *dev) | ||
142 | { | ||
143 | clkdev32k_disable_and_flush_irq(); | ||
144 | |||
145 | /* PIT for periodic irqs; fixed rate of 1/HZ */ | ||
146 | irqmask = AT91_ST_PITS; | ||
147 | regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); | ||
148 | regmap_write(regmap_st, AT91_ST_IER, irqmask); | ||
149 | return 0; | ||
139 | } | 150 | } |
140 | 151 | ||
141 | static int | 152 | static int |
@@ -170,11 +181,15 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) | |||
170 | } | 181 | } |
171 | 182 | ||
172 | static struct clock_event_device clkevt = { | 183 | static struct clock_event_device clkevt = { |
173 | .name = "at91_tick", | 184 | .name = "at91_tick", |
174 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 185 | .features = CLOCK_EVT_FEAT_PERIODIC | |
175 | .rating = 150, | 186 | CLOCK_EVT_FEAT_ONESHOT, |
176 | .set_next_event = clkevt32k_next_event, | 187 | .rating = 150, |
177 | .set_mode = clkevt32k_mode, | 188 | .set_next_event = clkevt32k_next_event, |
189 | .set_state_shutdown = clkevt32k_shutdown, | ||
190 | .set_state_periodic = clkevt32k_set_periodic, | ||
191 | .set_state_oneshot = clkevt32k_set_oneshot, | ||
192 | .tick_resume = clkevt32k_shutdown, | ||
178 | }; | 193 | }; |
179 | 194 | ||
180 | /* | 195 | /* |
diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c index 7f8388cfa810..e73947f0f86d 100644 --- a/drivers/clocksource/timer-digicolor.c +++ b/drivers/clocksource/timer-digicolor.c | |||
@@ -87,27 +87,27 @@ static inline void dc_timer_set_count(struct clock_event_device *ce, | |||
87 | writel(count, dt->base + COUNT(dt->timer_id)); | 87 | writel(count, dt->base + COUNT(dt->timer_id)); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void digicolor_clkevt_mode(enum clock_event_mode mode, | 90 | static int digicolor_clkevt_shutdown(struct clock_event_device *ce) |
91 | struct clock_event_device *ce) | 91 | { |
92 | dc_timer_disable(ce); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int digicolor_clkevt_set_oneshot(struct clock_event_device *ce) | ||
97 | { | ||
98 | dc_timer_disable(ce); | ||
99 | dc_timer_enable(ce, CONTROL_MODE_ONESHOT); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int digicolor_clkevt_set_periodic(struct clock_event_device *ce) | ||
92 | { | 104 | { |
93 | struct digicolor_timer *dt = dc_timer(ce); | 105 | struct digicolor_timer *dt = dc_timer(ce); |
94 | 106 | ||
95 | switch (mode) { | 107 | dc_timer_disable(ce); |
96 | case CLOCK_EVT_MODE_PERIODIC: | 108 | dc_timer_set_count(ce, dt->ticks_per_jiffy); |
97 | dc_timer_disable(ce); | 109 | dc_timer_enable(ce, CONTROL_MODE_PERIODIC); |
98 | dc_timer_set_count(ce, dt->ticks_per_jiffy); | 110 | return 0; |
99 | dc_timer_enable(ce, CONTROL_MODE_PERIODIC); | ||
100 | break; | ||
101 | case CLOCK_EVT_MODE_ONESHOT: | ||
102 | dc_timer_disable(ce); | ||
103 | dc_timer_enable(ce, CONTROL_MODE_ONESHOT); | ||
104 | break; | ||
105 | case CLOCK_EVT_MODE_UNUSED: | ||
106 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
107 | default: | ||
108 | dc_timer_disable(ce); | ||
109 | break; | ||
110 | } | ||
111 | } | 111 | } |
112 | 112 | ||
113 | static int digicolor_clkevt_next_event(unsigned long evt, | 113 | static int digicolor_clkevt_next_event(unsigned long evt, |
@@ -125,7 +125,10 @@ static struct digicolor_timer dc_timer_dev = { | |||
125 | .name = "digicolor_tick", | 125 | .name = "digicolor_tick", |
126 | .rating = 340, | 126 | .rating = 340, |
127 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 127 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
128 | .set_mode = digicolor_clkevt_mode, | 128 | .set_state_shutdown = digicolor_clkevt_shutdown, |
129 | .set_state_periodic = digicolor_clkevt_set_periodic, | ||
130 | .set_state_oneshot = digicolor_clkevt_set_oneshot, | ||
131 | .tick_resume = digicolor_clkevt_shutdown, | ||
129 | .set_next_event = digicolor_clkevt_next_event, | 132 | .set_next_event = digicolor_clkevt_next_event, |
130 | }, | 133 | }, |
131 | .timer_id = TIMER_C, | 134 | .timer_id = TIMER_C, |
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 86c7eb66bdfb..839aba92fc39 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c | |||
@@ -83,7 +83,6 @@ struct imx_timer { | |||
83 | struct clk *clk_ipg; | 83 | struct clk *clk_ipg; |
84 | const struct imx_gpt_data *gpt; | 84 | const struct imx_gpt_data *gpt; |
85 | struct clock_event_device ced; | 85 | struct clock_event_device ced; |
86 | enum clock_event_mode cem; | ||
87 | struct irqaction act; | 86 | struct irqaction act; |
88 | }; | 87 | }; |
89 | 88 | ||
@@ -212,18 +211,38 @@ static int v2_set_next_event(unsigned long evt, | |||
212 | -ETIME : 0; | 211 | -ETIME : 0; |
213 | } | 212 | } |
214 | 213 | ||
214 | static int mxc_shutdown(struct clock_event_device *ced) | ||
215 | { | ||
216 | struct imx_timer *imxtm = to_imx_timer(ced); | ||
217 | unsigned long flags; | ||
218 | u32 tcn; | ||
219 | |||
220 | /* | ||
221 | * The timer interrupt generation is disabled at least | ||
222 | * for enough time to call mxc_set_next_event() | ||
223 | */ | ||
224 | local_irq_save(flags); | ||
225 | |||
226 | /* Disable interrupt in GPT module */ | ||
227 | imxtm->gpt->gpt_irq_disable(imxtm); | ||
228 | |||
229 | tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); | ||
230 | /* Set event time into far-far future */ | ||
231 | writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); | ||
232 | |||
233 | /* Clear pending interrupt */ | ||
234 | imxtm->gpt->gpt_irq_acknowledge(imxtm); | ||
235 | |||
215 | #ifdef DEBUG | 236 | #ifdef DEBUG |
216 | static const char *clock_event_mode_label[] = { | 237 | printk(KERN_INFO "%s: changing mode\n", __func__); |
217 | [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", | ||
218 | [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", | ||
219 | [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", | ||
220 | [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED", | ||
221 | [CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME", | ||
222 | }; | ||
223 | #endif /* DEBUG */ | 238 | #endif /* DEBUG */ |
224 | 239 | ||
225 | static void mxc_set_mode(enum clock_event_mode mode, | 240 | local_irq_restore(flags); |
226 | struct clock_event_device *ced) | 241 | |
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int mxc_set_oneshot(struct clock_event_device *ced) | ||
227 | { | 246 | { |
228 | struct imx_timer *imxtm = to_imx_timer(ced); | 247 | struct imx_timer *imxtm = to_imx_timer(ced); |
229 | unsigned long flags; | 248 | unsigned long flags; |
@@ -237,7 +256,7 @@ static void mxc_set_mode(enum clock_event_mode mode, | |||
237 | /* Disable interrupt in GPT module */ | 256 | /* Disable interrupt in GPT module */ |
238 | imxtm->gpt->gpt_irq_disable(imxtm); | 257 | imxtm->gpt->gpt_irq_disable(imxtm); |
239 | 258 | ||
240 | if (mode != imxtm->cem) { | 259 | if (!clockevent_state_oneshot(ced)) { |
241 | u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); | 260 | u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); |
242 | /* Set event time into far-far future */ | 261 | /* Set event time into far-far future */ |
243 | writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); | 262 | writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); |
@@ -247,37 +266,19 @@ static void mxc_set_mode(enum clock_event_mode mode, | |||
247 | } | 266 | } |
248 | 267 | ||
249 | #ifdef DEBUG | 268 | #ifdef DEBUG |
250 | printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n", | 269 | printk(KERN_INFO "%s: changing mode\n", __func__); |
251 | clock_event_mode_label[imxtm->cem], | ||
252 | clock_event_mode_label[mode]); | ||
253 | #endif /* DEBUG */ | 270 | #endif /* DEBUG */ |
254 | 271 | ||
255 | /* Remember timer mode */ | ||
256 | imxtm->cem = mode; | ||
257 | local_irq_restore(flags); | ||
258 | |||
259 | switch (mode) { | ||
260 | case CLOCK_EVT_MODE_PERIODIC: | ||
261 | printk(KERN_ERR"mxc_set_mode: Periodic mode is not " | ||
262 | "supported for i.MX\n"); | ||
263 | break; | ||
264 | case CLOCK_EVT_MODE_ONESHOT: | ||
265 | /* | 272 | /* |
266 | * Do not put overhead of interrupt enable/disable into | 273 | * Do not put overhead of interrupt enable/disable into |
267 | * mxc_set_next_event(), the core has about 4 minutes | 274 | * mxc_set_next_event(), the core has about 4 minutes |
268 | * to call mxc_set_next_event() or shutdown clock after | 275 | * to call mxc_set_next_event() or shutdown clock after |
269 | * mode switching | 276 | * mode switching |
270 | */ | 277 | */ |
271 | local_irq_save(flags); | 278 | imxtm->gpt->gpt_irq_enable(imxtm); |
272 | imxtm->gpt->gpt_irq_enable(imxtm); | 279 | local_irq_restore(flags); |
273 | local_irq_restore(flags); | 280 | |
274 | break; | 281 | return 0; |
275 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
276 | case CLOCK_EVT_MODE_UNUSED: | ||
277 | case CLOCK_EVT_MODE_RESUME: | ||
278 | /* Left event sources disabled, no more interrupts appear */ | ||
279 | break; | ||
280 | } | ||
281 | } | 282 | } |
282 | 283 | ||
283 | /* | 284 | /* |
@@ -303,11 +304,11 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm) | |||
303 | struct clock_event_device *ced = &imxtm->ced; | 304 | struct clock_event_device *ced = &imxtm->ced; |
304 | struct irqaction *act = &imxtm->act; | 305 | struct irqaction *act = &imxtm->act; |
305 | 306 | ||
306 | imxtm->cem = CLOCK_EVT_MODE_UNUSED; | ||
307 | |||
308 | ced->name = "mxc_timer1"; | 307 | ced->name = "mxc_timer1"; |
309 | ced->features = CLOCK_EVT_FEAT_ONESHOT; | 308 | ced->features = CLOCK_EVT_FEAT_ONESHOT; |
310 | ced->set_mode = mxc_set_mode; | 309 | ced->set_state_shutdown = mxc_shutdown; |
310 | ced->set_state_oneshot = mxc_set_oneshot; | ||
311 | ced->tick_resume = mxc_shutdown; | ||
311 | ced->set_next_event = imxtm->gpt->set_next_event; | 312 | ced->set_next_event = imxtm->gpt->set_next_event; |
312 | ced->rating = 200; | 313 | ced->rating = 200; |
313 | ced->cpumask = cpumask_of(0); | 314 | ced->cpumask = cpumask_of(0); |
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c index a68866e0ecd4..3f59ac2180dc 100644 --- a/drivers/clocksource/timer-integrator-ap.c +++ b/drivers/clocksource/timer-integrator-ap.c | |||
@@ -75,33 +75,37 @@ static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) | |||
75 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) | 78 | static int clkevt_shutdown(struct clock_event_device *evt) |
79 | { | 79 | { |
80 | u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; | 80 | u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; |
81 | 81 | ||
82 | /* Disable timer */ | 82 | /* Disable timer */ |
83 | writel(ctrl, clkevt_base + TIMER_CTRL); | 83 | writel(ctrl, clkevt_base + TIMER_CTRL); |
84 | return 0; | ||
85 | } | ||
84 | 86 | ||
85 | switch (mode) { | 87 | static int clkevt_set_oneshot(struct clock_event_device *evt) |
86 | case CLOCK_EVT_MODE_PERIODIC: | 88 | { |
87 | /* Enable the timer and start the periodic tick */ | 89 | u32 ctrl = readl(clkevt_base + TIMER_CTRL) & |
88 | writel(timer_reload, clkevt_base + TIMER_LOAD); | 90 | ~(TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC); |
89 | ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; | 91 | |
90 | writel(ctrl, clkevt_base + TIMER_CTRL); | 92 | /* Leave the timer disabled, .set_next_event will enable it */ |
91 | break; | 93 | writel(ctrl, clkevt_base + TIMER_CTRL); |
92 | case CLOCK_EVT_MODE_ONESHOT: | 94 | return 0; |
93 | /* Leave the timer disabled, .set_next_event will enable it */ | 95 | } |
94 | ctrl &= ~TIMER_CTRL_PERIODIC; | ||
95 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
96 | break; | ||
97 | case CLOCK_EVT_MODE_UNUSED: | ||
98 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
99 | case CLOCK_EVT_MODE_RESUME: | ||
100 | default: | ||
101 | /* Just leave in disabled state */ | ||
102 | break; | ||
103 | } | ||
104 | 96 | ||
97 | static int clkevt_set_periodic(struct clock_event_device *evt) | ||
98 | { | ||
99 | u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; | ||
100 | |||
101 | /* Disable timer */ | ||
102 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
103 | |||
104 | /* Enable the timer and start the periodic tick */ | ||
105 | writel(timer_reload, clkevt_base + TIMER_LOAD); | ||
106 | ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; | ||
107 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
108 | return 0; | ||
105 | } | 109 | } |
106 | 110 | ||
107 | static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) | 111 | static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) |
@@ -116,11 +120,15 @@ static int clkevt_set_next_event(unsigned long next, struct clock_event_device * | |||
116 | } | 120 | } |
117 | 121 | ||
118 | static struct clock_event_device integrator_clockevent = { | 122 | static struct clock_event_device integrator_clockevent = { |
119 | .name = "timer1", | 123 | .name = "timer1", |
120 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 124 | .features = CLOCK_EVT_FEAT_PERIODIC | |
121 | .set_mode = clkevt_set_mode, | 125 | CLOCK_EVT_FEAT_ONESHOT, |
122 | .set_next_event = clkevt_set_next_event, | 126 | .set_state_shutdown = clkevt_shutdown, |
123 | .rating = 300, | 127 | .set_state_periodic = clkevt_set_periodic, |
128 | .set_state_oneshot = clkevt_set_oneshot, | ||
129 | .tick_resume = clkevt_shutdown, | ||
130 | .set_next_event = clkevt_set_next_event, | ||
131 | .rating = 300, | ||
124 | }; | 132 | }; |
125 | 133 | ||
126 | static struct irqaction integrator_timer_irq = { | 134 | static struct irqaction integrator_timer_irq = { |
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c index 0250354f7e55..edacf3902e10 100644 --- a/drivers/clocksource/timer-keystone.c +++ b/drivers/clocksource/timer-keystone.c | |||
@@ -72,10 +72,10 @@ static inline void keystone_timer_barrier(void) | |||
72 | 72 | ||
73 | /** | 73 | /** |
74 | * keystone_timer_config: configures timer to work in oneshot/periodic modes. | 74 | * keystone_timer_config: configures timer to work in oneshot/periodic modes. |
75 | * @ mode: mode to configure | 75 | * @ mask: mask of the mode to configure |
76 | * @ period: cycles number to configure for | 76 | * @ period: cycles number to configure for |
77 | */ | 77 | */ |
78 | static int keystone_timer_config(u64 period, enum clock_event_mode mode) | 78 | static int keystone_timer_config(u64 period, int mask) |
79 | { | 79 | { |
80 | u32 tcr; | 80 | u32 tcr; |
81 | u32 off; | 81 | u32 off; |
@@ -84,16 +84,7 @@ static int keystone_timer_config(u64 period, enum clock_event_mode mode) | |||
84 | off = tcr & ~(TCR_ENAMODE_MASK); | 84 | off = tcr & ~(TCR_ENAMODE_MASK); |
85 | 85 | ||
86 | /* set enable mode */ | 86 | /* set enable mode */ |
87 | switch (mode) { | 87 | tcr |= mask; |
88 | case CLOCK_EVT_MODE_ONESHOT: | ||
89 | tcr |= TCR_ENAMODE_ONESHOT_MASK; | ||
90 | break; | ||
91 | case CLOCK_EVT_MODE_PERIODIC: | ||
92 | tcr |= TCR_ENAMODE_PERIODIC_MASK; | ||
93 | break; | ||
94 | default: | ||
95 | return -1; | ||
96 | } | ||
97 | 88 | ||
98 | /* disable timer */ | 89 | /* disable timer */ |
99 | keystone_timer_writel(off, TCR); | 90 | keystone_timer_writel(off, TCR); |
@@ -138,24 +129,19 @@ static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id) | |||
138 | static int keystone_set_next_event(unsigned long cycles, | 129 | static int keystone_set_next_event(unsigned long cycles, |
139 | struct clock_event_device *evt) | 130 | struct clock_event_device *evt) |
140 | { | 131 | { |
141 | return keystone_timer_config(cycles, evt->mode); | 132 | return keystone_timer_config(cycles, TCR_ENAMODE_ONESHOT_MASK); |
142 | } | 133 | } |
143 | 134 | ||
144 | static void keystone_set_mode(enum clock_event_mode mode, | 135 | static int keystone_shutdown(struct clock_event_device *evt) |
145 | struct clock_event_device *evt) | ||
146 | { | 136 | { |
147 | switch (mode) { | 137 | keystone_timer_disable(); |
148 | case CLOCK_EVT_MODE_PERIODIC: | 138 | return 0; |
149 | keystone_timer_config(timer.hz_period, CLOCK_EVT_MODE_PERIODIC); | 139 | } |
150 | break; | 140 | |
151 | case CLOCK_EVT_MODE_UNUSED: | 141 | static int keystone_set_periodic(struct clock_event_device *evt) |
152 | case CLOCK_EVT_MODE_SHUTDOWN: | 142 | { |
153 | case CLOCK_EVT_MODE_ONESHOT: | 143 | keystone_timer_config(timer.hz_period, TCR_ENAMODE_PERIODIC_MASK); |
154 | keystone_timer_disable(); | 144 | return 0; |
155 | break; | ||
156 | default: | ||
157 | break; | ||
158 | } | ||
159 | } | 145 | } |
160 | 146 | ||
161 | static void __init keystone_timer_init(struct device_node *np) | 147 | static void __init keystone_timer_init(struct device_node *np) |
@@ -222,7 +208,9 @@ static void __init keystone_timer_init(struct device_node *np) | |||
222 | /* setup clockevent */ | 208 | /* setup clockevent */ |
223 | event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 209 | event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
224 | event_dev->set_next_event = keystone_set_next_event; | 210 | event_dev->set_next_event = keystone_set_next_event; |
225 | event_dev->set_mode = keystone_set_mode; | 211 | event_dev->set_state_shutdown = keystone_shutdown; |
212 | event_dev->set_state_periodic = keystone_set_periodic; | ||
213 | event_dev->set_state_oneshot = keystone_shutdown; | ||
226 | event_dev->cpumask = cpu_all_mask; | 214 | event_dev->cpumask = cpu_all_mask; |
227 | event_dev->owner = THIS_MODULE; | 215 | event_dev->owner = THIS_MODULE; |
228 | event_dev->name = TIMER_NAME; | 216 | event_dev->name = TIMER_NAME; |
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index ce18d570e1cd..78de982cc640 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c | |||
@@ -104,26 +104,21 @@ static int sirfsoc_timer_set_next_event(unsigned long delta, | |||
104 | return next - now > delta ? -ETIME : 0; | 104 | return next - now > delta ? -ETIME : 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | static void sirfsoc_timer_set_mode(enum clock_event_mode mode, | 107 | static int sirfsoc_timer_shutdown(struct clock_event_device *evt) |
108 | struct clock_event_device *ce) | ||
109 | { | 108 | { |
110 | u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); | 109 | u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); |
111 | switch (mode) { | 110 | |
112 | case CLOCK_EVT_MODE_PERIODIC: | 111 | writel_relaxed(val & ~BIT(0), |
113 | WARN_ON(1); | 112 | sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); |
114 | break; | 113 | return 0; |
115 | case CLOCK_EVT_MODE_ONESHOT: | 114 | } |
116 | writel_relaxed(val | BIT(0), | 115 | |
117 | sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); | 116 | static int sirfsoc_timer_set_oneshot(struct clock_event_device *evt) |
118 | break; | 117 | { |
119 | case CLOCK_EVT_MODE_SHUTDOWN: | 118 | u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); |
120 | writel_relaxed(val & ~BIT(0), | 119 | |
121 | sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); | 120 | writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); |
122 | break; | 121 | return 0; |
123 | case CLOCK_EVT_MODE_UNUSED: | ||
124 | case CLOCK_EVT_MODE_RESUME: | ||
125 | break; | ||
126 | } | ||
127 | } | 122 | } |
128 | 123 | ||
129 | static void sirfsoc_clocksource_suspend(struct clocksource *cs) | 124 | static void sirfsoc_clocksource_suspend(struct clocksource *cs) |
@@ -157,7 +152,8 @@ static struct clock_event_device sirfsoc_clockevent = { | |||
157 | .name = "sirfsoc_clockevent", | 152 | .name = "sirfsoc_clockevent", |
158 | .rating = 200, | 153 | .rating = 200, |
159 | .features = CLOCK_EVT_FEAT_ONESHOT, | 154 | .features = CLOCK_EVT_FEAT_ONESHOT, |
160 | .set_mode = sirfsoc_timer_set_mode, | 155 | .set_state_shutdown = sirfsoc_timer_shutdown, |
156 | .set_state_oneshot = sirfsoc_timer_set_oneshot, | ||
161 | .set_next_event = sirfsoc_timer_set_next_event, | 157 | .set_next_event = sirfsoc_timer_set_next_event, |
162 | }; | 158 | }; |
163 | 159 | ||
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index ca02503f17d1..5f45b9adef60 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c | |||
@@ -133,50 +133,50 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) | |||
133 | return IRQ_HANDLED; | 133 | return IRQ_HANDLED; |
134 | } | 134 | } |
135 | 135 | ||
136 | static void sp804_set_mode(enum clock_event_mode mode, | 136 | static inline void timer_shutdown(struct clock_event_device *evt) |
137 | struct clock_event_device *evt) | ||
138 | { | 137 | { |
139 | unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE; | 138 | writel(0, clkevt_base + TIMER_CTRL); |
139 | } | ||
140 | 140 | ||
141 | writel(ctrl, clkevt_base + TIMER_CTRL); | 141 | static int sp804_shutdown(struct clock_event_device *evt) |
142 | { | ||
143 | timer_shutdown(evt); | ||
144 | return 0; | ||
145 | } | ||
142 | 146 | ||
143 | switch (mode) { | 147 | static int sp804_set_periodic(struct clock_event_device *evt) |
144 | case CLOCK_EVT_MODE_PERIODIC: | 148 | { |
145 | writel(clkevt_reload, clkevt_base + TIMER_LOAD); | 149 | unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | |
146 | ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; | 150 | TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; |
147 | break; | ||
148 | |||
149 | case CLOCK_EVT_MODE_ONESHOT: | ||
150 | /* period set, and timer enabled in 'next_event' hook */ | ||
151 | ctrl |= TIMER_CTRL_ONESHOT; | ||
152 | break; | ||
153 | |||
154 | case CLOCK_EVT_MODE_UNUSED: | ||
155 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
156 | default: | ||
157 | break; | ||
158 | } | ||
159 | 151 | ||
152 | timer_shutdown(evt); | ||
153 | writel(clkevt_reload, clkevt_base + TIMER_LOAD); | ||
160 | writel(ctrl, clkevt_base + TIMER_CTRL); | 154 | writel(ctrl, clkevt_base + TIMER_CTRL); |
155 | return 0; | ||
161 | } | 156 | } |
162 | 157 | ||
163 | static int sp804_set_next_event(unsigned long next, | 158 | static int sp804_set_next_event(unsigned long next, |
164 | struct clock_event_device *evt) | 159 | struct clock_event_device *evt) |
165 | { | 160 | { |
166 | unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); | 161 | unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | |
162 | TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE; | ||
167 | 163 | ||
168 | writel(next, clkevt_base + TIMER_LOAD); | 164 | writel(next, clkevt_base + TIMER_LOAD); |
169 | writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); | 165 | writel(ctrl, clkevt_base + TIMER_CTRL); |
170 | 166 | ||
171 | return 0; | 167 | return 0; |
172 | } | 168 | } |
173 | 169 | ||
174 | static struct clock_event_device sp804_clockevent = { | 170 | static struct clock_event_device sp804_clockevent = { |
175 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | | 171 | .features = CLOCK_EVT_FEAT_PERIODIC | |
176 | CLOCK_EVT_FEAT_DYNIRQ, | 172 | CLOCK_EVT_FEAT_ONESHOT | |
177 | .set_mode = sp804_set_mode, | 173 | CLOCK_EVT_FEAT_DYNIRQ, |
178 | .set_next_event = sp804_set_next_event, | 174 | .set_state_shutdown = sp804_shutdown, |
179 | .rating = 300, | 175 | .set_state_periodic = sp804_set_periodic, |
176 | .set_state_oneshot = sp804_shutdown, | ||
177 | .tick_resume = sp804_shutdown, | ||
178 | .set_next_event = sp804_set_next_event, | ||
179 | .rating = 300, | ||
180 | }; | 180 | }; |
181 | 181 | ||
182 | static struct irqaction sp804_timer_irq = { | 182 | static struct irqaction sp804_timer_irq = { |
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c index a97e8b50701c..f3dcb76799b4 100644 --- a/drivers/clocksource/timer-stm32.c +++ b/drivers/clocksource/timer-stm32.c | |||
@@ -40,24 +40,25 @@ struct stm32_clock_event_ddata { | |||
40 | void __iomem *base; | 40 | void __iomem *base; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static void stm32_clock_event_set_mode(enum clock_event_mode mode, | 43 | static int stm32_clock_event_shutdown(struct clock_event_device *evtdev) |
44 | struct clock_event_device *evtdev) | ||
45 | { | 44 | { |
46 | struct stm32_clock_event_ddata *data = | 45 | struct stm32_clock_event_ddata *data = |
47 | container_of(evtdev, struct stm32_clock_event_ddata, evtdev); | 46 | container_of(evtdev, struct stm32_clock_event_ddata, evtdev); |
48 | void *base = data->base; | 47 | void *base = data->base; |
49 | 48 | ||
50 | switch (mode) { | 49 | writel_relaxed(0, base + TIM_CR1); |
51 | case CLOCK_EVT_MODE_PERIODIC: | 50 | return 0; |
52 | writel_relaxed(data->periodic_top, base + TIM_ARR); | 51 | } |
53 | writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1); | ||
54 | break; | ||
55 | 52 | ||
56 | case CLOCK_EVT_MODE_ONESHOT: | 53 | static int stm32_clock_event_set_periodic(struct clock_event_device *evtdev) |
57 | default: | 54 | { |
58 | writel_relaxed(0, base + TIM_CR1); | 55 | struct stm32_clock_event_ddata *data = |
59 | break; | 56 | container_of(evtdev, struct stm32_clock_event_ddata, evtdev); |
60 | } | 57 | void *base = data->base; |
58 | |||
59 | writel_relaxed(data->periodic_top, base + TIM_ARR); | ||
60 | writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1); | ||
61 | return 0; | ||
61 | } | 62 | } |
62 | 63 | ||
63 | static int stm32_clock_event_set_next_event(unsigned long evt, | 64 | static int stm32_clock_event_set_next_event(unsigned long evt, |
@@ -88,7 +89,10 @@ static struct stm32_clock_event_ddata clock_event_ddata = { | |||
88 | .evtdev = { | 89 | .evtdev = { |
89 | .name = "stm32 clockevent", | 90 | .name = "stm32 clockevent", |
90 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 91 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, |
91 | .set_mode = stm32_clock_event_set_mode, | 92 | .set_state_shutdown = stm32_clock_event_shutdown, |
93 | .set_state_periodic = stm32_clock_event_set_periodic, | ||
94 | .set_state_oneshot = stm32_clock_event_shutdown, | ||
95 | .tick_resume = stm32_clock_event_shutdown, | ||
92 | .set_next_event = stm32_clock_event_set_next_event, | 96 | .set_next_event = stm32_clock_event_set_next_event, |
93 | .rating = 200, | 97 | .rating = 200, |
94 | }, | 98 | }, |
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index 0ffb4ea7c925..bca9573e036a 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c | |||
@@ -103,27 +103,31 @@ static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, boo | |||
103 | ce->timer.base + TIMER_CTL_REG(timer)); | 103 | ce->timer.base + TIMER_CTL_REG(timer)); |
104 | } | 104 | } |
105 | 105 | ||
106 | static void sun5i_clkevt_mode(enum clock_event_mode mode, | 106 | static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt) |
107 | struct clock_event_device *clkevt) | ||
108 | { | 107 | { |
109 | struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); | 108 | struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); |
110 | 109 | ||
111 | switch (mode) { | 110 | sun5i_clkevt_time_stop(ce, 0); |
112 | case CLOCK_EVT_MODE_PERIODIC: | 111 | return 0; |
113 | sun5i_clkevt_time_stop(ce, 0); | 112 | } |
114 | sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy); | 113 | |
115 | sun5i_clkevt_time_start(ce, 0, true); | 114 | static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt) |
116 | break; | 115 | { |
117 | case CLOCK_EVT_MODE_ONESHOT: | 116 | struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); |
118 | sun5i_clkevt_time_stop(ce, 0); | 117 | |
119 | sun5i_clkevt_time_start(ce, 0, false); | 118 | sun5i_clkevt_time_stop(ce, 0); |
120 | break; | 119 | sun5i_clkevt_time_start(ce, 0, false); |
121 | case CLOCK_EVT_MODE_UNUSED: | 120 | return 0; |
122 | case CLOCK_EVT_MODE_SHUTDOWN: | 121 | } |
123 | default: | 122 | |
124 | sun5i_clkevt_time_stop(ce, 0); | 123 | static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt) |
125 | break; | 124 | { |
126 | } | 125 | struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); |
126 | |||
127 | sun5i_clkevt_time_stop(ce, 0); | ||
128 | sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy); | ||
129 | sun5i_clkevt_time_start(ce, 0, true); | ||
130 | return 0; | ||
127 | } | 131 | } |
128 | 132 | ||
129 | static int sun5i_clkevt_next_event(unsigned long evt, | 133 | static int sun5i_clkevt_next_event(unsigned long evt, |
@@ -286,7 +290,10 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem | |||
286 | ce->clkevt.name = node->name; | 290 | ce->clkevt.name = node->name; |
287 | ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 291 | ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
288 | ce->clkevt.set_next_event = sun5i_clkevt_next_event; | 292 | ce->clkevt.set_next_event = sun5i_clkevt_next_event; |
289 | ce->clkevt.set_mode = sun5i_clkevt_mode; | 293 | ce->clkevt.set_state_shutdown = sun5i_clkevt_shutdown; |
294 | ce->clkevt.set_state_periodic = sun5i_clkevt_set_periodic; | ||
295 | ce->clkevt.set_state_oneshot = sun5i_clkevt_set_oneshot; | ||
296 | ce->clkevt.tick_resume = sun5i_clkevt_shutdown; | ||
290 | ce->clkevt.rating = 340; | 297 | ce->clkevt.rating = 340; |
291 | ce->clkevt.irq = irq; | 298 | ce->clkevt.irq = irq; |
292 | ce->clkevt.cpumask = cpu_possible_mask; | 299 | ce->clkevt.cpumask = cpu_possible_mask; |
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c index 5dcf756970e7..1744b243898a 100644 --- a/drivers/clocksource/timer-u300.c +++ b/drivers/clocksource/timer-u300.c | |||
@@ -187,85 +187,82 @@ struct u300_clockevent_data { | |||
187 | unsigned ticks_per_jiffy; | 187 | unsigned ticks_per_jiffy; |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static int u300_shutdown(struct clock_event_device *evt) | ||
191 | { | ||
192 | /* Disable interrupts on GP1 */ | ||
193 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
194 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
195 | /* Disable GP1 */ | ||
196 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
197 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
190 | /* | 201 | /* |
191 | * The u300_set_mode() function is always called first, if we | 202 | * If we have oneshot timer active, the oneshot scheduling function |
192 | * have oneshot timer active, the oneshot scheduling function | ||
193 | * u300_set_next_event() is called immediately after. | 203 | * u300_set_next_event() is called immediately after. |
194 | */ | 204 | */ |
195 | static void u300_set_mode(enum clock_event_mode mode, | 205 | static int u300_set_oneshot(struct clock_event_device *evt) |
196 | struct clock_event_device *evt) | 206 | { |
207 | /* Just return; here? */ | ||
208 | /* | ||
209 | * The actual event will be programmed by the next event hook, | ||
210 | * so we just set a dummy value somewhere at the end of the | ||
211 | * universe here. | ||
212 | */ | ||
213 | /* Disable interrupts on GPT1 */ | ||
214 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
215 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
216 | /* Disable GP1 while we're reprogramming it. */ | ||
217 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
218 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
219 | /* | ||
220 | * Expire far in the future, u300_set_next_event() will be | ||
221 | * called soon... | ||
222 | */ | ||
223 | writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC); | ||
224 | /* We run one shot per tick here! */ | ||
225 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | ||
226 | u300_timer_base + U300_TIMER_APP_SGPT1M); | ||
227 | /* Enable interrupts for this timer */ | ||
228 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | ||
229 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
230 | /* Enable timer */ | ||
231 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | ||
232 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int u300_set_periodic(struct clock_event_device *evt) | ||
197 | { | 237 | { |
198 | struct u300_clockevent_data *cevdata = | 238 | struct u300_clockevent_data *cevdata = |
199 | container_of(evt, struct u300_clockevent_data, cevd); | 239 | container_of(evt, struct u300_clockevent_data, cevd); |
200 | 240 | ||
201 | switch (mode) { | 241 | /* Disable interrupts on GPT1 */ |
202 | case CLOCK_EVT_MODE_PERIODIC: | 242 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, |
203 | /* Disable interrupts on GPT1 */ | 243 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
204 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | 244 | /* Disable GP1 while we're reprogramming it. */ |
205 | u300_timer_base + U300_TIMER_APP_GPT1IE); | 245 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, |
206 | /* Disable GP1 while we're reprogramming it. */ | 246 | u300_timer_base + U300_TIMER_APP_DGPT1); |
207 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | 247 | /* |
208 | u300_timer_base + U300_TIMER_APP_DGPT1); | 248 | * Set the periodic mode to a certain number of ticks per |
209 | /* | 249 | * jiffy. |
210 | * Set the periodic mode to a certain number of ticks per | 250 | */ |
211 | * jiffy. | 251 | writel(cevdata->ticks_per_jiffy, |
212 | */ | 252 | u300_timer_base + U300_TIMER_APP_GPT1TC); |
213 | writel(cevdata->ticks_per_jiffy, | 253 | /* |
214 | u300_timer_base + U300_TIMER_APP_GPT1TC); | 254 | * Set continuous mode, so the timer keeps triggering |
215 | /* | 255 | * interrupts. |
216 | * Set continuous mode, so the timer keeps triggering | 256 | */ |
217 | * interrupts. | 257 | writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, |
218 | */ | 258 | u300_timer_base + U300_TIMER_APP_SGPT1M); |
219 | writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, | 259 | /* Enable timer interrupts */ |
220 | u300_timer_base + U300_TIMER_APP_SGPT1M); | 260 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, |
221 | /* Enable timer interrupts */ | 261 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
222 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | 262 | /* Then enable the OS timer again */ |
223 | u300_timer_base + U300_TIMER_APP_GPT1IE); | 263 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, |
224 | /* Then enable the OS timer again */ | 264 | u300_timer_base + U300_TIMER_APP_EGPT1); |
225 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | 265 | return 0; |
226 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
227 | break; | ||
228 | case CLOCK_EVT_MODE_ONESHOT: | ||
229 | /* Just break; here? */ | ||
230 | /* | ||
231 | * The actual event will be programmed by the next event hook, | ||
232 | * so we just set a dummy value somewhere at the end of the | ||
233 | * universe here. | ||
234 | */ | ||
235 | /* Disable interrupts on GPT1 */ | ||
236 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
237 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
238 | /* Disable GP1 while we're reprogramming it. */ | ||
239 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
240 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
241 | /* | ||
242 | * Expire far in the future, u300_set_next_event() will be | ||
243 | * called soon... | ||
244 | */ | ||
245 | writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC); | ||
246 | /* We run one shot per tick here! */ | ||
247 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | ||
248 | u300_timer_base + U300_TIMER_APP_SGPT1M); | ||
249 | /* Enable interrupts for this timer */ | ||
250 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | ||
251 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
252 | /* Enable timer */ | ||
253 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | ||
254 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
255 | break; | ||
256 | case CLOCK_EVT_MODE_UNUSED: | ||
257 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
258 | /* Disable interrupts on GP1 */ | ||
259 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
260 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
261 | /* Disable GP1 */ | ||
262 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
263 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
264 | break; | ||
265 | case CLOCK_EVT_MODE_RESUME: | ||
266 | /* Ignore this call */ | ||
267 | break; | ||
268 | } | ||
269 | } | 266 | } |
270 | 267 | ||
271 | /* | 268 | /* |
@@ -309,13 +306,15 @@ static int u300_set_next_event(unsigned long cycles, | |||
309 | static struct u300_clockevent_data u300_clockevent_data = { | 306 | static struct u300_clockevent_data u300_clockevent_data = { |
310 | /* Use general purpose timer 1 as clock event */ | 307 | /* Use general purpose timer 1 as clock event */ |
311 | .cevd = { | 308 | .cevd = { |
312 | .name = "GPT1", | 309 | .name = "GPT1", |
313 | /* Reasonably fast and accurate clock event */ | 310 | /* Reasonably fast and accurate clock event */ |
314 | .rating = 300, | 311 | .rating = 300, |
315 | .features = CLOCK_EVT_FEAT_PERIODIC | | 312 | .features = CLOCK_EVT_FEAT_PERIODIC | |
316 | CLOCK_EVT_FEAT_ONESHOT, | 313 | CLOCK_EVT_FEAT_ONESHOT, |
317 | .set_next_event = u300_set_next_event, | 314 | .set_next_event = u300_set_next_event, |
318 | .set_mode = u300_set_mode, | 315 | .set_state_shutdown = u300_shutdown, |
316 | .set_state_periodic = u300_set_periodic, | ||
317 | .set_state_oneshot = u300_set_oneshot, | ||
319 | }, | 318 | }, |
320 | }; | 319 | }; |
321 | 320 | ||
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c index b45ac6229b57..f07ba9932171 100644 --- a/drivers/clocksource/vf_pit_timer.c +++ b/drivers/clocksource/vf_pit_timer.c | |||
@@ -86,20 +86,16 @@ static int pit_set_next_event(unsigned long delta, | |||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | static void pit_set_mode(enum clock_event_mode mode, | 89 | static int pit_shutdown(struct clock_event_device *evt) |
90 | struct clock_event_device *evt) | ||
91 | { | 90 | { |
92 | switch (mode) { | 91 | pit_timer_disable(); |
93 | case CLOCK_EVT_MODE_PERIODIC: | 92 | return 0; |
94 | pit_set_next_event(cycle_per_jiffy, evt); | 93 | } |
95 | break; | 94 | |
96 | case CLOCK_EVT_MODE_SHUTDOWN: | 95 | static int pit_set_periodic(struct clock_event_device *evt) |
97 | case CLOCK_EVT_MODE_UNUSED: | 96 | { |
98 | pit_timer_disable(); | 97 | pit_set_next_event(cycle_per_jiffy, evt); |
99 | break; | 98 | return 0; |
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | } | 99 | } |
104 | 100 | ||
105 | static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) | 101 | static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) |
@@ -114,7 +110,7 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) | |||
114 | * and start the counter again. So software need to disable the timer | 110 | * and start the counter again. So software need to disable the timer |
115 | * to stop the counter loop in ONESHOT mode. | 111 | * to stop the counter loop in ONESHOT mode. |
116 | */ | 112 | */ |
117 | if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT)) | 113 | if (likely(clockevent_state_oneshot(evt))) |
118 | pit_timer_disable(); | 114 | pit_timer_disable(); |
119 | 115 | ||
120 | evt->event_handler(evt); | 116 | evt->event_handler(evt); |
@@ -125,7 +121,8 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) | |||
125 | static struct clock_event_device clockevent_pit = { | 121 | static struct clock_event_device clockevent_pit = { |
126 | .name = "VF pit timer", | 122 | .name = "VF pit timer", |
127 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 123 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
128 | .set_mode = pit_set_mode, | 124 | .set_state_shutdown = pit_shutdown, |
125 | .set_state_periodic = pit_set_periodic, | ||
129 | .set_next_event = pit_set_next_event, | 126 | .set_next_event = pit_set_next_event, |
130 | .rating = 300, | 127 | .rating = 300, |
131 | }; | 128 | }; |
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index 1098ed3b9b89..a92e94b40b5b 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c | |||
@@ -88,29 +88,20 @@ static int vt8500_timer_set_next_event(unsigned long cycles, | |||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static void vt8500_timer_set_mode(enum clock_event_mode mode, | 91 | static int vt8500_shutdown(struct clock_event_device *evt) |
92 | struct clock_event_device *evt) | ||
93 | { | 92 | { |
94 | switch (mode) { | 93 | writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL); |
95 | case CLOCK_EVT_MODE_RESUME: | 94 | writel(0, regbase + TIMER_IER_VAL); |
96 | case CLOCK_EVT_MODE_PERIODIC: | 95 | return 0; |
97 | break; | ||
98 | case CLOCK_EVT_MODE_ONESHOT: | ||
99 | case CLOCK_EVT_MODE_UNUSED: | ||
100 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
101 | writel(readl(regbase + TIMER_CTRL_VAL) | 1, | ||
102 | regbase + TIMER_CTRL_VAL); | ||
103 | writel(0, regbase + TIMER_IER_VAL); | ||
104 | break; | ||
105 | } | ||
106 | } | 96 | } |
107 | 97 | ||
108 | static struct clock_event_device clockevent = { | 98 | static struct clock_event_device clockevent = { |
109 | .name = "vt8500_timer", | 99 | .name = "vt8500_timer", |
110 | .features = CLOCK_EVT_FEAT_ONESHOT, | 100 | .features = CLOCK_EVT_FEAT_ONESHOT, |
111 | .rating = 200, | 101 | .rating = 200, |
112 | .set_next_event = vt8500_timer_set_next_event, | 102 | .set_next_event = vt8500_timer_set_next_event, |
113 | .set_mode = vt8500_timer_set_mode, | 103 | .set_state_shutdown = vt8500_shutdown, |
104 | .set_state_oneshot = vt8500_shutdown, | ||
114 | }; | 105 | }; |
115 | 106 | ||
116 | static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) | 107 | static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) |
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c index 7ce442148c3f..ceaa6133f9c2 100644 --- a/drivers/clocksource/zevio-timer.c +++ b/drivers/clocksource/zevio-timer.c | |||
@@ -76,32 +76,28 @@ static int zevio_timer_set_event(unsigned long delta, | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void zevio_timer_set_mode(enum clock_event_mode mode, | 79 | static int zevio_timer_shutdown(struct clock_event_device *dev) |
80 | struct clock_event_device *dev) | ||
81 | { | 80 | { |
82 | struct zevio_timer *timer = container_of(dev, struct zevio_timer, | 81 | struct zevio_timer *timer = container_of(dev, struct zevio_timer, |
83 | clkevt); | 82 | clkevt); |
84 | 83 | ||
85 | switch (mode) { | 84 | /* Disable timer interrupts */ |
86 | case CLOCK_EVT_MODE_RESUME: | 85 | writel(0, timer->interrupt_regs + IO_INTR_MSK); |
87 | case CLOCK_EVT_MODE_ONESHOT: | 86 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); |
88 | /* Enable timer interrupts */ | 87 | /* Stop timer */ |
89 | writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); | 88 | writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); |
90 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); | 89 | return 0; |
91 | break; | 90 | } |
92 | case CLOCK_EVT_MODE_SHUTDOWN: | 91 | |
93 | case CLOCK_EVT_MODE_UNUSED: | 92 | static int zevio_timer_set_oneshot(struct clock_event_device *dev) |
94 | /* Disable timer interrupts */ | 93 | { |
95 | writel(0, timer->interrupt_regs + IO_INTR_MSK); | 94 | struct zevio_timer *timer = container_of(dev, struct zevio_timer, |
96 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); | 95 | clkevt); |
97 | /* Stop timer */ | 96 | |
98 | writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); | 97 | /* Enable timer interrupts */ |
99 | break; | 98 | writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); |
100 | case CLOCK_EVT_MODE_PERIODIC: | 99 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); |
101 | default: | 100 | return 0; |
102 | /* Unsupported */ | ||
103 | break; | ||
104 | } | ||
105 | } | 101 | } |
106 | 102 | ||
107 | static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) | 103 | static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) |
@@ -162,7 +158,9 @@ static int __init zevio_timer_add(struct device_node *node) | |||
162 | if (timer->interrupt_regs && irqnr) { | 158 | if (timer->interrupt_regs && irqnr) { |
163 | timer->clkevt.name = timer->clockevent_name; | 159 | timer->clkevt.name = timer->clockevent_name; |
164 | timer->clkevt.set_next_event = zevio_timer_set_event; | 160 | timer->clkevt.set_next_event = zevio_timer_set_event; |
165 | timer->clkevt.set_mode = zevio_timer_set_mode; | 161 | timer->clkevt.set_state_shutdown = zevio_timer_shutdown; |
162 | timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot; | ||
163 | timer->clkevt.tick_resume = zevio_timer_set_oneshot; | ||
166 | timer->clkevt.rating = 200; | 164 | timer->clkevt.rating = 200; |
167 | timer->clkevt.cpumask = cpu_all_mask; | 165 | timer->clkevt.cpumask = cpu_all_mask; |
168 | timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; | 166 | timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; |
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 597a1e836f22..31ce435981fe 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
@@ -234,13 +234,10 @@ static inline int tick_check_broadcast_expired(void) { return 0; } | |||
234 | static inline void tick_setup_hrtimer_broadcast(void) { } | 234 | static inline void tick_setup_hrtimer_broadcast(void) { } |
235 | # endif | 235 | # endif |
236 | 236 | ||
237 | extern int clockevents_notify(unsigned long reason, void *arg); | ||
238 | |||
239 | #else /* !CONFIG_GENERIC_CLOCKEVENTS: */ | 237 | #else /* !CONFIG_GENERIC_CLOCKEVENTS: */ |
240 | 238 | ||
241 | static inline void clockevents_suspend(void) { } | 239 | static inline void clockevents_suspend(void) { } |
242 | static inline void clockevents_resume(void) { } | 240 | static inline void clockevents_resume(void) { } |
243 | static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; } | ||
244 | static inline int tick_check_broadcast_expired(void) { return 0; } | 241 | static inline int tick_check_broadcast_expired(void) { return 0; } |
245 | static inline void tick_setup_hrtimer_broadcast(void) { } | 242 | static inline void tick_setup_hrtimer_broadcast(void) { } |
246 | 243 | ||
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 9ea50da73513..5fdc55312334 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
@@ -409,9 +409,25 @@ static __always_inline unsigned long usecs_to_jiffies(const unsigned int u) | |||
409 | } | 409 | } |
410 | } | 410 | } |
411 | 411 | ||
412 | extern unsigned long timespec_to_jiffies(const struct timespec *value); | 412 | extern unsigned long timespec64_to_jiffies(const struct timespec64 *value); |
413 | extern void jiffies_to_timespec(const unsigned long jiffies, | 413 | extern void jiffies_to_timespec64(const unsigned long jiffies, |
414 | struct timespec *value); | 414 | struct timespec64 *value); |
415 | static inline unsigned long timespec_to_jiffies(const struct timespec *value) | ||
416 | { | ||
417 | struct timespec64 ts = timespec_to_timespec64(*value); | ||
418 | |||
419 | return timespec64_to_jiffies(&ts); | ||
420 | } | ||
421 | |||
422 | static inline void jiffies_to_timespec(const unsigned long jiffies, | ||
423 | struct timespec *value) | ||
424 | { | ||
425 | struct timespec64 ts; | ||
426 | |||
427 | jiffies_to_timespec64(jiffies, &ts); | ||
428 | *value = timespec64_to_timespec(ts); | ||
429 | } | ||
430 | |||
415 | extern unsigned long timeval_to_jiffies(const struct timeval *value); | 431 | extern unsigned long timeval_to_jiffies(const struct timeval *value); |
416 | extern void jiffies_to_timeval(const unsigned long jiffies, | 432 | extern void jiffies_to_timeval(const unsigned long jiffies, |
417 | struct timeval *value); | 433 | struct timeval *value); |
diff --git a/include/linux/time64.h b/include/linux/time64.h index 77b5df2acd2a..367d5af899e8 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h | |||
@@ -12,11 +12,18 @@ typedef __s64 time64_t; | |||
12 | */ | 12 | */ |
13 | #if __BITS_PER_LONG == 64 | 13 | #if __BITS_PER_LONG == 64 |
14 | # define timespec64 timespec | 14 | # define timespec64 timespec |
15 | #define itimerspec64 itimerspec | ||
15 | #else | 16 | #else |
16 | struct timespec64 { | 17 | struct timespec64 { |
17 | time64_t tv_sec; /* seconds */ | 18 | time64_t tv_sec; /* seconds */ |
18 | long tv_nsec; /* nanoseconds */ | 19 | long tv_nsec; /* nanoseconds */ |
19 | }; | 20 | }; |
21 | |||
22 | struct itimerspec64 { | ||
23 | struct timespec64 it_interval; | ||
24 | struct timespec64 it_value; | ||
25 | }; | ||
26 | |||
20 | #endif | 27 | #endif |
21 | 28 | ||
22 | /* Parameters used to convert the timespec values: */ | 29 | /* Parameters used to convert the timespec values: */ |
@@ -45,6 +52,16 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | |||
45 | return ts; | 52 | return ts; |
46 | } | 53 | } |
47 | 54 | ||
55 | static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) | ||
56 | { | ||
57 | return *its64; | ||
58 | } | ||
59 | |||
60 | static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) | ||
61 | { | ||
62 | return *its; | ||
63 | } | ||
64 | |||
48 | # define timespec64_equal timespec_equal | 65 | # define timespec64_equal timespec_equal |
49 | # define timespec64_compare timespec_compare | 66 | # define timespec64_compare timespec_compare |
50 | # define set_normalized_timespec64 set_normalized_timespec | 67 | # define set_normalized_timespec64 set_normalized_timespec |
@@ -77,6 +94,24 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | |||
77 | return ret; | 94 | return ret; |
78 | } | 95 | } |
79 | 96 | ||
97 | static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) | ||
98 | { | ||
99 | struct itimerspec ret; | ||
100 | |||
101 | ret.it_interval = timespec64_to_timespec(its64->it_interval); | ||
102 | ret.it_value = timespec64_to_timespec(its64->it_value); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) | ||
107 | { | ||
108 | struct itimerspec64 ret; | ||
109 | |||
110 | ret.it_interval = timespec_to_timespec64(its->it_interval); | ||
111 | ret.it_value = timespec_to_timespec64(its->it_value); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
80 | static inline int timespec64_equal(const struct timespec64 *a, | 115 | static inline int timespec64_equal(const struct timespec64 *a, |
81 | const struct timespec64 *b) | 116 | const struct timespec64 *b) |
82 | { | 117 | { |
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 6e191e4e6ab6..ba0ae09cbb21 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h | |||
@@ -18,10 +18,17 @@ extern int do_sys_settimeofday(const struct timespec *tv, | |||
18 | * Kernel time accessors | 18 | * Kernel time accessors |
19 | */ | 19 | */ |
20 | unsigned long get_seconds(void); | 20 | unsigned long get_seconds(void); |
21 | struct timespec current_kernel_time(void); | 21 | struct timespec64 current_kernel_time64(void); |
22 | /* does not take xtime_lock */ | 22 | /* does not take xtime_lock */ |
23 | struct timespec __current_kernel_time(void); | 23 | struct timespec __current_kernel_time(void); |
24 | 24 | ||
25 | static inline struct timespec current_kernel_time(void) | ||
26 | { | ||
27 | struct timespec64 now = current_kernel_time64(); | ||
28 | |||
29 | return timespec64_to_timespec(now); | ||
30 | } | ||
31 | |||
25 | /* | 32 | /* |
26 | * timespec based interfaces | 33 | * timespec based interfaces |
27 | */ | 34 | */ |
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 5c7ae4b641c4..457a373e2181 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c | |||
@@ -183,7 +183,7 @@ struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, | |||
183 | int pinned) | 183 | int pinned) |
184 | { | 184 | { |
185 | if (pinned || !base->migration_enabled) | 185 | if (pinned || !base->migration_enabled) |
186 | return this_cpu_ptr(&hrtimer_bases); | 186 | return base; |
187 | return &per_cpu(hrtimer_bases, get_nohz_timer_target()); | 187 | return &per_cpu(hrtimer_bases, get_nohz_timer_target()); |
188 | } | 188 | } |
189 | #else | 189 | #else |
@@ -191,23 +191,32 @@ static inline | |||
191 | struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, | 191 | struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, |
192 | int pinned) | 192 | int pinned) |
193 | { | 193 | { |
194 | return this_cpu_ptr(&hrtimer_bases); | 194 | return base; |
195 | } | 195 | } |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | /* | 198 | /* |
199 | * Switch the timer base to the current CPU when possible. | 199 | * We switch the timer base to a power-optimized selected CPU target, |
200 | * if: | ||
201 | * - NO_HZ_COMMON is enabled | ||
202 | * - timer migration is enabled | ||
203 | * - the timer callback is not running | ||
204 | * - the timer is not the first expiring timer on the new target | ||
205 | * | ||
206 | * If one of the above requirements is not fulfilled we move the timer | ||
207 | * to the current CPU or leave it on the previously assigned CPU if | ||
208 | * the timer callback is currently running. | ||
200 | */ | 209 | */ |
201 | static inline struct hrtimer_clock_base * | 210 | static inline struct hrtimer_clock_base * |
202 | switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, | 211 | switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, |
203 | int pinned) | 212 | int pinned) |
204 | { | 213 | { |
205 | struct hrtimer_cpu_base *new_cpu_base, *this_base; | 214 | struct hrtimer_cpu_base *new_cpu_base, *this_cpu_base; |
206 | struct hrtimer_clock_base *new_base; | 215 | struct hrtimer_clock_base *new_base; |
207 | int basenum = base->index; | 216 | int basenum = base->index; |
208 | 217 | ||
209 | this_base = this_cpu_ptr(&hrtimer_bases); | 218 | this_cpu_base = this_cpu_ptr(&hrtimer_bases); |
210 | new_cpu_base = get_target_base(this_base, pinned); | 219 | new_cpu_base = get_target_base(this_cpu_base, pinned); |
211 | again: | 220 | again: |
212 | new_base = &new_cpu_base->clock_base[basenum]; | 221 | new_base = &new_cpu_base->clock_base[basenum]; |
213 | 222 | ||
@@ -229,19 +238,19 @@ again: | |||
229 | raw_spin_unlock(&base->cpu_base->lock); | 238 | raw_spin_unlock(&base->cpu_base->lock); |
230 | raw_spin_lock(&new_base->cpu_base->lock); | 239 | raw_spin_lock(&new_base->cpu_base->lock); |
231 | 240 | ||
232 | if (new_cpu_base != this_base && | 241 | if (new_cpu_base != this_cpu_base && |
233 | hrtimer_check_target(timer, new_base)) { | 242 | hrtimer_check_target(timer, new_base)) { |
234 | raw_spin_unlock(&new_base->cpu_base->lock); | 243 | raw_spin_unlock(&new_base->cpu_base->lock); |
235 | raw_spin_lock(&base->cpu_base->lock); | 244 | raw_spin_lock(&base->cpu_base->lock); |
236 | new_cpu_base = this_base; | 245 | new_cpu_base = this_cpu_base; |
237 | timer->base = base; | 246 | timer->base = base; |
238 | goto again; | 247 | goto again; |
239 | } | 248 | } |
240 | timer->base = new_base; | 249 | timer->base = new_base; |
241 | } else { | 250 | } else { |
242 | if (new_cpu_base != this_base && | 251 | if (new_cpu_base != this_cpu_base && |
243 | hrtimer_check_target(timer, new_base)) { | 252 | hrtimer_check_target(timer, new_base)) { |
244 | new_cpu_base = this_base; | 253 | new_cpu_base = this_cpu_base; |
245 | goto again; | 254 | goto again; |
246 | } | 255 | } |
247 | } | 256 | } |
@@ -679,14 +688,14 @@ static void retrigger_next_event(void *arg) | |||
679 | /* | 688 | /* |
680 | * Switch to high resolution mode | 689 | * Switch to high resolution mode |
681 | */ | 690 | */ |
682 | static int hrtimer_switch_to_hres(void) | 691 | static void hrtimer_switch_to_hres(void) |
683 | { | 692 | { |
684 | struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases); | 693 | struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases); |
685 | 694 | ||
686 | if (tick_init_highres()) { | 695 | if (tick_init_highres()) { |
687 | printk(KERN_WARNING "Could not switch to high resolution " | 696 | printk(KERN_WARNING "Could not switch to high resolution " |
688 | "mode on CPU %d\n", base->cpu); | 697 | "mode on CPU %d\n", base->cpu); |
689 | return 0; | 698 | return; |
690 | } | 699 | } |
691 | base->hres_active = 1; | 700 | base->hres_active = 1; |
692 | hrtimer_resolution = HIGH_RES_NSEC; | 701 | hrtimer_resolution = HIGH_RES_NSEC; |
@@ -694,7 +703,6 @@ static int hrtimer_switch_to_hres(void) | |||
694 | tick_setup_sched_timer(); | 703 | tick_setup_sched_timer(); |
695 | /* "Retrigger" the interrupt to get things going */ | 704 | /* "Retrigger" the interrupt to get things going */ |
696 | retrigger_next_event(NULL); | 705 | retrigger_next_event(NULL); |
697 | return 1; | ||
698 | } | 706 | } |
699 | 707 | ||
700 | static void clock_was_set_work(struct work_struct *work) | 708 | static void clock_was_set_work(struct work_struct *work) |
@@ -718,7 +726,7 @@ void clock_was_set_delayed(void) | |||
718 | static inline int __hrtimer_hres_active(struct hrtimer_cpu_base *b) { return 0; } | 726 | static inline int __hrtimer_hres_active(struct hrtimer_cpu_base *b) { return 0; } |
719 | static inline int hrtimer_hres_active(void) { return 0; } | 727 | static inline int hrtimer_hres_active(void) { return 0; } |
720 | static inline int hrtimer_is_hres_enabled(void) { return 0; } | 728 | static inline int hrtimer_is_hres_enabled(void) { return 0; } |
721 | static inline int hrtimer_switch_to_hres(void) { return 0; } | 729 | static inline void hrtimer_switch_to_hres(void) { } |
722 | static inline void | 730 | static inline void |
723 | hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } | 731 | hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } |
724 | static inline int hrtimer_reprogram(struct hrtimer *timer, | 732 | static inline int hrtimer_reprogram(struct hrtimer *timer, |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index fb4d98c7fd43..df68cb875248 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -487,6 +487,11 @@ out: | |||
487 | } | 487 | } |
488 | 488 | ||
489 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 489 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
490 | int __weak update_persistent_clock(struct timespec now) | ||
491 | { | ||
492 | return -ENODEV; | ||
493 | } | ||
494 | |||
490 | int __weak update_persistent_clock64(struct timespec64 now64) | 495 | int __weak update_persistent_clock64(struct timespec64 now64) |
491 | { | 496 | { |
492 | struct timespec now; | 497 | struct timespec now; |
diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c index 3e7db49a2381..53d7184da0be 100644 --- a/kernel/time/tick-broadcast-hrtimer.c +++ b/kernel/time/tick-broadcast-hrtimer.c | |||
@@ -18,30 +18,23 @@ | |||
18 | 18 | ||
19 | static struct hrtimer bctimer; | 19 | static struct hrtimer bctimer; |
20 | 20 | ||
21 | static void bc_set_mode(enum clock_event_mode mode, | 21 | static int bc_shutdown(struct clock_event_device *evt) |
22 | struct clock_event_device *bc) | ||
23 | { | 22 | { |
24 | switch (mode) { | 23 | /* |
25 | case CLOCK_EVT_MODE_UNUSED: | 24 | * Note, we cannot cancel the timer here as we might |
26 | case CLOCK_EVT_MODE_SHUTDOWN: | 25 | * run into the following live lock scenario: |
27 | /* | 26 | * |
28 | * Note, we cannot cancel the timer here as we might | 27 | * cpu 0 cpu1 |
29 | * run into the following live lock scenario: | 28 | * lock(broadcast_lock); |
30 | * | 29 | * hrtimer_interrupt() |
31 | * cpu 0 cpu1 | 30 | * bc_handler() |
32 | * lock(broadcast_lock); | 31 | * tick_handle_oneshot_broadcast(); |
33 | * hrtimer_interrupt() | 32 | * lock(broadcast_lock); |
34 | * bc_handler() | 33 | * hrtimer_cancel() |
35 | * tick_handle_oneshot_broadcast(); | 34 | * wait_for_callback() |
36 | * lock(broadcast_lock); | 35 | */ |
37 | * hrtimer_cancel() | 36 | hrtimer_try_to_cancel(&bctimer); |
38 | * wait_for_callback() | 37 | return 0; |
39 | */ | ||
40 | hrtimer_try_to_cancel(&bctimer); | ||
41 | break; | ||
42 | default: | ||
43 | break; | ||
44 | } | ||
45 | } | 38 | } |
46 | 39 | ||
47 | /* | 40 | /* |
@@ -82,7 +75,7 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) | |||
82 | } | 75 | } |
83 | 76 | ||
84 | static struct clock_event_device ce_broadcast_hrtimer = { | 77 | static struct clock_event_device ce_broadcast_hrtimer = { |
85 | .set_mode = bc_set_mode, | 78 | .set_state_shutdown = bc_shutdown, |
86 | .set_next_ktime = bc_set_next, | 79 | .set_next_ktime = bc_set_next, |
87 | .features = CLOCK_EVT_FEAT_ONESHOT | | 80 | .features = CLOCK_EVT_FEAT_ONESHOT | |
88 | CLOCK_EVT_FEAT_KTIME | | 81 | CLOCK_EVT_FEAT_KTIME | |
@@ -102,13 +95,11 @@ static enum hrtimer_restart bc_handler(struct hrtimer *t) | |||
102 | { | 95 | { |
103 | ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer); | 96 | ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer); |
104 | 97 | ||
105 | switch (ce_broadcast_hrtimer.mode) { | 98 | if (clockevent_state_oneshot(&ce_broadcast_hrtimer)) |
106 | case CLOCK_EVT_MODE_ONESHOT: | ||
107 | if (ce_broadcast_hrtimer.next_event.tv64 != KTIME_MAX) | 99 | if (ce_broadcast_hrtimer.next_event.tv64 != KTIME_MAX) |
108 | return HRTIMER_RESTART; | 100 | return HRTIMER_RESTART; |
109 | default: | 101 | |
110 | return HRTIMER_NORESTART; | 102 | return HRTIMER_NORESTART; |
111 | } | ||
112 | } | 103 | } |
113 | 104 | ||
114 | void tick_setup_hrtimer_broadcast(void) | 105 | void tick_setup_hrtimer_broadcast(void) |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index f8bf47571dda..d11c55b6ab7d 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -304,9 +304,6 @@ void tick_check_new_device(struct clock_event_device *newdev) | |||
304 | int cpu; | 304 | int cpu; |
305 | 305 | ||
306 | cpu = smp_processor_id(); | 306 | cpu = smp_processor_id(); |
307 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) | ||
308 | goto out_bc; | ||
309 | |||
310 | td = &per_cpu(tick_cpu_device, cpu); | 307 | td = &per_cpu(tick_cpu_device, cpu); |
311 | curdev = td->evtdev; | 308 | curdev = td->evtdev; |
312 | 309 | ||
diff --git a/kernel/time/time.c b/kernel/time/time.c index ad1bf23e6eb7..86751c68e08d 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c | |||
@@ -291,26 +291,20 @@ EXPORT_SYMBOL(jiffies_to_usecs); | |||
291 | * @t: Timespec | 291 | * @t: Timespec |
292 | * @gran: Granularity in ns. | 292 | * @gran: Granularity in ns. |
293 | * | 293 | * |
294 | * Truncate a timespec to a granularity. gran must be smaller than a second. | 294 | * Truncate a timespec to a granularity. Always rounds down. gran must |
295 | * Always rounds down. | 295 | * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). |
296 | * | ||
297 | * This function should be only used for timestamps returned by | ||
298 | * current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because | ||
299 | * it doesn't handle the better resolution of the latter. | ||
300 | */ | 296 | */ |
301 | struct timespec timespec_trunc(struct timespec t, unsigned gran) | 297 | struct timespec timespec_trunc(struct timespec t, unsigned gran) |
302 | { | 298 | { |
303 | /* | 299 | /* Avoid division in the common cases 1 ns and 1 s. */ |
304 | * Division is pretty slow so avoid it for common cases. | 300 | if (gran == 1) { |
305 | * Currently current_kernel_time() never returns better than | ||
306 | * jiffies resolution. Exploit that. | ||
307 | */ | ||
308 | if (gran <= jiffies_to_usecs(1) * 1000) { | ||
309 | /* nothing */ | 301 | /* nothing */ |
310 | } else if (gran == 1000000000) { | 302 | } else if (gran == NSEC_PER_SEC) { |
311 | t.tv_nsec = 0; | 303 | t.tv_nsec = 0; |
312 | } else { | 304 | } else if (gran > 1 && gran < NSEC_PER_SEC) { |
313 | t.tv_nsec -= t.tv_nsec % gran; | 305 | t.tv_nsec -= t.tv_nsec % gran; |
306 | } else { | ||
307 | WARN(1, "illegal file time granularity: %u", gran); | ||
314 | } | 308 | } |
315 | return t; | 309 | return t; |
316 | } | 310 | } |
@@ -550,7 +544,7 @@ EXPORT_SYMBOL(__usecs_to_jiffies); | |||
550 | * value to a scaled second value. | 544 | * value to a scaled second value. |
551 | */ | 545 | */ |
552 | static unsigned long | 546 | static unsigned long |
553 | __timespec_to_jiffies(unsigned long sec, long nsec) | 547 | __timespec64_to_jiffies(u64 sec, long nsec) |
554 | { | 548 | { |
555 | nsec = nsec + TICK_NSEC - 1; | 549 | nsec = nsec + TICK_NSEC - 1; |
556 | 550 | ||
@@ -558,22 +552,27 @@ __timespec_to_jiffies(unsigned long sec, long nsec) | |||
558 | sec = MAX_SEC_IN_JIFFIES; | 552 | sec = MAX_SEC_IN_JIFFIES; |
559 | nsec = 0; | 553 | nsec = 0; |
560 | } | 554 | } |
561 | return (((u64)sec * SEC_CONVERSION) + | 555 | return ((sec * SEC_CONVERSION) + |
562 | (((u64)nsec * NSEC_CONVERSION) >> | 556 | (((u64)nsec * NSEC_CONVERSION) >> |
563 | (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; | 557 | (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; |
564 | 558 | ||
565 | } | 559 | } |
566 | 560 | ||
567 | unsigned long | 561 | static unsigned long |
568 | timespec_to_jiffies(const struct timespec *value) | 562 | __timespec_to_jiffies(unsigned long sec, long nsec) |
569 | { | 563 | { |
570 | return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); | 564 | return __timespec64_to_jiffies((u64)sec, nsec); |
571 | } | 565 | } |
572 | 566 | ||
573 | EXPORT_SYMBOL(timespec_to_jiffies); | 567 | unsigned long |
568 | timespec64_to_jiffies(const struct timespec64 *value) | ||
569 | { | ||
570 | return __timespec64_to_jiffies(value->tv_sec, value->tv_nsec); | ||
571 | } | ||
572 | EXPORT_SYMBOL(timespec64_to_jiffies); | ||
574 | 573 | ||
575 | void | 574 | void |
576 | jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) | 575 | jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value) |
577 | { | 576 | { |
578 | /* | 577 | /* |
579 | * Convert jiffies to nanoseconds and separate with | 578 | * Convert jiffies to nanoseconds and separate with |
@@ -584,7 +583,7 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) | |||
584 | NSEC_PER_SEC, &rem); | 583 | NSEC_PER_SEC, &rem); |
585 | value->tv_nsec = rem; | 584 | value->tv_nsec = rem; |
586 | } | 585 | } |
587 | EXPORT_SYMBOL(jiffies_to_timespec); | 586 | EXPORT_SYMBOL(jiffies_to_timespec64); |
588 | 587 | ||
589 | /* | 588 | /* |
590 | * We could use a similar algorithm to timespec_to_jiffies (with a | 589 | * We could use a similar algorithm to timespec_to_jiffies (with a |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index bca3667a2de1..f6ee2e6b6f5d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -911,6 +911,7 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
911 | struct timekeeper *tk = &tk_core.timekeeper; | 911 | struct timekeeper *tk = &tk_core.timekeeper; |
912 | struct timespec64 ts_delta, xt; | 912 | struct timespec64 ts_delta, xt; |
913 | unsigned long flags; | 913 | unsigned long flags; |
914 | int ret = 0; | ||
914 | 915 | ||
915 | if (!timespec64_valid_strict(ts)) | 916 | if (!timespec64_valid_strict(ts)) |
916 | return -EINVAL; | 917 | return -EINVAL; |
@@ -924,10 +925,15 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
924 | ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; | 925 | ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; |
925 | ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; | 926 | ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; |
926 | 927 | ||
928 | if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { | ||
929 | ret = -EINVAL; | ||
930 | goto out; | ||
931 | } | ||
932 | |||
927 | tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); | 933 | tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); |
928 | 934 | ||
929 | tk_set_xtime(tk, ts); | 935 | tk_set_xtime(tk, ts); |
930 | 936 | out: | |
931 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); | 937 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
932 | 938 | ||
933 | write_seqcount_end(&tk_core.seq); | 939 | write_seqcount_end(&tk_core.seq); |
@@ -936,7 +942,7 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
936 | /* signal hrtimers about time change */ | 942 | /* signal hrtimers about time change */ |
937 | clock_was_set(); | 943 | clock_was_set(); |
938 | 944 | ||
939 | return 0; | 945 | return ret; |
940 | } | 946 | } |
941 | EXPORT_SYMBOL(do_settimeofday64); | 947 | EXPORT_SYMBOL(do_settimeofday64); |
942 | 948 | ||
@@ -965,7 +971,8 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
965 | 971 | ||
966 | /* Make sure the proposed value is valid */ | 972 | /* Make sure the proposed value is valid */ |
967 | tmp = timespec64_add(tk_xtime(tk), ts64); | 973 | tmp = timespec64_add(tk_xtime(tk), ts64); |
968 | if (!timespec64_valid_strict(&tmp)) { | 974 | if (timespec64_compare(&tk->wall_to_monotonic, &ts64) > 0 || |
975 | !timespec64_valid_strict(&tmp)) { | ||
969 | ret = -EINVAL; | 976 | ret = -EINVAL; |
970 | goto error; | 977 | goto error; |
971 | } | 978 | } |
@@ -1874,7 +1881,7 @@ struct timespec __current_kernel_time(void) | |||
1874 | return timespec64_to_timespec(tk_xtime(tk)); | 1881 | return timespec64_to_timespec(tk_xtime(tk)); |
1875 | } | 1882 | } |
1876 | 1883 | ||
1877 | struct timespec current_kernel_time(void) | 1884 | struct timespec64 current_kernel_time64(void) |
1878 | { | 1885 | { |
1879 | struct timekeeper *tk = &tk_core.timekeeper; | 1886 | struct timekeeper *tk = &tk_core.timekeeper; |
1880 | struct timespec64 now; | 1887 | struct timespec64 now; |
@@ -1886,9 +1893,9 @@ struct timespec current_kernel_time(void) | |||
1886 | now = tk_xtime(tk); | 1893 | now = tk_xtime(tk); |
1887 | } while (read_seqcount_retry(&tk_core.seq, seq)); | 1894 | } while (read_seqcount_retry(&tk_core.seq, seq)); |
1888 | 1895 | ||
1889 | return timespec64_to_timespec(now); | 1896 | return now; |
1890 | } | 1897 | } |
1891 | EXPORT_SYMBOL(current_kernel_time); | 1898 | EXPORT_SYMBOL(current_kernel_time64); |
1892 | 1899 | ||
1893 | struct timespec64 get_monotonic_coarse64(void) | 1900 | struct timespec64 get_monotonic_coarse64(void) |
1894 | { | 1901 | { |
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index a4536e1e3e2a..129c96033e46 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c | |||
@@ -137,7 +137,7 @@ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now) | |||
137 | (unsigned long long) ktime_to_ns(base->offset)); | 137 | (unsigned long long) ktime_to_ns(base->offset)); |
138 | #endif | 138 | #endif |
139 | SEQ_printf(m, "active timers:\n"); | 139 | SEQ_printf(m, "active timers:\n"); |
140 | print_active_timers(m, base, now); | 140 | print_active_timers(m, base, now + ktime_to_ns(base->offset)); |
141 | } | 141 | } |
142 | 142 | ||
143 | static void print_cpu(struct seq_file *m, int cpu, u64 now) | 143 | static void print_cpu(struct seq_file *m, int cpu, u64 now) |