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

1 // SPDX-License-Identifier: GPL-2.0-or-later
10 #include <linux/counter.h>
24 #define ECAP_CEVT1 0
37 #define ECAP_TSCNT_REG 0x00
39 #define ECAP_CAP_REG(i) (((i) << 2) + 0x08)
41 #define ECAP_ECCTL_REG 0x28
43 #define ECAP_EV_MODE_MASK GENMASK(7, 0)
55 #define ECAP_ECINT_EN_FLG_REG 0x2c
59 #define ECAP_ECINT_CLR_FRC_REG 0x30
60 #define ECAP_INT_CLR_BIT BIT(0)
62 #define ECAP_EVT_CLR_MASK GENMASK(ECAP_NB_EVT, 0)
64 #define ECAP_PID_REG 0x5c
67 #define ECAP_CLOCK_SIG 0
78 * struct ecap_cnt_dev - device private data structure
86 * @pm_ctx.time_cntr: timestamp counter value
100 static u8 ecap_cnt_capture_get_evmode(struct counter_device *counter) in ecap_cnt_capture_get_evmode() argument
102 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_capture_get_evmode()
105 pm_runtime_get_sync(counter->parent); in ecap_cnt_capture_get_evmode()
106 regmap_read(ecap_dev->regmap, ECAP_ECCTL_REG, &regval); in ecap_cnt_capture_get_evmode()
107 pm_runtime_put_sync(counter->parent); in ecap_cnt_capture_get_evmode()
112 static void ecap_cnt_capture_set_evmode(struct counter_device *counter, u8 ev_mode) in ecap_cnt_capture_set_evmode() argument
114 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_capture_set_evmode()
116 pm_runtime_get_sync(counter->parent); in ecap_cnt_capture_set_evmode()
117 regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_EV_MODE_MASK, ev_mode); in ecap_cnt_capture_set_evmode()
118 pm_runtime_put_sync(counter->parent); in ecap_cnt_capture_set_evmode()
121 static void ecap_cnt_capture_enable(struct counter_device *counter) in ecap_cnt_capture_enable() argument
123 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_capture_enable()
125 pm_runtime_get_sync(counter->parent); in ecap_cnt_capture_enable()
128 regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, in ecap_cnt_capture_enable()
131 /* Run counter */ in ecap_cnt_capture_enable()
132 regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_CFG_MASK, in ecap_cnt_capture_enable()
136 static void ecap_cnt_capture_disable(struct counter_device *counter) in ecap_cnt_capture_disable() argument
138 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_capture_disable()
140 /* Stop counter */ in ecap_cnt_capture_disable()
141 regmap_update_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_EN_MASK, 0); in ecap_cnt_capture_disable()
144 regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, ECAP_EVT_EN_MASK, 0); in ecap_cnt_capture_disable()
146 pm_runtime_put_sync(counter->parent); in ecap_cnt_capture_disable()
149 static u32 ecap_cnt_count_get_val(struct counter_device *counter, unsigned int reg) in ecap_cnt_count_get_val() argument
151 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_count_get_val()
154 pm_runtime_get_sync(counter->parent); in ecap_cnt_count_get_val()
155 regmap_read(ecap_dev->regmap, reg, &regval); in ecap_cnt_count_get_val()
156 pm_runtime_put_sync(counter->parent); in ecap_cnt_count_get_val()
161 static void ecap_cnt_count_set_val(struct counter_device *counter, unsigned int reg, u32 val) in ecap_cnt_count_set_val() argument
163 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_count_set_val()
165 pm_runtime_get_sync(counter->parent); in ecap_cnt_count_set_val()
166 regmap_write(ecap_dev->regmap, reg, val); in ecap_cnt_count_set_val()
167 pm_runtime_put_sync(counter->parent); in ecap_cnt_count_set_val()
170 static int ecap_cnt_count_read(struct counter_device *counter, in ecap_cnt_count_read() argument
173 *val = ecap_cnt_count_get_val(counter, ECAP_TSCNT_REG); in ecap_cnt_count_read()
175 return 0; in ecap_cnt_count_read()
178 static int ecap_cnt_count_write(struct counter_device *counter, in ecap_cnt_count_write() argument
182 return -ERANGE; in ecap_cnt_count_write()
184 ecap_cnt_count_set_val(counter, ECAP_TSCNT_REG, val); in ecap_cnt_count_write()
186 return 0; in ecap_cnt_count_write()
189 static int ecap_cnt_function_read(struct counter_device *counter, in ecap_cnt_function_read() argument
195 return 0; in ecap_cnt_function_read()
198 static int ecap_cnt_action_read(struct counter_device *counter, in ecap_cnt_action_read() argument
203 *action = (synapse->signal->id == ECAP_CLOCK_SIG) ? in ecap_cnt_action_read()
207 return 0; in ecap_cnt_action_read()
210 static int ecap_cnt_watch_validate(struct counter_device *counter, in ecap_cnt_watch_validate() argument
213 if (watch->channel > ECAP_CEVT_LAST) in ecap_cnt_watch_validate()
214 return -EINVAL; in ecap_cnt_watch_validate()
216 switch (watch->event) { in ecap_cnt_watch_validate()
219 return 0; in ecap_cnt_watch_validate()
221 return -EINVAL; in ecap_cnt_watch_validate()
225 static int ecap_cnt_clk_get_freq(struct counter_device *counter, in ecap_cnt_clk_get_freq() argument
228 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_clk_get_freq()
230 *freq = clk_get_rate(ecap_dev->clk); in ecap_cnt_clk_get_freq()
232 return 0; in ecap_cnt_clk_get_freq()
235 static int ecap_cnt_pol_read(struct counter_device *counter, in ecap_cnt_pol_read() argument
239 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_pol_read()
242 pm_runtime_get_sync(counter->parent); in ecap_cnt_pol_read()
243 bitval = regmap_test_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); in ecap_cnt_pol_read()
244 pm_runtime_put_sync(counter->parent); in ecap_cnt_pol_read()
248 return 0; in ecap_cnt_pol_read()
251 static int ecap_cnt_pol_write(struct counter_device *counter, in ecap_cnt_pol_write() argument
255 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_pol_write()
257 pm_runtime_get_sync(counter->parent); in ecap_cnt_pol_write()
259 regmap_set_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); in ecap_cnt_pol_write()
261 regmap_clear_bits(ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); in ecap_cnt_pol_write()
262 pm_runtime_put_sync(counter->parent); in ecap_cnt_pol_write()
264 return 0; in ecap_cnt_pol_write()
267 static int ecap_cnt_cap_read(struct counter_device *counter, in ecap_cnt_cap_read() argument
271 *cap = ecap_cnt_count_get_val(counter, ECAP_CAP_REG(idx)); in ecap_cnt_cap_read()
273 return 0; in ecap_cnt_cap_read()
276 static int ecap_cnt_cap_write(struct counter_device *counter, in ecap_cnt_cap_write() argument
281 return -ERANGE; in ecap_cnt_cap_write()
283 ecap_cnt_count_set_val(counter, ECAP_CAP_REG(idx), cap); in ecap_cnt_cap_write()
285 return 0; in ecap_cnt_cap_write()
288 static int ecap_cnt_nb_ovf_read(struct counter_device *counter, in ecap_cnt_nb_ovf_read() argument
291 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_nb_ovf_read()
293 *val = atomic_read(&ecap_dev->nb_ovf); in ecap_cnt_nb_ovf_read()
295 return 0; in ecap_cnt_nb_ovf_read()
298 static int ecap_cnt_nb_ovf_write(struct counter_device *counter, in ecap_cnt_nb_ovf_write() argument
301 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_nb_ovf_write()
304 return -ERANGE; in ecap_cnt_nb_ovf_write()
306 atomic_set(&ecap_dev->nb_ovf, val); in ecap_cnt_nb_ovf_write()
308 return 0; in ecap_cnt_nb_ovf_write()
311 static int ecap_cnt_ceiling_read(struct counter_device *counter, in ecap_cnt_ceiling_read() argument
316 return 0; in ecap_cnt_ceiling_read()
319 static int ecap_cnt_enable_read(struct counter_device *counter, in ecap_cnt_enable_read() argument
322 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_enable_read()
324 *enable = ecap_dev->enabled; in ecap_cnt_enable_read()
326 return 0; in ecap_cnt_enable_read()
329 static int ecap_cnt_enable_write(struct counter_device *counter, in ecap_cnt_enable_write() argument
332 struct ecap_cnt_dev *ecap_dev = counter_priv(counter); in ecap_cnt_enable_write()
334 mutex_lock(&ecap_dev->lock); in ecap_cnt_enable_write()
336 if (enable == ecap_dev->enabled) in ecap_cnt_enable_write()
340 ecap_cnt_capture_enable(counter); in ecap_cnt_enable_write()
342 ecap_cnt_capture_disable(counter); in ecap_cnt_enable_write()
343 ecap_dev->enabled = enable; in ecap_cnt_enable_write()
346 mutex_unlock(&ecap_dev->lock); in ecap_cnt_enable_write()
348 return 0; in ecap_cnt_enable_write()
426 .name = "Timestamp Counter",
440 unsigned int clr = 0; in ecap_cnt_isr()
444 regmap_read(ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, &flg); in ecap_cnt_isr()
447 for (i = 0 ; i < ECAP_NB_CEVT ; i++) { in ecap_cnt_isr()
454 /* Check counter overflow */ in ecap_cnt_isr()
456 atomic_inc(&ecap_dev->nb_ovf); in ecap_cnt_isr()
457 for (i = 0 ; i < ECAP_NB_CEVT ; i++) in ecap_cnt_isr()
463 regmap_update_bits(ecap_dev->regmap, ECAP_ECINT_CLR_FRC_REG, ECAP_EVT_CLR_MASK, clr); in ecap_cnt_isr()
475 struct device *dev = &pdev->dev; in ecap_cnt_probe()
484 return -ENOMEM; in ecap_cnt_probe()
486 counter_dev->name = ECAP_DRV_NAME; in ecap_cnt_probe()
487 counter_dev->parent = dev; in ecap_cnt_probe()
488 counter_dev->ops = &ecap_cnt_ops; in ecap_cnt_probe()
489 counter_dev->signals = ecap_cnt_signals; in ecap_cnt_probe()
490 counter_dev->num_signals = ARRAY_SIZE(ecap_cnt_signals); in ecap_cnt_probe()
491 counter_dev->counts = ecap_cnt_counts; in ecap_cnt_probe()
492 counter_dev->num_counts = ARRAY_SIZE(ecap_cnt_counts); in ecap_cnt_probe()
496 mutex_init(&ecap_dev->lock); in ecap_cnt_probe()
498 ecap_dev->clk = devm_clk_get_enabled(dev, "fck"); in ecap_cnt_probe()
499 if (IS_ERR(ecap_dev->clk)) in ecap_cnt_probe()
500 return dev_err_probe(dev, PTR_ERR(ecap_dev->clk), "failed to get clock\n"); in ecap_cnt_probe()
502 clk_rate = clk_get_rate(ecap_dev->clk); in ecap_cnt_probe()
505 return -EINVAL; in ecap_cnt_probe()
508 mmio_base = devm_platform_ioremap_resource(pdev, 0); in ecap_cnt_probe()
512 ecap_dev->regmap = devm_regmap_init_mmio(dev, mmio_base, &ecap_cnt_regmap_config); in ecap_cnt_probe()
513 if (IS_ERR(ecap_dev->regmap)) in ecap_cnt_probe()
514 return dev_err_probe(dev, PTR_ERR(ecap_dev->regmap), "failed to init regmap\n"); in ecap_cnt_probe()
516 ret = platform_get_irq(pdev, 0); in ecap_cnt_probe()
517 if (ret < 0) in ecap_cnt_probe()
520 ret = devm_request_irq(dev, ret, ecap_cnt_isr, 0, pdev->name, counter_dev); in ecap_cnt_probe()
535 return dev_err_probe(dev, ret, "failed to add counter\n"); in ecap_cnt_probe()
537 return 0; in ecap_cnt_probe()
545 if (ecap_dev->enabled) in ecap_cnt_remove()
548 return 0; in ecap_cnt_remove()
556 /* If eCAP is running, stop capture then save timestamp counter */ in ecap_cnt_suspend()
557 if (ecap_dev->enabled) { in ecap_cnt_suspend()
560 * - interrupts are disabled in ecap_cnt_suspend()
561 * - loading of capture registers is disabled in ecap_cnt_suspend()
562 * - timebase counter is stopped in ecap_cnt_suspend()
565 ecap_dev->pm_ctx.time_cntr = ecap_cnt_count_get_val(counter_dev, ECAP_TSCNT_REG); in ecap_cnt_suspend()
568 ecap_dev->pm_ctx.ev_mode = ecap_cnt_capture_get_evmode(counter_dev); in ecap_cnt_suspend()
570 clk_disable(ecap_dev->clk); in ecap_cnt_suspend()
572 return 0; in ecap_cnt_suspend()
580 clk_enable(ecap_dev->clk); in ecap_cnt_resume()
582 ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); in ecap_cnt_resume()
584 /* If eCAP was running, restore timestamp counter then run capture */ in ecap_cnt_resume()
585 if (ecap_dev->enabled) { in ecap_cnt_resume()
586 ecap_cnt_count_set_val(counter_dev, ECAP_TSCNT_REG, ecap_dev->pm_ctx.time_cntr); in ecap_cnt_resume()
590 return 0; in ecap_cnt_resume()
596 { .compatible = "ti,am62-ecap-capture" },
605 .name = "ecap-capture",
615 MODULE_IMPORT_NS(COUNTER);