GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / iio / counter / stm32-lptimer-cnt.c
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/iio/iio.h>
15 #include <linux/mfd/stm32-lptimer.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18
19 struct stm32_lptim_cnt {
20         struct device *dev;
21         struct regmap *regmap;
22         struct clk *clk;
23         u32 preset;
24         u32 polarity;
25         u32 quadrature_mode;
26 };
27
28 static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv)
29 {
30         u32 val;
31         int ret;
32
33         ret = regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
34         if (ret)
35                 return ret;
36
37         return FIELD_GET(STM32_LPTIM_ENABLE, val);
38 }
39
40 static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv,
41                                         int enable)
42 {
43         int ret;
44         u32 val;
45
46         val = FIELD_PREP(STM32_LPTIM_ENABLE, enable);
47         ret = regmap_write(priv->regmap, STM32_LPTIM_CR, val);
48         if (ret)
49                 return ret;
50
51         if (!enable) {
52                 clk_disable(priv->clk);
53                 return 0;
54         }
55
56         /* LP timer must be enabled before writing CMP & ARR */
57         ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->preset);
58         if (ret)
59                 return ret;
60
61         ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0);
62         if (ret)
63                 return ret;
64
65         /* ensure CMP & ARR registers are properly written */
66         ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
67                                        (val & STM32_LPTIM_CMPOK_ARROK),
68                                        100, 1000);
69         if (ret)
70                 return ret;
71
72         ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
73                            STM32_LPTIM_CMPOKCF_ARROKCF);
74         if (ret)
75                 return ret;
76
77         ret = clk_enable(priv->clk);
78         if (ret) {
79                 regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
80                 return ret;
81         }
82
83         /* Start LP timer in continuous mode */
84         return regmap_update_bits(priv->regmap, STM32_LPTIM_CR,
85                                   STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT);
86 }
87
88 static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
89 {
90         u32 mask = STM32_LPTIM_ENC | STM32_LPTIM_COUNTMODE |
91                    STM32_LPTIM_CKPOL | STM32_LPTIM_PRESC;
92         u32 val;
93
94         /* Setup LP timer encoder/counter and polarity, without prescaler */
95         if (priv->quadrature_mode)
96                 val = enable ? STM32_LPTIM_ENC : 0;
97         else
98                 val = enable ? STM32_LPTIM_COUNTMODE : 0;
99         val |= FIELD_PREP(STM32_LPTIM_CKPOL, enable ? priv->polarity : 0);
100
101         return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val);
102 }
103
104 static int stm32_lptim_write_raw(struct iio_dev *indio_dev,
105                                  struct iio_chan_spec const *chan,
106                                  int val, int val2, long mask)
107 {
108         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
109         int ret;
110
111         switch (mask) {
112         case IIO_CHAN_INFO_ENABLE:
113                 if (val < 0 || val > 1)
114                         return -EINVAL;
115
116                 /* Check nobody uses the timer, or already disabled/enabled */
117                 ret = stm32_lptim_is_enabled(priv);
118                 if ((ret < 0) || (!ret && !val))
119                         return ret;
120                 if (val && ret)
121                         return -EBUSY;
122
123                 ret = stm32_lptim_setup(priv, val);
124                 if (ret)
125                         return ret;
126                 return stm32_lptim_set_enable_state(priv, val);
127
128         default:
129                 return -EINVAL;
130         }
131 }
132
133 static int stm32_lptim_read_raw(struct iio_dev *indio_dev,
134                                 struct iio_chan_spec const *chan,
135                                 int *val, int *val2, long mask)
136 {
137         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
138         u32 dat;
139         int ret;
140
141         switch (mask) {
142         case IIO_CHAN_INFO_RAW:
143                 ret = regmap_read(priv->regmap, STM32_LPTIM_CNT, &dat);
144                 if (ret)
145                         return ret;
146                 *val = dat;
147                 return IIO_VAL_INT;
148
149         case IIO_CHAN_INFO_ENABLE:
150                 ret = stm32_lptim_is_enabled(priv);
151                 if (ret < 0)
152                         return ret;
153                 *val = ret;
154                 return IIO_VAL_INT;
155
156         case IIO_CHAN_INFO_SCALE:
157                 /* Non-quadrature mode: scale = 1 */
158                 *val = 1;
159                 *val2 = 0;
160                 if (priv->quadrature_mode) {
161                         /*
162                          * Quadrature encoder mode:
163                          * - both edges, quarter cycle, scale is 0.25
164                          * - either rising/falling edge scale is 0.5
165                          */
166                         if (priv->polarity > 1)
167                                 *val2 = 2;
168                         else
169                                 *val2 = 1;
170                 }
171                 return IIO_VAL_FRACTIONAL_LOG2;
172
173         default:
174                 return -EINVAL;
175         }
176 }
177
178 static const struct iio_info stm32_lptim_cnt_iio_info = {
179         .read_raw = stm32_lptim_read_raw,
180         .write_raw = stm32_lptim_write_raw,
181 };
182
183 static const char *const stm32_lptim_quadrature_modes[] = {
184         "non-quadrature",
185         "quadrature",
186 };
187
188 static int stm32_lptim_get_quadrature_mode(struct iio_dev *indio_dev,
189                                            const struct iio_chan_spec *chan)
190 {
191         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
192
193         return priv->quadrature_mode;
194 }
195
196 static int stm32_lptim_set_quadrature_mode(struct iio_dev *indio_dev,
197                                            const struct iio_chan_spec *chan,
198                                            unsigned int type)
199 {
200         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
201
202         if (stm32_lptim_is_enabled(priv))
203                 return -EBUSY;
204
205         priv->quadrature_mode = type;
206
207         return 0;
208 }
209
210 static const struct iio_enum stm32_lptim_quadrature_mode_en = {
211         .items = stm32_lptim_quadrature_modes,
212         .num_items = ARRAY_SIZE(stm32_lptim_quadrature_modes),
213         .get = stm32_lptim_get_quadrature_mode,
214         .set = stm32_lptim_set_quadrature_mode,
215 };
216
217 static const char * const stm32_lptim_cnt_polarity[] = {
218         "rising-edge", "falling-edge", "both-edges",
219 };
220
221 static int stm32_lptim_cnt_get_polarity(struct iio_dev *indio_dev,
222                                         const struct iio_chan_spec *chan)
223 {
224         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
225
226         return priv->polarity;
227 }
228
229 static int stm32_lptim_cnt_set_polarity(struct iio_dev *indio_dev,
230                                         const struct iio_chan_spec *chan,
231                                         unsigned int type)
232 {
233         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
234
235         if (stm32_lptim_is_enabled(priv))
236                 return -EBUSY;
237
238         priv->polarity = type;
239
240         return 0;
241 }
242
243 static const struct iio_enum stm32_lptim_cnt_polarity_en = {
244         .items = stm32_lptim_cnt_polarity,
245         .num_items = ARRAY_SIZE(stm32_lptim_cnt_polarity),
246         .get = stm32_lptim_cnt_get_polarity,
247         .set = stm32_lptim_cnt_set_polarity,
248 };
249
250 static ssize_t stm32_lptim_cnt_get_preset(struct iio_dev *indio_dev,
251                                           uintptr_t private,
252                                           const struct iio_chan_spec *chan,
253                                           char *buf)
254 {
255         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
256
257         return snprintf(buf, PAGE_SIZE, "%u\n", priv->preset);
258 }
259
260 static ssize_t stm32_lptim_cnt_set_preset(struct iio_dev *indio_dev,
261                                           uintptr_t private,
262                                           const struct iio_chan_spec *chan,
263                                           const char *buf, size_t len)
264 {
265         struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
266         int ret;
267
268         if (stm32_lptim_is_enabled(priv))
269                 return -EBUSY;
270
271         ret = kstrtouint(buf, 0, &priv->preset);
272         if (ret)
273                 return ret;
274
275         if (priv->preset > STM32_LPTIM_MAX_ARR)
276                 return -EINVAL;
277
278         return len;
279 }
280
281 /* LP timer with encoder */
282 static const struct iio_chan_spec_ext_info stm32_lptim_enc_ext_info[] = {
283         {
284                 .name = "preset",
285                 .shared = IIO_SEPARATE,
286                 .read = stm32_lptim_cnt_get_preset,
287                 .write = stm32_lptim_cnt_set_preset,
288         },
289         IIO_ENUM("polarity", IIO_SEPARATE, &stm32_lptim_cnt_polarity_en),
290         IIO_ENUM_AVAILABLE("polarity", &stm32_lptim_cnt_polarity_en),
291         IIO_ENUM("quadrature_mode", IIO_SEPARATE,
292                  &stm32_lptim_quadrature_mode_en),
293         IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_lptim_quadrature_mode_en),
294         {}
295 };
296
297 static const struct iio_chan_spec stm32_lptim_enc_channels = {
298         .type = IIO_COUNT,
299         .channel = 0,
300         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
301                               BIT(IIO_CHAN_INFO_ENABLE) |
302                               BIT(IIO_CHAN_INFO_SCALE),
303         .ext_info = stm32_lptim_enc_ext_info,
304         .indexed = 1,
305 };
306
307 /* LP timer without encoder (counter only) */
308 static const struct iio_chan_spec_ext_info stm32_lptim_cnt_ext_info[] = {
309         {
310                 .name = "preset",
311                 .shared = IIO_SEPARATE,
312                 .read = stm32_lptim_cnt_get_preset,
313                 .write = stm32_lptim_cnt_set_preset,
314         },
315         IIO_ENUM("polarity", IIO_SEPARATE, &stm32_lptim_cnt_polarity_en),
316         IIO_ENUM_AVAILABLE("polarity", &stm32_lptim_cnt_polarity_en),
317         {}
318 };
319
320 static const struct iio_chan_spec stm32_lptim_cnt_channels = {
321         .type = IIO_COUNT,
322         .channel = 0,
323         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
324                               BIT(IIO_CHAN_INFO_ENABLE) |
325                               BIT(IIO_CHAN_INFO_SCALE),
326         .ext_info = stm32_lptim_cnt_ext_info,
327         .indexed = 1,
328 };
329
330 static int stm32_lptim_cnt_probe(struct platform_device *pdev)
331 {
332         struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
333         struct stm32_lptim_cnt *priv;
334         struct iio_dev *indio_dev;
335
336         if (IS_ERR_OR_NULL(ddata))
337                 return -EINVAL;
338
339         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
340         if (!indio_dev)
341                 return -ENOMEM;
342
343         priv = iio_priv(indio_dev);
344         priv->dev = &pdev->dev;
345         priv->regmap = ddata->regmap;
346         priv->clk = ddata->clk;
347         priv->preset = STM32_LPTIM_MAX_ARR;
348
349         indio_dev->name = dev_name(&pdev->dev);
350         indio_dev->dev.parent = &pdev->dev;
351         indio_dev->dev.of_node = pdev->dev.of_node;
352         indio_dev->info = &stm32_lptim_cnt_iio_info;
353         if (ddata->has_encoder)
354                 indio_dev->channels = &stm32_lptim_enc_channels;
355         else
356                 indio_dev->channels = &stm32_lptim_cnt_channels;
357         indio_dev->num_channels = 1;
358
359         platform_set_drvdata(pdev, priv);
360
361         return devm_iio_device_register(&pdev->dev, indio_dev);
362 }
363
364 static const struct of_device_id stm32_lptim_cnt_of_match[] = {
365         { .compatible = "st,stm32-lptimer-counter", },
366         {},
367 };
368 MODULE_DEVICE_TABLE(of, stm32_lptim_cnt_of_match);
369
370 static struct platform_driver stm32_lptim_cnt_driver = {
371         .probe = stm32_lptim_cnt_probe,
372         .driver = {
373                 .name = "stm32-lptimer-counter",
374                 .of_match_table = stm32_lptim_cnt_of_match,
375         },
376 };
377 module_platform_driver(stm32_lptim_cnt_driver);
378
379 MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
380 MODULE_ALIAS("platform:stm32-lptimer-counter");
381 MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver");
382 MODULE_LICENSE("GPL v2");