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