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 static const char *const counter_signal_level_str
[] = {
224 [COUNTER_SIGNAL_LEVEL_LOW
] = "low",
225 [COUNTER_SIGNAL_LEVEL_HIGH
] = "high"
229 * counter_signal_read_value_set - set counter_signal_read_value data
230 * @val: counter_signal_read_value structure to set
231 * @type: property Signal data represents
234 * This function sets an opaque counter_signal_read_value structure with the
235 * provided Signal data.
237 void counter_signal_read_value_set(struct counter_signal_read_value
*const val
,
238 const enum counter_signal_value_type type
,
241 if (type
== COUNTER_SIGNAL_LEVEL
)
242 val
->len
= sprintf(val
->buf
, "%s\n",
243 counter_signal_level_str
[*(enum counter_signal_level
*)data
]);
247 EXPORT_SYMBOL_GPL(counter_signal_read_value_set
);
250 * counter_count_read_value_set - set counter_count_read_value data
251 * @val: counter_count_read_value structure to set
252 * @type: property Count data represents
255 * This function sets an opaque counter_count_read_value structure with the
256 * provided Count data.
258 void counter_count_read_value_set(struct counter_count_read_value
*const val
,
259 const enum counter_count_value_type type
,
263 case COUNTER_COUNT_POSITION
:
264 val
->len
= sprintf(val
->buf
, "%lu\n", *(unsigned long *)data
);
270 EXPORT_SYMBOL_GPL(counter_count_read_value_set
);
273 * counter_count_write_value_get - get counter_count_write_value data
275 * @type: property Count data represents
276 * @val: counter_count_write_value structure containing data
278 * This function extracts Count data from the provided opaque
279 * counter_count_write_value structure and stores it at the address provided by
283 * 0 on success, negative error number on failure.
285 int counter_count_write_value_get(void *const data
,
286 const enum counter_count_value_type type
,
287 const struct counter_count_write_value
*const val
)
292 case COUNTER_COUNT_POSITION
:
293 err
= kstrtoul(val
->buf
, 0, data
);
301 EXPORT_SYMBOL_GPL(counter_count_write_value_get
);
303 struct counter_attr_parm
{
304 struct counter_device_attr_group
*group
;
307 ssize_t (*show
)(struct device
*dev
, struct device_attribute
*attr
,
309 ssize_t (*store
)(struct device
*dev
, struct device_attribute
*attr
,
310 const char *buf
, size_t len
);
314 struct counter_device_attr
{
315 struct device_attribute dev_attr
;
320 static int counter_attribute_create(const struct counter_attr_parm
*const parm
)
322 struct counter_device_attr
*counter_attr
;
323 struct device_attribute
*dev_attr
;
325 struct list_head
*const attr_list
= &parm
->group
->attr_list
;
327 /* Allocate a Counter device attribute */
328 counter_attr
= kzalloc(sizeof(*counter_attr
), GFP_KERNEL
);
331 dev_attr
= &counter_attr
->dev_attr
;
333 sysfs_attr_init(&dev_attr
->attr
);
335 /* Configure device attribute */
336 dev_attr
->attr
.name
= kasprintf(GFP_KERNEL
, "%s%s", parm
->prefix
,
338 if (!dev_attr
->attr
.name
) {
340 goto err_free_counter_attr
;
343 dev_attr
->attr
.mode
|= 0444;
344 dev_attr
->show
= parm
->show
;
347 dev_attr
->attr
.mode
|= 0200;
348 dev_attr
->store
= parm
->store
;
351 /* Store associated Counter component with attribute */
352 counter_attr
->component
= parm
->component
;
354 /* Keep track of the attribute for later cleanup */
355 list_add(&counter_attr
->l
, attr_list
);
356 parm
->group
->num_attr
++;
360 err_free_counter_attr
:
365 #define to_counter_attr(_dev_attr) \
366 container_of(_dev_attr, struct counter_device_attr, dev_attr)
368 struct counter_signal_unit
{
369 struct counter_signal
*signal
;
372 static ssize_t
counter_signal_show(struct device
*dev
,
373 struct device_attribute
*attr
, char *buf
)
375 struct counter_device
*const counter
= dev_get_drvdata(dev
);
376 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
377 const struct counter_signal_unit
*const component
= devattr
->component
;
378 struct counter_signal
*const signal
= component
->signal
;
380 struct counter_signal_read_value val
= { .buf
= buf
};
382 err
= counter
->ops
->signal_read(counter
, signal
, &val
);
389 struct counter_name_unit
{
393 static ssize_t
counter_device_attr_name_show(struct device
*dev
,
394 struct device_attribute
*attr
,
397 const struct counter_name_unit
*const comp
= to_counter_attr(attr
)->component
;
399 return sprintf(buf
, "%s\n", comp
->name
);
402 static int counter_name_attribute_create(
403 struct counter_device_attr_group
*const group
,
404 const char *const name
)
406 struct counter_name_unit
*name_comp
;
407 struct counter_attr_parm parm
;
410 /* Skip if no name */
414 /* Allocate name attribute component */
415 name_comp
= kmalloc(sizeof(*name_comp
), GFP_KERNEL
);
418 name_comp
->name
= name
;
420 /* Allocate Signal name attribute */
424 parm
.show
= counter_device_attr_name_show
;
426 parm
.component
= name_comp
;
427 err
= counter_attribute_create(&parm
);
429 goto err_free_name_comp
;
438 struct counter_signal_ext_unit
{
439 struct counter_signal
*signal
;
440 const struct counter_signal_ext
*ext
;
443 static ssize_t
counter_signal_ext_show(struct device
*dev
,
444 struct device_attribute
*attr
, char *buf
)
446 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
447 const struct counter_signal_ext_unit
*const comp
= devattr
->component
;
448 const struct counter_signal_ext
*const ext
= comp
->ext
;
450 return ext
->read(dev_get_drvdata(dev
), comp
->signal
, ext
->priv
, buf
);
453 static ssize_t
counter_signal_ext_store(struct device
*dev
,
454 struct device_attribute
*attr
,
455 const char *buf
, size_t len
)
457 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
458 const struct counter_signal_ext_unit
*const comp
= devattr
->component
;
459 const struct counter_signal_ext
*const ext
= comp
->ext
;
461 return ext
->write(dev_get_drvdata(dev
), comp
->signal
, ext
->priv
, buf
,
465 static void counter_device_attr_list_free(struct list_head
*attr_list
)
467 struct counter_device_attr
*p
, *n
;
469 list_for_each_entry_safe(p
, n
, attr_list
, l
) {
470 /* free attribute name and associated component memory */
471 kfree(p
->dev_attr
.attr
.name
);
478 static int counter_signal_ext_register(
479 struct counter_device_attr_group
*const group
,
480 struct counter_signal
*const signal
)
482 const size_t num_ext
= signal
->num_ext
;
484 const struct counter_signal_ext
*ext
;
485 struct counter_signal_ext_unit
*signal_ext_comp
;
486 struct counter_attr_parm parm
;
489 /* Create an attribute for each extension */
490 for (i
= 0 ; i
< num_ext
; i
++) {
491 ext
= signal
->ext
+ i
;
493 /* Allocate signal_ext attribute component */
494 signal_ext_comp
= kmalloc(sizeof(*signal_ext_comp
), GFP_KERNEL
);
495 if (!signal_ext_comp
) {
497 goto err_free_attr_list
;
499 signal_ext_comp
->signal
= signal
;
500 signal_ext_comp
->ext
= ext
;
502 /* Allocate a Counter device attribute */
505 parm
.name
= ext
->name
;
506 parm
.show
= (ext
->read
) ? counter_signal_ext_show
: NULL
;
507 parm
.store
= (ext
->write
) ? counter_signal_ext_store
: NULL
;
508 parm
.component
= signal_ext_comp
;
509 err
= counter_attribute_create(&parm
);
511 kfree(signal_ext_comp
);
512 goto err_free_attr_list
;
519 counter_device_attr_list_free(&group
->attr_list
);
523 static int counter_signal_attributes_create(
524 struct counter_device_attr_group
*const group
,
525 const struct counter_device
*const counter
,
526 struct counter_signal
*const signal
)
528 struct counter_signal_unit
*signal_comp
;
529 struct counter_attr_parm parm
;
532 /* Allocate Signal attribute component */
533 signal_comp
= kmalloc(sizeof(*signal_comp
), GFP_KERNEL
);
536 signal_comp
->signal
= signal
;
538 /* Create main Signal attribute */
541 parm
.name
= "signal";
542 parm
.show
= (counter
->ops
->signal_read
) ? counter_signal_show
: NULL
;
544 parm
.component
= signal_comp
;
545 err
= counter_attribute_create(&parm
);
551 /* Create Signal name attribute */
552 err
= counter_name_attribute_create(group
, signal
->name
);
554 goto err_free_attr_list
;
556 /* Register Signal extension attributes */
557 err
= counter_signal_ext_register(group
, signal
);
559 goto err_free_attr_list
;
564 counter_device_attr_list_free(&group
->attr_list
);
568 static int counter_signals_register(
569 struct counter_device_attr_group
*const groups_list
,
570 const struct counter_device
*const counter
)
572 const size_t num_signals
= counter
->num_signals
;
574 struct counter_signal
*signal
;
578 /* Register each Signal */
579 for (i
= 0; i
< num_signals
; i
++) {
580 signal
= counter
->signals
+ i
;
582 /* Generate Signal attribute directory name */
583 name
= kasprintf(GFP_KERNEL
, "signal%d", signal
->id
);
586 goto err_free_attr_groups
;
588 groups_list
[i
].attr_group
.name
= name
;
590 /* Create all attributes associated with Signal */
591 err
= counter_signal_attributes_create(groups_list
+ i
, counter
,
594 goto err_free_attr_groups
;
599 err_free_attr_groups
:
601 kfree(groups_list
[i
].attr_group
.name
);
602 counter_device_attr_list_free(&groups_list
[i
].attr_list
);
607 static const char *const counter_synapse_action_str
[] = {
608 [COUNTER_SYNAPSE_ACTION_NONE
] = "none",
609 [COUNTER_SYNAPSE_ACTION_RISING_EDGE
] = "rising edge",
610 [COUNTER_SYNAPSE_ACTION_FALLING_EDGE
] = "falling edge",
611 [COUNTER_SYNAPSE_ACTION_BOTH_EDGES
] = "both edges"
614 struct counter_action_unit
{
615 struct counter_synapse
*synapse
;
616 struct counter_count
*count
;
619 static ssize_t
counter_action_show(struct device
*dev
,
620 struct device_attribute
*attr
, char *buf
)
622 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
624 struct counter_device
*const counter
= dev_get_drvdata(dev
);
625 const struct counter_action_unit
*const component
= devattr
->component
;
626 struct counter_count
*const count
= component
->count
;
627 struct counter_synapse
*const synapse
= component
->synapse
;
629 enum counter_synapse_action action
;
631 err
= counter
->ops
->action_get(counter
, count
, synapse
, &action_index
);
635 synapse
->action
= action_index
;
637 action
= synapse
->actions_list
[action_index
];
638 return sprintf(buf
, "%s\n", counter_synapse_action_str
[action
]);
641 static ssize_t
counter_action_store(struct device
*dev
,
642 struct device_attribute
*attr
,
643 const char *buf
, size_t len
)
645 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
646 const struct counter_action_unit
*const component
= devattr
->component
;
647 struct counter_synapse
*const synapse
= component
->synapse
;
649 const size_t num_actions
= synapse
->num_actions
;
650 enum counter_synapse_action action
;
652 struct counter_device
*const counter
= dev_get_drvdata(dev
);
653 struct counter_count
*const count
= component
->count
;
655 /* Find requested action mode */
656 for (action_index
= 0; action_index
< num_actions
; action_index
++) {
657 action
= synapse
->actions_list
[action_index
];
658 if (sysfs_streq(buf
, counter_synapse_action_str
[action
]))
661 /* If requested action mode not found */
662 if (action_index
>= num_actions
)
665 err
= counter
->ops
->action_set(counter
, count
, synapse
, action_index
);
669 synapse
->action
= action_index
;
674 struct counter_action_avail_unit
{
675 const enum counter_synapse_action
*actions_list
;
679 static ssize_t
counter_synapse_action_available_show(struct device
*dev
,
680 struct device_attribute
*attr
, char *buf
)
682 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
683 const struct counter_action_avail_unit
*const component
= devattr
->component
;
685 enum counter_synapse_action action
;
688 for (i
= 0; i
< component
->num_actions
; i
++) {
689 action
= component
->actions_list
[i
];
690 len
+= sprintf(buf
+ len
, "%s\n",
691 counter_synapse_action_str
[action
]);
697 static int counter_synapses_register(
698 struct counter_device_attr_group
*const group
,
699 const struct counter_device
*const counter
,
700 struct counter_count
*const count
, const char *const count_attr_name
)
703 struct counter_synapse
*synapse
;
705 struct counter_action_unit
*action_comp
;
706 struct counter_attr_parm parm
;
708 struct counter_action_avail_unit
*avail_comp
;
710 /* Register each Synapse */
711 for (i
= 0; i
< count
->num_synapses
; i
++) {
712 synapse
= count
->synapses
+ i
;
714 /* Generate attribute prefix */
715 prefix
= kasprintf(GFP_KERNEL
, "signal%d_",
716 synapse
->signal
->id
);
719 goto err_free_attr_list
;
722 /* Allocate action attribute component */
723 action_comp
= kmalloc(sizeof(*action_comp
), GFP_KERNEL
);
726 goto err_free_prefix
;
728 action_comp
->synapse
= synapse
;
729 action_comp
->count
= count
;
731 /* Create action attribute */
733 parm
.prefix
= prefix
;
734 parm
.name
= "action";
735 parm
.show
= (counter
->ops
->action_get
) ? counter_action_show
: NULL
;
736 parm
.store
= (counter
->ops
->action_set
) ? counter_action_store
: NULL
;
737 parm
.component
= action_comp
;
738 err
= counter_attribute_create(&parm
);
741 goto err_free_prefix
;
744 /* Allocate action available attribute component */
745 avail_comp
= kmalloc(sizeof(*avail_comp
), GFP_KERNEL
);
748 goto err_free_prefix
;
750 avail_comp
->actions_list
= synapse
->actions_list
;
751 avail_comp
->num_actions
= synapse
->num_actions
;
753 /* Create action_available attribute */
755 parm
.prefix
= prefix
;
756 parm
.name
= "action_available";
757 parm
.show
= counter_synapse_action_available_show
;
759 parm
.component
= avail_comp
;
760 err
= counter_attribute_create(&parm
);
763 goto err_free_prefix
;
774 counter_device_attr_list_free(&group
->attr_list
);
778 struct counter_count_unit
{
779 struct counter_count
*count
;
782 static ssize_t
counter_count_show(struct device
*dev
,
783 struct device_attribute
*attr
,
786 struct counter_device
*const counter
= dev_get_drvdata(dev
);
787 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
788 const struct counter_count_unit
*const component
= devattr
->component
;
789 struct counter_count
*const count
= component
->count
;
791 struct counter_count_read_value val
= { .buf
= buf
};
793 err
= counter
->ops
->count_read(counter
, count
, &val
);
800 static ssize_t
counter_count_store(struct device
*dev
,
801 struct device_attribute
*attr
,
802 const char *buf
, size_t len
)
804 struct counter_device
*const counter
= dev_get_drvdata(dev
);
805 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
806 const struct counter_count_unit
*const component
= devattr
->component
;
807 struct counter_count
*const count
= component
->count
;
809 struct counter_count_write_value val
= { .buf
= buf
};
811 err
= counter
->ops
->count_write(counter
, count
, &val
);
818 static const char *const counter_count_function_str
[] = {
819 [COUNTER_COUNT_FUNCTION_INCREASE
] = "increase",
820 [COUNTER_COUNT_FUNCTION_DECREASE
] = "decrease",
821 [COUNTER_COUNT_FUNCTION_PULSE_DIRECTION
] = "pulse-direction",
822 [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A
] = "quadrature x1 a",
823 [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B
] = "quadrature x1 b",
824 [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A
] = "quadrature x2 a",
825 [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B
] = "quadrature x2 b",
826 [COUNTER_COUNT_FUNCTION_QUADRATURE_X4
] = "quadrature x4"
829 static ssize_t
counter_function_show(struct device
*dev
,
830 struct device_attribute
*attr
, char *buf
)
833 struct counter_device
*const counter
= dev_get_drvdata(dev
);
834 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
835 const struct counter_count_unit
*const component
= devattr
->component
;
836 struct counter_count
*const count
= component
->count
;
838 enum counter_count_function function
;
840 err
= counter
->ops
->function_get(counter
, count
, &func_index
);
844 count
->function
= func_index
;
846 function
= count
->functions_list
[func_index
];
847 return sprintf(buf
, "%s\n", counter_count_function_str
[function
]);
850 static ssize_t
counter_function_store(struct device
*dev
,
851 struct device_attribute
*attr
,
852 const char *buf
, size_t len
)
854 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
855 const struct counter_count_unit
*const component
= devattr
->component
;
856 struct counter_count
*const count
= component
->count
;
857 const size_t num_functions
= count
->num_functions
;
859 enum counter_count_function function
;
861 struct counter_device
*const counter
= dev_get_drvdata(dev
);
863 /* Find requested Count function mode */
864 for (func_index
= 0; func_index
< num_functions
; func_index
++) {
865 function
= count
->functions_list
[func_index
];
866 if (sysfs_streq(buf
, counter_count_function_str
[function
]))
869 /* Return error if requested Count function mode not found */
870 if (func_index
>= num_functions
)
873 err
= counter
->ops
->function_set(counter
, count
, func_index
);
877 count
->function
= func_index
;
882 struct counter_count_ext_unit
{
883 struct counter_count
*count
;
884 const struct counter_count_ext
*ext
;
887 static ssize_t
counter_count_ext_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_count_ext_unit
*const comp
= devattr
->component
;
892 const struct counter_count_ext
*const ext
= comp
->ext
;
894 return ext
->read(dev_get_drvdata(dev
), comp
->count
, ext
->priv
, buf
);
897 static ssize_t
counter_count_ext_store(struct device
*dev
,
898 struct device_attribute
*attr
,
899 const char *buf
, size_t len
)
901 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
902 const struct counter_count_ext_unit
*const comp
= devattr
->component
;
903 const struct counter_count_ext
*const ext
= comp
->ext
;
905 return ext
->write(dev_get_drvdata(dev
), comp
->count
, ext
->priv
, buf
,
909 static int counter_count_ext_register(
910 struct counter_device_attr_group
*const group
,
911 struct counter_count
*const count
)
914 const struct counter_count_ext
*ext
;
915 struct counter_count_ext_unit
*count_ext_comp
;
916 struct counter_attr_parm parm
;
919 /* Create an attribute for each extension */
920 for (i
= 0 ; i
< count
->num_ext
; i
++) {
921 ext
= count
->ext
+ i
;
923 /* Allocate count_ext attribute component */
924 count_ext_comp
= kmalloc(sizeof(*count_ext_comp
), GFP_KERNEL
);
925 if (!count_ext_comp
) {
927 goto err_free_attr_list
;
929 count_ext_comp
->count
= count
;
930 count_ext_comp
->ext
= ext
;
932 /* Allocate count_ext attribute */
935 parm
.name
= ext
->name
;
936 parm
.show
= (ext
->read
) ? counter_count_ext_show
: NULL
;
937 parm
.store
= (ext
->write
) ? counter_count_ext_store
: NULL
;
938 parm
.component
= count_ext_comp
;
939 err
= counter_attribute_create(&parm
);
941 kfree(count_ext_comp
);
942 goto err_free_attr_list
;
949 counter_device_attr_list_free(&group
->attr_list
);
953 struct counter_func_avail_unit
{
954 const enum counter_count_function
*functions_list
;
955 size_t num_functions
;
958 static ssize_t
counter_count_function_available_show(struct device
*dev
,
959 struct device_attribute
*attr
, char *buf
)
961 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
962 const struct counter_func_avail_unit
*const component
= devattr
->component
;
963 const enum counter_count_function
*const func_list
= component
->functions_list
;
964 const size_t num_functions
= component
->num_functions
;
966 enum counter_count_function function
;
969 for (i
= 0; i
< num_functions
; i
++) {
970 function
= func_list
[i
];
971 len
+= sprintf(buf
+ len
, "%s\n",
972 counter_count_function_str
[function
]);
978 static int counter_count_attributes_create(
979 struct counter_device_attr_group
*const group
,
980 const struct counter_device
*const counter
,
981 struct counter_count
*const count
)
983 struct counter_count_unit
*count_comp
;
984 struct counter_attr_parm parm
;
986 struct counter_count_unit
*func_comp
;
987 struct counter_func_avail_unit
*avail_comp
;
989 /* Allocate count attribute component */
990 count_comp
= kmalloc(sizeof(*count_comp
), GFP_KERNEL
);
993 count_comp
->count
= count
;
995 /* Create main Count attribute */
999 parm
.show
= (counter
->ops
->count_read
) ? counter_count_show
: NULL
;
1000 parm
.store
= (counter
->ops
->count_write
) ? counter_count_store
: NULL
;
1001 parm
.component
= count_comp
;
1002 err
= counter_attribute_create(&parm
);
1008 /* Allocate function attribute component */
1009 func_comp
= kmalloc(sizeof(*func_comp
), GFP_KERNEL
);
1012 goto err_free_attr_list
;
1014 func_comp
->count
= count
;
1016 /* Create Count function attribute */
1019 parm
.name
= "function";
1020 parm
.show
= (counter
->ops
->function_get
) ? counter_function_show
: NULL
;
1021 parm
.store
= (counter
->ops
->function_set
) ? counter_function_store
: NULL
;
1022 parm
.component
= func_comp
;
1023 err
= counter_attribute_create(&parm
);
1026 goto err_free_attr_list
;
1029 /* Allocate function available attribute component */
1030 avail_comp
= kmalloc(sizeof(*avail_comp
), GFP_KERNEL
);
1033 goto err_free_attr_list
;
1035 avail_comp
->functions_list
= count
->functions_list
;
1036 avail_comp
->num_functions
= count
->num_functions
;
1038 /* Create Count function_available attribute */
1041 parm
.name
= "function_available";
1042 parm
.show
= counter_count_function_available_show
;
1044 parm
.component
= avail_comp
;
1045 err
= counter_attribute_create(&parm
);
1048 goto err_free_attr_list
;
1051 /* Create Count name attribute */
1052 err
= counter_name_attribute_create(group
, count
->name
);
1054 goto err_free_attr_list
;
1056 /* Register Count extension attributes */
1057 err
= counter_count_ext_register(group
, count
);
1059 goto err_free_attr_list
;
1064 counter_device_attr_list_free(&group
->attr_list
);
1068 static int counter_counts_register(
1069 struct counter_device_attr_group
*const groups_list
,
1070 const struct counter_device
*const counter
)
1073 struct counter_count
*count
;
1077 /* Register each Count */
1078 for (i
= 0; i
< counter
->num_counts
; i
++) {
1079 count
= counter
->counts
+ i
;
1081 /* Generate Count attribute directory name */
1082 name
= kasprintf(GFP_KERNEL
, "count%d", count
->id
);
1085 goto err_free_attr_groups
;
1087 groups_list
[i
].attr_group
.name
= name
;
1089 /* Register the Synapses associated with each Count */
1090 err
= counter_synapses_register(groups_list
+ i
, counter
, count
,
1093 goto err_free_attr_groups
;
1095 /* Create all attributes associated with Count */
1096 err
= counter_count_attributes_create(groups_list
+ i
, counter
,
1099 goto err_free_attr_groups
;
1104 err_free_attr_groups
:
1106 kfree(groups_list
[i
].attr_group
.name
);
1107 counter_device_attr_list_free(&groups_list
[i
].attr_list
);
1112 struct counter_size_unit
{
1116 static ssize_t
counter_device_attr_size_show(struct device
*dev
,
1117 struct device_attribute
*attr
,
1120 const struct counter_size_unit
*const comp
= to_counter_attr(attr
)->component
;
1122 return sprintf(buf
, "%zu\n", comp
->size
);
1125 static int counter_size_attribute_create(
1126 struct counter_device_attr_group
*const group
,
1127 const size_t size
, const char *const name
)
1129 struct counter_size_unit
*size_comp
;
1130 struct counter_attr_parm parm
;
1133 /* Allocate size attribute component */
1134 size_comp
= kmalloc(sizeof(*size_comp
), GFP_KERNEL
);
1137 size_comp
->size
= size
;
1142 parm
.show
= counter_device_attr_size_show
;
1144 parm
.component
= size_comp
;
1145 err
= counter_attribute_create(&parm
);
1147 goto err_free_size_comp
;
1156 struct counter_ext_unit
{
1157 const struct counter_device_ext
*ext
;
1160 static ssize_t
counter_device_ext_show(struct device
*dev
,
1161 struct device_attribute
*attr
, char *buf
)
1163 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
1164 const struct counter_ext_unit
*const component
= devattr
->component
;
1165 const struct counter_device_ext
*const ext
= component
->ext
;
1167 return ext
->read(dev_get_drvdata(dev
), ext
->priv
, buf
);
1170 static ssize_t
counter_device_ext_store(struct device
*dev
,
1171 struct device_attribute
*attr
,
1172 const char *buf
, size_t len
)
1174 const struct counter_device_attr
*const devattr
= to_counter_attr(attr
);
1175 const struct counter_ext_unit
*const component
= devattr
->component
;
1176 const struct counter_device_ext
*const ext
= component
->ext
;
1178 return ext
->write(dev_get_drvdata(dev
), ext
->priv
, buf
, len
);
1181 static int counter_device_ext_register(
1182 struct counter_device_attr_group
*const group
,
1183 struct counter_device
*const counter
)
1186 struct counter_ext_unit
*ext_comp
;
1187 struct counter_attr_parm parm
;
1190 /* Create an attribute for each extension */
1191 for (i
= 0 ; i
< counter
->num_ext
; i
++) {
1192 /* Allocate extension attribute component */
1193 ext_comp
= kmalloc(sizeof(*ext_comp
), GFP_KERNEL
);
1196 goto err_free_attr_list
;
1199 ext_comp
->ext
= counter
->ext
+ i
;
1201 /* Allocate extension attribute */
1204 parm
.name
= counter
->ext
[i
].name
;
1205 parm
.show
= (counter
->ext
[i
].read
) ? counter_device_ext_show
: NULL
;
1206 parm
.store
= (counter
->ext
[i
].write
) ? counter_device_ext_store
: NULL
;
1207 parm
.component
= ext_comp
;
1208 err
= counter_attribute_create(&parm
);
1211 goto err_free_attr_list
;
1218 counter_device_attr_list_free(&group
->attr_list
);
1222 static int counter_global_attr_register(
1223 struct counter_device_attr_group
*const group
,
1224 struct counter_device
*const counter
)
1228 /* Create name attribute */
1229 err
= counter_name_attribute_create(group
, counter
->name
);
1233 /* Create num_counts attribute */
1234 err
= counter_size_attribute_create(group
, counter
->num_counts
,
1237 goto err_free_attr_list
;
1239 /* Create num_signals attribute */
1240 err
= counter_size_attribute_create(group
, counter
->num_signals
,
1243 goto err_free_attr_list
;
1245 /* Register Counter device extension attributes */
1246 err
= counter_device_ext_register(group
, counter
);
1248 goto err_free_attr_list
;
1253 counter_device_attr_list_free(&group
->attr_list
);
1257 static void counter_device_groups_list_free(
1258 struct counter_device_attr_group
*const groups_list
,
1259 const size_t num_groups
)
1261 struct counter_device_attr_group
*group
;
1264 /* loop through all attribute groups (signals, counts, global, etc.) */
1265 for (i
= 0; i
< num_groups
; i
++) {
1266 group
= groups_list
+ i
;
1268 /* free all attribute group and associated attributes memory */
1269 kfree(group
->attr_group
.name
);
1270 kfree(group
->attr_group
.attrs
);
1271 counter_device_attr_list_free(&group
->attr_list
);
1277 static int counter_device_groups_list_prepare(
1278 struct counter_device
*const counter
)
1280 const size_t total_num_groups
=
1281 counter
->num_signals
+ counter
->num_counts
+ 1;
1282 struct counter_device_attr_group
*groups_list
;
1285 size_t num_groups
= 0;
1287 /* Allocate space for attribute groups (signals, counts, and ext) */
1288 groups_list
= kcalloc(total_num_groups
, sizeof(*groups_list
),
1293 /* Initialize attribute lists */
1294 for (i
= 0; i
< total_num_groups
; i
++)
1295 INIT_LIST_HEAD(&groups_list
[i
].attr_list
);
1297 /* Register Signals */
1298 err
= counter_signals_register(groups_list
, counter
);
1300 goto err_free_groups_list
;
1301 num_groups
+= counter
->num_signals
;
1303 /* Register Counts and respective Synapses */
1304 err
= counter_counts_register(groups_list
+ num_groups
, counter
);
1306 goto err_free_groups_list
;
1307 num_groups
+= counter
->num_counts
;
1309 /* Register Counter global attributes */
1310 err
= counter_global_attr_register(groups_list
+ num_groups
, counter
);
1312 goto err_free_groups_list
;
1315 /* Store groups_list in device_state */
1316 counter
->device_state
->groups_list
= groups_list
;
1317 counter
->device_state
->num_groups
= num_groups
;
1321 err_free_groups_list
:
1322 counter_device_groups_list_free(groups_list
, num_groups
);
1326 static int counter_device_groups_prepare(
1327 struct counter_device_state
*const device_state
)
1330 struct counter_device_attr_group
*group
;
1332 struct counter_device_attr
*p
;
1334 /* Allocate attribute groups for association with device */
1335 device_state
->groups
= kcalloc(device_state
->num_groups
+ 1,
1336 sizeof(*device_state
->groups
),
1338 if (!device_state
->groups
)
1341 /* Prepare each group of attributes for association */
1342 for (i
= 0; i
< device_state
->num_groups
; i
++) {
1343 group
= device_state
->groups_list
+ i
;
1345 /* Allocate space for attribute pointers in attribute group */
1346 group
->attr_group
.attrs
= kcalloc(group
->num_attr
+ 1,
1347 sizeof(*group
->attr_group
.attrs
), GFP_KERNEL
);
1348 if (!group
->attr_group
.attrs
) {
1350 goto err_free_groups
;
1353 /* Add attribute pointers to attribute group */
1355 list_for_each_entry(p
, &group
->attr_list
, l
)
1356 group
->attr_group
.attrs
[j
++] = &p
->dev_attr
.attr
;
1358 /* Group attributes in attribute group */
1359 device_state
->groups
[i
] = &group
->attr_group
;
1361 /* Associate attributes with device */
1362 device_state
->dev
.groups
= device_state
->groups
;
1368 group
= device_state
->groups_list
+ i
;
1369 kfree(group
->attr_group
.attrs
);
1370 group
->attr_group
.attrs
= NULL
;
1372 kfree(device_state
->groups
);
1376 /* Provides a unique ID for each counter device */
1377 static DEFINE_IDA(counter_ida
);
1379 static void counter_device_release(struct device
*dev
)
1381 struct counter_device
*const counter
= dev_get_drvdata(dev
);
1382 struct counter_device_state
*const device_state
= counter
->device_state
;
1384 kfree(device_state
->groups
);
1385 counter_device_groups_list_free(device_state
->groups_list
,
1386 device_state
->num_groups
);
1387 ida_simple_remove(&counter_ida
, device_state
->id
);
1388 kfree(device_state
);
1391 static struct device_type counter_device_type
= {
1392 .name
= "counter_device",
1393 .release
= counter_device_release
1396 static struct bus_type counter_bus_type
= {
1401 * counter_register - register Counter to the system
1402 * @counter: pointer to Counter to register
1404 * This function registers a Counter to the system. A sysfs "counter" directory
1405 * will be created and populated with sysfs attributes correlating with the
1406 * Counter Signals, Synapses, and Counts respectively.
1408 int counter_register(struct counter_device
*const counter
)
1410 struct counter_device_state
*device_state
;
1413 /* Allocate internal state container for Counter device */
1414 device_state
= kzalloc(sizeof(*device_state
), GFP_KERNEL
);
1417 counter
->device_state
= device_state
;
1419 /* Acquire unique ID */
1420 device_state
->id
= ida_simple_get(&counter_ida
, 0, 0, GFP_KERNEL
);
1421 if (device_state
->id
< 0) {
1422 err
= device_state
->id
;
1423 goto err_free_device_state
;
1426 /* Configure device structure for Counter */
1427 device_state
->dev
.type
= &counter_device_type
;
1428 device_state
->dev
.bus
= &counter_bus_type
;
1429 if (counter
->parent
) {
1430 device_state
->dev
.parent
= counter
->parent
;
1431 device_state
->dev
.of_node
= counter
->parent
->of_node
;
1433 dev_set_name(&device_state
->dev
, "counter%d", device_state
->id
);
1434 device_initialize(&device_state
->dev
);
1435 dev_set_drvdata(&device_state
->dev
, counter
);
1437 /* Prepare device attributes */
1438 err
= counter_device_groups_list_prepare(counter
);
1442 /* Organize device attributes to groups and match to device */
1443 err
= counter_device_groups_prepare(device_state
);
1445 goto err_free_groups_list
;
1447 /* Add device to system */
1448 err
= device_add(&device_state
->dev
);
1450 goto err_free_groups
;
1455 kfree(device_state
->groups
);
1456 err_free_groups_list
:
1457 counter_device_groups_list_free(device_state
->groups_list
,
1458 device_state
->num_groups
);
1460 ida_simple_remove(&counter_ida
, device_state
->id
);
1461 err_free_device_state
:
1462 kfree(device_state
);
1465 EXPORT_SYMBOL_GPL(counter_register
);
1468 * counter_unregister - unregister Counter from the system
1469 * @counter: pointer to Counter to unregister
1471 * The Counter is unregistered from the system; all allocated memory is freed.
1473 void counter_unregister(struct counter_device
*const counter
)
1476 device_del(&counter
->device_state
->dev
);
1478 EXPORT_SYMBOL_GPL(counter_unregister
);
1480 static void devm_counter_unreg(struct device
*dev
, void *res
)
1482 counter_unregister(*(struct counter_device
**)res
);
1486 * devm_counter_register - Resource-managed counter_register
1487 * @dev: device to allocate counter_device for
1488 * @counter: pointer to Counter to register
1490 * Managed counter_register. The Counter registered with this function is
1491 * automatically unregistered on driver detach. This function calls
1492 * counter_register internally. Refer to that function for more information.
1494 * If an Counter registered with this function needs to be unregistered
1495 * separately, devm_counter_unregister must be used.
1498 * 0 on success, negative error number on failure.
1500 int devm_counter_register(struct device
*dev
,
1501 struct counter_device
*const counter
)
1503 struct counter_device
**ptr
;
1506 ptr
= devres_alloc(devm_counter_unreg
, sizeof(*ptr
), GFP_KERNEL
);
1510 ret
= counter_register(counter
);
1513 devres_add(dev
, ptr
);
1520 EXPORT_SYMBOL_GPL(devm_counter_register
);
1522 static int devm_counter_match(struct device
*dev
, void *res
, void *data
)
1524 struct counter_device
**r
= res
;
1535 * devm_counter_unregister - Resource-managed counter_unregister
1536 * @dev: device this counter_device belongs to
1537 * @counter: pointer to Counter associated with the device
1539 * Unregister Counter registered with devm_counter_register.
1541 void devm_counter_unregister(struct device
*dev
,
1542 struct counter_device
*const counter
)
1546 rc
= devres_release(dev
, devm_counter_unreg
, devm_counter_match
,
1550 EXPORT_SYMBOL_GPL(devm_counter_unregister
);
1552 static int __init
counter_init(void)
1554 return bus_register(&counter_bus_type
);
1557 static void __exit
counter_exit(void)
1559 bus_unregister(&counter_bus_type
);
1562 subsys_initcall(counter_init
);
1563 module_exit(counter_exit
);
1565 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1566 MODULE_DESCRIPTION("Generic Counter interface");
1567 MODULE_LICENSE("GPL v2");