Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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/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>
 33
 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
 39
 40struct gpio_la_poll_priv {
 41	struct mutex blob_lock; /* serialize access to the blob (data) */
 42	u32 buf_idx;
 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;
 50	struct device *dev;
 51	unsigned int trig_len;
 52	u8 *trig_data;
 53};
 54
 55static struct dentry *gpio_la_poll_debug_dir;
 56
 57static __always_inline int gpio_la_get_array(struct gpio_descs *d, unsigned long *sptr)
 58{
 59	int ret;
 60
 61	ret = gpiod_get_array_value(d->ndescs, d->desc, d->info, sptr);
 62	if (ret == 0 && fatal_signal_pending(current))
 63		ret = -EINTR;
 64
 65	return ret;
 66}
 67
 68static int fops_capture_set(void *data, u64 val)
 69{
 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 */
 73	unsigned long delay;
 74	ktime_t start_time;
 75	unsigned int i;
 76	int ret;
 77
 78	if (!val)
 79		return 0;
 80
 81	if (!la_buf)
 82		return -ENOMEM;
 83
 84	if (!priv->delay_ns)
 85		return -EINVAL;
 86
 87	mutex_lock(&priv->blob_lock);
 88	if (priv->blob_dent) {
 89		debugfs_remove(priv->blob_dent);
 90		priv->blob_dent = NULL;
 91	}
 92
 93	priv->buf_idx = 0;
 94
 95	local_irq_disable();
 96	preempt_disable_notrace();
 97
 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);
