1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * STM32 Low-Power Timer Encoder and Counter driver |
4 | * |
5 | * Copyright (C) STMicroelectronics 2017 |
6 | * |
7 | * Author: Fabrice Gasnier <fabrice.gasnier@st.com> |
8 | * |
9 | * Inspired by 104-quad-8 and stm32-timer-trigger drivers. |
10 | * |
11 | */ |
12 | |
13 | #include <linux/bitfield.h> |
14 | #include <linux/counter.h> |
15 | #include <linux/mfd/stm32-lptimer.h> |
16 | #include <linux/mod_devicetable.h> |
17 | #include <linux/module.h> |
18 | #include <linux/pinctrl/consumer.h> |
19 | #include <linux/platform_device.h> |
20 | #include <linux/types.h> |
21 | |
22 | struct stm32_lptim_cnt { |
23 | struct device *dev; |
24 | struct regmap *regmap; |
25 | struct clk *clk; |
26 | u32 ceiling; |
27 | u32 polarity; |
28 | u32 quadrature_mode; |
29 | bool enabled; |
30 | }; |
31 | |
32 | static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv) |
33 | { |
34 | u32 val; |
35 | int ret; |
36 | |
37 | ret = regmap_read(map: priv->regmap, STM32_LPTIM_CR, val: &val); |
38 | if (ret) |
39 | return ret; |
40 | |
41 | return FIELD_GET(STM32_LPTIM_ENABLE, val); |
42 | } |
43 | |
44 | static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, |
45 | int enable) |
46 | { |
47 | int ret; |
48 | u32 val; |
49 | |
50 | val = FIELD_PREP(STM32_LPTIM_ENABLE, enable); |
51 | ret = regmap_write(map: priv->regmap, STM32_LPTIM_CR, val); |
52 | if (ret) |
53 | return ret; |
54 | |
55 | if (!enable) { |
56 | clk_disable(clk: priv->clk); |
57 | priv->enabled = false; |
58 | return 0; |
59 | } |
60 | |
61 | /* LP timer must be enabled before writing CMP & ARR */ |
62 | ret = regmap_write(map: priv->regmap, STM32_LPTIM_ARR, val: priv->ceiling); |
63 | if (ret) |
64 | return ret; |
65 | |
66 | ret = regmap_write(map: priv->regmap, STM32_LPTIM_CMP, val: 0); |
67 | if (ret) |
68 | return ret; |
69 | |
70 | /* ensure CMP & ARR registers are properly written */ |
71 | ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, |
72 | (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK, |
73 | 100, 1000); |
74 | if (ret) |
75 | return ret; |
76 | |
77 | ret = regmap_write(map: priv->regmap, STM32_LPTIM_ICR, |
78 | STM32_LPTIM_CMPOKCF_ARROKCF); |
79 | if (ret) |
80 | return ret; |
81 | |
82 | ret = clk_enable(clk: priv->clk); |
83 | if (ret) { |
84 | regmap_write(map: priv->regmap, STM32_LPTIM_CR, val: 0); |
85 | return ret; |
86 | } |
87 | priv->enabled = true; |
88 | |
89 | /* Start LP timer in continuous mode */ |
90 | return regmap_update_bits(map: priv->regmap, STM32_LPTIM_CR, |
91 | STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT); |
92 | } |
93 | |
94 | static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable) |
95 | { |
96 | u32 mask = STM32_LPTIM_ENC | STM32_LPTIM_COUNTMODE | |
97 | STM32_LPTIM_CKPOL | STM32_LPTIM_PRESC; |
98 | u32 val; |
99 | |
100 | /* Setup LP timer encoder/counter and polarity, without prescaler */ |
101 | if (priv->quadrature_mode) |
102 | val = enable ? STM32_LPTIM_ENC : 0; |
103 | else |
104 | val = enable ? STM32_LPTIM_COUNTMODE : 0; |
105 | val |= FIELD_PREP(STM32_LPTIM_CKPOL, enable ? priv->polarity : 0); |
106 | |
107 | return regmap_update_bits(map: priv->regmap, STM32_LPTIM_CFGR, mask, val); |
108 | } |
109 | |
110 | /* |
111 | * In non-quadrature mode, device counts up on active edge. |
112 | * In quadrature mode, encoder counting scenarios are as follows: |
113 | * +---------+----------+--------------------+--------------------+ |
114 | * | Active | Level on | IN1 signal | IN2 signal | |
115 | * | edge | opposite +----------+---------+----------+---------+ |
116 | * | | signal | Rising | Falling | Rising | Falling | |
117 | * +---------+----------+----------+---------+----------+---------+ |
118 | * | Rising | High -> | Down | - | Up | - | |
119 | * | edge | Low -> | Up | - | Down | - | |
120 | * +---------+----------+----------+---------+----------+---------+ |
121 | * | Falling | High -> | - | Up | - | Down | |
122 | * | edge | Low -> | - | Down | - | Up | |
123 | * +---------+----------+----------+---------+----------+---------+ |
124 | * | Both | High -> | Down | Up | Up | Down | |
125 | * | edges | Low -> | Up | Down | Down | Up | |
126 | * +---------+----------+----------+---------+----------+---------+ |
127 | */ |
128 | static const enum counter_function stm32_lptim_cnt_functions[] = { |
129 | COUNTER_FUNCTION_INCREASE, |
130 | COUNTER_FUNCTION_QUADRATURE_X4, |
131 | }; |
132 | |
133 | static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { |
134 | COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
135 | COUNTER_SYNAPSE_ACTION_FALLING_EDGE, |
136 | COUNTER_SYNAPSE_ACTION_BOTH_EDGES, |
137 | COUNTER_SYNAPSE_ACTION_NONE, |
138 | }; |
139 | |
140 | static int stm32_lptim_cnt_read(struct counter_device *counter, |
141 | struct counter_count *count, u64 *val) |
142 | { |
143 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
144 | u32 cnt; |
145 | int ret; |
146 | |
147 | ret = regmap_read(map: priv->regmap, STM32_LPTIM_CNT, val: &cnt); |
148 | if (ret) |
149 | return ret; |
150 | |
151 | *val = cnt; |
152 | |
153 | return 0; |
154 | } |
155 | |
156 | static int stm32_lptim_cnt_function_read(struct counter_device *counter, |
157 | struct counter_count *count, |
158 | enum counter_function *function) |
159 | { |
160 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
161 | |
162 | if (!priv->quadrature_mode) { |
163 | *function = COUNTER_FUNCTION_INCREASE; |
164 | return 0; |
165 | } |
166 | |
167 | if (priv->polarity == STM32_LPTIM_CKPOL_BOTH_EDGES) { |
168 | *function = COUNTER_FUNCTION_QUADRATURE_X4; |
169 | return 0; |
170 | } |
171 | |
172 | return -EINVAL; |
173 | } |
174 | |
175 | static int stm32_lptim_cnt_function_write(struct counter_device *counter, |
176 | struct counter_count *count, |
177 | enum counter_function function) |
178 | { |
179 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
180 | |
181 | if (stm32_lptim_is_enabled(priv)) |
182 | return -EBUSY; |
183 | |
184 | switch (function) { |
185 | case COUNTER_FUNCTION_INCREASE: |
186 | priv->quadrature_mode = 0; |
187 | return 0; |
188 | case COUNTER_FUNCTION_QUADRATURE_X4: |
189 | priv->quadrature_mode = 1; |
190 | priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; |
191 | return 0; |
192 | default: |
193 | /* should never reach this path */ |
194 | return -EINVAL; |
195 | } |
196 | } |
197 | |
198 | static int stm32_lptim_cnt_enable_read(struct counter_device *counter, |
199 | struct counter_count *count, |
200 | u8 *enable) |
201 | { |
202 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
203 | int ret; |
204 | |
205 | ret = stm32_lptim_is_enabled(priv); |
206 | if (ret < 0) |
207 | return ret; |
208 | |
209 | *enable = ret; |
210 | |
211 | return 0; |
212 | } |
213 | |
214 | static int stm32_lptim_cnt_enable_write(struct counter_device *counter, |
215 | struct counter_count *count, |
216 | u8 enable) |
217 | { |
218 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
219 | int ret; |
220 | |
221 | /* Check nobody uses the timer, or already disabled/enabled */ |
222 | ret = stm32_lptim_is_enabled(priv); |
223 | if ((ret < 0) || (!ret && !enable)) |
224 | return ret; |
225 | if (enable && ret) |
226 | return -EBUSY; |
227 | |
228 | ret = stm32_lptim_setup(priv, enable); |
229 | if (ret) |
230 | return ret; |
231 | |
232 | ret = stm32_lptim_set_enable_state(priv, enable); |
233 | if (ret) |
234 | return ret; |
235 | |
236 | return 0; |
237 | } |
238 | |
239 | static int stm32_lptim_cnt_ceiling_read(struct counter_device *counter, |
240 | struct counter_count *count, |
241 | u64 *ceiling) |
242 | { |
243 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
244 | |
245 | *ceiling = priv->ceiling; |
246 | |
247 | return 0; |
248 | } |
249 | |
250 | static int stm32_lptim_cnt_ceiling_write(struct counter_device *counter, |
251 | struct counter_count *count, |
252 | u64 ceiling) |
253 | { |
254 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
255 | |
256 | if (stm32_lptim_is_enabled(priv)) |
257 | return -EBUSY; |
258 | |
259 | if (ceiling > STM32_LPTIM_MAX_ARR) |
260 | return -ERANGE; |
261 | |
262 | priv->ceiling = ceiling; |
263 | |
264 | return 0; |
265 | } |
266 | |
267 | static struct counter_comp stm32_lptim_cnt_ext[] = { |
268 | COUNTER_COMP_ENABLE(stm32_lptim_cnt_enable_read, |
269 | stm32_lptim_cnt_enable_write), |
270 | COUNTER_COMP_CEILING(stm32_lptim_cnt_ceiling_read, |
271 | stm32_lptim_cnt_ceiling_write), |
272 | }; |
273 | |
274 | static int stm32_lptim_cnt_action_read(struct counter_device *counter, |
275 | struct counter_count *count, |
276 | struct counter_synapse *synapse, |
277 | enum counter_synapse_action *action) |
278 | { |
279 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
280 | enum counter_function function; |
281 | int err; |
282 | |
283 | err = stm32_lptim_cnt_function_read(counter, count, function: &function); |
284 | if (err) |
285 | return err; |
286 | |
287 | switch (function) { |
288 | case COUNTER_FUNCTION_INCREASE: |
289 | /* LP Timer acts as up-counter on input 1 */ |
290 | if (synapse->signal->id != count->synapses[0].signal->id) { |
291 | *action = COUNTER_SYNAPSE_ACTION_NONE; |
292 | return 0; |
293 | } |
294 | |
295 | switch (priv->polarity) { |
296 | case STM32_LPTIM_CKPOL_RISING_EDGE: |
297 | *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; |
298 | return 0; |
299 | case STM32_LPTIM_CKPOL_FALLING_EDGE: |
300 | *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; |
301 | return 0; |
302 | case STM32_LPTIM_CKPOL_BOTH_EDGES: |
303 | *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; |
304 | return 0; |
305 | default: |
306 | /* should never reach this path */ |
307 | return -EINVAL; |
308 | } |
309 | case COUNTER_FUNCTION_QUADRATURE_X4: |
310 | *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; |
311 | return 0; |
312 | default: |
313 | /* should never reach this path */ |
314 | return -EINVAL; |
315 | } |
316 | } |
317 | |
318 | static int stm32_lptim_cnt_action_write(struct counter_device *counter, |
319 | struct counter_count *count, |
320 | struct counter_synapse *synapse, |
321 | enum counter_synapse_action action) |
322 | { |
323 | struct stm32_lptim_cnt *const priv = counter_priv(counter); |
324 | enum counter_function function; |
325 | int err; |
326 | |
327 | if (stm32_lptim_is_enabled(priv)) |
328 | return -EBUSY; |
329 | |
330 | err = stm32_lptim_cnt_function_read(counter, count, function: &function); |
331 | if (err) |
332 | return err; |
333 | |
334 | /* only set polarity when in counter mode (on input 1) */ |
335 | if (function != COUNTER_FUNCTION_INCREASE |
336 | || synapse->signal->id != count->synapses[0].signal->id) |
337 | return -EINVAL; |
338 | |
339 | switch (action) { |
340 | case COUNTER_SYNAPSE_ACTION_RISING_EDGE: |
341 | priv->polarity = STM32_LPTIM_CKPOL_RISING_EDGE; |
342 | return 0; |
343 | case COUNTER_SYNAPSE_ACTION_FALLING_EDGE: |
344 | priv->polarity = STM32_LPTIM_CKPOL_FALLING_EDGE; |
345 | return 0; |
346 | case COUNTER_SYNAPSE_ACTION_BOTH_EDGES: |
347 | priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; |
348 | return 0; |
349 | default: |
350 | return -EINVAL; |
351 | } |
352 | } |
353 | |
354 | static const struct counter_ops stm32_lptim_cnt_ops = { |
355 | .count_read = stm32_lptim_cnt_read, |
356 | .function_read = stm32_lptim_cnt_function_read, |
357 | .function_write = stm32_lptim_cnt_function_write, |
358 | .action_read = stm32_lptim_cnt_action_read, |
359 | .action_write = stm32_lptim_cnt_action_write, |
360 | }; |
361 | |
362 | static struct counter_signal stm32_lptim_cnt_signals[] = { |
363 | { |
364 | .id = 0, |
365 | .name = "Channel 1 Quadrature A" |
366 | }, |
367 | { |
368 | .id = 1, |
369 | .name = "Channel 1 Quadrature B" |
370 | } |
371 | }; |
372 | |
373 | static struct counter_synapse stm32_lptim_cnt_synapses[] = { |
374 | { |
375 | .actions_list = stm32_lptim_cnt_synapse_actions, |
376 | .num_actions = ARRAY_SIZE(stm32_lptim_cnt_synapse_actions), |
377 | .signal = &stm32_lptim_cnt_signals[0] |
378 | }, |
379 | { |
380 | .actions_list = stm32_lptim_cnt_synapse_actions, |
381 | .num_actions = ARRAY_SIZE(stm32_lptim_cnt_synapse_actions), |
382 | .signal = &stm32_lptim_cnt_signals[1] |
383 | } |
384 | }; |
385 | |
386 | /* LP timer with encoder */ |
387 | static struct counter_count stm32_lptim_enc_counts = { |
388 | .id = 0, |
389 | .name = "LPTimer Count" , |
390 | .functions_list = stm32_lptim_cnt_functions, |
391 | .num_functions = ARRAY_SIZE(stm32_lptim_cnt_functions), |
392 | .synapses = stm32_lptim_cnt_synapses, |
393 | .num_synapses = ARRAY_SIZE(stm32_lptim_cnt_synapses), |
394 | .ext = stm32_lptim_cnt_ext, |
395 | .num_ext = ARRAY_SIZE(stm32_lptim_cnt_ext) |
396 | }; |
397 | |
398 | /* LP timer without encoder (counter only) */ |
399 | static struct counter_count stm32_lptim_in1_counts = { |
400 | .id = 0, |
401 | .name = "LPTimer Count" , |
402 | .functions_list = stm32_lptim_cnt_functions, |
403 | .num_functions = 1, |
404 | .synapses = stm32_lptim_cnt_synapses, |
405 | .num_synapses = 1, |
406 | .ext = stm32_lptim_cnt_ext, |
407 | .num_ext = ARRAY_SIZE(stm32_lptim_cnt_ext) |
408 | }; |
409 | |
410 | static int stm32_lptim_cnt_probe(struct platform_device *pdev) |
411 | { |
412 | struct stm32_lptimer *ddata = dev_get_drvdata(dev: pdev->dev.parent); |
413 | struct counter_device *counter; |
414 | struct stm32_lptim_cnt *priv; |
415 | int ret; |
416 | |
417 | if (IS_ERR_OR_NULL(ptr: ddata)) |
418 | return -EINVAL; |
419 | |
420 | counter = devm_counter_alloc(dev: &pdev->dev, sizeof_priv: sizeof(*priv)); |
421 | if (!counter) |
422 | return -ENOMEM; |
423 | priv = counter_priv(counter); |
424 | |
425 | priv->dev = &pdev->dev; |
426 | priv->regmap = ddata->regmap; |
427 | priv->clk = ddata->clk; |
428 | priv->ceiling = STM32_LPTIM_MAX_ARR; |
429 | |
430 | /* Initialize Counter device */ |
431 | counter->name = dev_name(dev: &pdev->dev); |
432 | counter->parent = &pdev->dev; |
433 | counter->ops = &stm32_lptim_cnt_ops; |
434 | if (ddata->has_encoder) { |
435 | counter->counts = &stm32_lptim_enc_counts; |
436 | counter->num_signals = ARRAY_SIZE(stm32_lptim_cnt_signals); |
437 | } else { |
438 | counter->counts = &stm32_lptim_in1_counts; |
439 | counter->num_signals = 1; |
440 | } |
441 | counter->num_counts = 1; |
442 | counter->signals = stm32_lptim_cnt_signals; |
443 | |
444 | platform_set_drvdata(pdev, data: priv); |
445 | |
446 | ret = devm_counter_add(dev: &pdev->dev, counter); |
447 | if (ret < 0) |
448 | return dev_err_probe(dev: &pdev->dev, err: ret, fmt: "Failed to add counter\n" ); |
449 | |
450 | return 0; |
451 | } |
452 | |
453 | #ifdef CONFIG_PM_SLEEP |
454 | static int stm32_lptim_cnt_suspend(struct device *dev) |
455 | { |
456 | struct stm32_lptim_cnt *priv = dev_get_drvdata(dev); |
457 | int ret; |
458 | |
459 | /* Only take care of enabled counter: don't disturb other MFD child */ |
460 | if (priv->enabled) { |
461 | ret = stm32_lptim_setup(priv, enable: 0); |
462 | if (ret) |
463 | return ret; |
464 | |
465 | ret = stm32_lptim_set_enable_state(priv, enable: 0); |
466 | if (ret) |
467 | return ret; |
468 | |
469 | /* Force enable state for later resume */ |
470 | priv->enabled = true; |
471 | } |
472 | |
473 | return pinctrl_pm_select_sleep_state(dev); |
474 | } |
475 | |
476 | static int stm32_lptim_cnt_resume(struct device *dev) |
477 | { |
478 | struct stm32_lptim_cnt *priv = dev_get_drvdata(dev); |
479 | int ret; |
480 | |
481 | ret = pinctrl_pm_select_default_state(dev); |
482 | if (ret) |
483 | return ret; |
484 | |
485 | if (priv->enabled) { |
486 | priv->enabled = false; |
487 | ret = stm32_lptim_setup(priv, enable: 1); |
488 | if (ret) |
489 | return ret; |
490 | |
491 | ret = stm32_lptim_set_enable_state(priv, enable: 1); |
492 | if (ret) |
493 | return ret; |
494 | } |
495 | |
496 | return 0; |
497 | } |
498 | #endif |
499 | |
500 | static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops, stm32_lptim_cnt_suspend, |
501 | stm32_lptim_cnt_resume); |
502 | |
503 | static const struct of_device_id stm32_lptim_cnt_of_match[] = { |
504 | { .compatible = "st,stm32-lptimer-counter" , }, |
505 | {}, |
506 | }; |
507 | MODULE_DEVICE_TABLE(of, stm32_lptim_cnt_of_match); |
508 | |
509 | static struct platform_driver stm32_lptim_cnt_driver = { |
510 | .probe = stm32_lptim_cnt_probe, |
511 | .driver = { |
512 | .name = "stm32-lptimer-counter" , |
513 | .of_match_table = stm32_lptim_cnt_of_match, |
514 | .pm = &stm32_lptim_cnt_pm_ops, |
515 | }, |
516 | }; |
517 | module_platform_driver(stm32_lptim_cnt_driver); |
518 | |
519 | MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>" ); |
520 | MODULE_ALIAS("platform:stm32-lptimer-counter" ); |
521 | MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver" ); |
522 | MODULE_LICENSE("GPL v2" ); |
523 | MODULE_IMPORT_NS(COUNTER); |
524 | |