1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2020 Microchip
4 *
5 * Author: Kamel Bouhara <kamel.bouhara@bootlin.com>
6 */
7 #include <linux/clk.h>
8 #include <linux/counter.h>
9 #include <linux/interrupt.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/module.h>
12 #include <linux/mutex.h>
13 #include <linux/of.h>
14 #include <linux/of_irq.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <uapi/linux/counter/microchip-tcb-capture.h>
18 #include <soc/at91/atmel_tcb.h>
19
20 #define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
21 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
22 ATMEL_TC_LDBSTOP)
23
24 #define ATMEL_TC_DEF_IRQS (ATMEL_TC_ETRGS | ATMEL_TC_COVFS | \
25 ATMEL_TC_LDRAS | ATMEL_TC_LDRBS | ATMEL_TC_CPCS)
26
27 #define ATMEL_TC_QDEN BIT(8)
28 #define ATMEL_TC_POSEN BIT(9)
29
30 struct mchp_tc_data {
31 const struct atmel_tcb_config *tc_cfg;
32 struct regmap *regmap;
33 int qdec_mode;
34 int num_channels;
35 int channel[2];
36 };
37
38 static const enum counter_function mchp_tc_count_functions[] = {
39 COUNTER_FUNCTION_INCREASE,
40 COUNTER_FUNCTION_QUADRATURE_X4,
41 };
42
43 static const enum counter_synapse_action mchp_tc_synapse_actions[] = {
44 COUNTER_SYNAPSE_ACTION_NONE,
45 COUNTER_SYNAPSE_ACTION_RISING_EDGE,
46 COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
47 COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
48 };
49
50 static struct counter_signal mchp_tc_count_signals[] = {
51 {
52 .id = 0,
53 .name = "Channel A",
54 },
55 {
56 .id = 1,
57 .name = "Channel B",
58 }
59 };
60
61 static struct counter_synapse mchp_tc_count_synapses[] = {
62 {
63 .actions_list = mchp_tc_synapse_actions,
64 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
65 .signal = &mchp_tc_count_signals[0]
66 },
67 {
68 .actions_list = mchp_tc_synapse_actions,
69 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
70 .signal = &mchp_tc_count_signals[1]
71 }
72 };
73
mchp_tc_count_function_read(struct counter_device * counter,struct counter_count * count,enum counter_function * function)74 static int mchp_tc_count_function_read(struct counter_device *counter,
75 struct counter_count *count,
76 enum counter_function *function)
77 {
78 struct mchp_tc_data *const priv = counter_priv(counter);
79
80 if (priv->qdec_mode)
81 *function = COUNTER_FUNCTION_QUADRATURE_X4;
82 else
83 *function = COUNTER_FUNCTION_INCREASE;
84
85 return 0;
86 }
87
mchp_tc_count_function_write(struct counter_device * counter,struct counter_count * count,enum counter_function function)88 static int mchp_tc_count_function_write(struct counter_device *counter,
89 struct counter_count *count,
90 enum counter_function function)
91 {
92 struct mchp_tc_data *const priv = counter_priv(counter);
93 u32 bmr, cmr;
94
95 regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr);
96 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
97
98 /* Set capture mode */
99 cmr &= ~ATMEL_TC_WAVE;
100
101 switch (function) {
102 case COUNTER_FUNCTION_INCREASE:
103 priv->qdec_mode = 0;
104 /* Set highest rate based on whether soc has gclk or not */
105 bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN);
106 if (!priv->tc_cfg->has_gclk)
107 cmr |= ATMEL_TC_TIMER_CLOCK2;
108 else
109 cmr |= ATMEL_TC_TIMER_CLOCK1;
110 /* Setup the period capture mode */
111 cmr |= ATMEL_TC_CMR_MASK;
112 cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0);
113 break;
114 case COUNTER_FUNCTION_QUADRATURE_X4:
115 if (!priv->tc_cfg->has_qdec)
116 return -EINVAL;
117 /* In QDEC mode settings both channels 0 and 1 are required */
118 if (priv->num_channels < 2 || priv->channel[0] != 0 ||
119 priv->channel[1] != 1) {
120 pr_err("Invalid channels number or id for quadrature mode\n");
121 return -EINVAL;
122 }
123 priv->qdec_mode = 1;
124 bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN;
125 cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0;
126 break;
127 default:
128 /* should never reach this path */
129 return -EINVAL;
130 }
131
132 regmap_write(priv->regmap, ATMEL_TC_BMR, bmr);
133 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), cmr);
134
135 /* Enable clock and trigger counter */
136 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CCR),
137 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
138
139 if (priv->qdec_mode) {
140 regmap_write(priv->regmap,
141 ATMEL_TC_REG(priv->channel[1], CMR), cmr);
142 regmap_write(priv->regmap,
143 ATMEL_TC_REG(priv->channel[1], CCR),
144 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
145 }
146
147 return 0;
148 }
149
mchp_tc_count_signal_read(struct counter_device * counter,struct counter_signal * signal,enum counter_signal_level * lvl)150 static int mchp_tc_count_signal_read(struct counter_device *counter,
151 struct counter_signal *signal,
152 enum counter_signal_level *lvl)
153 {
154 struct mchp_tc_data *const priv = counter_priv(counter);
155 bool sigstatus;
156 u32 sr;
157
158 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
159
160 if (signal->id == 1)
161 sigstatus = (sr & ATMEL_TC_MTIOB);
162 else
163 sigstatus = (sr & ATMEL_TC_MTIOA);
164
165 *lvl = sigstatus ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
166
167 return 0;
168 }
169
mchp_tc_count_action_read(struct counter_device * counter,struct counter_count * count,struct counter_synapse * synapse,enum counter_synapse_action * action)170 static int mchp_tc_count_action_read(struct counter_device *counter,
171 struct counter_count *count,
172 struct counter_synapse *synapse,
173 enum counter_synapse_action *action)
174 {
175 struct mchp_tc_data *const priv = counter_priv(counter);
176 u32 cmr;
177
178 if (priv->qdec_mode) {
179 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
180 return 0;
181 }
182
183 /* Only TIOA signal is evaluated in non-QDEC mode */
184 if (synapse->signal->id != 0) {
185 *action = COUNTER_SYNAPSE_ACTION_NONE;
186 return 0;
187 }
188
189 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
190
191 switch (cmr & ATMEL_TC_ETRGEDG) {
192 default:
193 *action = COUNTER_SYNAPSE_ACTION_NONE;
194 break;
195 case ATMEL_TC_ETRGEDG_RISING:
196 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
197 break;
198 case ATMEL_TC_ETRGEDG_FALLING:
199 *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
200 break;
201 case ATMEL_TC_ETRGEDG_BOTH:
202 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
203 break;
204 }
205
206 return 0;
207 }
208
mchp_tc_count_action_write(struct counter_device * counter,struct counter_count * count,struct counter_synapse * synapse,enum counter_synapse_action action)209 static int mchp_tc_count_action_write(struct counter_device *counter,
210 struct counter_count *count,
211 struct counter_synapse *synapse,
212 enum counter_synapse_action action)
213 {
214 struct mchp_tc_data *const priv = counter_priv(counter);
215 u32 edge = ATMEL_TC_ETRGEDG_NONE;
216
217 /* QDEC mode is rising edge only; only TIOA handled in non-QDEC mode */
218 if (priv->qdec_mode || synapse->signal->id != 0)
219 return -EINVAL;
220
221 switch (action) {
222 case COUNTER_SYNAPSE_ACTION_NONE:
223 edge = ATMEL_TC_ETRGEDG_NONE;
224 break;
225 case COUNTER_SYNAPSE_ACTION_RISING_EDGE:
226 edge = ATMEL_TC_ETRGEDG_RISING;
227 break;
228 case COUNTER_SYNAPSE_ACTION_FALLING_EDGE:
229 edge = ATMEL_TC_ETRGEDG_FALLING;
230 break;
231 case COUNTER_SYNAPSE_ACTION_BOTH_EDGES:
232 edge = ATMEL_TC_ETRGEDG_BOTH;
233 break;
234 default:
235 /* should never reach this path */
236 return -EINVAL;
237 }
238
239 return regmap_write_bits(priv->regmap,
240 ATMEL_TC_REG(priv->channel[0], CMR),
241 ATMEL_TC_ETRGEDG, edge);
242 }
243
mchp_tc_count_read(struct counter_device * counter,struct counter_count * count,u64 * val)244 static int mchp_tc_count_read(struct counter_device *counter,
245 struct counter_count *count, u64 *val)
246 {
247 struct mchp_tc_data *const priv = counter_priv(counter);
248 u32 cnt;
249
250 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt);
251 *val = cnt;
252
253 return 0;
254 }
255
mchp_tc_count_cap_read(struct counter_device * counter,struct counter_count * count,size_t idx,u64 * val)256 static int mchp_tc_count_cap_read(struct counter_device *counter,
257 struct counter_count *count, size_t idx, u64 *val)
258 {
259 struct mchp_tc_data *const priv = counter_priv(counter);
260 u32 cnt;
261 int ret;
262
263 switch (idx) {
264 case COUNTER_MCHP_EXCAP_RA:
265 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), &cnt);
266 break;
267 case COUNTER_MCHP_EXCAP_RB:
268 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), &cnt);
269 break;
270 default:
271 return -EINVAL;
272 }
273
274 if (ret < 0)
275 return ret;
276
277 *val = cnt;
278
279 return 0;
280 }
281
mchp_tc_count_cap_write(struct counter_device * counter,struct counter_count * count,size_t idx,u64 val)282 static int mchp_tc_count_cap_write(struct counter_device *counter,
283 struct counter_count *count, size_t idx, u64 val)
284 {
285 struct mchp_tc_data *const priv = counter_priv(counter);
286 int ret;
287
288 if (val > U32_MAX)
289 return -ERANGE;
290
291 switch (idx) {
292 case COUNTER_MCHP_EXCAP_RA:
293 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RA), val);
294 break;
295 case COUNTER_MCHP_EXCAP_RB:
296 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RB), val);
297 break;
298 default:
299 return -EINVAL;
300 }
301
302 return ret;
303 }
304
mchp_tc_count_compare_read(struct counter_device * counter,struct counter_count * count,u64 * val)305 static int mchp_tc_count_compare_read(struct counter_device *counter, struct counter_count *count,
306 u64 *val)
307 {
308 struct mchp_tc_data *const priv = counter_priv(counter);
309 u32 cnt;
310 int ret;
311
312 ret = regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), &cnt);
313 if (ret < 0)
314 return ret;
315
316 *val = cnt;
317
318 return 0;
319 }
320
mchp_tc_count_compare_write(struct counter_device * counter,struct counter_count * count,u64 val)321 static int mchp_tc_count_compare_write(struct counter_device *counter, struct counter_count *count,
322 u64 val)
323 {
324 struct mchp_tc_data *const priv = counter_priv(counter);
325
326 if (val > U32_MAX)
327 return -ERANGE;
328
329 return regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], RC), val);
330 }
331
332 static DEFINE_COUNTER_ARRAY_CAPTURE(mchp_tc_cnt_cap_array, 2);
333
334 static struct counter_comp mchp_tc_count_ext[] = {
335 COUNTER_COMP_ARRAY_CAPTURE(mchp_tc_count_cap_read, mchp_tc_count_cap_write,
336 mchp_tc_cnt_cap_array),
337 COUNTER_COMP_COMPARE(mchp_tc_count_compare_read, mchp_tc_count_compare_write),
338 };
339
mchp_tc_watch_validate(struct counter_device * counter,const struct counter_watch * watch)340 static int mchp_tc_watch_validate(struct counter_device *counter,
341 const struct counter_watch *watch)
342 {
343 if (watch->channel == COUNTER_MCHP_EVCHN_CV || watch->channel == COUNTER_MCHP_EVCHN_RA)
344 switch (watch->event) {
345 case COUNTER_EVENT_CHANGE_OF_STATE:
346 case COUNTER_EVENT_OVERFLOW:
347 case COUNTER_EVENT_CAPTURE:
348 return 0;
349 default:
350 return -EINVAL;
351 }
352
353 if (watch->channel == COUNTER_MCHP_EVCHN_RB && watch->event == COUNTER_EVENT_CAPTURE)
354 return 0;
355
356 if (watch->channel == COUNTER_MCHP_EVCHN_RC && watch->event == COUNTER_EVENT_THRESHOLD)
357 return 0;
358
359 return -EINVAL;
360 }
361
362 static struct counter_count mchp_tc_counts[] = {
363 {
364 .id = 0,
365 .name = "Timer Counter",
366 .functions_list = mchp_tc_count_functions,
367 .num_functions = ARRAY_SIZE(mchp_tc_count_functions),
368 .synapses = mchp_tc_count_synapses,
369 .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
370 .ext = mchp_tc_count_ext,
371 .num_ext = ARRAY_SIZE(mchp_tc_count_ext),
372 },
373 };
374
375 static const struct counter_ops mchp_tc_ops = {
376 .signal_read = mchp_tc_count_signal_read,
377 .count_read = mchp_tc_count_read,
378 .function_read = mchp_tc_count_function_read,
379 .function_write = mchp_tc_count_function_write,
380 .action_read = mchp_tc_count_action_read,
381 .action_write = mchp_tc_count_action_write,
382 .watch_validate = mchp_tc_watch_validate,
383 };
384
385 static const struct atmel_tcb_config tcb_rm9200_config = {
386 .counter_width = 16,
387 };
388
389 static const struct atmel_tcb_config tcb_sam9x5_config = {
390 .counter_width = 32,
391 };
392
393 static const struct atmel_tcb_config tcb_sama5d2_config = {
394 .counter_width = 32,
395 .has_gclk = true,
396 .has_qdec = true,
397 };
398
399 static const struct atmel_tcb_config tcb_sama5d3_config = {
400 .counter_width = 32,
401 .has_qdec = true,
402 };
403
404 static const struct of_device_id atmel_tc_of_match[] = {
405 { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, },
406 { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, },
407 { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, },
408 { .compatible = "atmel,sama5d3-tcb", .data = &tcb_sama5d3_config, },
409 { /* sentinel */ }
410 };
411
mchp_tc_isr(int irq,void * dev_id)412 static irqreturn_t mchp_tc_isr(int irq, void *dev_id)
413 {
414 struct counter_device *const counter = dev_id;
415 struct mchp_tc_data *const priv = counter_priv(counter);
416 u32 sr, mask;
417
418 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
419 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], IMR), &mask);
420
421 sr &= mask;
422 if (!(sr & ATMEL_TC_ALL_IRQ))
423 return IRQ_NONE;
424
425 if (sr & ATMEL_TC_ETRGS)
426 counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE,
427 COUNTER_MCHP_EVCHN_CV);
428 if (sr & ATMEL_TC_LDRAS)
429 counter_push_event(counter, COUNTER_EVENT_CAPTURE,
430 COUNTER_MCHP_EVCHN_RA);
431 if (sr & ATMEL_TC_LDRBS)
432 counter_push_event(counter, COUNTER_EVENT_CAPTURE,
433 COUNTER_MCHP_EVCHN_RB);
434 if (sr & ATMEL_TC_CPCS)
435 counter_push_event(counter, COUNTER_EVENT_THRESHOLD,
436 COUNTER_MCHP_EVCHN_RC);
437 if (sr & ATMEL_TC_COVFS)
438 counter_push_event(counter, COUNTER_EVENT_OVERFLOW,
439 COUNTER_MCHP_EVCHN_CV);
440
441 return IRQ_HANDLED;
442 }
443
mchp_tc_irq_remove(void * ptr)444 static void mchp_tc_irq_remove(void *ptr)
445 {
446 struct mchp_tc_data *priv = ptr;
447
448 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IDR), ATMEL_TC_DEF_IRQS);
449 }
450
mchp_tc_irq_enable(struct counter_device * const counter,int irq)451 static int mchp_tc_irq_enable(struct counter_device *const counter, int irq)
452 {
453 struct mchp_tc_data *const priv = counter_priv(counter);
454 int ret = devm_request_irq(counter->parent, irq, mchp_tc_isr, 0,
455 dev_name(counter->parent), counter);
456
457 if (ret < 0)
458 return ret;
459
460 ret = regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], IER), ATMEL_TC_DEF_IRQS);
461 if (ret < 0)
462 return ret;
463
464 ret = devm_add_action_or_reset(counter->parent, mchp_tc_irq_remove, priv);
465 if (ret < 0)
466 return ret;
467
468 return 0;
469 }
470
mchp_tc_clk_remove(void * ptr)471 static void mchp_tc_clk_remove(void *ptr)
472 {
473 clk_disable_unprepare((struct clk *)ptr);
474 }
475
mchp_tc_probe(struct platform_device * pdev)476 static int mchp_tc_probe(struct platform_device *pdev)
477 {
478 struct device_node *np = pdev->dev.of_node;
479 const struct atmel_tcb_config *tcb_config;
480 const struct of_device_id *match;
481 struct counter_device *counter;
482 struct mchp_tc_data *priv;
483 char clk_name[7];
484 struct regmap *regmap;
485 struct clk *clk[3];
486 int channel;
487 int ret, i;
488
489 counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
490 if (!counter)
491 return -ENOMEM;
492 priv = counter_priv(counter);
493
494 match = of_match_node(atmel_tc_of_match, np->parent);
495 tcb_config = match->data;
496 if (!tcb_config) {
497 dev_err(&pdev->dev, "No matching parent node found\n");
498 return -ENODEV;
499 }
500
501 regmap = syscon_node_to_regmap(np->parent);
502 if (IS_ERR(regmap))
503 return PTR_ERR(regmap);
504
505 /* max. channels number is 2 when in QDEC mode */
506 priv->num_channels = of_property_count_u32_elems(np, "reg");
507 if (priv->num_channels < 0) {
508 dev_err(&pdev->dev, "Invalid or missing channel\n");
509 return -EINVAL;
510 }
511
512 /* Register channels and initialize clocks */
513 for (i = 0; i < priv->num_channels; i++) {
514 ret = of_property_read_u32_index(np, "reg", i, &channel);
515 if (ret < 0 || channel > 2)
516 return -ENODEV;
517
518 priv->channel[i] = channel;
519
520 snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
521
522 clk[i] = of_clk_get_by_name(np->parent, clk_name);
523 if (IS_ERR(clk[i])) {
524 /* Fallback to t0_clk */
525 clk[i] = of_clk_get_by_name(np->parent, "t0_clk");
526 if (IS_ERR(clk[i]))
527 return PTR_ERR(clk[i]);
528 }
529
530 ret = clk_prepare_enable(clk[i]);
531 if (ret)
532 return ret;
533
534 ret = devm_add_action_or_reset(&pdev->dev,
535 mchp_tc_clk_remove,
536 clk[i]);
537 if (ret)
538 return ret;
539
540 dev_dbg(&pdev->dev,
541 "Initialized capture mode on channel %d\n",
542 channel);
543 }
544
545 /* Disable Quadrature Decoder and position measure */
546 ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0);
547 if (ret)
548 return ret;
549
550 /* Setup the period capture mode */
551 ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR),
552 ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK |
553 ATMEL_TC_TCCLKS,
554 ATMEL_TC_CMR_MASK);
555 if (ret)
556 return ret;
557
558 /* Enable clock and trigger counter */
559 ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR),
560 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
561 if (ret)
562 return ret;
563
564 priv->tc_cfg = tcb_config;
565 priv->regmap = regmap;
566 counter->name = dev_name(&pdev->dev);
567 counter->parent = &pdev->dev;
568 counter->ops = &mchp_tc_ops;
569 counter->num_counts = ARRAY_SIZE(mchp_tc_counts);
570 counter->counts = mchp_tc_counts;
571 counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals);
572 counter->signals = mchp_tc_count_signals;
573
574 i = of_irq_get(np->parent, 0);
575 if (i == -EPROBE_DEFER)
576 return -EPROBE_DEFER;
577 if (i > 0) {
578 ret = mchp_tc_irq_enable(counter, i);
579 if (ret < 0)
580 return dev_err_probe(&pdev->dev, ret, "Failed to set up IRQ");
581 }
582
583 ret = devm_counter_add(&pdev->dev, counter);
584 if (ret < 0)
585 return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n");
586
587 return 0;
588 }
589
590 static const struct of_device_id mchp_tc_dt_ids[] = {
591 { .compatible = "microchip,tcb-capture", },
592 { /* sentinel */ },
593 };
594 MODULE_DEVICE_TABLE(of, mchp_tc_dt_ids);
595
596 static struct platform_driver mchp_tc_driver = {
597 .probe = mchp_tc_probe,
598 .driver = {
599 .name = "microchip-tcb-capture",
600 .of_match_table = mchp_tc_dt_ids,
601 },
602 };
603 module_platform_driver(mchp_tc_driver);
604
605 MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>");
606 MODULE_DESCRIPTION("Microchip TCB Capture driver");
607 MODULE_LICENSE("GPL v2");
608 MODULE_IMPORT_NS("COUNTER");
609