1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * ECAP Capture driver |
4 | * |
5 | * Copyright (C) 2022 Julien Panis <jpanis@baylibre.com> |
6 | */ |
7 | |
8 | #include <linux/atomic.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/counter.h> |
11 | #include <linux/err.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/io.h> |
14 | #include <linux/module.h> |
15 | #include <linux/mod_devicetable.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regmap.h> |
20 | |
21 | #define ECAP_DRV_NAME "ecap" |
22 | |
23 | /* ECAP event IDs */ |
24 | #define ECAP_CEVT1 0 |
25 | #define ECAP_CEVT2 1 |
26 | #define ECAP_CEVT3 2 |
27 | #define ECAP_CEVT4 3 |
28 | #define ECAP_CNTOVF 4 |
29 | |
30 | #define ECAP_CEVT_LAST ECAP_CEVT4 |
31 | #define ECAP_NB_CEVT (ECAP_CEVT_LAST + 1) |
32 | |
33 | #define ECAP_EVT_LAST ECAP_CNTOVF |
34 | #define ECAP_NB_EVT (ECAP_EVT_LAST + 1) |
35 | |
36 | /* Registers */ |
37 | #define ECAP_TSCNT_REG 0x00 |
38 | |
39 | #define ECAP_CAP_REG(i) (((i) << 2) + 0x08) |
40 | |
41 | #define ECAP_ECCTL_REG 0x28 |
42 | #define ECAP_CAPPOL_BIT(i) BIT((i) << 1) |
43 | #define ECAP_EV_MODE_MASK GENMASK(7, 0) |
44 | #define ECAP_CAPLDEN_BIT BIT(8) |
45 | #define ECAP_CONT_ONESHT_BIT BIT(16) |
46 | #define ECAP_STOPVALUE_MASK GENMASK(18, 17) |
47 | #define ECAP_TSCNTSTP_BIT BIT(20) |
48 | #define ECAP_SYNCO_DIS_MASK GENMASK(23, 22) |
49 | #define ECAP_CAP_APWM_BIT BIT(25) |
50 | #define ECAP_ECCTL_EN_MASK (ECAP_CAPLDEN_BIT | ECAP_TSCNTSTP_BIT) |
51 | #define ECAP_ECCTL_CFG_MASK (ECAP_SYNCO_DIS_MASK | ECAP_STOPVALUE_MASK \ |
52 | | ECAP_ECCTL_EN_MASK | ECAP_CAP_APWM_BIT \ |
53 | | ECAP_CONT_ONESHT_BIT) |
54 | |
55 | #define ECAP_ECINT_EN_FLG_REG 0x2c |
56 | #define ECAP_EVT_EN_MASK GENMASK(ECAP_NB_EVT, ECAP_NB_CEVT) |
57 | #define ECAP_EVT_FLG_BIT(i) BIT((i) + 17) |
58 | |
59 | #define ECAP_ECINT_CLR_FRC_REG 0x30 |
60 | #define ECAP_INT_CLR_BIT BIT(0) |
61 | #define ECAP_EVT_CLR_BIT(i) BIT((i) + 1) |
62 | #define ECAP_EVT_CLR_MASK GENMASK(ECAP_NB_EVT, 0) |
63 | |
64 | #define ECAP_PID_REG 0x5c |
65 | |
66 | /* ECAP signals */ |
67 | #define ECAP_CLOCK_SIG 0 |
68 | #define ECAP_INPUT_SIG 1 |
69 | |
70 | static const struct regmap_config ecap_cnt_regmap_config = { |
71 | .reg_bits = 32, |
72 | .reg_stride = 4, |
73 | .val_bits = 32, |
74 | .max_register = ECAP_PID_REG, |
75 | }; |
76 | |
77 | /** |
78 | * struct ecap_cnt_dev - device private data structure |
79 | * @enabled: device state |
80 | * @lock: synchronization lock to prevent I/O race conditions |
81 | * @clk: device clock |
82 | * @regmap: device register map |
83 | * @nb_ovf: number of overflows since capture start |
84 | * @pm_ctx: device context for PM operations |
85 | * @pm_ctx.ev_mode: event mode bits |
86 | * @pm_ctx.time_cntr: timestamp counter value |
87 | */ |
88 | struct ecap_cnt_dev { |
89 | bool enabled; |
90 | struct mutex lock; |
91 | struct clk *clk; |
92 | struct regmap *regmap; |
93 | atomic_t nb_ovf; |
94 | struct { |
95 | u8 ev_mode; |
96 | u32 time_cntr; |
97 | } pm_ctx; |
98 | }; |
99 | |
100 | static u8 ecap_cnt_capture_get_evmode(struct counter_device *counter) |
101 | { |
102 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
103 | unsigned int regval; |
104 | |
105 | pm_runtime_get_sync(dev: counter->parent); |
106 | regmap_read(map: ecap_dev->regmap, ECAP_ECCTL_REG, val: ®val); |
107 | pm_runtime_put_sync(dev: counter->parent); |
108 | |
109 | return regval; |
110 | } |
111 | |
112 | static void ecap_cnt_capture_set_evmode(struct counter_device *counter, u8 ev_mode) |
113 | { |
114 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
115 | |
116 | pm_runtime_get_sync(dev: counter->parent); |
117 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_EV_MODE_MASK, val: ev_mode); |
118 | pm_runtime_put_sync(dev: counter->parent); |
119 | } |
120 | |
121 | static void ecap_cnt_capture_enable(struct counter_device *counter) |
122 | { |
123 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
124 | |
125 | pm_runtime_get_sync(dev: counter->parent); |
126 | |
127 | /* Enable interrupts on events */ |
128 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, |
129 | ECAP_EVT_EN_MASK, ECAP_EVT_EN_MASK); |
130 | |
131 | /* Run counter */ |
132 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_CFG_MASK, |
133 | ECAP_SYNCO_DIS_MASK | ECAP_STOPVALUE_MASK | ECAP_ECCTL_EN_MASK); |
134 | } |
135 | |
136 | static void ecap_cnt_capture_disable(struct counter_device *counter) |
137 | { |
138 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
139 | |
140 | /* Stop counter */ |
141 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_ECCTL_EN_MASK, val: 0); |
142 | |
143 | /* Disable interrupts on events */ |
144 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, ECAP_EVT_EN_MASK, val: 0); |
145 | |
146 | pm_runtime_put_sync(dev: counter->parent); |
147 | } |
148 | |
149 | static u32 ecap_cnt_count_get_val(struct counter_device *counter, unsigned int reg) |
150 | { |
151 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
152 | unsigned int regval; |
153 | |
154 | pm_runtime_get_sync(dev: counter->parent); |
155 | regmap_read(map: ecap_dev->regmap, reg, val: ®val); |
156 | pm_runtime_put_sync(dev: counter->parent); |
157 | |
158 | return regval; |
159 | } |
160 | |
161 | static void ecap_cnt_count_set_val(struct counter_device *counter, unsigned int reg, u32 val) |
162 | { |
163 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
164 | |
165 | pm_runtime_get_sync(dev: counter->parent); |
166 | regmap_write(map: ecap_dev->regmap, reg, val); |
167 | pm_runtime_put_sync(dev: counter->parent); |
168 | } |
169 | |
170 | static int ecap_cnt_count_read(struct counter_device *counter, |
171 | struct counter_count *count, u64 *val) |
172 | { |
173 | *val = ecap_cnt_count_get_val(counter, ECAP_TSCNT_REG); |
174 | |
175 | return 0; |
176 | } |
177 | |
178 | static int ecap_cnt_count_write(struct counter_device *counter, |
179 | struct counter_count *count, u64 val) |
180 | { |
181 | if (val > U32_MAX) |
182 | return -ERANGE; |
183 | |
184 | ecap_cnt_count_set_val(counter, ECAP_TSCNT_REG, val); |
185 | |
186 | return 0; |
187 | } |
188 | |
189 | static int ecap_cnt_function_read(struct counter_device *counter, |
190 | struct counter_count *count, |
191 | enum counter_function *function) |
192 | { |
193 | *function = COUNTER_FUNCTION_INCREASE; |
194 | |
195 | return 0; |
196 | } |
197 | |
198 | static int ecap_cnt_action_read(struct counter_device *counter, |
199 | struct counter_count *count, |
200 | struct counter_synapse *synapse, |
201 | enum counter_synapse_action *action) |
202 | { |
203 | *action = (synapse->signal->id == ECAP_CLOCK_SIG) ? |
204 | COUNTER_SYNAPSE_ACTION_RISING_EDGE : |
205 | COUNTER_SYNAPSE_ACTION_NONE; |
206 | |
207 | return 0; |
208 | } |
209 | |
210 | static int ecap_cnt_watch_validate(struct counter_device *counter, |
211 | const struct counter_watch *watch) |
212 | { |
213 | if (watch->channel > ECAP_CEVT_LAST) |
214 | return -EINVAL; |
215 | |
216 | switch (watch->event) { |
217 | case COUNTER_EVENT_CAPTURE: |
218 | case COUNTER_EVENT_OVERFLOW: |
219 | return 0; |
220 | default: |
221 | return -EINVAL; |
222 | } |
223 | } |
224 | |
225 | static int ecap_cnt_clk_get_freq(struct counter_device *counter, |
226 | struct counter_signal *signal, u64 *freq) |
227 | { |
228 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
229 | |
230 | *freq = clk_get_rate(clk: ecap_dev->clk); |
231 | |
232 | return 0; |
233 | } |
234 | |
235 | static int ecap_cnt_pol_read(struct counter_device *counter, |
236 | struct counter_signal *signal, |
237 | size_t idx, enum counter_signal_polarity *pol) |
238 | { |
239 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
240 | int bitval; |
241 | |
242 | pm_runtime_get_sync(dev: counter->parent); |
243 | bitval = regmap_test_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); |
244 | pm_runtime_put_sync(dev: counter->parent); |
245 | |
246 | *pol = bitval ? COUNTER_SIGNAL_POLARITY_NEGATIVE : COUNTER_SIGNAL_POLARITY_POSITIVE; |
247 | |
248 | return 0; |
249 | } |
250 | |
251 | static int ecap_cnt_pol_write(struct counter_device *counter, |
252 | struct counter_signal *signal, |
253 | size_t idx, enum counter_signal_polarity pol) |
254 | { |
255 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
256 | |
257 | pm_runtime_get_sync(dev: counter->parent); |
258 | if (pol == COUNTER_SIGNAL_POLARITY_NEGATIVE) |
259 | regmap_set_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); |
260 | else |
261 | regmap_clear_bits(map: ecap_dev->regmap, ECAP_ECCTL_REG, ECAP_CAPPOL_BIT(idx)); |
262 | pm_runtime_put_sync(dev: counter->parent); |
263 | |
264 | return 0; |
265 | } |
266 | |
267 | static int ecap_cnt_cap_read(struct counter_device *counter, |
268 | struct counter_count *count, |
269 | size_t idx, u64 *cap) |
270 | { |
271 | *cap = ecap_cnt_count_get_val(counter, ECAP_CAP_REG(idx)); |
272 | |
273 | return 0; |
274 | } |
275 | |
276 | static int ecap_cnt_cap_write(struct counter_device *counter, |
277 | struct counter_count *count, |
278 | size_t idx, u64 cap) |
279 | { |
280 | if (cap > U32_MAX) |
281 | return -ERANGE; |
282 | |
283 | ecap_cnt_count_set_val(counter, ECAP_CAP_REG(idx), val: cap); |
284 | |
285 | return 0; |
286 | } |
287 | |
288 | static int ecap_cnt_nb_ovf_read(struct counter_device *counter, |
289 | struct counter_count *count, u64 *val) |
290 | { |
291 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
292 | |
293 | *val = atomic_read(v: &ecap_dev->nb_ovf); |
294 | |
295 | return 0; |
296 | } |
297 | |
298 | static int ecap_cnt_nb_ovf_write(struct counter_device *counter, |
299 | struct counter_count *count, u64 val) |
300 | { |
301 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
302 | |
303 | if (val > U32_MAX) |
304 | return -ERANGE; |
305 | |
306 | atomic_set(v: &ecap_dev->nb_ovf, i: val); |
307 | |
308 | return 0; |
309 | } |
310 | |
311 | static int ecap_cnt_ceiling_read(struct counter_device *counter, |
312 | struct counter_count *count, u64 *val) |
313 | { |
314 | *val = U32_MAX; |
315 | |
316 | return 0; |
317 | } |
318 | |
319 | static int ecap_cnt_enable_read(struct counter_device *counter, |
320 | struct counter_count *count, u8 *enable) |
321 | { |
322 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
323 | |
324 | *enable = ecap_dev->enabled; |
325 | |
326 | return 0; |
327 | } |
328 | |
329 | static int ecap_cnt_enable_write(struct counter_device *counter, |
330 | struct counter_count *count, u8 enable) |
331 | { |
332 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter); |
333 | |
334 | mutex_lock(&ecap_dev->lock); |
335 | |
336 | if (enable == ecap_dev->enabled) |
337 | goto out; |
338 | |
339 | if (enable) |
340 | ecap_cnt_capture_enable(counter); |
341 | else |
342 | ecap_cnt_capture_disable(counter); |
343 | ecap_dev->enabled = enable; |
344 | |
345 | out: |
346 | mutex_unlock(lock: &ecap_dev->lock); |
347 | |
348 | return 0; |
349 | } |
350 | |
351 | static const struct counter_ops ecap_cnt_ops = { |
352 | .count_read = ecap_cnt_count_read, |
353 | .count_write = ecap_cnt_count_write, |
354 | .function_read = ecap_cnt_function_read, |
355 | .action_read = ecap_cnt_action_read, |
356 | .watch_validate = ecap_cnt_watch_validate, |
357 | }; |
358 | |
359 | static const enum counter_function ecap_cnt_functions[] = { |
360 | COUNTER_FUNCTION_INCREASE, |
361 | }; |
362 | |
363 | static const enum counter_synapse_action ecap_cnt_clock_actions[] = { |
364 | COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
365 | }; |
366 | |
367 | static const enum counter_synapse_action ecap_cnt_input_actions[] = { |
368 | COUNTER_SYNAPSE_ACTION_NONE, |
369 | }; |
370 | |
371 | static struct counter_comp ecap_cnt_clock_ext[] = { |
372 | COUNTER_COMP_SIGNAL_U64("frequency" , ecap_cnt_clk_get_freq, NULL), |
373 | }; |
374 | |
375 | static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { |
376 | COUNTER_SIGNAL_POLARITY_POSITIVE, |
377 | COUNTER_SIGNAL_POLARITY_NEGATIVE, |
378 | }; |
379 | |
380 | static DEFINE_COUNTER_AVAILABLE(ecap_cnt_pol_available, ecap_cnt_pol_avail); |
381 | static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_available, ECAP_NB_CEVT); |
382 | |
383 | static struct counter_comp ecap_cnt_signal_ext[] = { |
384 | COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), |
385 | }; |
386 | |
387 | static struct counter_signal ecap_cnt_signals[] = { |
388 | { |
389 | .id = ECAP_CLOCK_SIG, |
390 | .name = "Clock Signal" , |
391 | .ext = ecap_cnt_clock_ext, |
392 | .num_ext = ARRAY_SIZE(ecap_cnt_clock_ext), |
393 | }, |
394 | { |
395 | .id = ECAP_INPUT_SIG, |
396 | .name = "Input Signal" , |
397 | .ext = ecap_cnt_signal_ext, |
398 | .num_ext = ARRAY_SIZE(ecap_cnt_signal_ext), |
399 | }, |
400 | }; |
401 | |
402 | static struct counter_synapse ecap_cnt_synapses[] = { |
403 | { |
404 | .actions_list = ecap_cnt_clock_actions, |
405 | .num_actions = ARRAY_SIZE(ecap_cnt_clock_actions), |
406 | .signal = &ecap_cnt_signals[ECAP_CLOCK_SIG], |
407 | }, |
408 | { |
409 | .actions_list = ecap_cnt_input_actions, |
410 | .num_actions = ARRAY_SIZE(ecap_cnt_input_actions), |
411 | .signal = &ecap_cnt_signals[ECAP_INPUT_SIG], |
412 | }, |
413 | }; |
414 | |
415 | static DEFINE_COUNTER_ARRAY_CAPTURE(ecap_cnt_cap_array, ECAP_NB_CEVT); |
416 | |
417 | static struct counter_comp ecap_cnt_count_ext[] = { |
418 | COUNTER_COMP_ARRAY_CAPTURE(ecap_cnt_cap_read, ecap_cnt_cap_write, ecap_cnt_cap_array), |
419 | COUNTER_COMP_COUNT_U64("num_overflows" , ecap_cnt_nb_ovf_read, ecap_cnt_nb_ovf_write), |
420 | COUNTER_COMP_CEILING(ecap_cnt_ceiling_read, NULL), |
421 | COUNTER_COMP_ENABLE(ecap_cnt_enable_read, ecap_cnt_enable_write), |
422 | }; |
423 | |
424 | static struct counter_count ecap_cnt_counts[] = { |
425 | { |
426 | .name = "Timestamp Counter" , |
427 | .functions_list = ecap_cnt_functions, |
428 | .num_functions = ARRAY_SIZE(ecap_cnt_functions), |
429 | .synapses = ecap_cnt_synapses, |
430 | .num_synapses = ARRAY_SIZE(ecap_cnt_synapses), |
431 | .ext = ecap_cnt_count_ext, |
432 | .num_ext = ARRAY_SIZE(ecap_cnt_count_ext), |
433 | }, |
434 | }; |
435 | |
436 | static irqreturn_t ecap_cnt_isr(int irq, void *dev_id) |
437 | { |
438 | struct counter_device *counter_dev = dev_id; |
439 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter: counter_dev); |
440 | unsigned int clr = 0; |
441 | unsigned int flg; |
442 | int i; |
443 | |
444 | regmap_read(map: ecap_dev->regmap, ECAP_ECINT_EN_FLG_REG, val: &flg); |
445 | |
446 | /* Check capture events */ |
447 | for (i = 0 ; i < ECAP_NB_CEVT ; i++) { |
448 | if (flg & ECAP_EVT_FLG_BIT(i)) { |
449 | counter_push_event(counter: counter_dev, event: COUNTER_EVENT_CAPTURE, channel: i); |
450 | clr |= ECAP_EVT_CLR_BIT(i); |
451 | } |
452 | } |
453 | |
454 | /* Check counter overflow */ |
455 | if (flg & ECAP_EVT_FLG_BIT(ECAP_CNTOVF)) { |
456 | atomic_inc(v: &ecap_dev->nb_ovf); |
457 | for (i = 0 ; i < ECAP_NB_CEVT ; i++) |
458 | counter_push_event(counter: counter_dev, event: COUNTER_EVENT_OVERFLOW, channel: i); |
459 | clr |= ECAP_EVT_CLR_BIT(ECAP_CNTOVF); |
460 | } |
461 | |
462 | clr |= ECAP_INT_CLR_BIT; |
463 | regmap_update_bits(map: ecap_dev->regmap, ECAP_ECINT_CLR_FRC_REG, ECAP_EVT_CLR_MASK, val: clr); |
464 | |
465 | return IRQ_HANDLED; |
466 | } |
467 | |
468 | static void ecap_cnt_pm_disable(void *dev) |
469 | { |
470 | pm_runtime_disable(dev); |
471 | } |
472 | |
473 | static int ecap_cnt_probe(struct platform_device *pdev) |
474 | { |
475 | struct device *dev = &pdev->dev; |
476 | struct ecap_cnt_dev *ecap_dev; |
477 | struct counter_device *counter_dev; |
478 | void __iomem *mmio_base; |
479 | unsigned long clk_rate; |
480 | int ret; |
481 | |
482 | counter_dev = devm_counter_alloc(dev, sizeof_priv: sizeof(*ecap_dev)); |
483 | if (!counter_dev) |
484 | return -ENOMEM; |
485 | |
486 | counter_dev->name = ECAP_DRV_NAME; |
487 | counter_dev->parent = dev; |
488 | counter_dev->ops = &ecap_cnt_ops; |
489 | counter_dev->signals = ecap_cnt_signals; |
490 | counter_dev->num_signals = ARRAY_SIZE(ecap_cnt_signals); |
491 | counter_dev->counts = ecap_cnt_counts; |
492 | counter_dev->num_counts = ARRAY_SIZE(ecap_cnt_counts); |
493 | |
494 | ecap_dev = counter_priv(counter: counter_dev); |
495 | |
496 | mutex_init(&ecap_dev->lock); |
497 | |
498 | ecap_dev->clk = devm_clk_get_enabled(dev, id: "fck" ); |
499 | if (IS_ERR(ptr: ecap_dev->clk)) |
500 | return dev_err_probe(dev, err: PTR_ERR(ptr: ecap_dev->clk), fmt: "failed to get clock\n" ); |
501 | |
502 | clk_rate = clk_get_rate(clk: ecap_dev->clk); |
503 | if (!clk_rate) { |
504 | dev_err(dev, "failed to get clock rate\n" ); |
505 | return -EINVAL; |
506 | } |
507 | |
508 | mmio_base = devm_platform_ioremap_resource(pdev, index: 0); |
509 | if (IS_ERR(ptr: mmio_base)) |
510 | return PTR_ERR(ptr: mmio_base); |
511 | |
512 | ecap_dev->regmap = devm_regmap_init_mmio(dev, mmio_base, &ecap_cnt_regmap_config); |
513 | if (IS_ERR(ptr: ecap_dev->regmap)) |
514 | return dev_err_probe(dev, err: PTR_ERR(ptr: ecap_dev->regmap), fmt: "failed to init regmap\n" ); |
515 | |
516 | ret = platform_get_irq(pdev, 0); |
517 | if (ret < 0) |
518 | return dev_err_probe(dev, err: ret, fmt: "failed to get irq\n" ); |
519 | |
520 | ret = devm_request_irq(dev, irq: ret, handler: ecap_cnt_isr, irqflags: 0, devname: pdev->name, dev_id: counter_dev); |
521 | if (ret) |
522 | return dev_err_probe(dev, err: ret, fmt: "failed to request irq\n" ); |
523 | |
524 | platform_set_drvdata(pdev, data: counter_dev); |
525 | |
526 | pm_runtime_enable(dev); |
527 | |
528 | /* Register a cleanup callback to care for disabling PM */ |
529 | ret = devm_add_action_or_reset(dev, ecap_cnt_pm_disable, dev); |
530 | if (ret) |
531 | return dev_err_probe(dev, err: ret, fmt: "failed to add pm disable action\n" ); |
532 | |
533 | ret = devm_counter_add(dev, counter: counter_dev); |
534 | if (ret) |
535 | return dev_err_probe(dev, err: ret, fmt: "failed to add counter\n" ); |
536 | |
537 | return 0; |
538 | } |
539 | |
540 | static int ecap_cnt_remove(struct platform_device *pdev) |
541 | { |
542 | struct counter_device *counter_dev = platform_get_drvdata(pdev); |
543 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter: counter_dev); |
544 | |
545 | if (ecap_dev->enabled) |
546 | ecap_cnt_capture_disable(counter: counter_dev); |
547 | |
548 | return 0; |
549 | } |
550 | |
551 | static int ecap_cnt_suspend(struct device *dev) |
552 | { |
553 | struct counter_device *counter_dev = dev_get_drvdata(dev); |
554 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter: counter_dev); |
555 | |
556 | /* If eCAP is running, stop capture then save timestamp counter */ |
557 | if (ecap_dev->enabled) { |
558 | /* |
559 | * Disabling capture has the following effects: |
560 | * - interrupts are disabled |
561 | * - loading of capture registers is disabled |
562 | * - timebase counter is stopped |
563 | */ |
564 | ecap_cnt_capture_disable(counter: counter_dev); |
565 | ecap_dev->pm_ctx.time_cntr = ecap_cnt_count_get_val(counter: counter_dev, ECAP_TSCNT_REG); |
566 | } |
567 | |
568 | ecap_dev->pm_ctx.ev_mode = ecap_cnt_capture_get_evmode(counter: counter_dev); |
569 | |
570 | clk_disable(clk: ecap_dev->clk); |
571 | |
572 | return 0; |
573 | } |
574 | |
575 | static int ecap_cnt_resume(struct device *dev) |
576 | { |
577 | struct counter_device *counter_dev = dev_get_drvdata(dev); |
578 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter: counter_dev); |
579 | |
580 | clk_enable(clk: ecap_dev->clk); |
581 | |
582 | ecap_cnt_capture_set_evmode(counter: counter_dev, ev_mode: ecap_dev->pm_ctx.ev_mode); |
583 | |
584 | /* If eCAP was running, restore timestamp counter then run capture */ |
585 | if (ecap_dev->enabled) { |
586 | ecap_cnt_count_set_val(counter: counter_dev, ECAP_TSCNT_REG, val: ecap_dev->pm_ctx.time_cntr); |
587 | ecap_cnt_capture_enable(counter: counter_dev); |
588 | } |
589 | |
590 | return 0; |
591 | } |
592 | |
593 | static DEFINE_SIMPLE_DEV_PM_OPS(ecap_cnt_pm_ops, ecap_cnt_suspend, ecap_cnt_resume); |
594 | |
595 | static const struct of_device_id ecap_cnt_of_match[] = { |
596 | { .compatible = "ti,am62-ecap-capture" }, |
597 | {}, |
598 | }; |
599 | MODULE_DEVICE_TABLE(of, ecap_cnt_of_match); |
600 | |
601 | static struct platform_driver ecap_cnt_driver = { |
602 | .probe = ecap_cnt_probe, |
603 | .remove = ecap_cnt_remove, |
604 | .driver = { |
605 | .name = "ecap-capture" , |
606 | .of_match_table = ecap_cnt_of_match, |
607 | .pm = pm_sleep_ptr(&ecap_cnt_pm_ops), |
608 | }, |
609 | }; |
610 | module_platform_driver(ecap_cnt_driver); |
611 | |
612 | MODULE_DESCRIPTION("ECAP Capture driver" ); |
613 | MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>" ); |
614 | MODULE_LICENSE("GPL" ); |
615 | MODULE_IMPORT_NS(COUNTER); |
616 | |