Blame view

drivers/clocksource/timer-stm32.c 8.43 KB
af873fcec   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
e37e45934   Maxime Coquelin   clockevents/drive...
2
3
4
  /*
   * Copyright (C) Maxime Coquelin 2015
   * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
e37e45934   Maxime Coquelin   clockevents/drive...
5
6
7
8
9
10
11
   *
   * Inspired by time-efm32.c from Uwe Kleine-Koenig
   */
  
  #include <linux/kernel.h>
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
81abdbbff   Daniel Lezcano   clocksource/drive...
12
  #include <linux/delay.h>
e37e45934   Maxime Coquelin   clockevents/drive...
13
14
15
16
17
18
19
  #include <linux/irq.h>
  #include <linux/interrupt.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
  #include <linux/clk.h>
  #include <linux/reset.h>
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
20
  #include <linux/sched_clock.h>
d04af4908   Benjamin Gaignard   clocksource/drive...
21
22
23
  #include <linux/slab.h>
  
  #include "timer-of.h"
e37e45934   Maxime Coquelin   clockevents/drive...
24
25
26
27
28
  
  #define TIM_CR1		0x00
  #define TIM_DIER	0x0c
  #define TIM_SR		0x10
  #define TIM_EGR		0x14
8e82df381   Benjamin Gaignard   clocksource/drive...
29
  #define TIM_CNT		0x24
e37e45934   Maxime Coquelin   clockevents/drive...
30
31
  #define TIM_PSC		0x28
  #define TIM_ARR		0x2c
8e82df381   Benjamin Gaignard   clocksource/drive...
32
  #define TIM_CCR1	0x34
e37e45934   Maxime Coquelin   clockevents/drive...
33
34
  
  #define TIM_CR1_CEN	BIT(0)
8e82df381   Benjamin Gaignard   clocksource/drive...
35
  #define TIM_CR1_UDIS	BIT(1)
e37e45934   Maxime Coquelin   clockevents/drive...
36
37
38
39
  #define TIM_CR1_OPM	BIT(3)
  #define TIM_CR1_ARPE	BIT(7)
  
  #define TIM_DIER_UIE	BIT(0)
8e82df381   Benjamin Gaignard   clocksource/drive...
40
  #define TIM_DIER_CC1IE	BIT(1)
e37e45934   Maxime Coquelin   clockevents/drive...
41
42
43
44
  
  #define TIM_SR_UIF	BIT(0)
  
  #define TIM_EGR_UG	BIT(0)
4744daa10   Benjamin Gaignard   clocksource/drive...
45
46
  #define TIM_PSC_MAX	USHRT_MAX
  #define TIM_PSC_CLKRATE	10000
3c84e75b1   Daniel Lezcano   clocksource/drive...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  struct stm32_timer_private {
  	int bits;
  };
  
  /**
   * stm32_timer_of_bits_set - set accessor helper
   * @to: a timer_of structure pointer
   * @bits: the number of bits (16 or 32)
   *
   * Accessor helper to set the number of bits in the timer-of private
   * structure.
   *
   */
  static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
  {
  	struct stm32_timer_private *pd = to->private_data;
  
  	pd->bits = bits;
  }
  
  /**
   * stm32_timer_of_bits_get - get accessor helper
   * @to: a timer_of structure pointer
   *
   * Accessor helper to get the number of bits in the timer-of private
   * structure.
   *
   * Returns an integer corresponding to the number of bits.
   */
  static int stm32_timer_of_bits_get(struct timer_of *to)
  {
  	struct stm32_timer_private *pd = to->private_data;
  
  	return pd->bits;
  }
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
82
83
84
85
86
87
  static void __iomem *stm32_timer_cnt __read_mostly;
  
  static u64 notrace stm32_read_sched_clock(void)
  {
  	return readl_relaxed(stm32_timer_cnt);
  }
81abdbbff   Daniel Lezcano   clocksource/drive...
88
89
90
91
92
93
  static struct delay_timer stm32_timer_delay;
  
  static unsigned long stm32_read_delay(void)
  {
  	return readl_relaxed(stm32_timer_cnt);
  }
