diff options
Diffstat (limited to 'drivers/gpio/gpio-mockup.c')
-rw-r--r-- | drivers/gpio/gpio-mockup.c | 158 |
1 files changed, 80 insertions, 78 deletions
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 1652897fdf90..67ed4f238d43 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -7,10 +7,10 @@ * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/debugfs.h> -#include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irq_sim.h> @@ -19,21 +19,19 @@ #include <linux/platform_device.h> #include <linux/property.h> #include <linux/slab.h> +#include <linux/string_helpers.h> #include <linux/uaccess.h> #include "gpiolib.h" -#define GPIO_MOCKUP_NAME "gpio-mockup" #define GPIO_MOCKUP_MAX_GC 10 /* * We're storing two values per chip: the GPIO base and the number * of GPIO lines. */ #define GPIO_MOCKUP_MAX_RANGES (GPIO_MOCKUP_MAX_GC * 2) -/* Maximum of three properties + the sentinel. */ -#define GPIO_MOCKUP_MAX_PROP 4 - -#define gpio_mockup_err(...) pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__) +/* Maximum of four properties + the sentinel. */ +#define GPIO_MOCKUP_MAX_PROP 5 /* * struct gpio_pin_status - structure describing a GPIO status @@ -375,31 +373,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, debugfs_create_file(name, 0200, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); } - - return; -} - -static int gpio_mockup_name_lines(struct device *dev, - struct gpio_mockup_chip *chip) -{ - struct gpio_chip *gc = &chip->gc; - char **names; - int i; - - names = devm_kcalloc(dev, gc->ngpio, sizeof(char *), GFP_KERNEL); - if (!names) - return -ENOMEM; - - for (i = 0; i < gc->ngpio; i++) { - names[i] = devm_kasprintf(dev, GFP_KERNEL, - "%s-%d", gc->label, i); - if (!names[i]) - return -ENOMEM; - } - - gc->names = (const char *const *)names; - - return 0; } static void gpio_mockup_dispose_mappings(void *data) @@ -434,21 +407,14 @@ static int gpio_mockup_probe(struct platform_device *pdev) if (rv) return rv; - rv = device_property_read_string(dev, "chip-name", &name); + rv = device_property_read_string(dev, "chip-label", &name); if (rv) - name = NULL; + name = dev_name(dev); chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; - if (!name) { - name = devm_kasprintf(dev, GFP_KERNEL, - "%s-%c", pdev->name, pdev->id + 'A'); - if (!name) - return -ENOMEM; - } - mutex_init(&chip->lock); gc = &chip->gc; @@ -476,12 +442,6 @@ static int gpio_mockup_probe(struct platform_device *pdev) for (i = 0; i < gc->ngpio; i++) chip->lines[i].dir = GPIO_LINE_DIRECTION_IN; - if (device_property_read_bool(dev, "named-gpio-lines")) { - rv = gpio_mockup_name_lines(dev, chip); - if (rv) - return rv; - } - chip->irq_sim_domain = devm_irq_domain_create_sim(dev, NULL, gc->ngpio); if (IS_ERR(chip->irq_sim_domain)) @@ -502,7 +462,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) static struct platform_driver gpio_mockup_driver = { .driver = { - .name = GPIO_MOCKUP_NAME, + .name = "gpio-mockup", }, .probe = gpio_mockup_probe, }; @@ -522,14 +482,80 @@ static void gpio_mockup_unregister_pdevs(void) } } -static int __init gpio_mockup_init(void) +static __init char **gpio_mockup_make_line_names(const char *label, + unsigned int num_lines) +{ + unsigned int i; + char **names; + + names = kcalloc(num_lines + 1, sizeof(char *), GFP_KERNEL); + if (!names) + return NULL; + + for (i = 0; i < num_lines; i++) { + names[i] = kasprintf(GFP_KERNEL, "%s-%u", label, i); + if (!names[i]) { + kfree_strarray(names, i); + return NULL; + } + } + + return names; +} + +static int __init gpio_mockup_register_chip(int idx) { struct property_entry properties[GPIO_MOCKUP_MAX_PROP]; - int i, prop, num_chips, err = 0, base; struct platform_device_info pdevinfo; struct platform_device *pdev; + char **line_names = NULL; + char chip_label[32]; + int prop = 0, base; u16 ngpio; + memset(properties, 0, sizeof(properties)); + memset(&pdevinfo, 0, sizeof(pdevinfo)); + + snprintf(chip_label, sizeof(chip_label), "gpio-mockup-%c", idx + 'A'); + properties[prop++] = PROPERTY_ENTRY_STRING("chip-label", chip_label); + + base = gpio_mockup_range_base(idx); + if (base >= 0) + properties[prop++] = PROPERTY_ENTRY_U32("gpio-base", base); + + ngpio = base < 0 ? gpio_mockup_range_ngpio(idx) + : gpio_mockup_range_ngpio(idx) - base; + properties[prop++] = PROPERTY_ENTRY_U16("nr-gpios", ngpio); + + if (gpio_mockup_named_lines) { + line_names = gpio_mockup_make_line_names(chip_label, ngpio); + if (!line_names) + return -ENOMEM; + + properties[prop++] = PROPERTY_ENTRY_STRING_ARRAY_LEN( + "gpio-line-names", line_names, ngpio); + } + + pdevinfo.name = "gpio-mockup"; + pdevinfo.id = idx; + pdevinfo.properties = properties; + + pdev = platform_device_register_full(&pdevinfo); + kfree_strarray(line_names, ngpio); + if (IS_ERR(pdev)) { + pr_err("error registering device"); + return PTR_ERR(pdev); + } + + gpio_mockup_pdevs[idx] = pdev; + + return 0; +} + +static int __init gpio_mockup_init(void) +{ + int i, num_chips, err; + if ((gpio_mockup_num_ranges < 2) || (gpio_mockup_num_ranges % 2) || (gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES)) @@ -551,43 +577,19 @@ static int __init gpio_mockup_init(void) err = platform_driver_register(&gpio_mockup_driver); if (err) { - gpio_mockup_err("error registering platform driver\n"); + pr_err("error registering platform driver\n"); debugfs_remove_recursive(gpio_mockup_dbg_dir); return err; } for (i = 0; i < num_chips; i++) { - memset(properties, 0, sizeof(properties)); - memset(&pdevinfo, 0, sizeof(pdevinfo)); - prop = 0; - - base = gpio_mockup_range_base(i); - if (base >= 0) - properties[prop++] = PROPERTY_ENTRY_U32("gpio-base", - base); - - ngpio = base < 0 ? gpio_mockup_range_ngpio(i) - : gpio_mockup_range_ngpio(i) - base; - properties[prop++] = PROPERTY_ENTRY_U16("nr-gpios", ngpio); - - if (gpio_mockup_named_lines) - properties[prop++] = PROPERTY_ENTRY_BOOL( - "named-gpio-lines"); - - pdevinfo.name = GPIO_MOCKUP_NAME; - pdevinfo.id = i; - pdevinfo.properties = properties; - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - gpio_mockup_err("error registering device"); + err = gpio_mockup_register_chip(i); + if (err) { platform_driver_unregister(&gpio_mockup_driver); gpio_mockup_unregister_pdevs(); debugfs_remove_recursive(gpio_mockup_dbg_dir); - return PTR_ERR(pdev); + return err; } - - gpio_mockup_pdevs[i] = pdev; } return 0; |