bcm27xx: switch to 5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.10 / 950-0481-gpio-fsm-Show-state-info-in-sys-class-gpio-fsm.patch
1 From 1e50027d42006cbc42957b5053caf96ee52c7f8c Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Sat, 17 Oct 2020 15:42:54 +0100
4 Subject: [PATCH] gpio-fsm: Show state info in /sys/class/gpio-fsm
5
6 Add gpio-fsm sysfs entries under /sys/class/gpio-fsm. For each state
7 machine show the current state, which state (if any) will be entered
8 after a delay, and the current value of that delay.
9
10 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
11 ---
12 drivers/gpio/gpio-fsm.c | 112 ++++++++++++++++++++++++++++++++++++++--
13 1 file changed, 108 insertions(+), 4 deletions(-)
14
15 --- a/drivers/gpio/gpio-fsm.c
16 +++ b/drivers/gpio/gpio-fsm.c
17 @@ -20,6 +20,7 @@
18 #include <linux/interrupt.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 +#include <linux/sysfs.h>
22
23 #include <dt-bindings/gpio/gpio-fsm.h>
24
25 @@ -120,6 +121,7 @@ struct gpio_fsm {
26 struct fsm_state *current_state;
27 struct fsm_state *next_state;
28 struct fsm_state *delay_target_state;
29 + unsigned int delay_jiffies;
30 int delay_ms;
31 unsigned int debug;
32 bool shutting_down;
33 @@ -364,9 +366,10 @@ static void gpio_fsm_enter_state(struct
34 jiffies + msecs_to_jiffies(state->shutdown_ms);
35
36 if (gf->shutting_down) {
37 + gf->delay_jiffies = gf->shutdown_jiffies;
38 gf->delay_target_state = state->shutdown_target;
39 gf->delay_ms = state->shutdown_ms;
40 - mod_timer(&gf->timer, gf->shutdown_jiffies);
41 + mod_timer(&gf->timer, gf->delay_jiffies);
42 }
43 }
44
45 @@ -421,9 +424,10 @@ static void gpio_fsm_enter_state(struct
46 // 6. Schedule a timer callback if delay_target
47 if (state->delay_target) {
48 gf->delay_target_state = state->delay_target;
49 + gf->delay_jiffies = jiffies +
50 + msecs_to_jiffies(state->delay_ms);
51 gf->delay_ms = state->delay_ms;
52 - mod_timer(&gf->timer,
53 - jiffies + msecs_to_jiffies(state->delay_ms));
54 + mod_timer(&gf->timer, gf->delay_jiffies);
55 }
56 }
57
58 @@ -847,10 +851,81 @@ static int resolve_sym_to_state(struct g
59 return 0;
60 }
61
62 +
63 +/*
64 + * /sys/class/gpio-fsm/<fsm-name>/
65 + * /state ... the current state
66 + */
67 +
68 +static ssize_t state_show(struct device *dev,
69 + struct device_attribute *attr, char *buf)
70 +{
71 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
72 +
73 + return sprintf(buf, "%s\n", gf->current_state->name);
74 +}
75 +static DEVICE_ATTR_RO(state);
76 +
77 +static ssize_t delay_state_show(struct device *dev,
78 + struct device_attribute *attr, char *buf)
79 +{
80 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
81 +
82 + return sprintf(buf, "%s\n",
83 + gf->delay_target_state ? gf->delay_target_state->name :
84 + "-");
85 +}
86 +
87 +static DEVICE_ATTR_RO(delay_state);
88 +
89 +static ssize_t delay_ms_show(struct device *dev,
90 + struct device_attribute *attr, char *buf)
91 +{
92 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
93 + int jiffies_left;
94 +
95 + jiffies_left = gf->delay_jiffies - jiffies;
96 + return sprintf(buf,
97 + gf->delay_target_state ? "%u\n" : "-\n",
98 + jiffies_to_msecs(jiffies_left));
99 +}
100 +static DEVICE_ATTR_RO(delay_ms);
101 +
102 +static struct attribute *gpio_fsm_attrs[] = {
103 + &dev_attr_state.attr,
104 + &dev_attr_delay_state.attr,
105 + &dev_attr_delay_ms.attr,
106 + NULL,
107 +};
108 +
109 +static const struct attribute_group gpio_fsm_group = {
110 + .attrs = gpio_fsm_attrs,
111 + //.is_visible = gpio_is_visible,
112 +};
113 +
114 +static const struct attribute_group *gpio_fsm_groups[] = {
115 + &gpio_fsm_group,
116 + NULL
117 +};
118 +
119 +static struct attribute *gpio_fsm_class_attrs[] = {
120 + // There are no top-level attributes
121 + NULL,
122 +};
123 +ATTRIBUTE_GROUPS(gpio_fsm_class);
124 +
125 +static struct class gpio_fsm_class = {
126 + .name = MODULE_NAME,
127 + .owner = THIS_MODULE,
128 +
129 + .class_groups = gpio_fsm_class_groups,
130 +};
131 +
132 static int gpio_fsm_probe(struct platform_device *pdev)
133 {
134 struct input_gpio_state *inp_state;
135 struct device *dev = &pdev->dev;
136 + struct device *sysfs_dev;
137 struct device_node *np = dev->of_node;
138 struct device_node *cp;
139 struct gpio_fsm *gf;
140 @@ -1029,6 +1104,13 @@ static int gpio_fsm_probe(struct platfor
141
142 platform_set_drvdata(pdev, gf);
143
144 + sysfs_dev = device_create_with_groups(&gpio_fsm_class, dev,
145 + MKDEV(0, 0), gf,
146 + gpio_fsm_groups,
147 + "%s", np->name);
148 + if (IS_ERR(sysfs_dev))
149 + dev_err(gf->dev, "Error creating sysfs entry\n");
150 +
151 if (gf->debug)
152 dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
153
154 @@ -1097,7 +1179,29 @@ static struct platform_driver gpio_fsm_d
155 .remove = gpio_fsm_remove,
156 .shutdown = gpio_fsm_shutdown,
157 };
158 -module_platform_driver(gpio_fsm_driver);
159 +
160 +static int gpio_fsm_init(void)
161 +{
162 + int ret;
163 +
164 + ret = class_register(&gpio_fsm_class);
165 + if (ret)
166 + return ret;
167 +
168 + ret = platform_driver_register(&gpio_fsm_driver);
169 + if (ret)
170 + class_unregister(&gpio_fsm_class);
171 +
172 + return ret;
173 +}
174 +module_init(gpio_fsm_init);
175 +
176 +static void gpio_fsm_exit(void)
177 +{
178 + platform_driver_unregister(&gpio_fsm_driver);
179 + class_unregister(&gpio_fsm_class);
180 +}
181 +module_exit(gpio_fsm_exit);
182
183 MODULE_LICENSE("GPL");
184 MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");