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