diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 09:40:46 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 10:09:12 -0800 |
commit | 8e5096607280d4e103389bfe8f8b7decbf538ff6 (patch) | |
tree | 60352a466e96c7b36d41263d7590ee79e0aaff35 /drivers/gpio/gpiolib.c | |
parent | 02d0a752460ea5dab34ce36c9ddc9c682e846a0d (diff) | |
parent | de755c330512364d3396c7da0c20b1c20b3b08b2 (diff) | |
download | blackbird-op-linux-8e5096607280d4e103389bfe8f8b7decbf538ff6.tar.gz blackbird-op-linux-8e5096607280d4e103389bfe8f8b7decbf538ff6.zip |
Merge tag 'gpio-v3.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO tree bulk changes from Linus Walleij:
"A big set this merge window, as we have much going on in this
subsystem. The changes to other subsystems (notably a slew of ARM
machines as I am doing away with their custom APIs) have all been
ACKed to the extent possible.
Major changes this time:
- Some core improvements and cleanups to the new GPIO descriptor API.
This seems to be working now so we can start the exodus to this
API, moving gradually away from the global GPIO numberspace.
- Incremental improvements to the ACPI GPIO core, and move the few
GPIO ACPI clients we have to the GPIO descriptor API right *now*
before we go any further. We actually managed to contain this
*before* we started to litter the kernel with yet another hackish
global numberspace for the ACPI GPIOs, which is a big win.
- The RFkill GPIO driver and all platforms using it have been
migrated to use the GPIO descriptors rather than fixed number
assignments. Tegra machine has been migrated as part of this.
- New drivers for MOXA ART, Xtensa GPIO32 and SMSC SCH311x. Those
should be really good examples of how I expect a nice GPIO driver
to look these days.
- Do away with custom GPIO implementations on a major part of the ARM
machines: ks8695, lpc32xx, mv78xx0. Make a first step towards the
same in the horribly convoluted Samsung S3C include forest. We
expect to continue to clean this up as we move forward.
- Flag GPIO lines used for IRQ on adnp, bcm-kona, em, intel-mid and
lynxpoint.
This makes the GPIOlib core aware that a certain GPIO line is used
for IRQs and can then enforce some semantics such as disallowing a
GPIO line marked as in use for IRQ to be switched to output mode.
- Drop all use of irq_set_chip_and_handler_name(). The name provided
in these cases were just unhelpful tags like "mux" or "demux".
- Extend the MCP23s08 driver to handle interrupts.
- Minor incremental improvements for rcar, lynxpoint, em 74x164 and
msm drivers.
- Some non-urgent bug fixes here and there, duplicate #includes and
that usual kind of cleanups"
Fix up broken Kconfig file manually to make this all compile.
* tag 'gpio-v3.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (71 commits)
gpio: mcp23s08: fix casting caused build warning
gpio: mcp23s08: depend on OF_GPIO
gpio: mcp23s08: Add irq functionality for i2c chips
ARM: S5P[v210|c100|64x0]: Fix build error
gpio: pxa: clamp gpio get value to [0,1]
ARM: s3c24xx: explicit dependency on <plat/gpio-cfg.h>
ARM: S3C[24|64]xx: move includes back under <mach/> scope
Documentation / ACPI: update to GPIO descriptor API
gpio / ACPI: get rid of acpi_gpio.h
gpio / ACPI: register to ACPI events automatically
mmc: sdhci-acpi: convert to use GPIO descriptor API
ARM: s3c24xx: fix build error
gpio: f7188x: set can_sleep attribute
gpio: samsung: Update documentation
gpio: samsung: Remove hardware.h inclusion
gpio: xtensa: depend on HAVE_XTENSA_GPIO32
gpio: clps711x: Enable driver compilation with COMPILE_TEST
gpio: clps711x: Use of_match_ptr()
net: rfkill: gpio: convert to descriptor-based GPIO interface
leds: s3c24xx: Fix build failure
...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 251 |
1 files changed, 137 insertions, 114 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c8a7c810bade..50c4922fe53a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -10,12 +10,13 @@ #include <linux/seq_file.h> #include <linux/gpio.h> #include <linux/of_gpio.h> -#include <linux/acpi_gpio.h> #include <linux/idr.h> #include <linux/slab.h> #include <linux/acpi.h> #include <linux/gpio/driver.h> +#include "gpiolib.h" + #define CREATE_TRACE_POINTS #include <trace/events/gpio.h> @@ -84,40 +85,57 @@ static DEFINE_IDR(dirent_idr); static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); +/* With descriptor prefix */ + #ifdef CONFIG_DEBUG_FS -#define gpiod_emerg(desc, fmt, ...) \ - pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_emerg(desc, fmt, ...) \ + pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ - pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_crit(desc, fmt, ...) \ + pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ - pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_err(desc, fmt, ...) \ + pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ - pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_warn(desc, fmt, ...) \ + pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ - pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_info(desc, fmt, ...) \ + pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ - pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_dbg(desc, fmt, ...) \ + pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) #else -#define gpiod_emerg(desc, fmt, ...) \ +#define gpiod_emerg(desc, fmt, ...) \ pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ +#define gpiod_crit(desc, fmt, ...) \ pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ +#define gpiod_err(desc, fmt, ...) \ pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ +#define gpiod_warn(desc, fmt, ...) \ pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ +#define gpiod_info(desc, fmt, ...) \ pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ +#define gpiod_dbg(desc, fmt, ...) \ pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) #endif +/* With chip prefix */ + +#define chip_emerg(chip, fmt, ...) \ + pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_crit(chip, fmt, ...) \ + pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_err(chip, fmt, ...) \ + pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_warn(chip, fmt, ...) \ + pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_info(chip, fmt, ...) \ + pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_dbg(chip, fmt, ...) \ + pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) + static inline void desc_set_label(struct gpio_desc *d, const char *label) { #ifdef CONFIG_DEBUG_FS @@ -151,9 +169,10 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip, unsigned int offset) { - unsigned int gpio = chip->base + offset; + if (offset >= chip->ngpio) + return ERR_PTR(-EINVAL); - return gpio_to_desc(gpio); + return &chip->desc[offset]; } /** @@ -187,7 +206,8 @@ static int gpio_ensure_requested(struct gpio_desc *desc) if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0, "autorequest GPIO-%d\n", gpio)) { if (!try_module_get(chip->owner)) { - pr_err("GPIO-%d: module can't be gotten \n", gpio); + gpiod_err(desc, "%s: module can't be gotten\n", + __func__); clear_bit(FLAG_REQUESTED, &desc->flags); /* lose */ return -EIO; @@ -808,8 +828,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) if (!test_bit(FLAG_REQUESTED, &desc->flags) || test_bit(FLAG_EXPORT, &desc->flags)) { spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", - __func__, desc_to_gpio(desc), + gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n", + __func__, test_bit(FLAG_REQUESTED, &desc->flags), test_bit(FLAG_EXPORT, &desc->flags)); status = -EPERM; @@ -857,8 +877,7 @@ fail_unregister_device: device_unregister(dev); fail_unlock: mutex_unlock(&sysfs_lock); - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_export); @@ -906,8 +925,7 @@ int gpiod_export_link(struct device *dev, const char *name, mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -951,8 +969,7 @@ unlock: mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -994,8 +1011,7 @@ void gpiod_unexport(struct gpio_desc *desc) } if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); } EXPORT_SYMBOL_GPL(gpiod_unexport); @@ -1034,8 +1050,7 @@ static int gpiochip_export(struct gpio_chip *chip) chip->desc[gpio++].chip = NULL; spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } return status; @@ -1051,15 +1066,14 @@ static void gpiochip_unexport(struct gpio_chip *chip) if (dev) { put_device(dev); device_unregister(dev); - chip->exported = 0; + chip->exported = false; status = 0; } else status = -ENODEV; mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } static int __init gpiolib_sysfs_init(void) @@ -1213,6 +1227,7 @@ int gpiochip_add(struct gpio_chip *chip) #endif of_gpiochip_add(chip); + acpi_gpiochip_add(chip); if (status) goto fail; @@ -1221,7 +1236,7 @@ int gpiochip_add(struct gpio_chip *chip) if (status) goto fail; - pr_debug("gpiochip_add: registered GPIOs %d to %d on device: %s\n", + pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); @@ -1231,7 +1246,7 @@ unlock: spin_unlock_irqrestore(&gpio_lock, flags); fail: /* failures here can mean systems won't boot... */ - pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", + pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; @@ -1254,6 +1269,7 @@ int gpiochip_remove(struct gpio_chip *chip) gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); + acpi_gpiochip_remove(chip); for (id = 0; id < chip->ngpio; id++) { if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { @@ -1339,8 +1355,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1361,9 +1376,8 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pinctrl_add_gpio_range(pctldev, &pin_range->range); - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n", - chip->label, gpio_offset, - gpio_offset + pin_range->range.npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n", + gpio_offset, gpio_offset + pin_range->range.npins - 1, pinctrl_dev_get_devname(pctldev), pin_group); list_add_tail(&pin_range->node, &chip->pin_ranges); @@ -1390,8 +1404,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1406,13 +1419,12 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, &pin_range->range); if (IS_ERR(pin_range->pctldev)) { ret = PTR_ERR(pin_range->pctldev); - pr_err("%s: GPIO chip: could not create pin range\n", - chip->label); + chip_err(chip, "could not create pin range\n"); kfree(pin_range); return ret; } - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", - chip->label, gpio_offset, gpio_offset + npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n", + gpio_offset, gpio_offset + npins - 1, pinctl_name, pin_offset, pin_offset + npins - 1); @@ -1499,8 +1511,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) } done: if (status) - pr_debug("_gpio_request: gpio-%d (%s) status %d\n", - desc_to_gpio(desc), label ? : "?", status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); spin_unlock_irqrestore(&gpio_lock, flags); return status; } @@ -1701,7 +1712,7 @@ int gpiod_direction_input(struct gpio_desc *desc) if (!chip->get || !chip->direction_input) { gpiod_warn(desc, "%s: missing get() or direction_input() operations\n", - __func__); + __func__); return -EIO; } @@ -1721,7 +1732,8 @@ int gpiod_direction_input(struct gpio_desc *desc) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -1739,7 +1751,7 @@ lose: fail: spin_unlock_irqrestore(&gpio_lock, flags); if (status) - gpiod_dbg(desc, "%s status %d\n", __func__, status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_direction_input); @@ -1806,7 +1818,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -2259,18 +2272,14 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); /** - * gpiod_add_table() - register GPIO device consumers - * @table: array of consumers to register - * @num: number of consumers in table + * gpiod_add_lookup_table() - register GPIO device consumers + * @table: table of consumers to register */ -void gpiod_add_table(struct gpiod_lookup *table, size_t size) +void gpiod_add_lookup_table(struct gpiod_lookup_table *table) { mutex_lock(&gpio_lookup_lock); - while (size--) { - list_add_tail(&table->list, &gpio_lookup_list); - table++; - } + list_add_tail(&table->list, &gpio_lookup_list); mutex_unlock(&gpio_lookup_lock); } @@ -2326,76 +2335,92 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, return desc; } -static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) +static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct gpio_desc *desc = ERR_PTR(-ENODEV); - unsigned int match, best = 0; - struct gpiod_lookup *p; + struct gpiod_lookup_table *table; mutex_lock(&gpio_lookup_lock); - list_for_each_entry(p, &gpio_lookup_list, list) { - match = 0; + list_for_each_entry(table, &gpio_lookup_list, list) { + if (table->dev_id && dev_id) { + /* + * Valid strings on both ends, must be identical to have + * a match + */ + if (!strcmp(table->dev_id, dev_id)) + goto found; + } else { + /* + * One of the pointers is NULL, so both must be to have + * a match + */ + if (dev_id == table->dev_id) + goto found; + } + } + table = NULL; - if (p->dev_id) { - if (!dev_id || strcmp(p->dev_id, dev_id)) - continue; +found: + mutex_unlock(&gpio_lookup_lock); + return table; +} - match += 2; - } +static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, + unsigned int idx, + enum gpio_lookup_flags *flags) +{ + struct gpio_desc *desc = ERR_PTR(-ENOENT); + struct gpiod_lookup_table *table; + struct gpiod_lookup *p; - if (p->con_id) { - if (!con_id || strcmp(p->con_id, con_id)) - continue; + table = gpiod_find_lookup_table(dev); + if (!table) + return desc; - match += 1; - } + for (p = &table->table[0]; p->chip_label; p++) { + struct gpio_chip *chip; + /* idx must always match exactly */ if (p->idx != idx) continue; - if (match > best) { - struct gpio_chip *chip; + /* If the lookup entry has a con_id, require exact match */ + if (p->con_id && (!con_id || strcmp(p->con_id, con_id))) + continue; - chip = find_chip_by_name(p->chip_label); + chip = find_chip_by_name(p->chip_label); - if (!chip) { - dev_warn(dev, "cannot find GPIO chip %s\n", - p->chip_label); - continue; - } + if (!chip) { + dev_err(dev, "cannot find GPIO chip %s\n", + p->chip_label); + return ERR_PTR(-ENODEV); + } - if (chip->ngpio <= p->chip_hwnum) { - dev_warn(dev, "GPIO chip %s has %d GPIOs\n", - chip->label, chip->ngpio); - continue; - } + if (chip->ngpio <= p->chip_hwnum) { + dev_err(dev, + "requested GPIO %d is out of range [0..%d] for chip %s\n", + idx, chip->ngpio, chip->label); + return ERR_PTR(-EINVAL); + } - desc = gpio_to_desc(chip->base + p->chip_hwnum); - *flags = p->flags; + desc = gpiochip_offset_to_desc(chip, p->chip_hwnum); + *flags = p->flags; - if (match != 3) - best = match; - else - break; - } + return desc; } - mutex_unlock(&gpio_lookup_lock); - return desc; } /** * gpio_get - obtain a GPIO for a given GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * * Return the GPIO descriptor corresponding to the function con_id of device - * dev, or an IS_ERR() condition if an error occured. + * dev, -ENOENT if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) { @@ -2405,14 +2430,16 @@ EXPORT_SYMBOL_GPL(gpiod_get); /** * gpiod_get_index - obtain a GPIO from a multi-index GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer * * This variant of gpiod_get() allows to access GPIOs other than the first * defined one for functions that define several GPIOs. * - * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error. + * Return a valid GPIO descriptor, -ENOENT if no GPIO has been assigned to the + * requested function and/or index, or another IS_ERR() code if an error + * occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, const char *con_id, @@ -2437,13 +2464,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * Either we are not using DT or ACPI, or their lookup did not return * a result. In that case, use platform lookup as a fallback. */ - if (!desc || IS_ERR(desc)) { - struct gpio_desc *pdesc; + if (!desc || desc == ERR_PTR(-ENOENT)) { dev_dbg(dev, "using lookup tables for GPIO lookup"); - pdesc = gpiod_find(dev, con_id, idx, &flags); - /* If used as fallback, do not replace the previous error */ - if (!IS_ERR(pdesc) || !desc) - desc = pdesc; + desc = gpiod_find(dev, con_id, idx, &flags); } if (IS_ERR(desc)) { |