102		if (ret)
103			goto out;
104	}
105
106	priv->acq_delay = ktime_sub(ktime_get(), start_time) / GPIO_LA_NUM_TESTS;
107	if (priv->delay_ns < priv->acq_delay) {
108		ret = -ERANGE;
109		goto out;
110	}
111
112	delay = priv->delay_ns - priv->acq_delay;
113
114	/* Wait for triggers */
115	for (i = 0; i < priv->trig_len; i += 2) {
116		do {
117			ret = gpio_la_get_array(priv->descs, &state);
118			if (ret)
119				goto out;
120
121			ndelay(delay);
122		} while ((state & priv->trig_data[i]) != priv->trig_data[i + 1]);
123	}
124
125	/* With triggers, final state is also the first sample */
126	if (priv->trig_len)
127		la_buf[priv->buf_idx++] = state;
128
129	/* Sample */
130	while (priv->buf_idx < priv->blob.size) {
131		ret = gpio_la_get_array(priv->descs, &state);
132		if (ret)
133			goto out;
134
135		la_buf[priv->buf_idx++] = state;
136		ndelay(delay);
137	}
138out:
139	preempt_enable_notrace();
140	local_irq_enable();
141	if (ret)
142		dev_err(priv->dev, "couldn't read GPIOs: %d\n", ret);
143
144	kfree(priv->trig_data);
145	priv->trig_data = NULL;
146	priv->trig_len = 0;
147
148	priv->blob_dent = debugfs_create_blob("sample_data", 0400, priv->debug_dir, &priv->blob);
149	mutex_unlock(&priv->blob_lock);
150
151	return ret;
152}
153DEFINE_DEBUGFS_ATTRIBUTE(fops_capture, NULL, fops_capture_set, "%llu\n");
154
155static int fops_buf_size_get(void *data, u64 *val)
156{
157	struct gpio_la_poll_priv *priv = data;
158
159	*val = priv->blob.size;
160
161	return 0;
162}
163
164static int fops_buf_size_set(void *data, u64 val)
165{
166	struct gpio_la_poll_priv *priv = data;
167	int ret = 0;
168	void *p;
169
170	if (!val)
171		return -EINVAL;
172
173	mutex_lock(&priv->blob_lock);
174
175	vfree(priv->blob.data);
176	p = vzalloc(val);
177	if (!p) {
178		val = 0;
179		ret = -ENOMEM;
180	}
181
182	priv->blob.data = p;
183	priv->blob.size = val;
184
185	mutex_unlock(&priv->blob_lock);
186	return ret;
187}
188DEFINE_DEBUGFS_ATTRIBUTE(fops_buf_size, fops_buf_size_get, fops_buf_size_set, "%llu\n");
189
190static int trigger_open(struct inode *inode, struct file *file)
191{
192	return single_open(file, NULL, inode->i_private);
193}
194
195static ssize_t trigger_write(struct file *file, const char __user *ubuf,
196			     size_t count, loff_t *offset)
197{
198	struct seq_file *m = file->private_data;
199	struct gpio_la_poll_priv *priv = m->private;
200	char *buf;
201
202	/* upper limit is arbitrary but should be less than PAGE_SIZE */
203	if (count > 2048 || count & 1)
204		return -EINVAL;
205
206	buf = memdup_user(ubuf, count);
207	if (IS_ERR(buf))
208		return PTR_ERR(buf);
209
210	priv->trig_data = buf;
211	priv->trig_len = count;
212
213	return count;
214}
215
216static const struct file_operations fops_trigger = {
217	.owner = THIS_MODULE,
218	.open = trigger_open,
219	.write = trigger_write,
220	.release = single_release,
221};
222
223static int gpio_la_poll_probe(struct platform_device *pdev)
224{
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];
229	char *meta = NULL;
230	unsigned int i, meta_len = 0;
231	int ret;
232
233	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
234	if (!priv)
235		return -ENOMEM;
236
237	ret = devm_mutex_init(dev, &priv->blob_lock);
238	if (ret)
239		return ret;
240
241	fops_buf_size_set(priv, GPIO_LA_DEFAULT_BUF_SIZE);
242
243	priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN);
244	if (IS_ERR(priv->descs))
245		return PTR_ERR(priv->descs);
246
247	/* artificial limit to keep 1 byte per sample for now */
248	if (priv->descs->ndescs > GPIO_LA_MAX_PROBES)
249		return -EFBIG;
250
251	ret = device_property_read_string_array(dev, "probe-names", gpio_names,
252						priv->descs->ndescs);
253	if (ret >= 0 && ret != priv->descs->ndescs)
254		ret = -EBADR;
255	if (ret < 0)
256		return dev_err_probe(dev, ret, "error naming the GPIOs");
257
258	for (i = 0; i < priv->descs->ndescs; i++) {
259		unsigned int add_len;
260		char *new_meta, *consumer_name;
261
262		if (gpiod_cansleep(priv->descs->desc[i]))
263			return -EREMOTE;
264
265		consumer_name = kasprintf(GFP_KERNEL, "%s: %s", devname, gpio_names[i]);
266		if (!consumer_name)
267			return -ENOMEM;
268		gpiod_set_consumer_name(priv->descs->desc[i], consumer_name);
269		kfree(consumer_name);
270
271		/* '10' is length of 'probe00=\n\0' */
272		add_len = strlen(gpio_names[i]) + 10;
273
274		new_meta = devm_krealloc(dev, meta, meta_len + add_len, GFP_KERNEL);
275		if (!new_meta)
276			return -ENOMEM;
277
278		meta = new_meta;
279		meta_len += snprintf(meta + meta_len, add_len, "probe%02u=%s\n",
280				     i + 1, gpio_names[i]);
281	}
282
283	platform_set_drvdata(pdev, priv);
284	priv->dev = dev;
285
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);
295
296	return 0;
297}
298
299static void gpio_la_poll_remove(struct platform_device *pdev)
300{
301	struct gpio_la_poll_priv *priv = platform_get_drvdata(pdev);
302
303	mutex_lock(&priv->blob_lock);
304	debugfs_remove_recursive(priv->debug_dir);
305	mutex_unlock(&priv->blob_lock);
306}
307
308static const struct of_device_id gpio_la_poll_of_match[] = {
309	{ .compatible = GPIO_LA_NAME },
310	{ }
311};
312MODULE_DEVICE_TABLE(of, gpio_la_poll_of_match);
313
314static struct platform_driver gpio_la_poll_device_driver = {
315	.probe = gpio_la_poll_probe,
316	.remove = gpio_la_poll_remove,
317	.driver = {
318		.name = GPIO_LA_NAME,
319		.of_match_table = gpio_la_poll_of_match,
320	}
321};
322
323static int __init gpio_la_poll_init(void)
324{
325	gpio_la_poll_debug_dir = debugfs_create_dir(GPIO_LA_NAME, NULL);
326
327	return platform_driver_register(&gpio_la_poll_device_driver);
328}
329/*
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'
333 */
334late_initcall(gpio_la_poll_init);
335
336static void __exit gpio_la_poll_exit(void)
337{
338	platform_driver_unregister(&gpio_la_poll_device_driver);
339	debugfs_remove_recursive(gpio_la_poll_debug_dir);
340}
341module_exit(gpio_la_poll_exit);
342
343MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
344MODULE_DESCRIPTION("Sloppy logic analyzer using GPIOs");
345MODULE_LICENSE("GPL");