8e82df381   Benjamin Gaignard   clocksource/drive...
94
95
96
97
  static void stm32_clock_event_disable(struct timer_of *to)
  {
  	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
  }
103bb56a2   Daniel Lezcano   clocksource/drive...
98
99
100
101
102
103
104
105
106
  /**
   * stm32_timer_start - Start the counter without event
   * @to: a timer_of structure pointer
   *
   * Start the timer in order to have the counter reset and start
   * incrementing but disable interrupt event when there is a counter
   * overflow. By default, the counter direction is used as upcounter.
   */
  static void stm32_timer_start(struct timer_of *to)
8e82df381   Benjamin Gaignard   clocksource/drive...
107
108
109
  {
  	writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
  }
d04af4908   Benjamin Gaignard   clocksource/drive...
110
  static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
e37e45934   Maxime Coquelin   clockevents/drive...
111
  {
d04af4908   Benjamin Gaignard   clocksource/drive...
112
  	struct timer_of *to = to_timer_of(clkevt);
8e82df381   Benjamin Gaignard   clocksource/drive...
113
  	stm32_clock_event_disable(to);
e37e45934   Maxime Coquelin   clockevents/drive...
114

8e8af4cd3   Viresh Kumar   clockevents/drive...
115
116
  	return 0;
  }
8e82df381   Benjamin Gaignard   clocksource/drive...
117
118
  static int stm32_clock_event_set_next_event(unsigned long evt,
  					    struct clock_event_device *clkevt)
8e8af4cd3   Viresh Kumar   clockevents/drive...
119
  {
d04af4908   Benjamin Gaignard   clocksource/drive...
120
  	struct timer_of *to = to_timer_of(clkevt);
8e82df381   Benjamin Gaignard   clocksource/drive...
121
122
123
124
125
126
127
128
  	unsigned long now, next;
  
  	next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
  	writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
  	now = readl_relaxed(timer_of_base(to) + TIM_CNT);
  
  	if ((next - now) > evt)
  		return -ETIME;
d04af4908   Benjamin Gaignard   clocksource/drive...
129

8e82df381   Benjamin Gaignard   clocksource/drive...
130
  	writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
8e8af4cd3   Viresh Kumar   clockevents/drive...
131

8e8af4cd3   Viresh Kumar   clockevents/drive...
132
  	return 0;
e37e45934   Maxime Coquelin   clockevents/drive...
133
  }
8e82df381   Benjamin Gaignard   clocksource/drive...
134
135
136
  static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
  {
  	struct timer_of *to = to_timer_of(clkevt);
103bb56a2   Daniel Lezcano   clocksource/drive...
137
  	stm32_timer_start(to);
8e82df381   Benjamin Gaignard   clocksource/drive...
138
139
140
141
142
  
  	return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
  }
  
  static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
e37e45934   Maxime Coquelin   clockevents/drive...
143
  {
d04af4908   Benjamin Gaignard   clocksource/drive...
144
  	struct timer_of *to = to_timer_of(clkevt);
e37e45934   Maxime Coquelin   clockevents/drive...
145

103bb56a2   Daniel Lezcano   clocksource/drive...
146
  	stm32_timer_start(to);
e37e45934   Maxime Coquelin   clockevents/drive...
147
148
149
150
151
152
  
  	return 0;
  }
  
  static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
  {
d04af4908   Benjamin Gaignard   clocksource/drive...
153
154
  	struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
  	struct timer_of *to = to_timer_of(clkevt);
e37e45934   Maxime Coquelin   clockevents/drive...
155

d04af4908   Benjamin Gaignard   clocksource/drive...
156
  	writel_relaxed(0, timer_of_base(to) + TIM_SR);
e37e45934   Maxime Coquelin   clockevents/drive...
157

8e82df381   Benjamin Gaignard   clocksource/drive...
158
159
160
161
  	if (clockevent_state_periodic(clkevt))
  		stm32_clock_event_set_periodic(clkevt);
  	else
  		stm32_clock_event_shutdown(clkevt);
d04af4908   Benjamin Gaignard   clocksource/drive...
162
  	clkevt->event_handler(clkevt);
e37e45934   Maxime Coquelin   clockevents/drive...
163
164
165
  
  	return IRQ_HANDLED;
  }
