1 // SPDX-License-Identifier: GPL-2.0
3 * STM32 Low-Power Timer Encoder and Counter driver
5 * Copyright (C) STMicroelectronics 2017
7 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
9 * Inspired by 104-quad-8 and stm32-timer-trigger drivers.
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>
21 struct stm32_lptim_cnt
{
22 struct counter_device counter
;
24 struct regmap
*regmap
;
32 static int stm32_lptim_is_enabled(struct stm32_lptim_cnt
*priv
)
37 ret
= regmap_read(priv
->regmap
, STM32_LPTIM_CR
, &val
);
41 return FIELD_GET(STM32_LPTIM_ENABLE
, val
);
44 static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt
*priv
,
50 val
= FIELD_PREP(STM32_LPTIM_ENABLE
, enable
);
51 ret
= regmap_write(priv
->regmap
, STM32_LPTIM_CR
, val
);
56 clk_disable(priv
->clk
);
57 priv
->enabled
= false;
61 /* LP timer must be enabled before writing CMP & ARR */
62 ret
= regmap_write(priv
->regmap
, STM32_LPTIM_ARR
, priv
->ceiling
);
66 ret
= regmap_write(priv
->regmap
, STM32_LPTIM_CMP
, 0);
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
),
77 ret
= regmap_write(priv
->regmap
, STM32_LPTIM_ICR
,
78 STM32_LPTIM_CMPOKCF_ARROKCF
);
82 ret
= clk_enable(priv
->clk
);
84 regmap_write(priv
->regmap
, STM32_LPTIM_CR
, 0);
89 /* Start LP timer in continuous mode */
90 return regmap_update_bits(priv
->regmap
, STM32_LPTIM_CR
,
91 STM32_LPTIM_CNTSTRT
, STM32_LPTIM_CNTSTRT
);
94 static int stm32_lptim_setup(struct stm32_lptim_cnt
*priv
, int enable
)
96 u32 mask
= STM32_LPTIM_ENC
| STM32_LPTIM_COUNTMODE
|
97 STM32_LPTIM_CKPOL
| STM32_LPTIM_PRESC
;
100 /* Setup LP timer encoder/counter and polarity, without prescaler */
101 if (priv
->quadrature_mode
)
102 val
= enable
? STM32_LPTIM_ENC
: 0;
104 val
= enable
? STM32_LPTIM_COUNTMODE
: 0;
105 val
|= FIELD_PREP(STM32_LPTIM_CKPOL
, enable
? priv
->polarity
: 0);
107 return regmap_update_bits(priv
->regmap
, STM32_LPTIM_CFGR
, mask
, val
);
111 * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes
112 * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges
113 * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature)
115 * In non-quadrature mode, device counts up on active edge.
116 * In quadrature mode, encoder counting scenarios are as follows:
117 * +---------+----------+--------------------+--------------------+
118 * | Active | Level on | IN1 signal | IN2 signal |
119 * | edge | opposite +----------+---------+----------+---------+
120 * | | signal | Rising | Falling | Rising | Falling |
121 * +---------+----------+----------+---------+----------+---------+
122 * | Rising | High -> | Down | - | Up | - |
123 * | edge | Low -> | Up | - | Down | - |
124 * +---------+----------+----------+---------+----------+---------+
125 * | Falling | High -> | - | Up | - | Down |
126 * | edge | Low -> | - | Down | - | Up |
127 * +---------+----------+----------+---------+----------+---------+
128 * | Both | High -> | Down | Up | Up | Down |
129 * | edges | Low -> | Up | Down | Down | Up |
130 * +---------+----------+----------+---------+----------+---------+
132 enum stm32_lptim_cnt_function
{
133 STM32_LPTIM_COUNTER_INCREASE
,
134 STM32_LPTIM_ENCODER_BOTH_EDGE
,
137 static const enum counter_count_function stm32_lptim_cnt_functions
[] = {
138 [STM32_LPTIM_COUNTER_INCREASE
] = COUNTER_COUNT_FUNCTION_INCREASE
,
139 [STM32_LPTIM_ENCODER_BOTH_EDGE
] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4
,
142 enum stm32_lptim_synapse_action
{
143 STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE
,
144 STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE
,
145 STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
,
146 STM32_LPTIM_SYNAPSE_ACTION_NONE
,
149 static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions
[] = {
150 /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */
151 [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE
] = COUNTER_SYNAPSE_ACTION_RISING_EDGE
,
152 [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE
] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE
,
153 [STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES
,
154 [STM32_LPTIM_SYNAPSE_ACTION_NONE
] = COUNTER_SYNAPSE_ACTION_NONE
,
157 static int stm32_lptim_cnt_read(struct counter_device
*counter
,
158 struct counter_count
*count
, unsigned long *val
)
160 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
164 ret
= regmap_read(priv
->regmap
, STM32_LPTIM_CNT
, &cnt
);
173 static int stm32_lptim_cnt_function_get(struct counter_device
*counter
,
174 struct counter_count
*count
,
177 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
179 if (!priv
->quadrature_mode
) {
180 *function
= STM32_LPTIM_COUNTER_INCREASE
;
184 if (priv
->polarity
== STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
) {
185 *function
= STM32_LPTIM_ENCODER_BOTH_EDGE
;
192 static int stm32_lptim_cnt_function_set(struct counter_device
*counter
,
193 struct counter_count
*count
,
196 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
198 if (stm32_lptim_is_enabled(priv
))
202 case STM32_LPTIM_COUNTER_INCREASE
:
203 priv
->quadrature_mode
= 0;
205 case STM32_LPTIM_ENCODER_BOTH_EDGE
:
206 priv
->quadrature_mode
= 1;
207 priv
->polarity
= STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
;
214 static ssize_t
stm32_lptim_cnt_enable_read(struct counter_device
*counter
,
215 struct counter_count
*count
,
216 void *private, char *buf
)
218 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
221 ret
= stm32_lptim_is_enabled(priv
);
225 return scnprintf(buf
, PAGE_SIZE
, "%u\n", ret
);
228 static ssize_t
stm32_lptim_cnt_enable_write(struct counter_device
*counter
,
229 struct counter_count
*count
,
231 const char *buf
, size_t len
)
233 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
237 ret
= kstrtobool(buf
, &enable
);
241 /* Check nobody uses the timer, or already disabled/enabled */
242 ret
= stm32_lptim_is_enabled(priv
);
243 if ((ret
< 0) || (!ret
&& !enable
))
248 ret
= stm32_lptim_setup(priv
, enable
);
252 ret
= stm32_lptim_set_enable_state(priv
, enable
);
259 static ssize_t
stm32_lptim_cnt_ceiling_read(struct counter_device
*counter
,
260 struct counter_count
*count
,
261 void *private, char *buf
)
263 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
265 return snprintf(buf
, PAGE_SIZE
, "%u\n", priv
->ceiling
);
268 static ssize_t
stm32_lptim_cnt_ceiling_write(struct counter_device
*counter
,
269 struct counter_count
*count
,
271 const char *buf
, size_t len
)
273 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
274 unsigned int ceiling
;
277 if (stm32_lptim_is_enabled(priv
))
280 ret
= kstrtouint(buf
, 0, &ceiling
);
284 if (ceiling
> STM32_LPTIM_MAX_ARR
)
287 priv
->ceiling
= ceiling
;
292 static const struct counter_count_ext stm32_lptim_cnt_ext
[] = {
295 .read
= stm32_lptim_cnt_enable_read
,
296 .write
= stm32_lptim_cnt_enable_write
300 .read
= stm32_lptim_cnt_ceiling_read
,
301 .write
= stm32_lptim_cnt_ceiling_write
305 static int stm32_lptim_cnt_action_get(struct counter_device
*counter
,
306 struct counter_count
*count
,
307 struct counter_synapse
*synapse
,
310 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
314 err
= stm32_lptim_cnt_function_get(counter
, count
, &function
);
319 case STM32_LPTIM_COUNTER_INCREASE
:
320 /* LP Timer acts as up-counter on input 1 */
321 if (synapse
->signal
->id
== count
->synapses
[0].signal
->id
)
322 *action
= priv
->polarity
;
324 *action
= STM32_LPTIM_SYNAPSE_ACTION_NONE
;
326 case STM32_LPTIM_ENCODER_BOTH_EDGE
:
327 *action
= priv
->polarity
;
334 static int stm32_lptim_cnt_action_set(struct counter_device
*counter
,
335 struct counter_count
*count
,
336 struct counter_synapse
*synapse
,
339 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
343 if (stm32_lptim_is_enabled(priv
))
346 err
= stm32_lptim_cnt_function_get(counter
, count
, &function
);
350 /* only set polarity when in counter mode (on input 1) */
351 if (function
== STM32_LPTIM_COUNTER_INCREASE
352 && synapse
->signal
->id
== count
->synapses
[0].signal
->id
) {
354 case STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE
:
355 case STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE
:
356 case STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
:
357 priv
->polarity
= action
;
365 static const struct counter_ops stm32_lptim_cnt_ops
= {
366 .count_read
= stm32_lptim_cnt_read
,
367 .function_get
= stm32_lptim_cnt_function_get
,
368 .function_set
= stm32_lptim_cnt_function_set
,
369 .action_get
= stm32_lptim_cnt_action_get
,
370 .action_set
= stm32_lptim_cnt_action_set
,
373 static struct counter_signal stm32_lptim_cnt_signals
[] = {
376 .name
= "Channel 1 Quadrature A"
380 .name
= "Channel 1 Quadrature B"
384 static struct counter_synapse stm32_lptim_cnt_synapses
[] = {
386 .actions_list
= stm32_lptim_cnt_synapse_actions
,
387 .num_actions
= ARRAY_SIZE(stm32_lptim_cnt_synapse_actions
),
388 .signal
= &stm32_lptim_cnt_signals
[0]
391 .actions_list
= stm32_lptim_cnt_synapse_actions
,
392 .num_actions
= ARRAY_SIZE(stm32_lptim_cnt_synapse_actions
),
393 .signal
= &stm32_lptim_cnt_signals
[1]
397 /* LP timer with encoder */
398 static struct counter_count stm32_lptim_enc_counts
= {
400 .name
= "LPTimer Count",
401 .functions_list
= stm32_lptim_cnt_functions
,
402 .num_functions
= ARRAY_SIZE(stm32_lptim_cnt_functions
),
403 .synapses
= stm32_lptim_cnt_synapses
,
404 .num_synapses
= ARRAY_SIZE(stm32_lptim_cnt_synapses
),
405 .ext
= stm32_lptim_cnt_ext
,
406 .num_ext
= ARRAY_SIZE(stm32_lptim_cnt_ext
)
409 /* LP timer without encoder (counter only) */
410 static struct counter_count stm32_lptim_in1_counts
= {
412 .name
= "LPTimer Count",
413 .functions_list
= stm32_lptim_cnt_functions
,
415 .synapses
= stm32_lptim_cnt_synapses
,
417 .ext
= stm32_lptim_cnt_ext
,
418 .num_ext
= ARRAY_SIZE(stm32_lptim_cnt_ext
)
421 static int stm32_lptim_cnt_probe(struct platform_device
*pdev
)
423 struct stm32_lptimer
*ddata
= dev_get_drvdata(pdev
->dev
.parent
);
424 struct stm32_lptim_cnt
*priv
;
426 if (IS_ERR_OR_NULL(ddata
))
429 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
433 priv
->dev
= &pdev
->dev
;
434 priv
->regmap
= ddata
->regmap
;
435 priv
->clk
= ddata
->clk
;
436 priv
->ceiling
= STM32_LPTIM_MAX_ARR
;
438 /* Initialize Counter device */
439 priv
->counter
.name
= dev_name(&pdev
->dev
);
440 priv
->counter
.parent
= &pdev
->dev
;
441 priv
->counter
.ops
= &stm32_lptim_cnt_ops
;
442 if (ddata
->has_encoder
) {
443 priv
->counter
.counts
= &stm32_lptim_enc_counts
;
444 priv
->counter
.num_signals
= ARRAY_SIZE(stm32_lptim_cnt_signals
);
446 priv
->counter
.counts
= &stm32_lptim_in1_counts
;
447 priv
->counter
.num_signals
= 1;
449 priv
->counter
.num_counts
= 1;
450 priv
->counter
.signals
= stm32_lptim_cnt_signals
;
451 priv
->counter
.priv
= priv
;
453 platform_set_drvdata(pdev
, priv
);
455 return devm_counter_register(&pdev
->dev
, &priv
->counter
);
458 #ifdef CONFIG_PM_SLEEP
459 static int stm32_lptim_cnt_suspend(struct device
*dev
)
461 struct stm32_lptim_cnt
*priv
= dev_get_drvdata(dev
);
464 /* Only take care of enabled counter: don't disturb other MFD child */
466 ret
= stm32_lptim_setup(priv
, 0);
470 ret
= stm32_lptim_set_enable_state(priv
, 0);
474 /* Force enable state for later resume */
475 priv
->enabled
= true;
478 return pinctrl_pm_select_sleep_state(dev
);
481 static int stm32_lptim_cnt_resume(struct device
*dev
)
483 struct stm32_lptim_cnt
*priv
= dev_get_drvdata(dev
);
486 ret
= pinctrl_pm_select_default_state(dev
);
491 priv
->enabled
= false;
492 ret
= stm32_lptim_setup(priv
, 1);
496 ret
= stm32_lptim_set_enable_state(priv
, 1);
505 static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops
, stm32_lptim_cnt_suspend
,
506 stm32_lptim_cnt_resume
);
508 static const struct of_device_id stm32_lptim_cnt_of_match
[] = {
509 { .compatible
= "st,stm32-lptimer-counter", },
512 MODULE_DEVICE_TABLE(of
, stm32_lptim_cnt_of_match
);
514 static struct platform_driver stm32_lptim_cnt_driver
= {
515 .probe
= stm32_lptim_cnt_probe
,
517 .name
= "stm32-lptimer-counter",
518 .of_match_table
= stm32_lptim_cnt_of_match
,
519 .pm
= &stm32_lptim_cnt_pm_ops
,
522 module_platform_driver(stm32_lptim_cnt_driver
);
524 MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
525 MODULE_ALIAS("platform:stm32-lptimer-counter");
526 MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver");
527 MODULE_LICENSE("GPL v2");