1 // SPDX-License-Identifier: GPL-2.0
3 * Generic Counter interface
4 * Copyright (C) 2018 William Breathitt Gray
6 #include <linux/counter.h>
7 #include <linux/device.h>
9 #include <linux/export.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>
23 const char *const counter_count_direction_str
[2] = {
24 [COUNTER_COUNT_DIRECTION_FORWARD
] = "forward",
25 [COUNTER_COUNT_DIRECTION_BACKWARD
] = "backward"
27 EXPORT_SYMBOL_GPL(counter_count_direction_str
);
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"
35 EXPORT_SYMBOL_GPL(counter_count_mode_str
);
37 ssize_t
counter_signal_enum_read(struct counter_device
*counter
,
38 struct counter_signal
*signal
, void *priv
,
41 const struct counter_signal_enum_ext
*const e
= priv
;
48 err
= e
->get(counter
, signal
, &index
);
52 if (index
>= e
->num_items
)
55 return sprintf(buf
, "%s\n", e
->items
[index
]);
57 EXPORT_SYMBOL_GPL(counter_signal_enum_read
);
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
)
63 const struct counter_signal_enum_ext
*const e
= priv
;
70 index
= __sysfs_match_string(e
->items
, e
->num_items
, buf
);
74 err
= e
->set(counter
, signal
, index
);
80 EXPORT_SYMBOL_GPL(counter_signal_enum_write
);
82 ssize_t
counter_signal_enum_available_read(struct counter_device
*counter
,
83 struct counter_signal
*signal
,
84 void *priv
, char *buf
)
86 const struct counter_signal_enum_ext
*const e
= priv
;
93 for (i
= 0; i
< e
->num_items
; i
++)
94 len
+= sprintf(buf
+ len
, "%s\n", e
->items
[i
]);
98 EXPORT_SYMBOL_GPL(counter_signal_enum_available_read
);
100 ssize_t
counter_count_enum_read(struct counter_device
*counter
,
101 struct counter_count
*count
, void *priv
,
104 const struct counter_count_enum_ext
*const e
= priv
;
111 err
= e
->get(counter
, count
, &index
);
115 if (index
>= e
->num_items
)
118 return sprintf(buf
, "%s\n", e
->items
[index
]);
120 EXPORT_SYMBOL_GPL(counter_count_enum_read
);
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
)
126 const struct counter_count_enum_ext
*const e
= priv
;
133 index
= __sysfs_match_string(e
->items
, e
->num_items
, buf
);
137 err
= e
->set(counter
, count
, index
);
143 EXPORT_SYMBOL_GPL(counter_count_enum_write
);
145 ssize_t
counter_count_enum_available_read(struct counter_device
*counter
,
146 struct counter_count
*count
,
147 void *priv
, char *buf
)
149 const struct counter_count_enum_ext
*const e
= priv
;
156 for (i
= 0; i
< e
->num_items
; i
++)
157 len
+= sprintf(buf
+ len
, "%s\n", e
->items
[i
]);
161 EXPORT_SYMBOL_GPL(counter_count_enum_available_read
);
163 ssize_t
counter_device_enum_read(struct counter_device
*counter
, void *priv
,
166 const struct counter_device_enum_ext
*const e
= priv
;
173 err
= e
->get(counter
, &index
);
177 if (index
>= e
->num_items
)
180 return sprintf(buf
, "%s\n", e
->items
[index
]);
182 EXPORT_SYMBOL_GPL(counter_device_enum_read
);
184 ssize_t
counter_device_enum_write(struct counter_device
*counter
, void *priv
,
185 const char *buf
, size_t len
)
187 const struct counter_device_enum_ext
*const e
= priv
;
194 index
= __sysfs_match_string(e
->items
, e
->num_items
, buf
);
198 err
= e
->set(counter
, index
);
204 EXPORT_SYMBOL_GPL(counter_device_enum_write
);
206 ssize_t
counter_device_enum_available_read(struct counter_device
*counter
,
207 void *priv
, char *buf
)
209 const struct counter_device_enum_ext
*const e
= priv
;
216 for (i
= 0; i
< e
->num_items
; i
++)
217 len
+= sprintf(buf
+ len
, "%s\n", e
->items
[i
]);
221 EXPORT_SYMBOL_GPL(counter_device_enum_available_read
);
223 struct counter_attr_parm
{
224 struct counter_device_attr_group
*group
;
227 ssize_t (*show
)(struct device
*dev
, struct device_attribute
*attr
,
229 ssize_t (*store
)(struct device
*dev
, struct device_attribute
*attr
,
230 const char *buf
, size_t len
);
234 struct counter_device_attr
{
235 struct device_attribute dev_attr
;
240 static int counter_attribute_create(const struct counter_attr_parm
*const parm
)
242 struct counter_device_attr
*counter_attr
;
243 struct device_attribute
*dev_attr
;
245 struct list_head
*const attr_list
= &parm
->group
->attr_list
;
247 /* Allocate a Counter device attribute */
248 counter_attr
= kzalloc(sizeof(*counter_attr
), GFP_KERNEL
);
251 dev_attr
= &counter_attr
->dev_attr
;
253 sysfs_attr_init(&dev_attr
->attr
);
255 /* Configure device attribute */
256 dev_attr
->attr
.name
= kasprintf(GFP_KERNEL
, "%s%s", parm
->prefix
,
258 if (!dev_attr
->attr
.name
) {
260 goto err_free_counter_attr
;
263 dev_attr
->attr
.mode
|= 0444;
264 dev_attr
->show
= parm
->show
;
267 dev_attr
->attr
.mode
|= 0200;
268 dev_attr
->store
= parm
->store
;
271 /* Store associated Counter component with attribute */
272 counter_attr
->component
= parm
->component
;
274 /* Keep track of the attribute for later cleanup */
275 list_add(&counter_attr
->l
, attr_list
);
276 parm
->group
->num_attr
++;
280 err_free_counter_attr
:
285 #define to_counter_attr(_dev_attr) \
286 container_of(_dev_attr, struct counter_device_attr, dev_attr)
288 struct counter_signal_unit
{
289 struct counter_signal
*signal
;
292 static const char *const counter_signal_value_str
[] = {
293 [COUNTER_SIGNAL_LOW
] = "low",
294 [COUNTER_SIGNAL_HIGH
] = "high"
297 static ssize_t
counter_signal_show(struct device
*dev
,
298 struct device_attribute
*attr
, char *buf
)
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
;
305 enum counter_signal_value val
;
307 err
= counter
->ops
->signal_read(counter
, signal
, &val
);
311 return sprintf(buf
, "%s\n", counter_signal_value_str
[val
]);
314 struct counter_name_unit
{
318 static ssize_t
counter_device_attr_name_show(struct device
*dev
,
319 struct device_attribute
*attr
,
322 const struct counter_name_unit
*const comp
= to_counter_attr(attr
)->component
;
324 return sprintf(buf
, "%s\n", comp
->name
);
327 static int counter_name_attribute_create(
328 struct counter_device_attr_group
*const group
,
329 const char *const name
)
331 struct counter_name_unit
*name_comp
;
332 struct counter_attr_parm parm
;
335 /* Skip if no name */
339 /* Allocate name attribute component */
340 name_comp
= kmalloc(sizeof(*name_comp
), GFP_KERNEL
);
343 name_comp
->name
= name
;
345 /* Allocate Signal name attribute */
349 parm
.show
= counter_device_attr_name_show
;
351 parm
.component
= name_comp
;
352 err
= counter_attribute_create(&parm
);
354 goto err_free_name_comp
;
363 struct counter_signal_ext_unit
{
364 struct counter_signal
*signal
;
365 const struct counter_signal_ext
*ext
;
368 static ssize_t
counter_signal_ext_show(struct device
*dev
,
369 struct device_attribute
*attr
, char *buf
)
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
;
375 return ext
->read(dev_get_drvdata(dev
), comp
->signal
, ext
->priv
, buf
);
378 static ssize_t
counter_signal_ext_store(struct device
*dev
,
379 struct device_attribute
*attr
,
380 const char *buf
, size_t len
)
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
;
386 return ext
->write(dev_get_drvdata(dev
), comp
->signal
, ext
->priv
, buf
,
390 static void counter_device_attr_list_free(struct list_head
*attr_list
)
392 struct counter_device_attr
*p
, *n
;
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
);
403 static int counter_signal_ext_register(
404 struct counter_device_attr_group
*const group
,
405 struct counter_signal
*const signal
)
407 const size_t num_ext
= signal
->num_ext
;
409 const struct counter_signal_ext
*ext
;
410 struct counter_signal_ext_unit
*signal_ext_comp
;
411 struct counter_attr_parm parm
;
414 /* Create an attribute for each extension */
415 for (i
= 0 ; i
< num_ext
; i
++) {
416 ext
= signal
->ext
+ i
;
418 /* Allocate signal_ext attribute component */
419 signal_ext_comp
= kmalloc(sizeof(*signal_ext_comp
), GFP_KERNEL
);
420 if (!signal_ext_comp
) {
422 goto err_free_attr_list
;
424 signal_ext_comp
->signal
= signal
;
425 signal_ext_comp
->ext
= ext
;
427 /* Allocate a Counter device attribute */
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
);
436 kfree(signal_ext_comp
);
437 goto err_free_attr_list
;
444 counter_device_attr_list_free(&group
->attr_list
);
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
)
453 struct counter_signal_unit
*signal_comp
;
454 struct counter_attr_parm parm
;
457 /* Allocate Signal attribute component */
458 signal_comp
= kmalloc(sizeof(*signal_comp
), GFP_KERNEL
);
461 signal_comp
->signal
= signal
;
463 /* Create main Signal attribute */
466 parm
.name
= "signal";
467 parm
.show
= (counter
->ops
->signal_read
) ? counter_signal_show
: NULL
;
469 parm
.component
= signal_comp
;
470 err
= counter_attribute_create(&parm
);
476 /* Create Signal name attribute */
477 err
= counter_name_attribute_create(group
, signal
->name
);
479 goto err_free_attr_list
;
481 /* Register Signal extension attributes */
482 err
= counter_signal_ext_register(group
, signal
);
484 goto err_free_attr_list
;
489 counter_device_attr_list_free(&group
->attr_list
);
493 static int counter_signals_register(
494 struct counter_device_attr_group
*const groups_list
,
495 const struct counter_device
*const counter
)
497 const size_t num_signals
= counter
->num_signals
;
499 struct counter_signal
*signal
;
503 /* Register each Signal */
504 for (i
= 0; i
< num_signals
; i
++) {
505 signal
= counter
->signals
+ i
;
507 /* Generate Signal attribute directory name */
508 name
= kasprintf(GFP_KERNEL
, "signal%d", signal
->id
);
511 goto err_free_attr_groups
;
513 groups_list
[i
].attr_group
.name
= name
;
515 /* Create all attributes associated with Signal */
516 err
= counter_signal_attributes_create(groups_list
+ i
, counter
,
519 goto err_free_attr_groups
;
524 err_free_attr_groups
:
526 kfree(groups_list
[i
].attr_group
.name
);
527 counter_device_attr_list_free(&groups_list
[i
].attr_list
);
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"
539 struct counter_action_unit
{
540 struct counter_synapse
*synapse
;
541 struct counter_count
*count
;
544 static ssize_t
counter_action_show(struct device
*dev
,
545 struct device_attribute
*attr
, char *buf
)
547 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
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
;
554 enum counter_synapse_action action
;
556 err
= counter
->ops
->action_get(counter
, count
, synapse
, &action_index
);
560 synapse
->action
= action_index
;
562 action
= synapse
->actions_list
[action_index
];
563 return sprintf(buf
, "%s\n", counter_synapse_action_str
[action
]);
566 static ssize_t
counter_action_store(struct device
*dev
,
567 struct device_attribute
*attr
,
568 const char *buf
, size_t len
)
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
;
574 const size_t num_actions
= synapse
->num_actions
;
575 enum counter_synapse_action action
;
577 struct counter_device
*const counter
= dev_get_drvdata(dev
);
578 struct counter_count
*const count
= component
->count
;
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
]))
586 /* If requested action mode not found */
587 if (action_index
>= num_actions
)
590 err
= counter
->ops
->action_set(counter
, count
, synapse
, action_index
);
594 synapse
->action
= action_index
;
599 struct counter_action_avail_unit
{
600 const enum counter_synapse_action
*actions_list
;
604 static ssize_t
counter_synapse_action_available_show(struct device
*dev
,
605 struct device_attribute
*attr
, char *buf
)
607 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
608 const struct counter_action_avail_unit
*const component
= devattr
->component
;
610 enum counter_synapse_action action
;
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
]);
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
)
628 struct counter_synapse
*synapse
;
630 struct counter_action_unit
*action_comp
;
631 struct counter_attr_parm parm
;
633 struct counter_action_avail_unit
*avail_comp
;
635 /* Register each Synapse */
636 for (i
= 0; i
< count
->num_synapses
; i
++) {
637 synapse
= count
->synapses
+ i
;
639 /* Generate attribute prefix */
640 prefix
= kasprintf(GFP_KERNEL
, "signal%d_",
641 synapse
->signal
->id
);
644 goto err_free_attr_list
;
647 /* Allocate action attribute component */
648 action_comp
= kmalloc(sizeof(*action_comp
), GFP_KERNEL
);
651 goto err_free_prefix
;
653 action_comp
->synapse
= synapse
;
654 action_comp
->count
= count
;
656 /* Create action attribute */
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
);
666 goto err_free_prefix
;
669 /* Allocate action available attribute component */
670 avail_comp
= kmalloc(sizeof(*avail_comp
), GFP_KERNEL
);
673 goto err_free_prefix
;
675 avail_comp
->actions_list
= synapse
->actions_list
;
676 avail_comp
->num_actions
= synapse
->num_actions
;
678 /* Create action_available attribute */
680 parm
.prefix
= prefix
;
681 parm
.name
= "action_available";
682 parm
.show
= counter_synapse_action_available_show
;
684 parm
.component
= avail_comp
;
685 err
= counter_attribute_create(&parm
);
688 goto err_free_prefix
;
699 counter_device_attr_list_free(&group
->attr_list
);
703 struct counter_count_unit
{
704 struct counter_count
*count
;
707 static ssize_t
counter_count_show(struct device
*dev
,
708 struct device_attribute
*attr
,
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
;
718 err
= counter
->ops
->count_read(counter
, count
, &val
);
722 return sprintf(buf
, "%lu\n", val
);
725 static ssize_t
counter_count_store(struct device
*dev
,
726 struct device_attribute
*attr
,
727 const char *buf
, size_t len
)
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
;
736 err
= kstrtoul(buf
, 0, &val
);
740 err
= counter
->ops
->count_write(counter
, count
, val
);
747 static const char *const counter_count_function_str
[] = {
748 [COUNTER_COUNT_FUNCTION_INCREASE
] = "increase",
749 [COUNTER_COUNT_FUNCTION_DECREASE
] = "decrease",
750 [COUNTER_COUNT_FUNCTION_PULSE_DIRECTION
] = "pulse-direction",
751 [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A
] = "quadrature x1 a",
752 [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B
] = "quadrature x1 b",
753 [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A
] = "quadrature x2 a",
754 [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B
] = "quadrature x2 b",
755 [COUNTER_COUNT_FUNCTION_QUADRATURE_X4
] = "quadrature x4"
758 static ssize_t
counter_function_show(struct device
*dev
,
759 struct device_attribute
*attr
, char *buf
)
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
;
767 enum counter_count_function function
;
769 err
= counter
->ops
->function_get(counter
, count
, &func_index
);
773 count
->function
= func_index
;
775 function
= count
->functions_list
[func_index
];
776 return sprintf(buf
, "%s\n", counter_count_function_str
[function
]);
779 static ssize_t
counter_function_store(struct device
*dev
,
780 struct device_attribute
*attr
,
781 const char *buf
, size_t len
)
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
;
788 enum counter_count_function function
;
790 struct counter_device
*const counter
= dev_get_drvdata(dev
);
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_count_function_str
[function
]))
798 /* Return error if requested Count function mode not found */
799 if (func_index
>= num_functions
)
802 err
= counter
->ops
->function_set(counter
, count
, func_index
);
806 count
->function
= func_index
;
811 struct counter_count_ext_unit
{
812 struct counter_count
*count
;
813 const struct counter_count_ext
*ext
;
816 static ssize_t
counter_count_ext_show(struct device
*dev
,
817 struct device_attribute
*attr
, char *buf
)
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
;
823 return ext
->read(dev_get_drvdata(dev
), comp
->count
, ext
->priv
, buf
);
826 static ssize_t
counter_count_ext_store(struct device
*dev
,
827 struct device_attribute
*attr
,
828 const char *buf
, size_t len
)
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
;
834 return ext
->write(dev_get_drvdata(dev
), comp
->count
, ext
->priv
, buf
,
838 static int counter_count_ext_register(
839 struct counter_device_attr_group
*const group
,
840 struct counter_count
*const count
)
843 const struct counter_count_ext
*ext
;
844 struct counter_count_ext_unit
*count_ext_comp
;
845 struct counter_attr_parm parm
;
848 /* Create an attribute for each extension */
849 for (i
= 0 ; i
< count
->num_ext
; i
++) {
850 ext
= count
->ext
+ i
;
852 /* Allocate count_ext attribute component */
853 count_ext_comp
= kmalloc(sizeof(*count_ext_comp
), GFP_KERNEL
);
854 if (!count_ext_comp
) {
856 goto err_free_attr_list
;
858 count_ext_comp
->count
= count
;
859 count_ext_comp
->ext
= ext
;
861 /* Allocate count_ext attribute */
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
);
870 kfree(count_ext_comp
);
871 goto err_free_attr_list
;
878 counter_device_attr_list_free(&group
->attr_list
);
882 struct counter_func_avail_unit
{
883 const enum counter_count_function
*functions_list
;
884 size_t num_functions
;
887 static ssize_t
counter_count_function_available_show(struct device
*dev
,
888 struct device_attribute
*attr
, char *buf
)
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_count_function
*const func_list
= component
->functions_list
;
893 const size_t num_functions
= component
->num_functions
;
895 enum counter_count_function function
;
898 for (i
= 0; i
< num_functions
; i
++) {
899 function
= func_list
[i
];
900 len
+= sprintf(buf
+ len
, "%s\n",
901 counter_count_function_str
[function
]);
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
)
912 struct counter_count_unit
*count_comp
;
913 struct counter_attr_parm parm
;
915 struct counter_count_unit
*func_comp
;
916 struct counter_func_avail_unit
*avail_comp
;
918 /* Allocate count attribute component */
919 count_comp
= kmalloc(sizeof(*count_comp
), GFP_KERNEL
);
922 count_comp
->count
= count
;
924 /* Create main Count attribute */
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
);
937 /* Allocate function attribute component */
938 func_comp
= kmalloc(sizeof(*func_comp
), GFP_KERNEL
);
941 goto err_free_attr_list
;
943 func_comp
->count
= count
;
945 /* Create Count function attribute */
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
);
955 goto err_free_attr_list
;
958 /* Allocate function available attribute component */
959 avail_comp
= kmalloc(sizeof(*avail_comp
), GFP_KERNEL
);
962 goto err_free_attr_list
;
964 avail_comp
->functions_list
= count
->functions_list
;
965 avail_comp
->num_functions
= count
->num_functions
;
967 /* Create Count function_available attribute */
970 parm
.name
= "function_available";
971 parm
.show
= counter_count_function_available_show
;
973 parm
.component
= avail_comp
;
974 err
= counter_attribute_create(&parm
);
977 goto err_free_attr_list
;
980 /* Create Count name attribute */
981 err
= counter_name_attribute_create(group
, count
->name
);
983 goto err_free_attr_list
;
985 /* Register Count extension attributes */
986 err
= counter_count_ext_register(group
, count
);
988 goto err_free_attr_list
;
993 counter_device_attr_list_free(&group
->attr_list
);
997 static int counter_counts_register(
998 struct counter_device_attr_group
*const groups_list
,
999 const struct counter_device
*const counter
)
1002 struct counter_count
*count
;
1006 /* Register each Count */
1007 for (i
= 0; i
< counter
->num_counts
; i
++) {
1008 count
= counter
->counts
+ i
;
1010 /* Generate Count attribute directory name */
1011 name
= kasprintf(GFP_KERNEL
, "count%d", count
->id
);
1014 goto err_free_attr_groups
;
1016 groups_list
[i
].attr_group
.name
= name
;
1018 /* Register the Synapses associated with each Count */
1019 err
= counter_synapses_register(groups_list
+ i
, counter
, count
,
1022 goto err_free_attr_groups
;
1024 /* Create all attributes associated with Count */
1025 err
= counter_count_attributes_create(groups_list
+ i
, counter
,
1028 goto err_free_attr_groups
;
1033 err_free_attr_groups
:
1035 kfree(groups_list
[i
].attr_group
.name
);
1036 counter_device_attr_list_free(&groups_list
[i
].attr_list
);
1041 struct counter_size_unit
{
1045 static ssize_t
counter_device_attr_size_show(struct device
*dev
,
1046 struct device_attribute
*attr
,
1049 const struct counter_size_unit
*const comp
= to_counter_attr(attr
)->component
;
1051 return sprintf(buf
, "%zu\n", comp
->size
);
1054 static int counter_size_attribute_create(
1055 struct counter_device_attr_group
*const group
,
1056 const size_t size
, const char *const name
)
1058 struct counter_size_unit
*size_comp
;
1059 struct counter_attr_parm parm
;
1062 /* Allocate size attribute component */
1063 size_comp
= kmalloc(sizeof(*size_comp
), GFP_KERNEL
);
1066 size_comp
->size
= size
;
1071 parm
.show
= counter_device_attr_size_show
;
1073 parm
.component
= size_comp
;
1074 err
= counter_attribute_create(&parm
);
1076 goto err_free_size_comp
;
1085 struct counter_ext_unit
{
1086 const struct counter_device_ext
*ext
;
1089 static ssize_t
counter_device_ext_show(struct device
*dev
,
1090 struct device_attribute
*attr
, char *buf
)
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
;
1096 return ext
->read(dev_get_drvdata(dev
), ext
->priv
, buf
);
1099 static ssize_t
counter_device_ext_store(struct device
*dev
,
1100 struct device_attribute
*attr
,
1101 const char *buf
, size_t len
)
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
;
1107 return ext
->write(dev_get_drvdata(dev
), ext
->priv
, buf
, len
);
1110 static int counter_device_ext_register(
1111 struct counter_device_attr_group
*const group
,
1112 struct counter_device
*const counter
)
1115 struct counter_ext_unit
*ext_comp
;
1116 struct counter_attr_parm parm
;
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
);
1125 goto err_free_attr_list
;
1128 ext_comp
->ext
= counter
->ext
+ i
;
1130 /* Allocate extension attribute */
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
);
1140 goto err_free_attr_list
;
1147 counter_device_attr_list_free(&group
->attr_list
);
1151 static int counter_global_attr_register(
1152 struct counter_device_attr_group
*const group
,
1153 struct counter_device
*const counter
)
1157 /* Create name attribute */
1158 err
= counter_name_attribute_create(group
, counter
->name
);
1162 /* Create num_counts attribute */
1163 err
= counter_size_attribute_create(group
, counter
->num_counts
,
1166 goto err_free_attr_list
;
1168 /* Create num_signals attribute */
1169 err
= counter_size_attribute_create(group
, counter
->num_signals
,
1172 goto err_free_attr_list
;
1174 /* Register Counter device extension attributes */
1175 err
= counter_device_ext_register(group
, counter
);
1177 goto err_free_attr_list
;
1182 counter_device_attr_list_free(&group
->attr_list
);
1186 static void counter_device_groups_list_free(
1187 struct counter_device_attr_group
*const groups_list
,
1188 const size_t num_groups
)
1190 struct counter_device_attr_group
*group
;
1193 /* loop through all attribute groups (signals, counts, global, etc.) */
1194 for (i
= 0; i
< num_groups
; i
++) {
1195 group
= groups_list
+ i
;
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
);
1206 static int counter_device_groups_list_prepare(
1207 struct counter_device
*const counter
)
1209 const size_t total_num_groups
=
1210 counter
->num_signals
+ counter
->num_counts
+ 1;
1211 struct counter_device_attr_group
*groups_list
;
1214 size_t num_groups
= 0;
1216 /* Allocate space for attribute groups (signals, counts, and ext) */
1217 groups_list
= kcalloc(total_num_groups
, sizeof(*groups_list
),
1222 /* Initialize attribute lists */
1223 for (i
= 0; i
< total_num_groups
; i
++)
1224 INIT_LIST_HEAD(&groups_list
[i
].attr_list
);
1226 /* Register Signals */
1227 err
= counter_signals_register(groups_list
, counter
);
1229 goto err_free_groups_list
;
1230 num_groups
+= counter
->num_signals
;
1232 /* Register Counts and respective Synapses */
1233 err
= counter_counts_register(groups_list
+ num_groups
, counter
);
1235 goto err_free_groups_list
;
1236 num_groups
+= counter
->num_counts
;
1238 /* Register Counter global attributes */
1239 err
= counter_global_attr_register(groups_list
+ num_groups
, counter
);
1241 goto err_free_groups_list
;
1244 /* Store groups_list in device_state */
1245 counter
->device_state
->groups_list
= groups_list
;
1246 counter
->device_state
->num_groups
= num_groups
;
1250 err_free_groups_list
:
1251 counter_device_groups_list_free(groups_list
, num_groups
);
1255 static int counter_device_groups_prepare(
1256 struct counter_device_state
*const device_state
)
1259 struct counter_device_attr_group
*group
;
1261 struct counter_device_attr
*p
;
1263 /* Allocate attribute groups for association with device */
1264 device_state
->groups
= kcalloc(device_state
->num_groups
+ 1,
1265 sizeof(*device_state
->groups
),
1267 if (!device_state
->groups
)
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
;
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
) {
1279 goto err_free_groups
;
1282 /* Add attribute pointers to attribute group */
1284 list_for_each_entry(p
, &group
->attr_list
, l
)
1285 group
->attr_group
.attrs
[j
++] = &p
->dev_attr
.attr
;
1287 /* Group attributes in attribute group */
1288 device_state
->groups
[i
] = &group
->attr_group
;
1290 /* Associate attributes with device */
1291 device_state
->dev
.groups
= device_state
->groups
;
1297 group
= device_state
->groups_list
+ i
;
1298 kfree(group
->attr_group
.attrs
);
1299 group
->attr_group
.attrs
= NULL
;
1301 kfree(device_state
->groups
);
1305 /* Provides a unique ID for each counter device */
1306 static DEFINE_IDA(counter_ida
);
1308 static void counter_device_release(struct device
*dev
)
1310 struct counter_device
*const counter
= dev_get_drvdata(dev
);
1311 struct counter_device_state
*const device_state
= counter
->device_state
;
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
);
1320 static struct device_type counter_device_type
= {
1321 .name
= "counter_device",
1322 .release
= counter_device_release
1325 static struct bus_type counter_bus_type
= {
1330 * counter_register - register Counter to the system
1331 * @counter: pointer to Counter to register
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.
1337 int counter_register(struct counter_device
*const counter
)
1339 struct counter_device_state
*device_state
;
1342 /* Allocate internal state container for Counter device */
1343 device_state
= kzalloc(sizeof(*device_state
), GFP_KERNEL
);
1346 counter
->device_state
= device_state
;
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
;
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
;
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
);
1366 /* Prepare device attributes */
1367 err
= counter_device_groups_list_prepare(counter
);
1371 /* Organize device attributes to groups and match to device */
1372 err
= counter_device_groups_prepare(device_state
);
1374 goto err_free_groups_list
;
1376 /* Add device to system */
1377 err
= device_add(&device_state
->dev
);
1379 goto 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
);
1389 ida_simple_remove(&counter_ida
, device_state
->id
);
1390 err_free_device_state
:
1391 kfree(device_state
);
1394 EXPORT_SYMBOL_GPL(counter_register
);
1397 * counter_unregister - unregister Counter from the system
1398 * @counter: pointer to Counter to unregister
1400 * The Counter is unregistered from the system; all allocated memory is freed.
1402 void counter_unregister(struct counter_device
*const counter
)
1405 device_del(&counter
->device_state
->dev
);
1407 EXPORT_SYMBOL_GPL(counter_unregister
);
1409 static void devm_counter_unreg(struct device
*dev
, void *res
)
1411 counter_unregister(*(struct counter_device
**)res
);
1415 * devm_counter_register - Resource-managed counter_register
1416 * @dev: device to allocate counter_device for
1417 * @counter: pointer to Counter to register
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.
1423 * If an Counter registered with this function needs to be unregistered
1424 * separately, devm_counter_unregister must be used.
1427 * 0 on success, negative error number on failure.
1429 int devm_counter_register(struct device
*dev
,
1430 struct counter_device
*const counter
)
1432 struct counter_device
**ptr
;
1435 ptr
= devres_alloc(devm_counter_unreg
, sizeof(*ptr
), GFP_KERNEL
);
1439 ret
= counter_register(counter
);
1442 devres_add(dev
, ptr
);
1449 EXPORT_SYMBOL_GPL(devm_counter_register
);
1451 static int devm_counter_match(struct device
*dev
, void *res
, void *data
)
1453 struct counter_device
**r
= res
;
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
1468 * Unregister Counter registered with devm_counter_register.
1470 void devm_counter_unregister(struct device
*dev
,
1471 struct counter_device
*const counter
)
1475 rc
= devres_release(dev
, devm_counter_unreg
, devm_counter_match
,
1479 EXPORT_SYMBOL_GPL(devm_counter_unregister
);
1481 static int __init
counter_init(void)
1483 return bus_register(&counter_bus_type
);
1486 static void __exit
counter_exit(void)
1488 bus_unregister(&counter_bus_type
);
1491 subsys_initcall(counter_init
);
1492 module_exit(counter_exit
);
1494 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1495 MODULE_DESCRIPTION("Generic Counter interface");
1496 MODULE_LICENSE("GPL v2");