Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * STM32 Timer Encoder and Counter driver
4 *
5 * Copyright (C) STMicroelectronics 2018
6 *
7 * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
8 *
9 */
10#include <linux/counter.h>
11#include <linux/iio/iio.h>
12#include <linux/iio/types.h>
13#include <linux/mfd/stm32-timers.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16
17#define TIM_CCMR_CCXS (BIT(8) | BIT(0))
18#define TIM_CCMR_MASK (TIM_CCMR_CC1S | TIM_CCMR_CC2S | \
19 TIM_CCMR_IC1F | TIM_CCMR_IC2F)
20#define TIM_CCER_MASK (TIM_CCER_CC1P | TIM_CCER_CC1NP | \
21 TIM_CCER_CC2P | TIM_CCER_CC2NP)
22
23struct stm32_timer_cnt {
24 struct counter_device counter;
25 struct regmap *regmap;
26 struct clk *clk;
27 u32 ceiling;
28};
29
30/**
31 * enum stm32_count_function - enumerates stm32 timer counter encoder modes
32 * @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1
33 * @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level
34 * @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level
35 * @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges
36 */
37enum stm32_count_function {
38 STM32_COUNT_SLAVE_MODE_DISABLED = -1,
39 STM32_COUNT_ENCODER_MODE_1,
40 STM32_COUNT_ENCODER_MODE_2,
41 STM32_COUNT_ENCODER_MODE_3,
42};
43
44static enum counter_count_function stm32_count_functions[] = {
45 [STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
46 [STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
47 [STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
48};
49
50static int stm32_count_read(struct counter_device *counter,
51 struct counter_count *count, unsigned long *val)
52{
53 struct stm32_timer_cnt *const priv = counter->priv;
54 u32 cnt;
55
56 regmap_read(priv->regmap, TIM_CNT, &cnt);
57 *val = cnt;
58
59 return 0;
60}
61
62static int stm32_count_write(struct counter_device *counter,
63 struct counter_count *count,
64 const unsigned long val)
65{
66 struct stm32_timer_cnt *const priv = counter->priv;
67
68 if (val > priv->ceiling)
69 return -EINVAL;
70
71 return regmap_write(priv->regmap, TIM_CNT, val);
72}
73
74static int stm32_count_function_get(struct counter_device *counter,
75 struct counter_count *count,
76 size_t *function)
77{
78 struct stm32_timer_cnt *const priv = counter->priv;
79 u32 smcr;
80
81 regmap_read(priv->regmap, TIM_SMCR, &smcr);
82
83 switch (smcr & TIM_SMCR_SMS) {
84 case 1:
85 *function = STM32_COUNT_ENCODER_MODE_1;
86 return 0;
87 case 2:
88 *function = STM32_COUNT_ENCODER_MODE_2;
89 return 0;
90 case 3:
91 *function = STM32_COUNT_ENCODER_MODE_3;
92 return 0;
93 }
94
95 return -EINVAL;
96}
97
98static int stm32_count_function_set(struct counter_device *counter,
99 struct counter_count *count,
100 size_t function)
101{
102 struct stm32_timer_cnt *const priv = counter->priv;
103 u32 cr1, sms;
104
105 switch (function) {
106 case STM32_COUNT_ENCODER_MODE_1:
107 sms = 1;
108 break;
109 case STM32_COUNT_ENCODER_MODE_2:
110 sms = 2;
111 break;
112 case STM32_COUNT_ENCODER_MODE_3:
113 sms = 3;
114 break;
115 default:
116 sms = 0;
117 break;
118 }
119
120 /* Store enable status */
121 regmap_read(priv->regmap, TIM_CR1, &cr1);
122
123 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
124
125 /* TIMx_ARR register shouldn't be buffered (ARPE=0) */
126 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
127 regmap_write(priv->regmap, TIM_ARR, priv->ceiling);
128
129 regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
130
131 /* Make sure that registers are updated */
132 regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
133
134 /* Restore the enable status */
135 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, cr1);
136
137 return 0;
138}
139
140static ssize_t stm32_count_direction_read(struct counter_device *counter,
141 struct counter_count *count,
142 void *private, char *buf)
143{
144 struct stm32_timer_cnt *const priv = counter->priv;
145 const char *direction;
146 u32 cr1;
147
148 regmap_read(priv->regmap, TIM_CR1, &cr1);
149 direction = (cr1 & TIM_CR1_DIR) ? "backward" : "forward";
150
151 return scnprintf(buf, PAGE_SIZE, "%s\n", direction);
152}
153
154static ssize_t stm32_count_ceiling_read(struct counter_device *counter,
155 struct counter_count *count,
156 void *private, char *buf)
157{
158 struct stm32_timer_cnt *const priv = counter->priv;
159 u32 arr;
160
161 regmap_read(priv->regmap, TIM_ARR, &arr);
162
163 return snprintf(buf, PAGE_SIZE, "%u\n", arr);
164}
165
166static ssize_t stm32_count_ceiling_write(struct counter_device *counter,
167 struct counter_count *count,
168 void *private,
169 const char *buf, size_t len)
170{
171 struct stm32_timer_cnt *const priv = counter->priv;
172 unsigned int ceiling;
173 int ret;
174
175 ret = kstrtouint(buf, 0, &ceiling);
176 if (ret)
177 return ret;
178
179 /* TIMx_ARR register shouldn't be buffered (ARPE=0) */
180 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
181 regmap_write(priv->regmap, TIM_ARR, ceiling);
182
183 priv->ceiling = ceiling;
184 return len;
185}
186
187static ssize_t stm32_count_enable_read(struct counter_device *counter,
188 struct counter_count *count,
189 void *private, char *buf)
190{
191 struct stm32_timer_cnt *const priv = counter->priv;
192 u32 cr1;
193
194 regmap_read(priv->regmap, TIM_CR1, &cr1);
195
196 return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)(cr1 & TIM_CR1_CEN));
197}
198
199static ssize_t stm32_count_enable_write(struct counter_device *counter,
200 struct counter_count *count,
201 void *private,
202 const char *buf, size_t len)
203{
204 struct stm32_timer_cnt *const priv = counter->priv;
205 int err;
206 u32 cr1;
207 bool enable;
208
209 err = kstrtobool(buf, &enable);
210 if (err)
211 return err;
212
213 if (enable) {
214 regmap_read(priv->regmap, TIM_CR1, &cr1);
215 if (!(cr1 & TIM_CR1_CEN))
216 clk_enable(priv->clk);
217
218 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
219 TIM_CR1_CEN);
220 } else {
221 regmap_read(priv->regmap, TIM_CR1, &cr1);
222 regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
223 if (cr1 & TIM_CR1_CEN)
224 clk_disable(priv->clk);
225 }
226
227 return len;
228}
229
230static const struct counter_count_ext stm32_count_ext[] = {
231 {
232 .name = "direction",
233 .read = stm32_count_direction_read,
234 },
235 {
236 .name = "enable",
237 .read = stm32_count_enable_read,
238 .write = stm32_count_enable_write
239 },
240 {
241 .name = "ceiling",
242 .read = stm32_count_ceiling_read,
243 .write = stm32_count_ceiling_write
244 },
245};
246
247enum stm32_synapse_action {
248 STM32_SYNAPSE_ACTION_NONE,
249 STM32_SYNAPSE_ACTION_BOTH_EDGES
250};
251
252static enum counter_synapse_action stm32_synapse_actions[] = {
253 [STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
254 [STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES
255};
256
257static int stm32_action_get(struct counter_device *counter,
258 struct counter_count *count,
259 struct counter_synapse *synapse,
260 size_t *action)
261{
262 size_t function;
263 int err;
264
265 /* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */
266 *action = STM32_SYNAPSE_ACTION_NONE;
267
268 err = stm32_count_function_get(counter, count, &function);
269 if (err)
270 return 0;
271
272 switch (function) {
273 case STM32_COUNT_ENCODER_MODE_1:
274 /* counts up/down on TI1FP1 edge depending on TI2FP2 level */
275 if (synapse->signal->id == count->synapses[0].signal->id)
276 *action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
277 break;
278 case STM32_COUNT_ENCODER_MODE_2:
279 /* counts up/down on TI2FP2 edge depending on TI1FP1 level */
280 if (synapse->signal->id == count->synapses[1].signal->id)
281 *action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
282 break;
283 case STM32_COUNT_ENCODER_MODE_3:
284 /* counts up/down on both TI1FP1 and TI2FP2 edges */
285 *action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
286 break;
287 }
288
289 return 0;
290}
291
292static const struct counter_ops stm32_timer_cnt_ops = {
293 .count_read = stm32_count_read,
294 .count_write = stm32_count_write,
295 .function_get = stm32_count_function_get,
296 .function_set = stm32_count_function_set,
297 .action_get = stm32_action_get,
298};
299
300static struct counter_signal stm32_signals[] = {
301 {
302 .id = 0,
303 .name = "Channel 1 Quadrature A"
304 },
305 {
306 .id = 1,
307 .name = "Channel 1 Quadrature B"
308 }
309};
310
311static struct counter_synapse stm32_count_synapses[] = {
312 {
313 .actions_list = stm32_synapse_actions,
314 .num_actions = ARRAY_SIZE(stm32_synapse_actions),
315 .signal = &stm32_signals[0]
316 },
317 {
318 .actions_list = stm32_synapse_actions,
319 .num_actions = ARRAY_SIZE(stm32_synapse_actions),
320 .signal = &stm32_signals[1]
321 }
322};
323
324static struct counter_count stm32_counts = {
325 .id = 0,
326 .name = "Channel 1 Count",
327 .functions_list = stm32_count_functions,
328 .num_functions = ARRAY_SIZE(stm32_count_functions),
329 .synapses = stm32_count_synapses,
330 .num_synapses = ARRAY_SIZE(stm32_count_synapses),
331 .ext = stm32_count_ext,
332 .num_ext = ARRAY_SIZE(stm32_count_ext)
333};
334
335static int stm32_timer_cnt_probe(struct platform_device *pdev)
336{
337 struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent);
338 struct device *dev = &pdev->dev;
339 struct stm32_timer_cnt *priv;
340
341 if (IS_ERR_OR_NULL(ddata))
342 return -EINVAL;
343
344 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
345 if (!priv)
346 return -ENOMEM;
347
348 priv->regmap = ddata->regmap;
349 priv->clk = ddata->clk;
350 priv->ceiling = ddata->max_arr;
351
352 priv->counter.name = dev_name(dev);
353 priv->counter.parent = dev;
354 priv->counter.ops = &stm32_timer_cnt_ops;
355 priv->counter.counts = &stm32_counts;
356 priv->counter.num_counts = 1;
357 priv->counter.signals = stm32_signals;
358 priv->counter.num_signals = ARRAY_SIZE(stm32_signals);
359 priv->counter.priv = priv;
360
361 /* Register Counter device */
362 return devm_counter_register(dev, &priv->counter);
363}
364
365static const struct of_device_id stm32_timer_cnt_of_match[] = {
366 { .compatible = "st,stm32-timer-counter", },
367 {},
368};
369MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
370
371static struct platform_driver stm32_timer_cnt_driver = {
372 .probe = stm32_timer_cnt_probe,
373 .driver = {
374 .name = "stm32-timer-counter",
375 .of_match_table = stm32_timer_cnt_of_match,
376 },
377};
378module_platform_driver(stm32_timer_cnt_driver);
379
380MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
381MODULE_ALIAS("platform:stm32-timer-counter");
382MODULE_DESCRIPTION("STMicroelectronics STM32 TIMER counter driver");
383MODULE_LICENSE("GPL v2");