Lines Matching +full:out +full:- +full:gpios

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
7 * analyzer which can be affected by latencies and non-deterministic code
11 * Copyright (C) Wolfram Sang <wsa@sang-engineering.com>
34 #define GPIO_LA_NAME "gpio-sloppy-logic-analyzer"
61 ret = gpiod_get_array_value(d->ndescs, d->desc, d->info, sptr); in gpio_la_get_array()
63 ret = -EINTR; in gpio_la_get_array()
71 u8 *la_buf = priv->blob.data; in fops_capture_set()
82 return -ENOMEM; in fops_capture_set()
84 if (!priv->delay_ns) in fops_capture_set()
85 return -EINVAL; in fops_capture_set()
87 mutex_lock(&priv->blob_lock); in fops_capture_set()
88 if (priv->blob_dent) { in fops_capture_set()
89 debugfs_remove(priv->blob_dent); in fops_capture_set()
90 priv->blob_dent = NULL; in fops_capture_set()
93 priv->buf_idx = 0; in fops_capture_set()
98 /* Measure delay of reading GPIOs */ in fops_capture_set()
101 ret = gpio_la_get_array(priv->descs, &state); in fops_capture_set()
103 goto out; in fops_capture_set()
106 priv->acq_delay = ktime_sub(ktime_get(), start_time) / GPIO_LA_NUM_TESTS; in fops_capture_set()
107 if (priv->delay_ns < priv->acq_delay) { in fops_capture_set()
108 ret = -ERANGE; in fops_capture_set()
109 goto out; in fops_capture_set()
112 delay = priv->delay_ns - priv->acq_delay; in fops_capture_set()
115 for (i = 0; i < priv->trig_len; i += 2) { in fops_capture_set()
117 ret = gpio_la_get_array(priv->descs, &state); in fops_capture_set()
119 goto out; in fops_capture_set()
122 } while ((state & priv->trig_data[i]) != priv->trig_data[i + 1]); in fops_capture_set()
126 if (priv->trig_len) in fops_capture_set()
127 la_buf[priv->buf_idx++] = state; in fops_capture_set()
130 while (priv->buf_idx < priv->blob.size) { in fops_capture_set()
131 ret = gpio_la_get_array(priv->descs, &state); in fops_capture_set()
133 goto out; in fops_capture_set()
135 la_buf[priv->buf_idx++] = state; in fops_capture_set()
138 out: in fops_capture_set()
142 dev_err(priv->dev, "couldn't read GPIOs: %d\n", ret); in fops_capture_set()
144 kfree(priv->trig_data); in fops_capture_set()
145 priv->trig_data = NULL; in fops_capture_set()
146 priv->trig_len = 0; in fops_capture_set()
148 priv->blob_dent = debugfs_create_blob("sample_data", 0400, priv->debug_dir, &priv->blob); in fops_capture_set()
149 mutex_unlock(&priv->blob_lock); in fops_capture_set()
159 *val = priv->blob.size; in fops_buf_size_get()
171 return -EINVAL; in fops_buf_size_set()
173 mutex_lock(&priv->blob_lock); in fops_buf_size_set()
175 vfree(priv->blob.data); in fops_buf_size_set()
179 ret = -ENOMEM; in fops_buf_size_set()
182 priv->blob.data = p; in fops_buf_size_set()
183 priv->blob.size = val; in fops_buf_size_set()
185 mutex_unlock(&priv->blob_lock); in fops_buf_size_set()
192 return single_open(file, NULL, inode->i_private); in trigger_open()
198 struct seq_file *m = file->private_data; in trigger_write()
199 struct gpio_la_poll_priv *priv = m->private; in trigger_write()
204 return -EINVAL; in trigger_write()
210 priv->trig_data = buf; in trigger_write()
211 priv->trig_len = count; in trigger_write()
226 struct device *dev = &pdev->dev; in gpio_la_poll_probe()
235 return -ENOMEM; in gpio_la_poll_probe()
237 ret = devm_mutex_init(dev, &priv->blob_lock); in gpio_la_poll_probe()
243 priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN); in gpio_la_poll_probe()
244 if (IS_ERR(priv->descs)) in gpio_la_poll_probe()
245 return PTR_ERR(priv->descs); in gpio_la_poll_probe()
248 if (priv->descs->ndescs > GPIO_LA_MAX_PROBES) in gpio_la_poll_probe()
249 return -EFBIG; in gpio_la_poll_probe()
251 ret = device_property_read_string_array(dev, "probe-names", gpio_names, in gpio_la_poll_probe()
252 priv->descs->ndescs); in gpio_la_poll_probe()
253 if (ret >= 0 && ret != priv->descs->ndescs) in gpio_la_poll_probe()
254 ret = -EBADR; in gpio_la_poll_probe()
256 return dev_err_probe(dev, ret, "error naming the GPIOs"); in gpio_la_poll_probe()
258 for (i = 0; i < priv->descs->ndescs; i++) { in gpio_la_poll_probe()
262 if (gpiod_cansleep(priv->descs->desc[i])) in gpio_la_poll_probe()
263 return -EREMOTE; in gpio_la_poll_probe()
267 return -ENOMEM; in gpio_la_poll_probe()
268 gpiod_set_consumer_name(priv->descs->desc[i], consumer_name); in gpio_la_poll_probe()
276 return -ENOMEM; in gpio_la_poll_probe()
284 priv->dev = dev; in gpio_la_poll_probe()
286 priv->meta.data = meta; in gpio_la_poll_probe()
287 priv->meta.size = meta_len; in gpio_la_poll_probe()
288 priv->debug_dir = debugfs_create_dir(devname, gpio_la_poll_debug_dir); in gpio_la_poll_probe()
289 debugfs_create_blob("meta_data", 0400, priv->debug_dir, &priv->meta); in gpio_la_poll_probe()
290 debugfs_create_ulong("delay_ns", 0600, priv->debug_dir, &priv->delay_ns); in gpio_la_poll_probe()
291 debugfs_create_ulong("delay_ns_acquisition", 0400, priv->debug_dir, &priv->acq_delay); in gpio_la_poll_probe()
292 debugfs_create_file_unsafe("buf_size", 0600, priv->debug_dir, priv, &fops_buf_size); in gpio_la_poll_probe()
293 debugfs_create_file_unsafe("capture", 0200, priv->debug_dir, priv, &fops_capture); in gpio_la_poll_probe()
294 debugfs_create_file_unsafe("trigger", 0200, priv->debug_dir, priv, &fops_trigger); in gpio_la_poll_probe()
303 mutex_lock(&priv->blob_lock); in gpio_la_poll_remove()
304 debugfs_remove_recursive(priv->debug_dir); in gpio_la_poll_remove()
305 mutex_unlock(&priv->blob_lock); in gpio_la_poll_remove()
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,
343 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
344 MODULE_DESCRIPTION("Sloppy logic analyzer using GPIOs");