346 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 for6 * easier usage and further documentation. Note that this is a last resort7 * analyzer which can be affected by latencies and non-deterministic code8 * paths. However, for e.g. remote development, it may be useful to get a first9 * view and aid further debugging.10 *11 * Copyright (C) Wolfram Sang <wsa@sang-engineering.com>12 * Copyright (C) Renesas Electronics Corporation13 */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_256K36/* can be increased but then we need to extend the u8 buffers */37#define GPIO_LA_MAX_PROBES 838#define GPIO_LA_NUM_TESTS 102439 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_new = 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");346