aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartosz Golaszewski <brgl@bgdev.pl>2018-04-10 16:30:28 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-05-16 08:35:24 -0400
commita411e81e61df24023f40255145d8f023402002c9 (patch)
tree9fce75978e1553b206fea79511034453a174b5b7
parent192a35b1348275c8decf42452d382be21add938c (diff)
gpiolib: add hogs support for machine code
Board files constitute a significant part of the users of the legacy GPIO framework. In many cases they only export a line and set its desired value. We could use GPIO hogs for that like we do for DT and ACPI but there's no support for that in machine code. This patch proposes to extend the machine.h API with support for registering hog tables in board files. Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/driver-api/gpio/board.rst16
-rw-r--r--drivers/gpio/gpiolib.c67
-rw-r--r--include/linux/gpio/machine.h31
3 files changed, 114 insertions, 0 deletions
diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
index 25d62b2e9fd0..2c112553df84 100644
--- a/Documentation/driver-api/gpio/board.rst
+++ b/Documentation/driver-api/gpio/board.rst
@@ -177,3 +177,19 @@ mapping and is thus transparent to GPIO consumers.
177 177
178A set of functions such as gpiod_set_value() is available to work with 178A set of functions such as gpiod_set_value() is available to work with
179the new descriptor-oriented interface. 179the new descriptor-oriented interface.
180
181Boards using platform data can also hog GPIO lines by defining GPIO hog tables.
182
183.. code-block:: c
184
185 struct gpiod_hog gpio_hog_table[] = {
186 GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH),
187 { }
188 };
189
190And the table can be added to the board code as follows::
191
192 gpiod_add_hogs(gpio_hog_table);
193
194The line will be hogged as soon as the gpiochip is created or - in case the
195chip was created earlier - when the hog table is registered.
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 43aeb07343ec..547adc149b62 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -71,6 +71,9 @@ static DEFINE_MUTEX(gpio_lookup_lock);
71static LIST_HEAD(gpio_lookup_list); 71static LIST_HEAD(gpio_lookup_list);
72LIST_HEAD(gpio_devices); 72LIST_HEAD(gpio_devices);
73 73
74static DEFINE_MUTEX(gpio_machine_hogs_mutex);
75static LIST_HEAD(gpio_machine_hogs);
76
74static void gpiochip_free_hogs(struct gpio_chip *chip); 77static void gpiochip_free_hogs(struct gpio_chip *chip);
75static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, 78static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
76 struct lock_class_key *lock_key, 79 struct lock_class_key *lock_key,
@@ -1171,6 +1174,41 @@ err_remove_device:
1171 return status; 1174 return status;
1172} 1175}
1173 1176
1177static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
1178{
1179 struct gpio_desc *desc;
1180 int rv;
1181
1182 desc = gpiochip_get_desc(chip, hog->chip_hwnum);
1183 if (IS_ERR(desc)) {
1184 pr_err("%s: unable to get GPIO desc: %ld\n",
1185 __func__, PTR_ERR(desc));
1186 return;
1187 }
1188
1189 if (desc->flags & FLAG_IS_HOGGED)
1190 return;
1191
1192 rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags);
1193 if (rv)
1194 pr_err("%s: unable to hog GPIO line (%s:%u): %d\n",
1195 __func__, chip->label, hog->chip_hwnum, rv);
1196}
1197
1198static void machine_gpiochip_add(struct gpio_chip *chip)
1199{
1200 struct gpiod_hog *hog;
1201
1202 mutex_lock(&gpio_machine_hogs_mutex);
1203
1204 list_for_each_entry(hog, &gpio_machine_hogs, list) {
1205 if (!strcmp(chip->label, hog->chip_label))
1206 gpiochip_machine_hog(chip, hog);
1207 }
1208
1209 mutex_unlock(&gpio_machine_hogs_mutex);
1210}
1211
1174static void gpiochip_setup_devs(void) 1212static void gpiochip_setup_devs(void)
1175{ 1213{
1176 struct gpio_device *gdev; 1214 struct gpio_device *gdev;
@@ -1326,6 +1364,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
1326 1364
1327 acpi_gpiochip_add(chip); 1365 acpi_gpiochip_add(chip);
1328 1366
1367 machine_gpiochip_add(chip);
1368
1329 /* 1369 /*
1330 * By first adding the chardev, and then adding the device, 1370 * By first adding the chardev, and then adding the device,
1331 * we get a device node entry in sysfs under 1371 * we get a device node entry in sysfs under
@@ -3462,6 +3502,33 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
3462} 3502}
3463EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table); 3503EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table);
3464 3504
3505/**
3506 * gpiod_add_hogs() - register a set of GPIO hogs from machine code
3507 * @hogs: table of gpio hog entries with a zeroed sentinel at the end
3508 */
3509void gpiod_add_hogs(struct gpiod_hog *hogs)
3510{
3511 struct gpio_chip *chip;
3512 struct gpiod_hog *hog;
3513
3514 mutex_lock(&gpio_machine_hogs_mutex);
3515
3516 for (hog = &hogs[0]; hog->chip_label; hog++) {
3517 list_add_tail(&hog->list, &gpio_machine_hogs);
3518
3519 /*
3520 * The chip may have been registered earlier, so check if it
3521 * exists and, if so, try to hog the line now.
3522 */
3523 chip = find_chip_by_name(hog->chip_label);
3524 if (chip)
3525 gpiochip_machine_hog(chip, hog);
3526 }
3527
3528 mutex_unlock(&gpio_machine_hogs_mutex);
3529}
3530EXPORT_SYMBOL_GPL(gpiod_add_hogs);
3531
3465static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) 3532static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
3466{ 3533{
3467 const char *dev_id = dev ? dev_name(dev) : NULL; 3534 const char *dev_id = dev ? dev_name(dev) : NULL;
diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h
index b2f2dc638463..daa44eac9241 100644
--- a/include/linux/gpio/machine.h
+++ b/include/linux/gpio/machine.h
@@ -39,6 +39,23 @@ struct gpiod_lookup_table {
39 struct gpiod_lookup table[]; 39 struct gpiod_lookup table[];
40}; 40};
41 41
42/**
43 * struct gpiod_hog - GPIO line hog table
44 * @chip_label: name of the chip the GPIO belongs to
45 * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO
46 * @line_name: consumer name for the hogged line
47 * @lflags: mask of GPIO lookup flags
48 * @dflags: GPIO flags used to specify the direction and value
49 */
50struct gpiod_hog {
51 struct list_head list;
52 const char *chip_label;
53 u16 chip_hwnum;
54 const char *line_name;
55 enum gpio_lookup_flags lflags;
56 int dflags;
57};
58
42/* 59/*
43 * Simple definition of a single GPIO under a con_id 60 * Simple definition of a single GPIO under a con_id
44 */ 61 */
@@ -59,10 +76,23 @@ struct gpiod_lookup_table {
59 .flags = _flags, \ 76 .flags = _flags, \
60} 77}
61 78
79/*
80 * Simple definition of a single GPIO hog in an array.
81 */
82#define GPIO_HOG(_chip_label, _chip_hwnum, _line_name, _lflags, _dflags) \
83{ \
84 .chip_label = _chip_label, \
85 .chip_hwnum = _chip_hwnum, \
86 .line_name = _line_name, \
87 .lflags = _lflags, \
88 .dflags = _dflags, \
89}
90
62#ifdef CONFIG_GPIOLIB 91#ifdef CONFIG_GPIOLIB
63void gpiod_add_lookup_table(struct gpiod_lookup_table *table); 92void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
64void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n); 93void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n);
65void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); 94void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
95void gpiod_add_hogs(struct gpiod_hog *hogs);
66#else 96#else
67static inline 97static inline
68void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} 98void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {}
@@ -70,6 +100,7 @@ static inline
70void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {} 100void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {}
71static inline 101static inline
72void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} 102void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {}
103static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {}
73#endif 104#endif
74 105
75#endif /* __LINUX_GPIO_MACHINE_H */ 106#endif /* __LINUX_GPIO_MACHINE_H */