Lines Matching +full:stm32 +full:- +full:timer +full:- +full:counter

1 // SPDX-License-Identifier: GPL-2.0
3 * STM32 Low-Power Timer Encoder and Counter driver
9 * Inspired by 104-quad-8 and stm32-timer-trigger drivers.
14 #include <linux/counter.h>
16 #include <linux/mfd/stm32-lptimer.h>
22 struct counter_device counter; member
37 ret = regmap_read(priv->regmap, STM32_LPTIM_CR, &val); in stm32_lptim_is_enabled()
51 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, val); in stm32_lptim_set_enable_state()
56 clk_disable(priv->clk); in stm32_lptim_set_enable_state()
57 priv->enabled = false; in stm32_lptim_set_enable_state()
61 /* LP timer must be enabled before writing CMP & ARR */ in stm32_lptim_set_enable_state()
62 ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling); in stm32_lptim_set_enable_state()
66 ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0); in stm32_lptim_set_enable_state()
71 ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, in stm32_lptim_set_enable_state()
77 ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, in stm32_lptim_set_enable_state()
82 ret = clk_enable(priv->clk); in stm32_lptim_set_enable_state()
84 regmap_write(priv->regmap, STM32_LPTIM_CR, 0); in stm32_lptim_set_enable_state()
87 priv->enabled = true; in stm32_lptim_set_enable_state()
89 /* Start LP timer in continuous mode */ in stm32_lptim_set_enable_state()
90 return regmap_update_bits(priv->regmap, STM32_LPTIM_CR, in stm32_lptim_set_enable_state()
100 /* Setup LP timer encoder/counter and polarity, without prescaler */ in stm32_lptim_setup()
101 if (priv->quadrature_mode) in stm32_lptim_setup()
105 val |= FIELD_PREP(STM32_LPTIM_CKPOL, enable ? priv->polarity : 0); in stm32_lptim_setup()
107 return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val); in stm32_lptim_setup()
120 return -EINVAL; in stm32_lptim_write_raw()
122 /* Check nobody uses the timer, or already disabled/enabled */ in stm32_lptim_write_raw()
127 return -EBUSY; in stm32_lptim_write_raw()
135 return -EINVAL; in stm32_lptim_write_raw()
149 ret = regmap_read(priv->regmap, STM32_LPTIM_CNT, &dat); in stm32_lptim_read_raw()
163 /* Non-quadrature mode: scale = 1 */ in stm32_lptim_read_raw()
166 if (priv->quadrature_mode) { in stm32_lptim_read_raw()
169 * - both edges, quarter cycle, scale is 0.25 in stm32_lptim_read_raw()
170 * - either rising/falling edge scale is 0.5 in stm32_lptim_read_raw()
172 if (priv->polarity > 1) in stm32_lptim_read_raw()
180 return -EINVAL; in stm32_lptim_read_raw()
190 "non-quadrature",
199 return priv->quadrature_mode; in stm32_lptim_get_quadrature_mode()
209 return -EBUSY; in stm32_lptim_set_quadrature_mode()
211 priv->quadrature_mode = type; in stm32_lptim_set_quadrature_mode()
224 "rising-edge", "falling-edge", "both-edges",
232 return priv->polarity; in stm32_lptim_cnt_get_polarity()
242 return -EBUSY; in stm32_lptim_cnt_set_polarity()
244 priv->polarity = type; in stm32_lptim_cnt_set_polarity()
259 return snprintf(buf, PAGE_SIZE, "%u\n", priv->ceiling); in stm32_lptim_cnt_get_ceiling()
268 return -EBUSY; in stm32_lptim_cnt_set_ceiling()
270 ret = kstrtouint(buf, 0, &priv->ceiling); in stm32_lptim_cnt_set_ceiling()
274 if (priv->ceiling > STM32_LPTIM_MAX_ARR) in stm32_lptim_cnt_set_ceiling()
275 return -EINVAL; in stm32_lptim_cnt_set_ceiling()
300 /* LP timer with encoder */
326 /* LP timer without encoder (counter only) */
350 * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes
372 /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */
379 static int stm32_lptim_cnt_read(struct counter_device *counter, in stm32_lptim_cnt_read() argument
382 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_read()
386 ret = regmap_read(priv->regmap, STM32_LPTIM_CNT, &cnt); in stm32_lptim_cnt_read()
395 static int stm32_lptim_cnt_function_get(struct counter_device *counter, in stm32_lptim_cnt_function_get() argument
399 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_function_get()
401 if (!priv->quadrature_mode) { in stm32_lptim_cnt_function_get()
406 if (priv->polarity == STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES) { in stm32_lptim_cnt_function_get()
411 return -EINVAL; in stm32_lptim_cnt_function_get()
414 static int stm32_lptim_cnt_function_set(struct counter_device *counter, in stm32_lptim_cnt_function_set() argument
418 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_function_set()
421 return -EBUSY; in stm32_lptim_cnt_function_set()
425 priv->quadrature_mode = 0; in stm32_lptim_cnt_function_set()
428 priv->quadrature_mode = 1; in stm32_lptim_cnt_function_set()
429 priv->polarity = STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES; in stm32_lptim_cnt_function_set()
433 return -EINVAL; in stm32_lptim_cnt_function_set()
436 static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter, in stm32_lptim_cnt_enable_read() argument
440 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_enable_read()
450 static ssize_t stm32_lptim_cnt_enable_write(struct counter_device *counter, in stm32_lptim_cnt_enable_write() argument
455 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_enable_write()
463 /* Check nobody uses the timer, or already disabled/enabled */ in stm32_lptim_cnt_enable_write()
468 return -EBUSY; in stm32_lptim_cnt_enable_write()
481 static ssize_t stm32_lptim_cnt_ceiling_read(struct counter_device *counter, in stm32_lptim_cnt_ceiling_read() argument
485 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_ceiling_read()
490 static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter, in stm32_lptim_cnt_ceiling_write() argument
495 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_ceiling_write()
513 static int stm32_lptim_cnt_action_get(struct counter_device *counter, in stm32_lptim_cnt_action_get() argument
518 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_action_get()
522 err = stm32_lptim_cnt_function_get(counter, count, &function); in stm32_lptim_cnt_action_get()
528 /* LP Timer acts as up-counter on input 1 */ in stm32_lptim_cnt_action_get()
529 if (synapse->signal->id == count->synapses[0].signal->id) in stm32_lptim_cnt_action_get()
530 *action = priv->polarity; in stm32_lptim_cnt_action_get()
535 *action = priv->polarity; in stm32_lptim_cnt_action_get()
539 return -EINVAL; in stm32_lptim_cnt_action_get()
542 static int stm32_lptim_cnt_action_set(struct counter_device *counter, in stm32_lptim_cnt_action_set() argument
547 struct stm32_lptim_cnt *const priv = counter->priv; in stm32_lptim_cnt_action_set()
552 return -EBUSY; in stm32_lptim_cnt_action_set()
554 err = stm32_lptim_cnt_function_get(counter, count, &function); in stm32_lptim_cnt_action_set()
558 /* only set polarity when in counter mode (on input 1) */ in stm32_lptim_cnt_action_set()
560 && synapse->signal->id == count->synapses[0].signal->id) { in stm32_lptim_cnt_action_set()
565 priv->polarity = action; in stm32_lptim_cnt_action_set()
570 return -EINVAL; in stm32_lptim_cnt_action_set()
605 /* LP timer with encoder */
617 /* LP timer without encoder (counter only) */
631 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); in stm32_lptim_cnt_probe()
637 return -EINVAL; in stm32_lptim_cnt_probe()
639 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); in stm32_lptim_cnt_probe()
641 return -ENOMEM; in stm32_lptim_cnt_probe()
644 priv->dev = &pdev->dev; in stm32_lptim_cnt_probe()
645 priv->regmap = ddata->regmap; in stm32_lptim_cnt_probe()
646 priv->clk = ddata->clk; in stm32_lptim_cnt_probe()
647 priv->ceiling = STM32_LPTIM_MAX_ARR; in stm32_lptim_cnt_probe()
650 indio_dev->name = dev_name(&pdev->dev); in stm32_lptim_cnt_probe()
651 indio_dev->dev.of_node = pdev->dev.of_node; in stm32_lptim_cnt_probe()
652 indio_dev->info = &stm32_lptim_cnt_iio_info; in stm32_lptim_cnt_probe()
653 if (ddata->has_encoder) in stm32_lptim_cnt_probe()
654 indio_dev->channels = &stm32_lptim_enc_channels; in stm32_lptim_cnt_probe()
656 indio_dev->channels = &stm32_lptim_cnt_channels; in stm32_lptim_cnt_probe()
657 indio_dev->num_channels = 1; in stm32_lptim_cnt_probe()
659 /* Initialize Counter device */ in stm32_lptim_cnt_probe()
660 priv->counter.name = dev_name(&pdev->dev); in stm32_lptim_cnt_probe()
661 priv->counter.parent = &pdev->dev; in stm32_lptim_cnt_probe()
662 priv->counter.ops = &stm32_lptim_cnt_ops; in stm32_lptim_cnt_probe()
663 if (ddata->has_encoder) { in stm32_lptim_cnt_probe()
664 priv->counter.counts = &stm32_lptim_enc_counts; in stm32_lptim_cnt_probe()
665 priv->counter.num_signals = ARRAY_SIZE(stm32_lptim_cnt_signals); in stm32_lptim_cnt_probe()
667 priv->counter.counts = &stm32_lptim_in1_counts; in stm32_lptim_cnt_probe()
668 priv->counter.num_signals = 1; in stm32_lptim_cnt_probe()
670 priv->counter.num_counts = 1; in stm32_lptim_cnt_probe()
671 priv->counter.signals = stm32_lptim_cnt_signals; in stm32_lptim_cnt_probe()
672 priv->counter.priv = priv; in stm32_lptim_cnt_probe()
676 ret = devm_iio_device_register(&pdev->dev, indio_dev); in stm32_lptim_cnt_probe()
680 return devm_counter_register(&pdev->dev, &priv->counter); in stm32_lptim_cnt_probe()
689 /* Only take care of enabled counter: don't disturb other MFD child */ in stm32_lptim_cnt_suspend()
690 if (priv->enabled) { in stm32_lptim_cnt_suspend()
700 priv->enabled = true; in stm32_lptim_cnt_suspend()
715 if (priv->enabled) { in stm32_lptim_cnt_resume()
716 priv->enabled = false; in stm32_lptim_cnt_resume()
734 { .compatible = "st,stm32-lptimer-counter", },
742 .name = "stm32-lptimer-counter",
750 MODULE_ALIAS("platform:stm32-lptimer-counter");
751 MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver");