aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mockup.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-mockup.c')
-rw-r--r--drivers/gpio/gpio-mockup.c160
1 files changed, 82 insertions, 78 deletions
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index bc345185db26..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,41 +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();
- return PTR_ERR(pdev);
+ debugfs_remove_recursive(gpio_mockup_dbg_dir);
+ return err;
}
-
- gpio_mockup_pdevs[i] = pdev;
}
return 0;