Lines Matching +full:counter +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Counter driver for Texas Instruments Enhanced Quadrature Encoder Pulse (eQEP)
9 #include <linux/counter.h>
18 /* 32-bit registers */
19 #define QPOSCNT 0x0
20 #define QPOSINIT 0x4
21 #define QPOSMAX 0x8
22 #define QPOSCMP 0xc
23 #define QPOSILAT 0x10
24 #define QPOSSLAT 0x14
25 #define QPOSLAT 0x18
26 #define QUTMR 0x1c
27 #define QUPRD 0x20
29 /* 16-bit registers */
30 #define QWDTMR 0x0 /* 0x24 */
31 #define QWDPRD 0x2 /* 0x26 */
32 #define QDECCTL 0x4 /* 0x28 */
33 #define QEPCTL 0x6 /* 0x2a */
34 #define QCAPCTL 0x8 /* 0x2c */
35 #define QPOSCTL 0xa /* 0x2e */
36 #define QEINT 0xc /* 0x30 */
37 #define QFLG 0xe /* 0x32 */
38 #define QCLR 0x10 /* 0x34 */
39 #define QFRC 0x12 /* 0x36 */
40 #define QEPSTS 0x14 /* 0x38 */
41 #define QCTMR 0x16 /* 0x3a */
42 #define QCPRD 0x18 /* 0x3c */
43 #define QCTMRLAT 0x1a /* 0x3e */
44 #define QCPRDLAT 0x1c /* 0x40 */
68 #define QEPCTL_WDE BIT(0)
76 /* Position Counter Input Modes */
85 struct counter_device counter; member
90 static struct ti_eqep_cnt *ti_eqep_count_from_counter(struct counter_device *counter) in ti_eqep_count_from_counter() argument
92 return counter_priv(counter); in ti_eqep_count_from_counter()
95 static int ti_eqep_count_read(struct counter_device *counter, in ti_eqep_count_read() argument
98 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_count_read()
101 regmap_read(priv->regmap32, QPOSCNT, &cnt); in ti_eqep_count_read()
104 return 0; in ti_eqep_count_read()
107 static int ti_eqep_count_write(struct counter_device *counter, in ti_eqep_count_write() argument
110 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_count_write()
113 regmap_read(priv->regmap32, QPOSMAX, &max); in ti_eqep_count_write()
115 return -EINVAL; in ti_eqep_count_write()
117 return regmap_write(priv->regmap32, QPOSCNT, val); in ti_eqep_count_write()
120 static int ti_eqep_function_read(struct counter_device *counter, in ti_eqep_function_read() argument
124 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_function_read()
127 regmap_read(priv->regmap16, QDECCTL, &qdecctl); in ti_eqep_function_read()
144 return 0; in ti_eqep_function_read()
147 static int ti_eqep_function_write(struct counter_device *counter, in ti_eqep_function_write() argument
151 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_function_write()
169 return -EINVAL; in ti_eqep_function_write()
172 return regmap_write_bits(priv->regmap16, QDECCTL, QDECCTL_QSRC, in ti_eqep_function_write()
176 static int ti_eqep_action_read(struct counter_device *counter, in ti_eqep_action_read() argument
181 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_action_read()
186 err = ti_eqep_function_read(counter, count, &function); in ti_eqep_action_read()
196 return 0; in ti_eqep_action_read()
198 /* In direction-count mode only rising edge of QEPA is counted in ti_eqep_action_read()
201 switch (synapse->signal->id) { in ti_eqep_action_read()
204 return 0; in ti_eqep_action_read()
207 return 0; in ti_eqep_action_read()
210 return -EINVAL; in ti_eqep_action_read()
214 /* In up/down-count modes only QEPA is counted and QEPB is not in ti_eqep_action_read()
217 switch (synapse->signal->id) { in ti_eqep_action_read()
219 err = regmap_read(priv->regmap16, QDECCTL, &qdecctl); in ti_eqep_action_read()
227 return 0; in ti_eqep_action_read()
230 return 0; in ti_eqep_action_read()
233 return -EINVAL; in ti_eqep_action_read()
237 return -EINVAL; in ti_eqep_action_read()
249 static int ti_eqep_position_ceiling_read(struct counter_device *counter, in ti_eqep_position_ceiling_read() argument
253 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_position_ceiling_read()
256 regmap_read(priv->regmap32, QPOSMAX, &qposmax); in ti_eqep_position_ceiling_read()
260 return 0; in ti_eqep_position_ceiling_read()
263 static int ti_eqep_position_ceiling_write(struct counter_device *counter, in ti_eqep_position_ceiling_write() argument
267 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_position_ceiling_write()
270 return -ERANGE; in ti_eqep_position_ceiling_write()
272 regmap_write(priv->regmap32, QPOSMAX, ceiling); in ti_eqep_position_ceiling_write()
274 return 0; in ti_eqep_position_ceiling_write()
277 static int ti_eqep_position_enable_read(struct counter_device *counter, in ti_eqep_position_enable_read() argument
280 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_position_enable_read()
283 regmap_read(priv->regmap16, QEPCTL, &qepctl); in ti_eqep_position_enable_read()
287 return 0; in ti_eqep_position_enable_read()
290 static int ti_eqep_position_enable_write(struct counter_device *counter, in ti_eqep_position_enable_write() argument
293 struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); in ti_eqep_position_enable_write()
295 regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0); in ti_eqep_position_enable_write()
297 return 0; in ti_eqep_position_enable_write()
346 .id = 0,
358 .name = "32-bit",
366 .name = "16-bit",
375 struct device *dev = &pdev->dev; in ti_eqep_probe()
376 struct counter_device *counter; in ti_eqep_probe() local
381 counter = devm_counter_alloc(dev, sizeof(*priv)); in ti_eqep_probe()
382 if (!counter) in ti_eqep_probe()
383 return -ENOMEM; in ti_eqep_probe()
384 priv = counter_priv(counter); in ti_eqep_probe()
386 base = devm_platform_ioremap_resource(pdev, 0); in ti_eqep_probe()
390 priv->regmap32 = devm_regmap_init_mmio(dev, base, in ti_eqep_probe()
392 if (IS_ERR(priv->regmap32)) in ti_eqep_probe()
393 return PTR_ERR(priv->regmap32); in ti_eqep_probe()
395 priv->regmap16 = devm_regmap_init_mmio(dev, base + 0x24, in ti_eqep_probe()
397 if (IS_ERR(priv->regmap16)) in ti_eqep_probe()
398 return PTR_ERR(priv->regmap16); in ti_eqep_probe()
400 counter->name = dev_name(dev); in ti_eqep_probe()
401 counter->parent = dev; in ti_eqep_probe()
402 counter->ops = &ti_eqep_counter_ops; in ti_eqep_probe()
403 counter->counts = ti_eqep_counts; in ti_eqep_probe()
404 counter->num_counts = ARRAY_SIZE(ti_eqep_counts); in ti_eqep_probe()
405 counter->signals = ti_eqep_signals; in ti_eqep_probe()
406 counter->num_signals = ARRAY_SIZE(ti_eqep_signals); in ti_eqep_probe()
408 platform_set_drvdata(pdev, counter); in ti_eqep_probe()
418 err = counter_add(counter); in ti_eqep_probe()
419 if (err < 0) { in ti_eqep_probe()
425 return 0; in ti_eqep_probe()
430 struct counter_device *counter = platform_get_drvdata(pdev); in ti_eqep_remove() local
431 struct device *dev = &pdev->dev; in ti_eqep_remove()
433 counter_unregister(counter); in ti_eqep_remove()
437 return 0; in ti_eqep_remove()
441 { .compatible = "ti,am3352-eqep", },
450 .name = "ti-eqep-cnt",
457 MODULE_DESCRIPTION("TI eQEP counter driver");
459 MODULE_IMPORT_NS(COUNTER);