1 // SPDX-License-Identifier: GPL-2.0-only
3 * Sloppy logic analyzer using GPIOs (to be run on an isolated CPU)
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.
11 * Copyright (C) Wolfram Sang <wsa@sang-engineering.com>
12 * Copyright (C) Renesas Electronics Corporation
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/mod_devicetable.h>
24 #include <linux/module.h>
25 #include <linux/mutex.h>
26 #include <linux/platform_device.h>
27 #include <linux/property.h>
28 #include <linux/slab.h>
29 #include <linux/sizes.h>
30 #include <linux/timekeeping.h>
31 #include <linux/types.h>
32 #include <linux/vmalloc.h>
34 #define GPIO_LA_NAME "gpio-sloppy-logic-analyzer"
35 #define GPIO_LA_DEFAULT_BUF_SIZE SZ_256K
36 /* can be increased but then we need to extend the u8 buffers */
37 #define GPIO_LA_MAX_PROBES 8
38 #define GPIO_LA_NUM_TESTS 1024
40 struct gpio_la_poll_priv
{
41 struct mutex blob_lock
; /* serialize access to the blob (data) */
43 struct gpio_descs
*descs
;
44 unsigned long delay_ns
;
45 unsigned long acq_delay
;
46 struct debugfs_blob_wrapper blob
;
47 struct dentry
*debug_dir
;
48 struct dentry
*blob_dent
;
49 struct debugfs_blob_wrapper meta
;
51 unsigned int trig_len
;
55 static struct dentry
*gpio_la_poll_debug_dir
;
57 static __always_inline
int gpio_la_get_array(struct gpio_descs
*d
, unsigned long *sptr
)
61 ret
= gpiod_get_array_value(d
->ndescs
, d
->desc
, d
->info
, sptr
);
62 if (ret
== 0 && fatal_signal_pending(current
))
68 static int fops_capture_set(void *data
, u64 val
)
70 struct gpio_la_poll_priv
*priv
= data
;
71 u8
*la_buf
= priv
->blob
.data
;
72 unsigned long state
= 0; /* zeroed because GPIO arrays are bitfields */
87 mutex_lock(&priv
->blob_lock
);
88 if (priv
->blob_dent
) {
89 debugfs_remove(priv
->blob_dent
);
90 priv
->blob_dent
= NULL
;
96 preempt_disable_notrace();
98 /* Measure delay of reading GPIOs */
99 start_time
= ktime_get();
100 for (i
= 0; i
< GPIO_LA_NUM_TESTS
; i
++) {
101 ret
= gpio_la_get_array(priv
->descs
, &state
);
106 priv
->acq_delay
= ktime_sub(ktime_get(), start_time
) / GPIO_LA_NUM_TESTS
;
107 if (priv
->delay_ns
< priv
->acq_delay
) {
112 delay
= priv
->delay_ns
- priv
->acq_delay
;
114 /* Wait for triggers */
115 for (i
= 0; i
< priv
->trig_len
; i
+= 2) {
117 ret
= gpio_la_get_array(priv
->descs
, &state
);
122 } while ((state
& priv
->trig_data
[i
]) != priv
->trig_data
[i
+ 1]);
125 /* With triggers, final state is also the first sample */
127 la_buf
[priv
->buf_idx
++] = state
;
130 while (priv
->buf_idx
< priv
->blob
.size
) {
131 ret
= gpio_la_get_array(priv
->descs
, &state
);
135 la_buf
[priv
->buf_idx
++] = state
;
139 preempt_enable_notrace();
142 dev_err(priv
->dev
, "couldn't read GPIOs: %d\n", ret
);
144 kfree(priv
->trig_data
);
145 priv
->trig_data
= NULL
;
148 priv
->blob_dent
= debugfs_create_blob("sample_data", 0400, priv
->debug_dir
, &priv
->blob
);
149 mutex_unlock(&priv
->blob_lock
);
153 DEFINE_DEBUGFS_ATTRIBUTE(fops_capture
, NULL
, fops_capture_set
, "%llu\n");
155 static int fops_buf_size_get(void *data
, u64
*val
)
157 struct gpio_la_poll_priv
*priv
= data
;
159 *val
= priv
->blob
.size
;
164 static int fops_buf_size_set(void *data
, u64 val
)
166 struct gpio_la_poll_priv
*priv
= data
;
173 mutex_lock(&priv
->blob_lock
);
175 vfree(priv
->blob
.data
);
183 priv
->blob
.size
= val
;
185 mutex_unlock(&priv
->blob_lock
);
188 DEFINE_DEBUGFS_ATTRIBUTE(fops_buf_size
, fops_buf_size_get
, fops_buf_size_set
, "%llu\n");
190 static int trigger_open(struct inode
*inode
, struct file
*file
)
192 return single_open(file
, NULL
, inode
->i_private
);
195 static ssize_t
trigger_write(struct file
*file
, const char __user
*ubuf
,
196 size_t count
, loff_t
*offset
)
198 struct seq_file
*m
= file
->private_data
;
199 struct gpio_la_poll_priv
*priv
= m
->private;
202 /* upper limit is arbitrary but should be less than PAGE_SIZE */
203 if (count
> 2048 || count
& 1)
206 buf
= memdup_user(ubuf
, count
);
210 priv
->trig_data
= buf
;
211 priv
->trig_len
= count
;
216 static const struct file_operations fops_trigger
= {
217 .owner
= THIS_MODULE
,
218 .open
= trigger_open
,
219 .write
= trigger_write
,
220 .release
= single_release
,
223 static int gpio_la_poll_probe(struct platform_device
*pdev
)
225 struct gpio_la_poll_priv
*priv
;
226 struct device
*dev
= &pdev
->dev
;
227 const char *devname
= dev_name(dev
);
228 const char *gpio_names
[GPIO_LA_MAX_PROBES
];
230 unsigned int i
, meta_len
= 0;
233 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
237 ret
= devm_mutex_init(dev
, &priv
->blob_lock
);
241 fops_buf_size_set(priv
, GPIO_LA_DEFAULT_BUF_SIZE
);
243 priv
->descs
= devm_gpiod_get_array(dev
, "probe", GPIOD_IN
);
244 if (IS_ERR(priv
->descs
))
245 return PTR_ERR(priv
->descs
);
247 /* artificial limit to keep 1 byte per sample for now */
248 if (priv
->descs
->ndescs
> GPIO_LA_MAX_PROBES
)
251 ret
= device_property_read_string_array(dev
, "probe-names", gpio_names
,
252 priv
->descs
->ndescs
);
253 if (ret
>= 0 && ret
!= priv
->descs
->ndescs
)
256 return dev_err_probe(dev
, ret
, "error naming the GPIOs");
258 for (i
= 0; i
< priv
->descs
->ndescs
; i
++) {
259 unsigned int add_len
;
260 char *new_meta
, *consumer_name
;
262 if (gpiod_cansleep(priv
->descs
->desc
[i
]))
265 consumer_name
= kasprintf(GFP_KERNEL
, "%s: %s", devname
, gpio_names
[i
]);
268 gpiod_set_consumer_name(priv
->descs
->desc
[i
], consumer_name
);
269 kfree(consumer_name
);
271 /* '10' is length of 'probe00=\n\0' */
272 add_len
= strlen(gpio_names
[i
]) + 10;
274 new_meta
= devm_krealloc(dev
, meta
, meta_len
+ add_len
, GFP_KERNEL
);
279 meta_len
+= snprintf(meta
+ meta_len
, add_len
, "probe%02u=%s\n",
280 i
+ 1, gpio_names
[i
]);
283 platform_set_drvdata(pdev
, priv
);
286 priv
->meta
.data
= meta
;
287 priv
->meta
.size
= meta_len
;
288 priv
->debug_dir
= debugfs_create_dir(devname
, gpio_la_poll_debug_dir
);
289 debugfs_create_blob("meta_data", 0400, priv
->debug_dir
, &priv
->meta
);
290 debugfs_create_ulong("delay_ns", 0600, priv
->debug_dir
, &priv
->delay_ns
);
291 debugfs_create_ulong("delay_ns_acquisition", 0400, priv
->debug_dir
, &priv
->acq_delay
);
292 debugfs_create_file_unsafe("buf_size", 0600, priv
->debug_dir
, priv
, &fops_buf_size
);
293 debugfs_create_file_unsafe("capture", 0200, priv
->debug_dir
, priv
, &fops_capture
);
294 debugfs_create_file_unsafe("trigger", 0200, priv
->debug_dir
, priv
, &fops_trigger
);
299 static void gpio_la_poll_remove(struct platform_device
*pdev
)
301 struct gpio_la_poll_priv
*priv
= platform_get_drvdata(pdev
);
303 mutex_lock(&priv
->blob_lock
);
304 debugfs_remove_recursive(priv
->debug_dir
);
305 mutex_unlock(&priv
->blob_lock
);
308 static const struct of_device_id gpio_la_poll_of_match
[] = {
309 { .compatible
= GPIO_LA_NAME
},
312 MODULE_DEVICE_TABLE(of
, gpio_la_poll_of_match
);
314 static struct platform_driver gpio_la_poll_device_driver
= {
315 .probe
= gpio_la_poll_probe
,
316 .remove
= gpio_la_poll_remove
,
318 .name
= GPIO_LA_NAME
,
319 .of_match_table
= gpio_la_poll_of_match
,
323 static int __init
gpio_la_poll_init(void)
325 gpio_la_poll_debug_dir
= debugfs_create_dir(GPIO_LA_NAME
, NULL
);
327 return platform_driver_register(&gpio_la_poll_device_driver
);
330 * Non-strict pin controllers can read GPIOs while being muxed to something else.
331 * To support that, we need to claim GPIOs before further pinmuxing happens. So,
332 * we probe early using 'late_initcall'
334 late_initcall(gpio_la_poll_init
);
336 static void __exit
gpio_la_poll_exit(void)
338 platform_driver_unregister(&gpio_la_poll_device_driver
);
339 debugfs_remove_recursive(gpio_la_poll_debug_dir
);
341 module_exit(gpio_la_poll_exit
);
343 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
344 MODULE_DESCRIPTION("Sloppy logic analyzer using GPIOs");
345 MODULE_LICENSE("GPL");