70c62cf91   Daniel Lezcano   clocksource/drive...
166
167
168
169
170
171
172
173
  /**
   * stm32_timer_width - Sort out the timer width (32/16)
   * @to: a pointer to a timer-of structure
   *
   * Write the 32-bit max value and read/return the result. If the timer
   * is 32 bits wide, the result will be UINT_MAX, otherwise it will
   * be truncated by the 16-bit register to USHRT_MAX.
   *
70c62cf91   Daniel Lezcano   clocksource/drive...
174
   */
3c84e75b1   Daniel Lezcano   clocksource/drive...
175
  static void __init stm32_timer_set_width(struct timer_of *to)
70c62cf91   Daniel Lezcano   clocksource/drive...
176
  {
3c84e75b1   Daniel Lezcano   clocksource/drive...
177
  	u32 width;
70c62cf91   Daniel Lezcano   clocksource/drive...
178
  	writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
3c84e75b1   Daniel Lezcano   clocksource/drive...
179
180
181
  	width = readl_relaxed(timer_of_base(to) + TIM_ARR);
  
  	stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
70c62cf91   Daniel Lezcano   clocksource/drive...
182
  }
3c84e75b1   Daniel Lezcano   clocksource/drive...
183
184
185
186
187
188
189
190
191
  /**
   * stm32_timer_set_prescaler - Compute and set the prescaler register
   * @to: a pointer to a timer-of structure
   *
   * Depending on the timer width, compute the prescaler to always
   * target a 10MHz timer rate for 16 bits. 32-bit timers are
   * considered precise and long enough to not use the prescaler.
   */
  static void __init stm32_timer_set_prescaler(struct timer_of *to)
e37e45934   Maxime Coquelin   clockevents/drive...
192
  {
3c84e75b1   Daniel Lezcano   clocksource/drive...
193
  	int prescaler = 1;
e37e45934   Maxime Coquelin   clockevents/drive...
194

3c84e75b1   Daniel Lezcano   clocksource/drive...
195
  	if (stm32_timer_of_bits_get(to) != 32) {
4744daa10   Benjamin Gaignard   clocksource/drive...
196
197
198
199
200
201
202
203
  		prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
  					      TIM_PSC_CLKRATE);
  		/*
  		 * The prescaler register is an u16, the variable
  		 * can't be greater than TIM_PSC_MAX, let's cap it in
  		 * this case.
  		 */
  		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
e37e45934   Maxime Coquelin   clockevents/drive...
204
  	}
e37e45934   Maxime Coquelin   clockevents/drive...
205

d04af4908   Benjamin Gaignard   clocksource/drive...
206
207
208
  	writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
  	writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
  	writel_relaxed(0, timer_of_base(to) + TIM_SR);
e37e45934   Maxime Coquelin   clockevents/drive...
209

d04af4908   Benjamin Gaignard   clocksource/drive...
210
211
212
  	/* Adjust rate and period given the prescaler value */
  	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
  	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
