1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Sloppy logic analyzer using GPIOs (to be run on an isolated CPU)
4 *
5 * Use the 'gpio-sloppy-logic-analyzer' script in the 'tools/gpio' folder for
6 * easier usage and further documentation. Note that this is a last resort
7 * analyzer which can be affected by latencies and non-deterministic code
8 * paths. However, for e.g. remote development, it may be useful to get a first
9 * view and aid further debugging.
10 *
11 * Copyright (C) Wolfram Sang <wsa@sang-engineering.com>
12 * Copyright (C) Renesas Electronics Corporation
13 */
14
15 #include <linux/ctype.h>
16 #include <linux/debugfs.h>
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <linux/err.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/init.h>
22 #include <linux/ktime.h>
23 #include <linux/module.h>
24 #include <linux/mutex.h>
25 #include <linux/platform_device.h>
26 #include <linux/property.h>
27 #include <linux/slab.h>
28 #include <linux/sizes.h>
29 #include <linux/timekeeping.h>
30 #include <linux/types.h>
31 #include <linux/vmalloc.h>
32
33 #define GPIO_LA_NAME "gpio-sloppy-logic-analyzer"
34 #define GPIO_LA_DEFAULT_BUF_SIZE SZ_256K
35 /* can be increased but then we need to extend the u8 buffers */
36 #define GPIO_LA_MAX_PROBES 8
37 #define GPIO_LA_NUM_TESTS 1024
38
39 struct gpio_la_poll_priv {
40 struct mutex blob_lock; /* serialize access to the blob (data) */
41 u32 buf_idx;
42 struct gpio_descs *descs;
43 unsigned long delay_ns;
44 unsigned long acq_delay;
45 struct debugfs_blob_wrapper blob;
46 struct dentry *debug_dir;
47 struct dentry *blob_dent;
48 struct debugfs_blob_wrapper meta;
49 struct device *dev;
50 unsigned int trig_len;
51 u8 *trig_data;
52 };
53
54 static struct dentry *gpio_la_poll_debug_dir;
55
gpio_la_get_array(struct gpio_descs * d,unsigned long * sptr)56 static __always_inline int gpio_la_get_array(struct gpio_descs *d, unsigned long *sptr)
57 {
58 int ret;
59
60 ret = gpiod_get_array_value(d->ndescs, d->desc, d->info, sptr);
61 if (ret == 0 && fatal_signal_pending(current))
62 ret = -EINTR;
63
64 return ret;
65 }
66
fops_capture_set(void * data,u64 val)67 static int fops_capture_set(void *data, u64 val)
68 {
69 struct gpio_la_poll_priv *priv = data;
70 u8 *la_buf = priv->blob.data;
71 unsigned long state = 0; /* zeroed because GPIO arrays are bitfields */
72 unsigned long delay;
73 ktime_t start_time;
74 unsigned int i;
75 int ret;
76
77 if (!val)
78 return 0;
79
80 if (!la_buf)
81 return -ENOMEM;
82
83 if (!priv->delay_ns)
84 return -EINVAL;
85
86 mutex_lock(&priv->blob_lock);
87 if (priv->blob_dent) {
88 debugfs_remove(priv->blob_dent);
89 priv->blob_dent = NULL;
90 }
91
92 priv->buf_idx = 0;
93
94 local_irq_disable();
95 preempt_disable_notrace();
96
97 /* Measure delay of reading GPIOs */
98 start_time = ktime_get();
99 for (i = 0; i < GPIO_LA_NUM_TESTS; i++) {
100 ret = gpio_la_get_array(priv->descs, &state);
101 if (ret)
102 goto out;
103 }
104
105 priv->acq_delay = ktime_sub(ktime_get(), start_time) / GPIO_LA_NUM_TESTS;
106 if (priv->delay_ns < priv->acq_delay) {
107 ret = -ERANGE;
108 goto out;
109 }
110
111 delay = priv->delay_ns - priv->acq_delay;
112
113 /* Wait for triggers */
114 for (i = 0; i < priv->trig_len; i += 2) {
115 do {
116 ret = gpio_la_get_array(priv->descs, &state);
117 if (ret)
118 goto out;
119
120 ndelay(delay);
121 } while ((state & priv->trig_data[i]) != priv->trig_data[i + 1]);
122 }
123
124 /* With triggers, final state is also the first sample */
125 if (priv->trig_len)
126 la_buf[priv->buf_idx++] = state;
127
128 /* Sample */
129 while (priv->buf_idx < priv->blob.size) {
130 ret = gpio_la_get_array(priv->descs, &state);
131 if (ret)
132 goto out;
133
134 la_buf[priv->buf_idx++] = state;
135 ndelay(delay);
136 }
137 out:
138 preempt_enable_notrace();
139 local_irq_enable();
140 if (ret)
141 dev_err(priv->dev, "couldn't read GPIOs: %d\n", ret);
142
143 kfree(priv->trig_data);
144 priv->trig_data = NULL;
145 priv->trig_len = 0;
146
147 priv->blob_dent = debugfs_create_blob("sample_data", 0400, priv->debug_dir, &priv->blob);
148 mutex_unlock(&priv->blob_lock);
149
150 return ret;
151 }
152 DEFINE_DEBUGFS_ATTRIBUTE(fops_capture, NULL, fops_capture_set, "%llu\n");
153
fops_buf_size_get(void * data,u64 * val)154 static int fops_buf_size_get(void *data, u64 *val)
155 {
156 struct gpio_la_poll_priv *priv = data;
157
158 *val = priv->blob.size;
159
160 return 0;
161 }
162
fops_buf_release(void * data)163 static void fops_buf_release(void *data)
164 {
165 struct gpio_la_poll_priv *priv = data;
166
167 vfree(priv->blob.data);
168 }
169
fops_buf_size_set(void * data,u64 val)170 static int fops_buf_size_set(void *data, u64 val)
171 {
172 struct gpio_la_poll_priv *priv = data;
173 int ret = 0;
174 void *p;
175
176 if (!val)
177 return -EINVAL;
178
179 mutex_lock(&priv->blob_lock);
180
181 vfree(priv->blob.data);
182 p = vzalloc(val);
183 if (!p) {
184 val = 0;
185 ret = -ENOMEM;
186 }
187
188 priv->blob.data = p;
189 priv->blob.size = val;
190
191 mutex_unlock(&priv->blob_lock);
192 return ret;
193 }
194 DEFINE_DEBUGFS_ATTRIBUTE(fops_buf_size, fops_buf_size_get, fops_buf_size_set, "%llu\n");
195
trigger_open(struct inode * inode,struct file * file)196 static int trigger_open(struct inode *inode, struct file *file)
197 {
198 return single_open(file, NULL, inode->i_private);
199 }
200
trigger_write(struct file * file,const char __user * ubuf,size_t count,loff_t * offset)201 static ssize_t trigger_write(struct file *file, const char __user *ubuf,
202 size_t count, loff_t *offset)
203 {
204 struct seq_file *m = file->private_data;
205 struct gpio_la_poll_priv *priv = m->private;
206 char *buf;
207
208 /* upper limit is arbitrary but should be less than PAGE_SIZE */
209 if (count > 2048 || count & 1)
210 return -EINVAL;
211
212 buf = memdup_user(ubuf, count);
213 if (IS_ERR(buf))
214 return PTR_ERR(buf);
215
216 priv->trig_data = buf;
217 priv->trig_len = count;
218
219 return count;
220 }
221
222 static const struct file_operations fops_trigger = {
223 .owner = THIS_MODULE,
224 .open = trigger_open,
225 .write = trigger_write,
226 .release = single_release,
227 };
228
gpio_la_poll_probe(struct platform_device * pdev)229 static int gpio_la_poll_probe(struct platform_device *pdev)
230 {
231 struct gpio_la_poll_priv *priv;
232 struct device *dev = &pdev->dev;
233 const char *devname = dev_name(dev);
234 const char *gpio_names[GPIO_LA_MAX_PROBES];
235 char *meta = NULL;
236 unsigned int i, meta_len = 0;
237 int ret;
238
239 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
240 if (!priv)
241 return -ENOMEM;
242
243 ret = devm_mutex_init(dev, &priv->blob_lock);
244 if (ret)
245 return ret;
246
247 /* Initially allocate a buffer. It currently is NULL */
248 fops_buf_size_set(priv, GPIO_LA_DEFAULT_BUF_SIZE);
249 ret = devm_add_action_or_reset(dev, fops_buf_release, priv);
250 if (ret)
251 return ret;
252
253 priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN);
254 if (IS_ERR(priv->descs))
255 return PTR_ERR(priv->descs);
256
257 /* artificial limit to keep 1 byte per sample for now */
258 if (priv->descs->ndescs > GPIO_LA_MAX_PROBES)
259 return -EFBIG;
260
261 ret = device_property_read_string_array(dev, "probe-names", gpio_names,
262 priv->descs->ndescs);
263 if (ret >= 0 && ret != priv->descs->ndescs)
264 ret = -EBADR;
265 if (ret < 0)
266 return dev_err_probe(dev, ret, "error naming the GPIOs");
267
268 for (i = 0; i < priv->descs->ndescs; i++) {
269 unsigned int add_len;
270 char *new_meta, *consumer_name;
271
272 if (gpiod_cansleep(priv->descs->desc[i]))
273 return -EREMOTE;
274
275 consumer_name = kasprintf(GFP_KERNEL, "%s: %s", devname, gpio_names[i]);
276 if (!consumer_name)
277 return -ENOMEM;
278 gpiod_set_consumer_name(priv->descs->desc[i], consumer_name);
279 kfree(consumer_name);
280
281 /* '10' is length of 'probe00=\n\0' */
282 add_len = strlen(gpio_names[i]) + 10;
283
284 new_meta = devm_krealloc(dev, meta, meta_len + add_len, GFP_KERNEL);
285 if (!new_meta)
286 return -ENOMEM;
287
288 meta = new_meta;
289 meta_len += snprintf(meta + meta_len, add_len, "probe%02u=%s\n",
290 i + 1, gpio_names[i]);
291 }
292
293 platform_set_drvdata(pdev, priv);
294 priv->dev = dev;
295
296 priv->meta.data = meta;
297 priv->meta.size = meta_len;
298 priv->debug_dir = debugfs_create_dir(devname, gpio_la_poll_debug_dir);
299 debugfs_create_blob("meta_data", 0400, priv->debug_dir, &priv->meta);
300 debugfs_create_ulong("delay_ns", 0600, priv->debug_dir, &priv->delay_ns);
301 debugfs_create_ulong("delay_ns_acquisition", 0400, priv->debug_dir, &priv->acq_delay);
302 debugfs_create_file_unsafe("buf_size", 0600, priv->debug_dir, priv, &fops_buf_size);
303 debugfs_create_file_unsafe("capture", 0200, priv->debug_dir, priv, &fops_capture);
304 debugfs_create_file("trigger", 0200, priv->debug_dir, priv, &fops_trigger);
305
306 return 0;
307 }
308
gpio_la_poll_remove(struct platform_device * pdev)309 static void gpio_la_poll_remove(struct platform_device *pdev)
310 {
311 struct gpio_la_poll_priv *priv = platform_get_drvdata(pdev);
312
313 mutex_lock(&priv->blob_lock);
314 debugfs_remove_recursive(priv->debug_dir);
315 mutex_unlock(&priv->blob_lock);
316 }
317
318 static const struct of_device_id gpio_la_poll_of_match[] = {
319 { .compatible = "gpio-sloppy-logic-analyzer" },
320 { }
321 };
322 MODULE_DEVICE_TABLE(of, gpio_la_poll_of_match);
323
324 static struct platform_driver gpio_la_poll_device_driver = {
325 .probe = gpio_la_poll_probe,
326 .remove = gpio_la_poll_remove,
327 .driver = {
328 .name = GPIO_LA_NAME,
329 .of_match_table = gpio_la_poll_of_match,
330 }
331 };
332
gpio_la_poll_init(void)333 static int __init gpio_la_poll_init(void)
334 {
335 gpio_la_poll_debug_dir = debugfs_create_dir(GPIO_LA_NAME, NULL);
336
337 return platform_driver_register(&gpio_la_poll_device_driver);
338 }
339 /*
340 * Non-strict pin controllers can read GPIOs while being muxed to something else.
341 * To support that, we need to claim GPIOs before further pinmuxing happens. So,
342 * we probe early using 'late_initcall'
343 */
344 late_initcall(gpio_la_poll_init);
345
gpio_la_poll_exit(void)346 static void __exit gpio_la_poll_exit(void)
347 {
348 platform_driver_unregister(&gpio_la_poll_device_driver);
349 debugfs_remove_recursive(gpio_la_poll_debug_dir);
350 }
351 module_exit(gpio_la_poll_exit);
352
353 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
354 MODULE_DESCRIPTION("Sloppy logic analyzer using GPIOs");
355 MODULE_LICENSE("GPL");
356