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_function stm32_lptim_cnt_functions
[] = {
138 [STM32_LPTIM_COUNTER_INCREASE
] = COUNTER_FUNCTION_INCREASE
,
139 [STM32_LPTIM_ENCODER_BOTH_EDGE
] = COUNTER_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
;
210 /* should never reach this path */
215 static ssize_t
stm32_lptim_cnt_enable_read(struct counter_device
*counter
,
216 struct counter_count
*count
,
217 void *private, char *buf
)
219 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
222 ret
= stm32_lptim_is_enabled(priv
);
226 return scnprintf(buf
, PAGE_SIZE
, "%u\n", ret
);
229 static ssize_t
stm32_lptim_cnt_enable_write(struct counter_device
*counter
,
230 struct counter_count
*count
,
232 const char *buf
, size_t len
)
234 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
238 ret
= kstrtobool(buf
, &enable
);
242 /* Check nobody uses the timer, or already disabled/enabled */
243 ret
= stm32_lptim_is_enabled(priv
);
244 if ((ret
< 0) || (!ret
&& !enable
))
249 ret
= stm32_lptim_setup(priv
, enable
);
253 ret
= stm32_lptim_set_enable_state(priv
, enable
);
260 static ssize_t
stm32_lptim_cnt_ceiling_read(struct counter_device
*counter
,
261 struct counter_count
*count
,
262 void *private, char *buf
)
264 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
266 return snprintf(buf
, PAGE_SIZE
, "%u\n", priv
->ceiling
);
269 static ssize_t
stm32_lptim_cnt_ceiling_write(struct counter_device
*counter
,
270 struct counter_count
*count
,
272 const char *buf
, size_t len
)
274 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
275 unsigned int ceiling
;
278 if (stm32_lptim_is_enabled(priv
))
281 ret
= kstrtouint(buf
, 0, &ceiling
);
285 if (ceiling
> STM32_LPTIM_MAX_ARR
)
288 priv
->ceiling
= ceiling
;
293 static const struct counter_count_ext stm32_lptim_cnt_ext
[] = {
296 .read
= stm32_lptim_cnt_enable_read
,
297 .write
= stm32_lptim_cnt_enable_write
301 .read
= stm32_lptim_cnt_ceiling_read
,
302 .write
= stm32_lptim_cnt_ceiling_write
306 static int stm32_lptim_cnt_action_get(struct counter_device
*counter
,
307 struct counter_count
*count
,
308 struct counter_synapse
*synapse
,
311 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
315 err
= stm32_lptim_cnt_function_get(counter
, count
, &function
);
320 case STM32_LPTIM_COUNTER_INCREASE
:
321 /* LP Timer acts as up-counter on input 1 */
322 if (synapse
->signal
->id
== count
->synapses
[0].signal
->id
)
323 *action
= priv
->polarity
;
325 *action
= STM32_LPTIM_SYNAPSE_ACTION_NONE
;
327 case STM32_LPTIM_ENCODER_BOTH_EDGE
:
328 *action
= priv
->polarity
;
331 /* should never reach this path */
336 static int stm32_lptim_cnt_action_set(struct counter_device
*counter
,
337 struct counter_count
*count
,
338 struct counter_synapse
*synapse
,
341 struct stm32_lptim_cnt
*const priv
= counter
->priv
;
345 if (stm32_lptim_is_enabled(priv
))
348 err
= stm32_lptim_cnt_function_get(counter
, count
, &function
);
352 /* only set polarity when in counter mode (on input 1) */
353 if (function
== STM32_LPTIM_COUNTER_INCREASE
354 && synapse
->signal
->id
== count
->synapses
[0].signal
->id
) {
356 case STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE
:
357 case STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE
:
358 case STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES
:
359 priv
->polarity
= action
;
367 static const struct counter_ops stm32_lptim_cnt_ops
= {
368 .count_read
= stm32_lptim_cnt_read
,
369 .function_get
= stm32_lptim_cnt_function_get
,
370 .function_set
= stm32_lptim_cnt_function_set
,
371 .action_get
= stm32_lptim_cnt_action_get
,
372 .action_set
= stm32_lptim_cnt_action_set
,
375 static struct counter_signal stm32_lptim_cnt_signals
[] = {
378 .name
= "Channel 1 Quadrature A"
382 .name
= "Channel 1 Quadrature B"
386 static struct counter_synapse stm32_lptim_cnt_synapses
[] = {
388 .actions_list
= stm32_lptim_cnt_synapse_actions
,
389 .num_actions
= ARRAY_SIZE(stm32_lptim_cnt_synapse_actions
),
390 .signal
= &stm32_lptim_cnt_signals
[0]
393 .actions_list
= stm32_lptim_cnt_synapse_actions
,
394 .num_actions
= ARRAY_SIZE(stm32_lptim_cnt_synapse_actions
),
395 .signal
= &stm32_lptim_cnt_signals
[1]
399 /* LP timer with encoder */
400 static struct counter_count stm32_lptim_enc_counts
= {
402 .name
= "LPTimer Count",
403 .functions_list
= stm32_lptim_cnt_functions
,
404 .num_functions
= ARRAY_SIZE(stm32_lptim_cnt_functions
),
405 .synapses
= stm32_lptim_cnt_synapses
,
406 .num_synapses
= ARRAY_SIZE(stm32_lptim_cnt_synapses
),
407 .ext
= stm32_lptim_cnt_ext
,
408 .num_ext
= ARRAY_SIZE(stm32_lptim_cnt_ext
)
411 /* LP timer without encoder (counter only) */
412 static struct counter_count stm32_lptim_in1_counts
= {
414 .name
= "LPTimer Count",
415 .functions_list
= stm32_lptim_cnt_functions
,
417 .synapses
= stm32_lptim_cnt_synapses
,
419 .ext
= stm32_lptim_cnt_ext
,
420 .num_ext
= ARRAY_SIZE(stm32_lptim_cnt_ext
)
423 static int stm32_lptim_cnt_probe(struct platform_device
*pdev
)
425 struct stm32_lptimer
*ddata
= dev_get_drvdata(pdev
->dev
.parent
);
426 struct stm32_lptim_cnt
*priv
;
428 if (IS_ERR_OR_NULL(ddata
))
431 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
435 priv
->dev
= &pdev
->dev
;
436 priv
->regmap
= ddata
->regmap
;
437 priv
->clk
= ddata
->clk
;
438 priv
->ceiling
= STM32_LPTIM_MAX_ARR
;
440 /* Initialize Counter device */
441 priv
->counter
.name
= dev_name(&pdev
->dev
);
442 priv
->counter
.parent
= &pdev
->dev
;
443 priv
->counter
.ops
= &stm32_lptim_cnt_ops
;
444 if (ddata
->has_encoder
) {
445 priv
->counter
.counts
= &stm32_lptim_enc_counts
;
446 priv
->counter
.num_signals
= ARRAY_SIZE(stm32_lptim_cnt_signals
);
448 priv
->counter
.counts
= &stm32_lptim_in1_counts
;
449 priv
->counter
.num_signals
= 1;
451 priv
->counter
.num_counts
= 1;
452 priv
->counter
.signals
= stm32_lptim_cnt_signals
;
453 priv
->counter
.priv
= priv
;
455 platform_set_drvdata(pdev
, priv
);
457 return devm_counter_register(&pdev
->dev
, &priv
->counter
);
460 #ifdef CONFIG_PM_SLEEP
461 static int stm32_lptim_cnt_suspend(struct device
*dev
)
463 struct stm32_lptim_cnt
*priv
= dev_get_drvdata(dev
);
466 /* Only take care of enabled counter: don't disturb other MFD child */
468 ret
= stm32_lptim_setup(priv
, 0);
472 ret
= stm32_lptim_set_enable_state(priv
, 0);
476 /* Force enable state for later resume */
477 priv
->enabled
= true;
480 return pinctrl_pm_select_sleep_state(dev
);
483 static int stm32_lptim_cnt_resume(struct device
*dev
)
485 struct stm32_lptim_cnt
*priv
= dev_get_drvdata(dev
);
488 ret
= pinctrl_pm_select_default_state(dev
);
493 priv
->enabled
= false;
494 ret
= stm32_lptim_setup(priv
, 1);
498 ret
= stm32_lptim_set_enable_state(priv
, 1);
507 static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops
, stm32_lptim_cnt_suspend
,
508 stm32_lptim_cnt_resume
);
510 static const struct of_device_id stm32_lptim_cnt_of_match
[] = {
511 { .compatible
= "st,stm32-lptimer-counter", },
514 MODULE_DEVICE_TABLE(of
, stm32_lptim_cnt_of_match
);
516 static struct platform_driver stm32_lptim_cnt_driver
= {
517 .probe
= stm32_lptim_cnt_probe
,
519 .name
= "stm32-lptimer-counter",
520 .of_match_table
= stm32_lptim_cnt_of_match
,
521 .pm
= &stm32_lptim_cnt_pm_ops
,
524 module_platform_driver(stm32_lptim_cnt_driver
);
526 MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
527 MODULE_ALIAS("platform:stm32-lptimer-counter");
528 MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver");
529 MODULE_LICENSE("GPL v2");