3c84e75b1   Daniel Lezcano   clocksource/drive...
213
  }
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  static int __init stm32_clocksource_init(struct timer_of *to)
  {
          u32 bits = stm32_timer_of_bits_get(to);
  	const char *name = to->np->full_name;
  
  	/*
  	 * This driver allows to register several timers and relies on
  	 * the generic time framework to select the right one.
  	 * However, nothing allows to do the same for the
  	 * sched_clock. We are not interested in a sched_clock for the
  	 * 16-bit timers but only for the 32-bit one, so if no 32-bit
  	 * timer is registered yet, we select this 32-bit timer as a
  	 * sched_clock.
  	 */
  	if (bits == 32 && !stm32_timer_cnt) {
103bb56a2   Daniel Lezcano   clocksource/drive...
229
230
231
232
233
234
  
  		/*
  		 * Start immediately the counter as we will be using
  		 * it right after.
  		 */
  		stm32_timer_start(to);
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
235
236
237
238
  		stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
  		sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
  		pr_info("%s: STM32 sched_clock registered
  ", name);
81abdbbff   Daniel Lezcano   clocksource/drive...
239
240
241
242
243
244
  
  		stm32_timer_delay.read_current_timer = stm32_read_delay;
  		stm32_timer_delay.freq = timer_of_rate(to);
  		register_current_timer_delay(&stm32_timer_delay);
  		pr_info("%s: STM32 delay timer registered
  ", name);
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
245
246
247
248
249
250
  	}
  
  	return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
  				     timer_of_rate(to), bits == 32 ? 250 : 100,
  				     bits, clocksource_mmio_readl_up);
  }
3c84e75b1   Daniel Lezcano   clocksource/drive...
251
252
253
  static void __init stm32_clockevent_init(struct timer_of *to)
  {
  	u32 bits = stm32_timer_of_bits_get(to);
e37e45934   Maxime Coquelin   clockevents/drive...
254

3c84e75b1   Daniel Lezcano   clocksource/drive...
255
256
257
258
259
260
261
262
263
264
265
  	to->clkevt.name = to->np->full_name;
  	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
  	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
  	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
  	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
  	to->clkevt.tick_resume = stm32_clock_event_shutdown;
  	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
  	to->clkevt.rating = bits == 32 ? 250 : 100;
  
  	clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
  					(1 <<  bits) - 1);
e37e45934   Maxime Coquelin   clockevents/drive...
266

469869d18   Rob Herring   clocksource: Conv...
267
268
  	pr_info("%pOF: STM32 clockevent driver initialized (%d bits)
  ",
3c84e75b1   Daniel Lezcano   clocksource/drive...
269
  		to->np, bits);
d04af4908   Benjamin Gaignard   clocksource/drive...
270
  }
e37e45934   Maxime Coquelin   clockevents/drive...
271

d04af4908   Benjamin Gaignard   clocksource/drive...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  static int __init stm32_timer_init(struct device_node *node)
  {
  	struct reset_control *rstc;
  	struct timer_of *to;
  	int ret;
  
  	to = kzalloc(sizeof(*to), GFP_KERNEL);
  	if (!to)
  		return -ENOMEM;
  
  	to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
  	to->of_irq.handler = stm32_clock_event_handler;
  
  	ret = timer_of_init(node, to);
  	if (ret)
  		goto err;
e37e45934   Maxime Coquelin   clockevents/drive...
288

3c84e75b1   Daniel Lezcano   clocksource/drive...
289
290
  	to->private_data = kzalloc(sizeof(struct stm32_timer_private),
  				   GFP_KERNEL);
a26ed66c2   Julia Lawall   clocksource/drive...
291
292
  	if (!to->private_data) {
  		ret = -ENOMEM;
3c84e75b1   Daniel Lezcano   clocksource/drive...
293
  		goto deinit;
a26ed66c2   Julia Lawall   clocksource/drive...
294
  	}
3c84e75b1   Daniel Lezcano   clocksource/drive...
295

d04af4908   Benjamin Gaignard   clocksource/drive...
296
297
298
299
300
  	rstc = of_reset_control_get(node, NULL);
  	if (!IS_ERR(rstc)) {
  		reset_control_assert(rstc);
  		reset_control_deassert(rstc);
  	}
3c84e75b1   Daniel Lezcano   clocksource/drive...
301
302
303
  	stm32_timer_set_width(to);
  
  	stm32_timer_set_prescaler(to);
f5ef02bd0   Benjamin Gaignard   clocksource/drive...
304
305
306
  	ret = stm32_clocksource_init(to);
  	if (ret)
  		goto deinit;
d04af4908   Benjamin Gaignard   clocksource/drive...
307
308
  	stm32_clockevent_init(to);
  	return 0;
3c84e75b1   Daniel Lezcano   clocksource/drive...
309
310
311
  
  deinit:
  	timer_of_cleanup(to);
d04af4908   Benjamin Gaignard   clocksource/drive...
312
313
  err:
  	kfree(to);
38d94c5ae   Daniel Lezcano   clocksource/drive...
314
  	return ret;
e37e45934   Maxime Coquelin   clockevents/drive...
315
  }
d04af4908   Benjamin Gaignard   clocksource/drive...
316
  TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);