1 /* 2 * GPIO Testing Device Driver 3 * 4 * Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com> 5 * Copyright (C) 2015-2016 Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> 6 * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15 #include <linux/init.h> 16 #include <linux/module.h> 17 #include <linux/gpio/driver.h> 18 #include <linux/gpio/consumer.h> 19 #include <linux/platform_device.h> 20 #include <linux/slab.h> 21 #include <linux/interrupt.h> 22 #include <linux/irq.h> 23 #include <linux/irq_sim.h> 24 #include <linux/debugfs.h> 25 #include <linux/uaccess.h> 26 27 #include "gpiolib.h" 28 29 #define GPIO_MOCKUP_NAME "gpio-mockup" 30 #define GPIO_MOCKUP_MAX_GC 10 31 /* 32 * We're storing two values per chip: the GPIO base and the number 33 * of GPIO lines. 34 */ 35 #define GPIO_MOCKUP_MAX_RANGES (GPIO_MOCKUP_MAX_GC * 2) 36 37 #define gpio_mockup_err(...) pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__) 38 39 enum { 40 GPIO_MOCKUP_DIR_OUT = 0, 41 GPIO_MOCKUP_DIR_IN = 1, 42 }; 43 44 /* 45 * struct gpio_pin_status - structure describing a GPIO status 46 * @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out 47 * @value: Configures status of the gpio as 0(low) or 1(high) 48 */ 49 struct gpio_mockup_line_status { 50 int dir; 51 int value; 52 }; 53 54 struct gpio_mockup_chip { 55 struct gpio_chip gc; 56 struct gpio_mockup_line_status *lines; 57 struct irq_sim irqsim; 58 struct dentry *dbg_dir; 59 }; 60 61 struct gpio_mockup_dbgfs_private { 62 struct gpio_mockup_chip *chip; 63 struct gpio_desc *desc; 64 int offset; 65 }; 66 67 struct gpio_mockup_platform_data { 68 int base; 69 int ngpio; 70 int index; 71 bool named_lines; 72 }; 73 74 static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES]; 75 static int gpio_mockup_params_nr; 76 module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400); 77 78 static bool gpio_mockup_named_lines; 79 module_param_named(gpio_mockup_named_lines, 80 gpio_mockup_named_lines, bool, 0400); 81 82 static struct dentry *gpio_mockup_dbg_dir; 83 84 static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) 85 { 86 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 87 88 return chip->lines[offset].value; 89 } 90 91 static void gpio_mockup_set(struct gpio_chip *gc, 92 unsigned int offset, int value) 93 { 94 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 95 96 chip->lines[offset].value = !!value; 97 } 98 99 static int gpio_mockup_dirout(struct gpio_chip *gc, 100 unsigned int offset, int value) 101 { 102 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 103 104 gpio_mockup_set(gc, offset, value); 105 chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT; 106 107 return 0; 108 } 109 110 static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset) 111 { 112 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 113 114 chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN; 115 116 return 0; 117 } 118 119 static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset) 120 { 121 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 122 123 return chip->lines[offset].dir; 124 } 125 126 static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) 127 { 128 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 129 130 return irq_sim_irqnum(&chip->irqsim, offset); 131 } 132 133 static ssize_t gpio_mockup_event_write(struct file *file, 134 const char __user *usr_buf, 135 size_t size, loff_t *ppos) 136 { 137 struct gpio_mockup_dbgfs_private *priv; 138 struct gpio_mockup_chip *chip; 139 struct seq_file *sfile; 140 struct gpio_desc *desc; 141 int rv, val; 142 143 rv = kstrtoint_from_user(usr_buf, size, 0, &val); 144 if (rv) 145 return rv; 146 if (val != 0 && val != 1) 147 return -EINVAL; 148 149 sfile = file->private_data; 150 priv = sfile->private; 151 desc = priv->desc; 152 chip = priv->chip; 153 154 gpiod_set_value_cansleep(desc, val); 155 irq_sim_fire(&chip->irqsim, priv->offset); 156 157 return size; 158 } 159 160 static int gpio_mockup_event_open(struct inode *inode, struct file *file) 161 { 162 return single_open(file, NULL, inode->i_private); 163 } 164 165 static const struct file_operations gpio_mockup_event_ops = { 166 .owner = THIS_MODULE, 167 .open = gpio_mockup_event_open, 168 .write = gpio_mockup_event_write, 169 .llseek = no_llseek, 170 }; 171 172 static void gpio_mockup_debugfs_setup(struct device *dev, 173 struct gpio_mockup_chip *chip) 174 { 175 struct gpio_mockup_dbgfs_private *priv; 176 struct dentry *evfile, *link; 177 struct gpio_chip *gc; 178 const char *devname; 179 char *name; 180 int i; 181 182 gc = &chip->gc; 183 devname = dev_name(&gc->gpiodev->dev); 184 185 chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir); 186 if (IS_ERR_OR_NULL(chip->dbg_dir)) 187 goto err; 188 189 link = debugfs_create_symlink(gc->label, gpio_mockup_dbg_dir, devname); 190 if (IS_ERR_OR_NULL(link)) 191 goto err; 192 193 for (i = 0; i < gc->ngpio; i++) { 194 name = devm_kasprintf(dev, GFP_KERNEL, "%d", i); 195 if (!name) 196 goto err; 197 198 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 199 if (!priv) 200 goto err; 201 202 priv->chip = chip; 203 priv->offset = i; 204 priv->desc = &gc->gpiodev->descs[i]; 205 206 evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, 207 &gpio_mockup_event_ops); 208 if (IS_ERR_OR_NULL(evfile)) 209 goto err; 210 } 211 212 return; 213 214 err: 215 dev_err(dev, "error creating debugfs event files\n"); 216 } 217 218 static int gpio_mockup_name_lines(struct device *dev, 219 struct gpio_mockup_chip *chip) 220 { 221 struct gpio_chip *gc = &chip->gc; 222 char **names; 223 int i; 224 225 names = devm_kcalloc(dev, gc->ngpio, sizeof(char *), GFP_KERNEL); 226 if (!names) 227 return -ENOMEM; 228 229 for (i = 0; i < gc->ngpio; i++) { 230 names[i] = devm_kasprintf(dev, GFP_KERNEL, 231 "%s-%d", gc->label, i); 232 if (!names[i]) 233 return -ENOMEM; 234 } 235 236 gc->names = (const char *const *)names; 237 238 return 0; 239 } 240 241 static int gpio_mockup_probe(struct platform_device *pdev) 242 { 243 struct gpio_mockup_platform_data *pdata; 244 struct gpio_mockup_chip *chip; 245 struct gpio_chip *gc; 246 int rv, base, ngpio; 247 struct device *dev; 248 char *name; 249 250 dev = &pdev->dev; 251 pdata = dev_get_platdata(dev); 252 base = pdata->base; 253 ngpio = pdata->ngpio; 254 255 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 256 if (!chip) 257 return -ENOMEM; 258 259 name = devm_kasprintf(dev, GFP_KERNEL, "%s-%c", 260 pdev->name, pdata->index); 261 if (!name) 262 return -ENOMEM; 263 264 gc = &chip->gc; 265 gc->base = base; 266 gc->ngpio = ngpio; 267 gc->label = name; 268 gc->owner = THIS_MODULE; 269 gc->parent = dev; 270 gc->get = gpio_mockup_get; 271 gc->set = gpio_mockup_set; 272 gc->direction_output = gpio_mockup_dirout; 273 gc->direction_input = gpio_mockup_dirin; 274 gc->get_direction = gpio_mockup_get_direction; 275 gc->to_irq = gpio_mockup_to_irq; 276 277 chip->lines = devm_kcalloc(dev, gc->ngpio, 278 sizeof(*chip->lines), GFP_KERNEL); 279 if (!chip->lines) 280 return -ENOMEM; 281 282 if (pdata->named_lines) { 283 rv = gpio_mockup_name_lines(dev, chip); 284 if (rv) 285 return rv; 286 } 287 288 rv = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio); 289 if (rv) 290 return rv; 291 292 rv = devm_gpiochip_add_data(dev, &chip->gc, chip); 293 if (rv) 294 return rv; 295 296 if (gpio_mockup_dbg_dir) 297 gpio_mockup_debugfs_setup(dev, chip); 298 299 return 0; 300 } 301 302 static struct platform_driver gpio_mockup_driver = { 303 .driver = { 304 .name = GPIO_MOCKUP_NAME, 305 }, 306 .probe = gpio_mockup_probe, 307 }; 308 309 static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC]; 310 311 static void gpio_mockup_unregister_pdevs(void) 312 { 313 struct platform_device *pdev; 314 int i; 315 316 for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) { 317 pdev = gpio_mockup_pdevs[i]; 318 319 if (pdev) 320 platform_device_unregister(pdev); 321 } 322 } 323 324 static int __init gpio_mockup_init(void) 325 { 326 int i, num_chips, err = 0, index = 'A'; 327 struct gpio_mockup_platform_data pdata; 328 struct platform_device *pdev; 329 330 if ((gpio_mockup_params_nr < 2) || 331 (gpio_mockup_params_nr % 2) || 332 (gpio_mockup_params_nr > GPIO_MOCKUP_MAX_RANGES)) 333 return -EINVAL; 334 335 /* Each chip is described by two values. */ 336 num_chips = gpio_mockup_params_nr / 2; 337 338 /* 339 * The second value in the <base GPIO - number of GPIOS> pair must 340 * always be greater than 0. 341 */ 342 for (i = 0; i < num_chips; i++) { 343 if (gpio_mockup_ranges[i * 2 + 1] < 0) 344 return -EINVAL; 345 } 346 347 gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL); 348 if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) 349 gpio_mockup_err("error creating debugfs directory\n"); 350 351 err = platform_driver_register(&gpio_mockup_driver); 352 if (err) { 353 gpio_mockup_err("error registering platform driver\n"); 354 return err; 355 } 356 357 for (i = 0; i < num_chips; i++) { 358 pdata.index = index++; 359 pdata.base = gpio_mockup_ranges[i * 2]; 360 pdata.ngpio = pdata.base < 0 361 ? gpio_mockup_ranges[i * 2 + 1] 362 : gpio_mockup_ranges[i * 2 + 1] - pdata.base; 363 pdata.named_lines = gpio_mockup_named_lines; 364 365 pdev = platform_device_register_resndata(NULL, 366 GPIO_MOCKUP_NAME, 367 i, NULL, 0, &pdata, 368 sizeof(pdata)); 369 if (!pdev) { 370 gpio_mockup_err("error registering device"); 371 platform_driver_unregister(&gpio_mockup_driver); 372 gpio_mockup_unregister_pdevs(); 373 return -ENOMEM; 374 } 375 376 gpio_mockup_pdevs[i] = pdev; 377 } 378 379 return 0; 380 } 381 382 static void __exit gpio_mockup_exit(void) 383 { 384 debugfs_remove_recursive(gpio_mockup_dbg_dir); 385 platform_driver_unregister(&gpio_mockup_driver); 386 gpio_mockup_unregister_pdevs(); 387 } 388 389 module_init(gpio_mockup_init); 390 module_exit(gpio_mockup_exit); 391 392 MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>"); 393 MODULE_AUTHOR("Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>"); 394 MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>"); 395 MODULE_DESCRIPTION("GPIO Testing driver"); 396 MODULE_LICENSE("GPL v2"); 397