Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / counter / counter.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Generic Counter interface
4  * Copyright (C) 2018 William Breathitt Gray
5  */
6 #include <linux/counter.h>
7 #include <linux/device.h>
8 #include <linux/err.h>
9 #include <linux/export.h>
10 #include <linux/fs.h>
11 #include <linux/gfp.h>
12 #include <linux/idr.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/list.h>
16 #include <linux/module.h>
17 #include <linux/printk.h>
18 #include <linux/slab.h>
19 #include <linux/string.h>
20 #include <linux/sysfs.h>
21 #include <linux/types.h>
22
23 const char *const counter_count_direction_str[2] = {
24         [COUNTER_COUNT_DIRECTION_FORWARD] = "forward",
25         [COUNTER_COUNT_DIRECTION_BACKWARD] = "backward"
26 };
27 EXPORT_SYMBOL_GPL(counter_count_direction_str);
28
29 const char *const counter_count_mode_str[4] = {
30         [COUNTER_COUNT_MODE_NORMAL] = "normal",
31         [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
32         [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
33         [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
34 };
35 EXPORT_SYMBOL_GPL(counter_count_mode_str);
36
37 ssize_t counter_signal_enum_read(struct counter_device *counter,
38                                  struct counter_signal *signal, void *priv,
39                                  char *buf)
40 {
41         const struct counter_signal_enum_ext *const e = priv;
42         int err;
43         size_t index;
44
45         if (!e->get)
46                 return -EINVAL;
47
48         err = e->get(counter, signal, &index);
49         if (err)
50                 return err;
51
52         if (index >= e->num_items)
53                 return -EINVAL;
54
55         return sprintf(buf, "%s\n", e->items[index]);
56 }
57 EXPORT_SYMBOL_GPL(counter_signal_enum_read);
58
59 ssize_t counter_signal_enum_write(struct counter_device *counter,
60                                   struct counter_signal *signal, void *priv,
61                                   const char *buf, size_t len)
62 {
63         const struct counter_signal_enum_ext *const e = priv;
64         ssize_t index;
65         int err;
66
67         if (!e->set)
68                 return -EINVAL;
69
70         index = __sysfs_match_string(e->items, e->num_items, buf);
71         if (index < 0)
72                 return index;
73
74         err = e->set(counter, signal, index);
75         if (err)
76                 return err;
77
78         return len;
79 }
80 EXPORT_SYMBOL_GPL(counter_signal_enum_write);
81
82 ssize_t counter_signal_enum_available_read(struct counter_device *counter,
83                                            struct counter_signal *signal,
84                                            void *priv, char *buf)
85 {
86         const struct counter_signal_enum_ext *const e = priv;
87         size_t i;
88         size_t len = 0;
89
90         if (!e->num_items)
91                 return 0;
92
93         for (i = 0; i < e->num_items; i++)
94                 len += sprintf(buf + len, "%s\n", e->items[i]);
95
96         return len;
97 }
98 EXPORT_SYMBOL_GPL(counter_signal_enum_available_read);
99
100 ssize_t counter_count_enum_read(struct counter_device *counter,
101                                 struct counter_count *count, void *priv,
102                                 char *buf)
103 {
104         const struct counter_count_enum_ext *const e = priv;
105         int err;
106         size_t index;
107
108         if (!e->get)
109                 return -EINVAL;
110
111         err = e->get(counter, count, &index);
112         if (err)
113                 return err;
114
115         if (index >= e->num_items)
116                 return -EINVAL;
117
118         return sprintf(buf, "%s\n", e->items[index]);
119 }
120 EXPORT_SYMBOL_GPL(counter_count_enum_read);
121
122 ssize_t counter_count_enum_write(struct counter_device *counter,
123                                  struct counter_count *count, void *priv,
124                                  const char *buf, size_t len)
125 {
126         const struct counter_count_enum_ext *const e = priv;
127         ssize_t index;
128         int err;
129
130         if (!e->set)
131                 return -EINVAL;
132
133         index = __sysfs_match_string(e->items, e->num_items, buf);
134         if (index < 0)
135                 return index;
136
137         err = e->set(counter, count, index);
138         if (err)
139                 return err;
140
141         return len;
142 }
143 EXPORT_SYMBOL_GPL(counter_count_enum_write);
144
145 ssize_t counter_count_enum_available_read(struct counter_device *counter,
146                                           struct counter_count *count,
147                                           void *priv, char *buf)
148 {
149         const struct counter_count_enum_ext *const e = priv;
150         size_t i;
151         size_t len = 0;
152
153         if (!e->num_items)
154                 return 0;
155
156         for (i = 0; i < e->num_items; i++)
157                 len += sprintf(buf + len, "%s\n", e->items[i]);
158
159         return len;
160 }
161 EXPORT_SYMBOL_GPL(counter_count_enum_available_read);
162
163 ssize_t counter_device_enum_read(struct counter_device *counter, void *priv,
164                                  char *buf)
165 {
166         const struct counter_device_enum_ext *const e = priv;
167         int err;
168         size_t index;
169
170         if (!e->get)
171                 return -EINVAL;
172
173         err = e->get(counter, &index);
174         if (err)
175                 return err;
176
177         if (index >= e->num_items)
178                 return -EINVAL;
179
180         return sprintf(buf, "%s\n", e->items[index]);
181 }
182 EXPORT_SYMBOL_GPL(counter_device_enum_read);
183
184 ssize_t counter_device_enum_write(struct counter_device *counter, void *priv,
185                                   const char *buf, size_t len)
186 {
187         const struct counter_device_enum_ext *const e = priv;
188         ssize_t index;
189         int err;
190
191         if (!e->set)
192                 return -EINVAL;
193
194         index = __sysfs_match_string(e->items, e->num_items, buf);
195         if (index < 0)
196                 return index;
197
198         err = e->set(counter, index);
199         if (err)
200                 return err;
201
202         return len;
203 }
204 EXPORT_SYMBOL_GPL(counter_device_enum_write);
205
206 ssize_t counter_device_enum_available_read(struct counter_device *counter,
207                                            void *priv, char *buf)
208 {
209         const struct counter_device_enum_ext *const e = priv;
210         size_t i;
211         size_t len = 0;
212
213         if (!e->num_items)
214                 return 0;
215
216         for (i = 0; i < e->num_items; i++)
217                 len += sprintf(buf + len, "%s\n", e->items[i]);
218
219         return len;
220 }
221 EXPORT_SYMBOL_GPL(counter_device_enum_available_read);
222
223 static const char *const counter_signal_level_str[] = {
224         [COUNTER_SIGNAL_LEVEL_LOW] = "low",
225         [COUNTER_SIGNAL_LEVEL_HIGH] = "high"
226 };
227
228 /**
229  * counter_signal_read_value_set - set counter_signal_read_value data
230  * @val:        counter_signal_read_value structure to set
231  * @type:       property Signal data represents
232  * @data:       Signal data
233  *
234  * This function sets an opaque counter_signal_read_value structure with the
235  * provided Signal data.
236  */
237 void counter_signal_read_value_set(struct counter_signal_read_value *const val,
238                                    const enum counter_signal_value_type type,
239                                    void *const data)
240 {
241         if (type == COUNTER_SIGNAL_LEVEL)
242                 val->len = sprintf(val->buf, "%s\n",
243                                    counter_signal_level_str[*(enum counter_signal_level *)data]);
244         else
245                 val->len = 0;
246 }
247 EXPORT_SYMBOL_GPL(counter_signal_read_value_set);
248
249 /**
250  * counter_count_read_value_set - set counter_count_read_value data
251  * @val:        counter_count_read_value structure to set
252  * @type:       property Count data represents
253  * @data:       Count data
254  *
255  * This function sets an opaque counter_count_read_value structure with the
256  * provided Count data.
257  */
258 void counter_count_read_value_set(struct counter_count_read_value *const val,
259                                   const enum counter_count_value_type type,
260                                   void *const data)
261 {
262         switch (type) {
263         case COUNTER_COUNT_POSITION:
264                 val->len = sprintf(val->buf, "%lu\n", *(unsigned long *)data);
265                 break;
266         default:
267                 val->len = 0;
268         }
269 }
270 EXPORT_SYMBOL_GPL(counter_count_read_value_set);
271
272 /**
273  * counter_count_write_value_get - get counter_count_write_value data
274  * @data:       Count data
275  * @type:       property Count data represents
276  * @val:        counter_count_write_value structure containing data
277  *
278  * This function extracts Count data from the provided opaque
279  * counter_count_write_value structure and stores it at the address provided by
280  * @data.
281  *
282  * RETURNS:
283  * 0 on success, negative error number on failure.
284  */
285 int counter_count_write_value_get(void *const data,
286                                   const enum counter_count_value_type type,
287                                   const struct counter_count_write_value *const val)
288 {
289         int err;
290
291         switch (type) {
292         case COUNTER_COUNT_POSITION:
293                 err = kstrtoul(val->buf, 0, data);
294                 if (err)
295                         return err;
296                 break;
297         }
298
299         return 0;
300 }
301 EXPORT_SYMBOL_GPL(counter_count_write_value_get);
302
303 struct counter_attr_parm {
304         struct counter_device_attr_group *group;
305         const char *prefix;
306         const char *name;
307         ssize_t (*show)(struct device *dev, struct device_attribute *attr,
308                         char *buf);
309         ssize_t (*store)(struct device *dev, struct device_attribute *attr,
310                          const char *buf, size_t len);
311         void *component;
312 };
313
314 struct counter_device_attr {
315         struct device_attribute dev_attr;
316         struct list_head l;
317         void *component;
318 };
319
320 static int counter_attribute_create(const struct counter_attr_parm *const parm)
321 {
322         struct counter_device_attr *counter_attr;
323         struct device_attribute *dev_attr;
324         int err;
325         struct list_head *const attr_list = &parm->group->attr_list;
326
327         /* Allocate a Counter device attribute */
328         counter_attr = kzalloc(sizeof(*counter_attr), GFP_KERNEL);
329         if (!counter_attr)
330                 return -ENOMEM;
331         dev_attr = &counter_attr->dev_attr;
332
333         sysfs_attr_init(&dev_attr->attr);
334
335         /* Configure device attribute */
336         dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s%s", parm->prefix,
337                                         parm->name);
338         if (!dev_attr->attr.name) {
339                 err = -ENOMEM;
340                 goto err_free_counter_attr;
341         }
342         if (parm->show) {
343                 dev_attr->attr.mode |= 0444;
344                 dev_attr->show = parm->show;
345         }
346         if (parm->store) {
347                 dev_attr->attr.mode |= 0200;
348                 dev_attr->store = parm->store;
349         }
350
351         /* Store associated Counter component with attribute */
352         counter_attr->component = parm->component;
353
354         /* Keep track of the attribute for later cleanup */
355         list_add(&counter_attr->l, attr_list);
356         parm->group->num_attr++;
357
358         return 0;
359
360 err_free_counter_attr:
361         kfree(counter_attr);
362         return err;
363 }
364
365 #define to_counter_attr(_dev_attr) \
366         container_of(_dev_attr, struct counter_device_attr, dev_attr)
367
368 struct counter_signal_unit {
369         struct counter_signal *signal;
370 };
371
372 static ssize_t counter_signal_show(struct device *dev,
373                                    struct device_attribute *attr, char *buf)
374 {
375         struct counter_device *const counter = dev_get_drvdata(dev);
376         const struct counter_device_attr *const devattr = to_counter_attr(attr);
377         const struct counter_signal_unit *const component = devattr->component;
378         struct counter_signal *const signal = component->signal;
379         int err;
380         struct counter_signal_read_value val = { .buf = buf };
381
382         err = counter->ops->signal_read(counter, signal, &val);
383         if (err)
384                 return err;
385
386         return val.len;
387 }
388
389 struct counter_name_unit {
390         const char *name;
391 };
392
393 static ssize_t counter_device_attr_name_show(struct device *dev,
394                                              struct device_attribute *attr,
395                                              char *buf)
396 {
397         const struct counter_name_unit *const comp = to_counter_attr(attr)->component;
398
399         return sprintf(buf, "%s\n", comp->name);
400 }
401
402 static int counter_name_attribute_create(
403         struct counter_device_attr_group *const group,
404         const char *const name)
405 {
406         struct counter_name_unit *name_comp;
407         struct counter_attr_parm parm;
408         int err;
409
410         /* Skip if no name */
411         if (!name)
412                 return 0;
413
414         /* Allocate name attribute component */
415         name_comp = kmalloc(sizeof(*name_comp), GFP_KERNEL);
416         if (!name_comp)
417                 return -ENOMEM;
418         name_comp->name = name;
419
420         /* Allocate Signal name attribute */
421         parm.group = group;
422         parm.prefix = "";
423         parm.name = "name";
424         parm.show = counter_device_attr_name_show;
425         parm.store = NULL;
426         parm.component = name_comp;
427         err = counter_attribute_create(&parm);
428         if (err)
429                 goto err_free_name_comp;
430
431         return 0;
432
433 err_free_name_comp:
434         kfree(name_comp);
435         return err;
436 }
437
438 struct counter_signal_ext_unit {
439         struct counter_signal *signal;
440         const struct counter_signal_ext *ext;
441 };
442
443 static ssize_t counter_signal_ext_show(struct device *dev,
444                                        struct device_attribute *attr, char *buf)
445 {
446         const struct counter_device_attr *const devattr = to_counter_attr(attr);
447         const struct counter_signal_ext_unit *const comp = devattr->component;
448         const struct counter_signal_ext *const ext = comp->ext;
449
450         return ext->read(dev_get_drvdata(dev), comp->signal, ext->priv, buf);
451 }
452
453 static ssize_t counter_signal_ext_store(struct device *dev,
454                                         struct device_attribute *attr,
455                                         const char *buf, size_t len)
456 {
457         const struct counter_device_attr *const devattr = to_counter_attr(attr);
458         const struct counter_signal_ext_unit *const comp = devattr->component;
459         const struct counter_signal_ext *const ext = comp->ext;
460
461         return ext->write(dev_get_drvdata(dev), comp->signal, ext->priv, buf,
462                 len);
463 }
464
465 static void counter_device_attr_list_free(struct list_head *attr_list)
466 {
467         struct counter_device_attr *p, *n;
468
469         list_for_each_entry_safe(p, n, attr_list, l) {
470                 /* free attribute name and associated component memory */
471                 kfree(p->dev_attr.attr.name);
472                 kfree(p->component);
473                 list_del(&p->l);
474                 kfree(p);
475         }
476 }
477
478 static int counter_signal_ext_register(
479         struct counter_device_attr_group *const group,
480         struct counter_signal *const signal)
481 {
482         const size_t num_ext = signal->num_ext;
483         size_t i;
484         const struct counter_signal_ext *ext;
485         struct counter_signal_ext_unit *signal_ext_comp;
486         struct counter_attr_parm parm;
487         int err;
488
489         /* Create an attribute for each extension */
490         for (i = 0 ; i < num_ext; i++) {
491                 ext = signal->ext + i;
492
493                 /* Allocate signal_ext attribute component */
494                 signal_ext_comp = kmalloc(sizeof(*signal_ext_comp), GFP_KERNEL);
495                 if (!signal_ext_comp) {
496                         err = -ENOMEM;
497                         goto err_free_attr_list;
498                 }
499                 signal_ext_comp->signal = signal;
500                 signal_ext_comp->ext = ext;
501
502                 /* Allocate a Counter device attribute */
503                 parm.group = group;
504                 parm.prefix = "";
505                 parm.name = ext->name;
506                 parm.show = (ext->read) ? counter_signal_ext_show : NULL;
507                 parm.store = (ext->write) ? counter_signal_ext_store : NULL;
508                 parm.component = signal_ext_comp;
509                 err = counter_attribute_create(&parm);
510                 if (err) {
511                         kfree(signal_ext_comp);
512                         goto err_free_attr_list;
513                 }
514         }
515
516         return 0;
517
518 err_free_attr_list:
519         counter_device_attr_list_free(&group->attr_list);
520         return err;
521 }
522
523 static int counter_signal_attributes_create(
524         struct counter_device_attr_group *const group,
525         const struct counter_device *const counter,
526         struct counter_signal *const signal)
527 {
528         struct counter_signal_unit *signal_comp;
529         struct counter_attr_parm parm;
530         int err;
531
532         /* Allocate Signal attribute component */
533         signal_comp = kmalloc(sizeof(*signal_comp), GFP_KERNEL);
534         if (!signal_comp)
535                 return -ENOMEM;
536         signal_comp->signal = signal;
537
538         /* Create main Signal attribute */
539         parm.group = group;
540         parm.prefix = "";
541         parm.name = "signal";
542         parm.show = (counter->ops->signal_read) ? counter_signal_show : NULL;
543         parm.store = NULL;
544         parm.component = signal_comp;
545         err = counter_attribute_create(&parm);
546         if (err) {
547                 kfree(signal_comp);
548                 return err;
549         }
550
551         /* Create Signal name attribute */
552         err = counter_name_attribute_create(group, signal->name);
553         if (err)
554                 goto err_free_attr_list;
555
556         /* Register Signal extension attributes */
557         err = counter_signal_ext_register(group, signal);
558         if (err)
559                 goto err_free_attr_list;
560
561         return 0;
562
563 err_free_attr_list:
564         counter_device_attr_list_free(&group->attr_list);
565         return err;
566 }
567
568 static int counter_signals_register(
569         struct counter_device_attr_group *const groups_list,
570         const struct counter_device *const counter)
571 {
572         const size_t num_signals = counter->num_signals;
573         size_t i;
574         struct counter_signal *signal;
575         const char *name;
576         int err;
577
578         /* Register each Signal */
579         for (i = 0; i < num_signals; i++) {
580                 signal = counter->signals + i;
581
582                 /* Generate Signal attribute directory name */
583                 name = kasprintf(GFP_KERNEL, "signal%d", signal->id);
584                 if (!name) {
585                         err = -ENOMEM;
586                         goto err_free_attr_groups;
587                 }
588                 groups_list[i].attr_group.name = name;
589
590                 /* Create all attributes associated with Signal */
591                 err = counter_signal_attributes_create(groups_list + i, counter,
592                                                        signal);
593                 if (err)
594                         goto err_free_attr_groups;
595         }
596
597         return 0;
598
599 err_free_attr_groups:
600         do {
601                 kfree(groups_list[i].attr_group.name);
602                 counter_device_attr_list_free(&groups_list[i].attr_list);
603         } while (i--);
604         return err;
605 }
606
607 static const char *const counter_synapse_action_str[] = {
608         [COUNTER_SYNAPSE_ACTION_NONE] = "none",
609         [COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge",
610         [COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge",
611         [COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges"
612 };
613
614 struct counter_action_unit {
615         struct counter_synapse *synapse;
616         struct counter_count *count;
617 };
618
619 static ssize_t counter_action_show(struct device *dev,
620                                    struct device_attribute *attr, char *buf)
621 {
622         const struct counter_device_attr *const devattr = to_counter_attr(attr);
623         int err;
624         struct counter_device *const counter = dev_get_drvdata(dev);
625         const struct counter_action_unit *const component = devattr->component;
626         struct counter_count *const count = component->count;
627         struct counter_synapse *const synapse = component->synapse;
628         size_t action_index;
629         enum counter_synapse_action action;
630
631         err = counter->ops->action_get(counter, count, synapse, &action_index);
632         if (err)
633                 return err;
634
635         synapse->action = action_index;
636
637         action = synapse->actions_list[action_index];
638         return sprintf(buf, "%s\n", counter_synapse_action_str[action]);
639 }
640
641 static ssize_t counter_action_store(struct device *dev,
642                                     struct device_attribute *attr,
643                                     const char *buf, size_t len)
644 {
645         const struct counter_device_attr *const devattr = to_counter_attr(attr);
646         const struct counter_action_unit *const component = devattr->component;
647         struct counter_synapse *const synapse = component->synapse;
648         size_t action_index;
649         const size_t num_actions = synapse->num_actions;
650         enum counter_synapse_action action;
651         int err;
652         struct counter_device *const counter = dev_get_drvdata(dev);
653         struct counter_count *const count = component->count;
654
655         /* Find requested action mode */
656         for (action_index = 0; action_index < num_actions; action_index++) {
657                 action = synapse->actions_list[action_index];
658                 if (sysfs_streq(buf, counter_synapse_action_str[action]))
659                         break;
660         }
661         /* If requested action mode not found */
662         if (action_index >= num_actions)
663                 return -EINVAL;
664
665         err = counter->ops->action_set(counter, count, synapse, action_index);
666         if (err)
667                 return err;
668
669         synapse->action = action_index;
670
671         return len;
672 }
673
674 struct counter_action_avail_unit {
675         const enum counter_synapse_action *actions_list;
676         size_t num_actions;
677 };
678
679 static ssize_t counter_synapse_action_available_show(struct device *dev,
680         struct device_attribute *attr, char *buf)
681 {
682         const struct counter_device_attr *const devattr = to_counter_attr(attr);
683         const struct counter_action_avail_unit *const component = devattr->component;
684         size_t i;
685         enum counter_synapse_action action;
686         ssize_t len = 0;
687
688         for (i = 0; i < component->num_actions; i++) {
689                 action = component->actions_list[i];
690                 len += sprintf(buf + len, "%s\n",
691                                counter_synapse_action_str[action]);
692         }
693
694         return len;
695 }
696
697 static int counter_synapses_register(
698         struct counter_device_attr_group *const group,
699         const struct counter_device *const counter,
700         struct counter_count *const count, const char *const count_attr_name)
701 {
702         size_t i;
703         struct counter_synapse *synapse;
704         const char *prefix;
705         struct counter_action_unit *action_comp;
706         struct counter_attr_parm parm;
707         int err;
708         struct counter_action_avail_unit *avail_comp;
709
710         /* Register each Synapse */
711         for (i = 0; i < count->num_synapses; i++) {
712                 synapse = count->synapses + i;
713
714                 /* Generate attribute prefix */
715                 prefix = kasprintf(GFP_KERNEL, "signal%d_",
716                                    synapse->signal->id);
717                 if (!prefix) {
718                         err = -ENOMEM;
719                         goto err_free_attr_list;
720                 }
721
722                 /* Allocate action attribute component */
723                 action_comp = kmalloc(sizeof(*action_comp), GFP_KERNEL);
724                 if (!action_comp) {
725                         err = -ENOMEM;
726                         goto err_free_prefix;
727                 }
728                 action_comp->synapse = synapse;
729                 action_comp->count = count;
730
731                 /* Create action attribute */
732                 parm.group = group;
733                 parm.prefix = prefix;
734                 parm.name = "action";
735                 parm.show = (counter->ops->action_get) ? counter_action_show : NULL;
736                 parm.store = (counter->ops->action_set) ? counter_action_store : NULL;
737                 parm.component = action_comp;
738                 err = counter_attribute_create(&parm);
739                 if (err) {
740                         kfree(action_comp);
741                         goto err_free_prefix;
742                 }
743
744                 /* Allocate action available attribute component */
745                 avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
746                 if (!avail_comp) {
747                         err = -ENOMEM;
748                         goto err_free_prefix;
749                 }
750                 avail_comp->actions_list = synapse->actions_list;
751                 avail_comp->num_actions = synapse->num_actions;
752
753                 /* Create action_available attribute */
754                 parm.group = group;
755                 parm.prefix = prefix;
756                 parm.name = "action_available";
757                 parm.show = counter_synapse_action_available_show;
758                 parm.store = NULL;
759                 parm.component = avail_comp;
760                 err = counter_attribute_create(&parm);
761                 if (err) {
762                         kfree(avail_comp);
763                         goto err_free_prefix;
764                 }
765
766                 kfree(prefix);
767         }
768
769         return 0;
770
771 err_free_prefix:
772         kfree(prefix);
773 err_free_attr_list:
774         counter_device_attr_list_free(&group->attr_list);
775         return err;
776 }
777
778 struct counter_count_unit {
779         struct counter_count *count;
780 };
781
782 static ssize_t counter_count_show(struct device *dev,
783                                   struct device_attribute *attr,
784                                   char *buf)
785 {
786         struct counter_device *const counter = dev_get_drvdata(dev);
787         const struct counter_device_attr *const devattr = to_counter_attr(attr);
788         const struct counter_count_unit *const component = devattr->component;
789         struct counter_count *const count = component->count;
790         int err;
791         struct counter_count_read_value val = { .buf = buf };
792
793         err = counter->ops->count_read(counter, count, &val);
794         if (err)
795                 return err;
796
797         return val.len;
798 }
799
800 static ssize_t counter_count_store(struct device *dev,
801                                    struct device_attribute *attr,
802                                    const char *buf, size_t len)
803 {
804         struct counter_device *const counter = dev_get_drvdata(dev);
805         const struct counter_device_attr *const devattr = to_counter_attr(attr);
806         const struct counter_count_unit *const component = devattr->component;
807         struct counter_count *const count = component->count;
808         int err;
809         struct counter_count_write_value val = { .buf = buf };
810
811         err = counter->ops->count_write(counter, count, &val);
812         if (err)
813                 return err;
814
815         return len;
816 }
817
818 static const char *const counter_count_function_str[] = {
819         [COUNTER_COUNT_FUNCTION_INCREASE] = "increase",
820         [COUNTER_COUNT_FUNCTION_DECREASE] = "decrease",
821         [COUNTER_COUNT_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
822         [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
823         [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
824         [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
825         [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
826         [COUNTER_COUNT_FUNCTION_QUADRATURE_X4] = "quadrature x4"
827 };
828
829 static ssize_t counter_function_show(struct device *dev,
830                                      struct device_attribute *attr, char *buf)
831 {
832         int err;
833         struct counter_device *const counter = dev_get_drvdata(dev);
834         const struct counter_device_attr *const devattr = to_counter_attr(attr);
835         const struct counter_count_unit *const component = devattr->component;
836         struct counter_count *const count = component->count;
837         size_t func_index;
838         enum counter_count_function function;
839
840         err = counter->ops->function_get(counter, count, &func_index);
841         if (err)
842                 return err;
843
844         count->function = func_index;
845
846         function = count->functions_list[func_index];
847         return sprintf(buf, "%s\n", counter_count_function_str[function]);
848 }
849
850 static ssize_t counter_function_store(struct device *dev,
851                                       struct device_attribute *attr,
852                                       const char *buf, size_t len)
853 {
854         const struct counter_device_attr *const devattr = to_counter_attr(attr);
855         const struct counter_count_unit *const component = devattr->component;
856         struct counter_count *const count = component->count;
857         const size_t num_functions = count->num_functions;
858         size_t func_index;
859         enum counter_count_function function;
860         int err;
861         struct counter_device *const counter = dev_get_drvdata(dev);
862
863         /* Find requested Count function mode */
864         for (func_index = 0; func_index < num_functions; func_index++) {
865                 function = count->functions_list[func_index];
866                 if (sysfs_streq(buf, counter_count_function_str[function]))
867                         break;
868         }
869         /* Return error if requested Count function mode not found */
870         if (func_index >= num_functions)
871                 return -EINVAL;
872
873         err = counter->ops->function_set(counter, count, func_index);
874         if (err)
875                 return err;
876
877         count->function = func_index;
878
879         return len;
880 }
881
882 struct counter_count_ext_unit {
883         struct counter_count *count;
884         const struct counter_count_ext *ext;
885 };
886
887 static ssize_t counter_count_ext_show(struct device *dev,
888                                       struct device_attribute *attr, char *buf)
889 {
890         const struct counter_device_attr *const devattr = to_counter_attr(attr);
891         const struct counter_count_ext_unit *const comp = devattr->component;
892         const struct counter_count_ext *const ext = comp->ext;
893
894         return ext->read(dev_get_drvdata(dev), comp->count, ext->priv, buf);
895 }
896
897 static ssize_t counter_count_ext_store(struct device *dev,
898                                        struct device_attribute *attr,
899                                        const char *buf, size_t len)
900 {
901         const struct counter_device_attr *const devattr = to_counter_attr(attr);
902         const struct counter_count_ext_unit *const comp = devattr->component;
903         const struct counter_count_ext *const ext = comp->ext;
904
905         return ext->write(dev_get_drvdata(dev), comp->count, ext->priv, buf,
906                 len);
907 }
908
909 static int counter_count_ext_register(
910         struct counter_device_attr_group *const group,
911         struct counter_count *const count)
912 {
913         size_t i;
914         const struct counter_count_ext *ext;
915         struct counter_count_ext_unit *count_ext_comp;
916         struct counter_attr_parm parm;
917         int err;
918
919         /* Create an attribute for each extension */
920         for (i = 0 ; i < count->num_ext; i++) {
921                 ext = count->ext + i;
922
923                 /* Allocate count_ext attribute component */
924                 count_ext_comp = kmalloc(sizeof(*count_ext_comp), GFP_KERNEL);
925                 if (!count_ext_comp) {
926                         err = -ENOMEM;
927                         goto err_free_attr_list;
928                 }
929                 count_ext_comp->count = count;
930                 count_ext_comp->ext = ext;
931
932                 /* Allocate count_ext attribute */
933                 parm.group = group;
934                 parm.prefix = "";
935                 parm.name = ext->name;
936                 parm.show = (ext->read) ? counter_count_ext_show : NULL;
937                 parm.store = (ext->write) ? counter_count_ext_store : NULL;
938                 parm.component = count_ext_comp;
939                 err = counter_attribute_create(&parm);
940                 if (err) {
941                         kfree(count_ext_comp);
942                         goto err_free_attr_list;
943                 }
944         }
945
946         return 0;
947
948 err_free_attr_list:
949         counter_device_attr_list_free(&group->attr_list);
950         return err;
951 }
952
953 struct counter_func_avail_unit {
954         const enum counter_count_function *functions_list;
955         size_t num_functions;
956 };
957
958 static ssize_t counter_count_function_available_show(struct device *dev,
959         struct device_attribute *attr, char *buf)
960 {
961         const struct counter_device_attr *const devattr = to_counter_attr(attr);
962         const struct counter_func_avail_unit *const component = devattr->component;
963         const enum counter_count_function *const func_list = component->functions_list;
964         const size_t num_functions = component->num_functions;
965         size_t i;
966         enum counter_count_function function;
967         ssize_t len = 0;
968
969         for (i = 0; i < num_functions; i++) {
970                 function = func_list[i];
971                 len += sprintf(buf + len, "%s\n",
972                                counter_count_function_str[function]);
973         }
974
975         return len;
976 }
977
978 static int counter_count_attributes_create(
979         struct counter_device_attr_group *const group,
980         const struct counter_device *const counter,
981         struct counter_count *const count)
982 {
983         struct counter_count_unit *count_comp;
984         struct counter_attr_parm parm;
985         int err;
986         struct counter_count_unit *func_comp;
987         struct counter_func_avail_unit *avail_comp;
988
989         /* Allocate count attribute component */
990         count_comp = kmalloc(sizeof(*count_comp), GFP_KERNEL);
991         if (!count_comp)
992                 return -ENOMEM;
993         count_comp->count = count;
994
995         /* Create main Count attribute */
996         parm.group = group;
997         parm.prefix = "";
998         parm.name = "count";
999         parm.show = (counter->ops->count_read) ? counter_count_show : NULL;
1000         parm.store = (counter->ops->count_write) ? counter_count_store : NULL;
1001         parm.component = count_comp;
1002         err = counter_attribute_create(&parm);
1003         if (err) {
1004                 kfree(count_comp);
1005                 return err;
1006         }
1007
1008         /* Allocate function attribute component */
1009         func_comp = kmalloc(sizeof(*func_comp), GFP_KERNEL);
1010         if (!func_comp) {
1011                 err = -ENOMEM;
1012                 goto err_free_attr_list;
1013         }
1014         func_comp->count = count;
1015
1016         /* Create Count function attribute */
1017         parm.group = group;
1018         parm.prefix = "";
1019         parm.name = "function";
1020         parm.show = (counter->ops->function_get) ? counter_function_show : NULL;
1021         parm.store = (counter->ops->function_set) ? counter_function_store : NULL;
1022         parm.component = func_comp;
1023         err = counter_attribute_create(&parm);
1024         if (err) {
1025                 kfree(func_comp);
1026                 goto err_free_attr_list;
1027         }
1028
1029         /* Allocate function available attribute component */
1030         avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
1031         if (!avail_comp) {
1032                 err = -ENOMEM;
1033                 goto err_free_attr_list;
1034         }
1035         avail_comp->functions_list = count->functions_list;
1036         avail_comp->num_functions = count->num_functions;
1037
1038         /* Create Count function_available attribute */
1039         parm.group = group;
1040         parm.prefix = "";
1041         parm.name = "function_available";
1042         parm.show = counter_count_function_available_show;
1043         parm.store = NULL;
1044         parm.component = avail_comp;
1045         err = counter_attribute_create(&parm);
1046         if (err) {
1047                 kfree(avail_comp);
1048                 goto err_free_attr_list;
1049         }
1050
1051         /* Create Count name attribute */
1052         err = counter_name_attribute_create(group, count->name);
1053         if (err)
1054                 goto err_free_attr_list;
1055
1056         /* Register Count extension attributes */
1057         err = counter_count_ext_register(group, count);
1058         if (err)
1059                 goto err_free_attr_list;
1060
1061         return 0;
1062
1063 err_free_attr_list:
1064         counter_device_attr_list_free(&group->attr_list);
1065         return err;
1066 }
1067
1068 static int counter_counts_register(
1069         struct counter_device_attr_group *const groups_list,
1070         const struct counter_device *const counter)
1071 {
1072         size_t i;
1073         struct counter_count *count;
1074         const char *name;
1075         int err;
1076
1077         /* Register each Count */
1078         for (i = 0; i < counter->num_counts; i++) {
1079                 count = counter->counts + i;
1080
1081                 /* Generate Count attribute directory name */
1082                 name = kasprintf(GFP_KERNEL, "count%d", count->id);
1083                 if (!name) {
1084                         err = -ENOMEM;
1085                         goto err_free_attr_groups;
1086                 }
1087                 groups_list[i].attr_group.name = name;
1088
1089                 /* Register the Synapses associated with each Count */
1090                 err = counter_synapses_register(groups_list + i, counter, count,
1091                                                 name);
1092                 if (err)
1093                         goto err_free_attr_groups;
1094
1095                 /* Create all attributes associated with Count */
1096                 err = counter_count_attributes_create(groups_list + i, counter,
1097                                                       count);
1098                 if (err)
1099                         goto err_free_attr_groups;
1100         }
1101
1102         return 0;
1103
1104 err_free_attr_groups:
1105         do {
1106                 kfree(groups_list[i].attr_group.name);
1107                 counter_device_attr_list_free(&groups_list[i].attr_list);
1108         } while (i--);
1109         return err;
1110 }
1111
1112 struct counter_size_unit {
1113         size_t size;
1114 };
1115
1116 static ssize_t counter_device_attr_size_show(struct device *dev,
1117                                              struct device_attribute *attr,
1118                                              char *buf)
1119 {
1120         const struct counter_size_unit *const comp = to_counter_attr(attr)->component;
1121
1122         return sprintf(buf, "%zu\n", comp->size);
1123 }
1124
1125 static int counter_size_attribute_create(
1126         struct counter_device_attr_group *const group,
1127         const size_t size, const char *const name)
1128 {
1129         struct counter_size_unit *size_comp;
1130         struct counter_attr_parm parm;
1131         int err;
1132
1133         /* Allocate size attribute component */
1134         size_comp = kmalloc(sizeof(*size_comp), GFP_KERNEL);
1135         if (!size_comp)
1136                 return -ENOMEM;
1137         size_comp->size = size;
1138
1139         parm.group = group;
1140         parm.prefix = "";
1141         parm.name = name;
1142         parm.show = counter_device_attr_size_show;
1143         parm.store = NULL;
1144         parm.component = size_comp;
1145         err = counter_attribute_create(&parm);
1146         if (err)
1147                 goto err_free_size_comp;
1148
1149         return 0;
1150
1151 err_free_size_comp:
1152         kfree(size_comp);
1153         return err;
1154 }
1155
1156 struct counter_ext_unit {
1157         const struct counter_device_ext *ext;
1158 };
1159
1160 static ssize_t counter_device_ext_show(struct device *dev,
1161                                        struct device_attribute *attr, char *buf)
1162 {
1163         const struct counter_device_attr *const devattr = to_counter_attr(attr);
1164         const struct counter_ext_unit *const component = devattr->component;
1165         const struct counter_device_ext *const ext = component->ext;
1166
1167         return ext->read(dev_get_drvdata(dev), ext->priv, buf);
1168 }
1169
1170 static ssize_t counter_device_ext_store(struct device *dev,
1171                                         struct device_attribute *attr,
1172                                         const char *buf, size_t len)
1173 {
1174         const struct counter_device_attr *const devattr = to_counter_attr(attr);
1175         const struct counter_ext_unit *const component = devattr->component;
1176         const struct counter_device_ext *const ext = component->ext;
1177
1178         return ext->write(dev_get_drvdata(dev), ext->priv, buf, len);
1179 }
1180
1181 static int counter_device_ext_register(
1182         struct counter_device_attr_group *const group,
1183         struct counter_device *const counter)
1184 {
1185         size_t i;
1186         struct counter_ext_unit *ext_comp;
1187         struct counter_attr_parm parm;
1188         int err;
1189
1190         /* Create an attribute for each extension */
1191         for (i = 0 ; i < counter->num_ext; i++) {
1192                 /* Allocate extension attribute component */
1193                 ext_comp = kmalloc(sizeof(*ext_comp), GFP_KERNEL);
1194                 if (!ext_comp) {
1195                         err = -ENOMEM;
1196                         goto err_free_attr_list;
1197                 }
1198
1199                 ext_comp->ext = counter->ext + i;
1200
1201                 /* Allocate extension attribute */
1202                 parm.group = group;
1203                 parm.prefix = "";
1204                 parm.name = counter->ext[i].name;
1205                 parm.show = (counter->ext[i].read) ? counter_device_ext_show : NULL;
1206                 parm.store = (counter->ext[i].write) ? counter_device_ext_store : NULL;
1207                 parm.component = ext_comp;
1208                 err = counter_attribute_create(&parm);
1209                 if (err) {
1210                         kfree(ext_comp);
1211                         goto err_free_attr_list;
1212                 }
1213         }
1214
1215         return 0;
1216
1217 err_free_attr_list:
1218         counter_device_attr_list_free(&group->attr_list);
1219         return err;
1220 }
1221
1222 static int counter_global_attr_register(
1223         struct counter_device_attr_group *const group,
1224         struct counter_device *const counter)
1225 {
1226         int err;
1227
1228         /* Create name attribute */
1229         err = counter_name_attribute_create(group, counter->name);
1230         if (err)
1231                 return err;
1232
1233         /* Create num_counts attribute */
1234         err = counter_size_attribute_create(group, counter->num_counts,
1235                                             "num_counts");
1236         if (err)
1237                 goto err_free_attr_list;
1238
1239         /* Create num_signals attribute */
1240         err = counter_size_attribute_create(group, counter->num_signals,
1241                                             "num_signals");
1242         if (err)
1243                 goto err_free_attr_list;
1244
1245         /* Register Counter device extension attributes */
1246         err = counter_device_ext_register(group, counter);
1247         if (err)
1248                 goto err_free_attr_list;
1249
1250         return 0;
1251
1252 err_free_attr_list:
1253         counter_device_attr_list_free(&group->attr_list);
1254         return err;
1255 }
1256
1257 static void counter_device_groups_list_free(
1258         struct counter_device_attr_group *const groups_list,
1259         const size_t num_groups)
1260 {
1261         struct counter_device_attr_group *group;
1262         size_t i;
1263
1264         /* loop through all attribute groups (signals, counts, global, etc.) */
1265         for (i = 0; i < num_groups; i++) {
1266                 group = groups_list + i;
1267
1268                 /* free all attribute group and associated attributes memory */
1269                 kfree(group->attr_group.name);
1270                 kfree(group->attr_group.attrs);
1271                 counter_device_attr_list_free(&group->attr_list);
1272         }
1273
1274         kfree(groups_list);
1275 }
1276
1277 static int counter_device_groups_list_prepare(
1278         struct counter_device *const counter)
1279 {
1280         const size_t total_num_groups =
1281                 counter->num_signals + counter->num_counts + 1;
1282         struct counter_device_attr_group *groups_list;
1283         size_t i;
1284         int err;
1285         size_t num_groups = 0;
1286
1287         /* Allocate space for attribute groups (signals, counts, and ext) */
1288         groups_list = kcalloc(total_num_groups, sizeof(*groups_list),
1289                               GFP_KERNEL);
1290         if (!groups_list)
1291                 return -ENOMEM;
1292
1293         /* Initialize attribute lists */
1294         for (i = 0; i < total_num_groups; i++)
1295                 INIT_LIST_HEAD(&groups_list[i].attr_list);
1296
1297         /* Register Signals */
1298         err = counter_signals_register(groups_list, counter);
1299         if (err)
1300                 goto err_free_groups_list;
1301         num_groups += counter->num_signals;
1302
1303         /* Register Counts and respective Synapses */
1304         err = counter_counts_register(groups_list + num_groups, counter);
1305         if (err)
1306                 goto err_free_groups_list;
1307         num_groups += counter->num_counts;
1308
1309         /* Register Counter global attributes */
1310         err = counter_global_attr_register(groups_list + num_groups, counter);
1311         if (err)
1312                 goto err_free_groups_list;
1313         num_groups++;
1314
1315         /* Store groups_list in device_state */
1316         counter->device_state->groups_list = groups_list;
1317         counter->device_state->num_groups = num_groups;
1318
1319         return 0;
1320
1321 err_free_groups_list:
1322         counter_device_groups_list_free(groups_list, num_groups);
1323         return err;
1324 }
1325
1326 static int counter_device_groups_prepare(
1327         struct counter_device_state *const device_state)
1328 {
1329         size_t i, j;
1330         struct counter_device_attr_group *group;
1331         int err;
1332         struct counter_device_attr *p;
1333
1334         /* Allocate attribute groups for association with device */
1335         device_state->groups = kcalloc(device_state->num_groups + 1,
1336                                        sizeof(*device_state->groups),
1337                                        GFP_KERNEL);
1338         if (!device_state->groups)
1339                 return -ENOMEM;
1340
1341         /* Prepare each group of attributes for association */
1342         for (i = 0; i < device_state->num_groups; i++) {
1343                 group = device_state->groups_list + i;
1344
1345                 /* Allocate space for attribute pointers in attribute group */
1346                 group->attr_group.attrs = kcalloc(group->num_attr + 1,
1347                         sizeof(*group->attr_group.attrs), GFP_KERNEL);
1348                 if (!group->attr_group.attrs) {
1349                         err = -ENOMEM;
1350                         goto err_free_groups;
1351                 }
1352
1353                 /* Add attribute pointers to attribute group */
1354                 j = 0;
1355                 list_for_each_entry(p, &group->attr_list, l)
1356                         group->attr_group.attrs[j++] = &p->dev_attr.attr;
1357
1358                 /* Group attributes in attribute group */
1359                 device_state->groups[i] = &group->attr_group;
1360         }
1361         /* Associate attributes with device */
1362         device_state->dev.groups = device_state->groups;
1363
1364         return 0;
1365
1366 err_free_groups:
1367         do {
1368                 group = device_state->groups_list + i;
1369                 kfree(group->attr_group.attrs);
1370                 group->attr_group.attrs = NULL;
1371         } while (i--);
1372         kfree(device_state->groups);
1373         return err;
1374 }
1375
1376 /* Provides a unique ID for each counter device */
1377 static DEFINE_IDA(counter_ida);
1378
1379 static void counter_device_release(struct device *dev)
1380 {
1381         struct counter_device *const counter = dev_get_drvdata(dev);
1382         struct counter_device_state *const device_state = counter->device_state;
1383
1384         kfree(device_state->groups);
1385         counter_device_groups_list_free(device_state->groups_list,
1386                                         device_state->num_groups);
1387         ida_simple_remove(&counter_ida, device_state->id);
1388         kfree(device_state);
1389 }
1390
1391 static struct device_type counter_device_type = {
1392         .name = "counter_device",
1393         .release = counter_device_release
1394 };
1395
1396 static struct bus_type counter_bus_type = {
1397         .name = "counter"
1398 };
1399
1400 /**
1401  * counter_register - register Counter to the system
1402  * @counter:    pointer to Counter to register
1403  *
1404  * This function registers a Counter to the system. A sysfs "counter" directory
1405  * will be created and populated with sysfs attributes correlating with the
1406  * Counter Signals, Synapses, and Counts respectively.
1407  */
1408 int counter_register(struct counter_device *const counter)
1409 {
1410         struct counter_device_state *device_state;
1411         int err;
1412
1413         /* Allocate internal state container for Counter device */
1414         device_state = kzalloc(sizeof(*device_state), GFP_KERNEL);
1415         if (!device_state)
1416                 return -ENOMEM;
1417         counter->device_state = device_state;
1418
1419         /* Acquire unique ID */
1420         device_state->id = ida_simple_get(&counter_ida, 0, 0, GFP_KERNEL);
1421         if (device_state->id < 0) {
1422                 err = device_state->id;
1423                 goto err_free_device_state;
1424         }
1425
1426         /* Configure device structure for Counter */
1427         device_state->dev.type = &counter_device_type;
1428         device_state->dev.bus = &counter_bus_type;
1429         if (counter->parent) {
1430                 device_state->dev.parent = counter->parent;
1431                 device_state->dev.of_node = counter->parent->of_node;
1432         }
1433         dev_set_name(&device_state->dev, "counter%d", device_state->id);
1434         device_initialize(&device_state->dev);
1435         dev_set_drvdata(&device_state->dev, counter);
1436
1437         /* Prepare device attributes */
1438         err = counter_device_groups_list_prepare(counter);
1439         if (err)
1440                 goto err_free_id;
1441
1442         /* Organize device attributes to groups and match to device */
1443         err = counter_device_groups_prepare(device_state);
1444         if (err)
1445                 goto err_free_groups_list;
1446
1447         /* Add device to system */
1448         err = device_add(&device_state->dev);
1449         if (err)
1450                 goto err_free_groups;
1451
1452         return 0;
1453
1454 err_free_groups:
1455         kfree(device_state->groups);
1456 err_free_groups_list:
1457         counter_device_groups_list_free(device_state->groups_list,
1458                                         device_state->num_groups);
1459 err_free_id:
1460         ida_simple_remove(&counter_ida, device_state->id);
1461 err_free_device_state:
1462         kfree(device_state);
1463         return err;
1464 }
1465 EXPORT_SYMBOL_GPL(counter_register);
1466
1467 /**
1468  * counter_unregister - unregister Counter from the system
1469  * @counter:    pointer to Counter to unregister
1470  *
1471  * The Counter is unregistered from the system; all allocated memory is freed.
1472  */
1473 void counter_unregister(struct counter_device *const counter)
1474 {
1475         if (counter)
1476                 device_del(&counter->device_state->dev);
1477 }
1478 EXPORT_SYMBOL_GPL(counter_unregister);
1479
1480 static void devm_counter_unreg(struct device *dev, void *res)
1481 {
1482         counter_unregister(*(struct counter_device **)res);
1483 }
1484
1485 /**
1486  * devm_counter_register - Resource-managed counter_register
1487  * @dev:        device to allocate counter_device for
1488  * @counter:    pointer to Counter to register
1489  *
1490  * Managed counter_register. The Counter registered with this function is
1491  * automatically unregistered on driver detach. This function calls
1492  * counter_register internally. Refer to that function for more information.
1493  *
1494  * If an Counter registered with this function needs to be unregistered
1495  * separately, devm_counter_unregister must be used.
1496  *
1497  * RETURNS:
1498  * 0 on success, negative error number on failure.
1499  */
1500 int devm_counter_register(struct device *dev,
1501                           struct counter_device *const counter)
1502 {
1503         struct counter_device **ptr;
1504         int ret;
1505
1506         ptr = devres_alloc(devm_counter_unreg, sizeof(*ptr), GFP_KERNEL);
1507         if (!ptr)
1508                 return -ENOMEM;
1509
1510         ret = counter_register(counter);
1511         if (!ret) {
1512                 *ptr = counter;
1513                 devres_add(dev, ptr);
1514         } else {
1515                 devres_free(ptr);
1516         }
1517
1518         return ret;
1519 }
1520 EXPORT_SYMBOL_GPL(devm_counter_register);
1521
1522 static int devm_counter_match(struct device *dev, void *res, void *data)
1523 {
1524         struct counter_device **r = res;
1525
1526         if (!r || !*r) {
1527                 WARN_ON(!r || !*r);
1528                 return 0;
1529         }
1530
1531         return *r == data;
1532 }
1533
1534 /**
1535  * devm_counter_unregister - Resource-managed counter_unregister
1536  * @dev:        device this counter_device belongs to
1537  * @counter:    pointer to Counter associated with the device
1538  *
1539  * Unregister Counter registered with devm_counter_register.
1540  */
1541 void devm_counter_unregister(struct device *dev,
1542                              struct counter_device *const counter)
1543 {
1544         int rc;
1545
1546         rc = devres_release(dev, devm_counter_unreg, devm_counter_match,
1547                             counter);
1548         WARN_ON(rc);
1549 }
1550 EXPORT_SYMBOL_GPL(devm_counter_unregister);
1551
1552 static int __init counter_init(void)
1553 {
1554         return bus_register(&counter_bus_type);
1555 }
1556
1557 static void __exit counter_exit(void)
1558 {
1559         bus_unregister(&counter_bus_type);
1560 }
1561
1562 subsys_initcall(counter_init);
1563 module_exit(counter_exit);
1564
1565 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1566 MODULE_DESCRIPTION("Generic Counter interface");
1567 MODULE_LICENSE("GPL v2");