diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-17 18:07:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-17 18:07:20 -0800 |
commit | a409ed156a90093a03fe6a93721ddf4c591eac87 (patch) | |
tree | 2a3c6f6f81c8b233627cf14da7149c7f312b475e /drivers/gpio/gpiolib.c | |
parent | 345b17acb1aa7a443741d9220f66b30d5ddd7c39 (diff) | |
parent | 7ac554888233468a9fd7c4f28721396952dd9959 (diff) |
Merge tag 'gpio-v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij:
"This is the bulk of the GPIO changes for the v5.11 kernel cycle:
Core changes:
- Retired the old set-up function for GPIO IRQ chips. All chips now
use the template struct gpio_irq_chip and pass that to the core to
be set up alongside the gpio_chip. We can finally get rid of the
old cruft.
- Some refactoring and clean up of the core code.
- Support edge event timestamps to be stamped using REALTIME (wall
clock) timestamps. We have found solid use cases for this, so we
support it.
New drivers:
- MStar MSC313 GPIO driver.
- HiSilicon GPIO driver.
Driver improvements:
- The PCA953x driver now also supports the NXP PCAL9554B/C chips.
- The mockup driver can now be probed from the device tree which is
pretty useful for virtual prototyping of devices.
- The Rcar driver now supports .get_multiple()
- The MXC driver dropped some legacy and became a pure device tree
client.
- The Exar driver was moved over to the IDA interface for
enumerating, and also switched over to using regmap for register
access"
* tag 'gpio-v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (87 commits)
MAINTAINERS: Remove reference to non-existing file
gpio: hisi: Do not require ACPI for COMPILE_TEST
MAINTAINERS: Add maintainer for HiSilicon GPIO driver
gpio: gpio-hisi: Add HiSilicon GPIO support
gpio: cs5535: Simplify the return expression of cs5535_gpio_probe()
gpiolib: irq hooks: fix recursion in gpiochip_irq_unmask
dt-bindings: mt7621-gpio: convert bindings to YAML format
gpiolib: cdev: Flag invalid GPIOs as used
gpio: put virtual gpio device into their own submenu
drivers: gpio: amd8111: use SPDX-License-Identifier
drivers: gpio: amd8111: prefer dev_err()/dev_info() over raw printk
drivers: gpio: bt8xx: prefer dev_err()/dev_warn() over of raw printk
gpio: Add TODO item for debugfs interface
gpio: just plain warning when nonexisting gpio requested
tools: gpio: add option to report wall-clock time to gpio-event-mon
tools: gpio: add support for reporting realtime event clock to lsgpio
gpiolib: cdev: allow edge event timestamps to be configured as REALTIME
gpio: msc313: MStar MSC313 GPIO driver
dt-bindings: gpio: Binding for MStar MSC313 GPIO controller
dt-bindings: gpio: Add a binding header for the MSC313 GPIO driver
...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 301 |
1 files changed, 84 insertions, 217 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6e3c4d7a7d14..b02cc2abd3b6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 + #include <linux/bitmap.h> #include <linux/kernel.h> #include <linux/module.h> @@ -119,7 +120,7 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) spin_unlock_irqrestore(&gpio_lock, flags); if (!gpio_is_valid(gpio)) - WARN(1, "invalid GPIO %d\n", gpio); + pr_warn("invalid GPIO %d\n", gpio); return NULL; } @@ -211,7 +212,7 @@ static int gpiochip_find_base(int ngpio) int gpiod_get_direction(struct gpio_desc *desc) { struct gpio_chip *gc; - unsigned offset; + unsigned int offset; int ret; gc = gpiod_to_chip(desc); @@ -771,9 +772,11 @@ err_free_ida: ida_free(&gpio_ida, gdev->id); err_free_gdev: /* failures here can mean systems won't boot... */ - pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, - gdev->base, gdev->base + gdev->ngpio - 1, - gc->label ? : "generic", ret); + if (ret != -EPROBE_DEFER) { + pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, + gdev->base, gdev->base + gdev->ngpio - 1, + gc->label ? : "generic", ret); + } kfree(gdev); return ret; } @@ -936,67 +939,6 @@ bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, } EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid); -/** - * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip - * @gc: the gpiochip to set the irqchip chain to - * @parent_irq: the irq number corresponding to the parent IRQ for this - * cascaded irqchip - * @parent_handler: the parent interrupt handler for the accumulated IRQ - * coming out of the gpiochip. If the interrupt is nested rather than - * cascaded, pass NULL in this handler argument - */ -static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gc, - unsigned int parent_irq, - irq_flow_handler_t parent_handler) -{ - struct gpio_irq_chip *girq = &gc->irq; - struct device *dev = &gc->gpiodev->dev; - - if (!girq->domain) { - chip_err(gc, "called %s before setting up irqchip\n", - __func__); - return; - } - - if (parent_handler) { - if (gc->can_sleep) { - chip_err(gc, - "you cannot have chained interrupts on a chip that may sleep\n"); - return; - } - girq->parents = devm_kcalloc(dev, 1, - sizeof(*girq->parents), - GFP_KERNEL); - if (!girq->parents) { - chip_err(gc, "out of memory allocating parent IRQ\n"); - return; - } - girq->parents[0] = parent_irq; - girq->num_parents = 1; - /* - * The parent irqchip is already using the chip_data for this - * irqchip, so our callbacks simply use the handler_data. - */ - irq_set_chained_handler_and_data(parent_irq, parent_handler, - gc); - } -} - -/** - * gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip - * @gc: the gpiochip to set the irqchip nested handler to - * @irqchip: the irqchip to nest to the gpiochip - * @parent_irq: the irq number corresponding to the parent IRQ for this - * nested irqchip - */ -void gpiochip_set_nested_irqchip(struct gpio_chip *gc, - struct irq_chip *irqchip, - unsigned int parent_irq) -{ - gpiochip_set_cascaded_irqchip(gc, parent_irq, NULL); -} -EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip); - #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /** @@ -1394,7 +1336,7 @@ void gpiochip_irq_domain_deactivate(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate); -static int gpiochip_to_irq(struct gpio_chip *gc, unsigned offset) +static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset) { struct irq_domain *domain = gc->irq.domain; @@ -1477,7 +1419,8 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gc) if (WARN_ON(gc->irq.irq_enable)) return; /* Check if the irqchip already has this hook... */ - if (irqchip->irq_enable == gpiochip_irq_enable) { + if (irqchip->irq_enable == gpiochip_irq_enable || + irqchip->irq_mask == gpiochip_irq_mask) { /* * ...and if so, give a gentle warning that this is bad * practice. @@ -1648,98 +1591,6 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc) } /** - * gpiochip_irqchip_add_key() - adds an irqchip to a gpiochip - * @gc: the gpiochip to add the irqchip to - * @irqchip: the irqchip to add to the gpiochip - * @first_irq: if not dynamically assigned, the base (first) IRQ to - * allocate gpiochip irqs from - * @handler: the irq handler to use (often a predefined irq core function) - * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE - * to have the core avoid setting up any default type in the hardware. - * @threaded: whether this irqchip uses a nested thread handler - * @lock_key: lockdep class for IRQ lock - * @request_key: lockdep class for IRQ request - * - * This function closely associates a certain irqchip with a certain - * gpiochip, providing an irq domain to translate the local IRQs to - * global irqs in the gpiolib core, and making sure that the gpiochip - * is passed as chip data to all related functions. Driver callbacks - * need to use gpiochip_get_data() to get their local state containers back - * from the gpiochip passed as chip data. An irqdomain will be stored - * in the gpiochip that shall be used by the driver to handle IRQ number - * translation. The gpiochip will need to be initialized and registered - * before calling this function. - * - * This function will handle two cell:ed simple IRQs and assumes all - * the pins on the gpiochip can generate a unique IRQ. Everything else - * need to be open coded. - */ -int gpiochip_irqchip_add_key(struct gpio_chip *gc, - struct irq_chip *irqchip, - unsigned int first_irq, - irq_flow_handler_t handler, - unsigned int type, - bool threaded, - struct lock_class_key *lock_key, - struct lock_class_key *request_key) -{ - struct device_node *of_node; - - if (!gc || !irqchip) - return -EINVAL; - - if (!gc->parent) { - chip_err(gc, "missing gpiochip .dev parent pointer\n"); - return -EINVAL; - } - gc->irq.threaded = threaded; - of_node = gc->parent->of_node; -#ifdef CONFIG_OF_GPIO - /* - * If the gpiochip has an assigned OF node this takes precedence - * FIXME: get rid of this and use gc->parent->of_node - * everywhere - */ - if (gc->of_node) - of_node = gc->of_node; -#endif - /* - * Specifying a default trigger is a terrible idea if DT or ACPI is - * used to configure the interrupts, as you may end-up with - * conflicting triggers. Tell the user, and reset to NONE. - */ - if (WARN(of_node && type != IRQ_TYPE_NONE, - "%pOF: Ignoring %d default trigger\n", of_node, type)) - type = IRQ_TYPE_NONE; - if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) { - acpi_handle_warn(ACPI_HANDLE(gc->parent), - "Ignoring %d default trigger\n", type); - type = IRQ_TYPE_NONE; - } - - gc->irq.chip = irqchip; - gc->irq.handler = handler; - gc->irq.default_type = type; - gc->to_irq = gpiochip_to_irq; - gc->irq.lock_key = lock_key; - gc->irq.request_key = request_key; - gc->irq.domain = irq_domain_add_simple(of_node, - gc->ngpio, first_irq, - &gpiochip_domain_ops, gc); - if (!gc->irq.domain) { - gc->irq.chip = NULL; - return -EINVAL; - } - - gpiochip_set_irq_hooks(gc); - - acpi_gpiochip_request_interrupts(gc); - - return 0; -} -EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key); - -/** * gpiochip_irqchip_add_domain() - adds an irqdomain to a gpiochip * @gc: the gpiochip to add the irqchip to * @domain: the irqdomain to add to the gpiochip @@ -1788,7 +1639,7 @@ static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc) * @gc: the gpiochip owning the GPIO * @offset: the offset of the GPIO to request for GPIO function */ -int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset) +int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset) { #ifdef CONFIG_PINCTRL if (list_empty(&gc->gpiodev->pin_ranges)) @@ -1804,7 +1655,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_request); * @gc: the gpiochip to request the gpio function for * @offset: the offset of the GPIO to free from GPIO function */ -void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset) +void gpiochip_generic_free(struct gpio_chip *gc, unsigned int offset) { #ifdef CONFIG_PINCTRL if (list_empty(&gc->gpiodev->pin_ranges)) @@ -1821,7 +1672,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_free); * @offset: the offset of the GPIO to apply the configuration * @config: the configuration to be applied */ -int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset, +int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset, unsigned long config) { return pinctrl_gpio_set_config(gc->gpiodev->base + offset, config); @@ -1985,11 +1836,9 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { desc_set_label(desc, label ? : "?"); - ret = 0; } else { - kfree_const(label); ret = -EBUSY; - goto done; + goto out_free_unlock; } if (gc->request) { @@ -2002,11 +1851,10 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) ret = -EINVAL; spin_lock_irqsave(&gpio_lock, flags); - if (ret < 0) { + if (ret) { desc_set_label(desc, NULL); - kfree_const(label); clear_bit(FLAG_REQUESTED, &desc->flags); - goto done; + goto out_free_unlock; } } if (gc->get_direction) { @@ -2015,8 +1863,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) gpiod_get_direction(desc); spin_lock_irqsave(&gpio_lock, flags); } -done: spin_unlock_irqrestore(&gpio_lock, flags); + return 0; + +out_free_unlock: + spin_unlock_irqrestore(&gpio_lock, flags); + kfree_const(label); return ret; } @@ -2068,7 +1920,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label) if (try_module_get(gdev->owner)) { ret = gpiod_request_commit(desc, label); - if (ret < 0) + if (ret) module_put(gdev->owner); else get_device(&gdev->dev); @@ -2151,7 +2003,7 @@ void gpiod_free(struct gpio_desc *desc) * help with diagnostics, and knowing that the signal is used as a GPIO * can help avoid accidentally multiplexing it to another controller. */ -const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned offset) +const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; @@ -2251,30 +2103,49 @@ static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset, return gc->set_config(gc, offset, config); } -static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) +static int gpio_set_config_with_argument(struct gpio_desc *desc, + enum pin_config_param mode, + u32 argument) { struct gpio_chip *gc = desc->gdev->chip; unsigned long config; - unsigned arg; + + config = pinconf_to_config_packed(mode, argument); + return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config); +} + +static int gpio_set_config_with_argument_optional(struct gpio_desc *desc, + enum pin_config_param mode, + u32 argument) +{ + struct device *dev = &desc->gdev->dev; + int gpio = gpio_chip_hwgpio(desc); + int ret; + + ret = gpio_set_config_with_argument(desc, mode, argument); + if (ret != -ENOTSUPP) + return ret; switch (mode) { - case PIN_CONFIG_BIAS_PULL_DOWN: - case PIN_CONFIG_BIAS_PULL_UP: - arg = 1; + case PIN_CONFIG_PERSIST_STATE: + dev_dbg(dev, "Persistence not supported for GPIO %d\n", gpio); break; - default: - arg = 0; + break; } - config = PIN_CONF_PACKED(mode, arg); - return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config); + return 0; +} + +static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) +{ + return gpio_set_config_with_argument(desc, mode, 0); } static int gpio_set_bias(struct gpio_desc *desc) { - int bias = 0; - int ret = 0; + enum pin_config_param bias; + unsigned int arg; if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) bias = PIN_CONFIG_BIAS_DISABLE; @@ -2282,13 +2153,28 @@ static int gpio_set_bias(struct gpio_desc *desc) bias = PIN_CONFIG_BIAS_PULL_UP; else if (test_bit(FLAG_PULL_DOWN, &desc->flags)) bias = PIN_CONFIG_BIAS_PULL_DOWN; + else + return 0; - if (bias) { - ret = gpio_set_config(desc, bias); - if (ret != -ENOTSUPP) - return ret; + switch (bias) { + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + arg = 1; + break; + + default: + arg = 0; + break; } - return 0; + + return gpio_set_config_with_argument_optional(desc, bias, arg); +} + +int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce) +{ + return gpio_set_config_with_argument_optional(desc, + PIN_CONFIG_INPUT_DEBOUNCE, + debounce); } /** @@ -2510,7 +2396,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_config); * 0 on success, %-ENOTSUPP if the controller doesn't support setting the * debounce time. */ -int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) +int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce) { unsigned long config; @@ -2529,11 +2415,6 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce); */ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) { - struct gpio_chip *gc; - unsigned long packed; - int gpio; - int rc; - VALIDATE_DESC(desc); /* * Handle FLAG_TRANSITORY first, enabling queries to gpiolib for @@ -2542,21 +2423,9 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) assign_bit(FLAG_TRANSITORY, &desc->flags, transitory); /* If the driver supports it, set the persistence state now */ - gc = desc->gdev->chip; - if (!gc->set_config) - return 0; - - packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, - !transitory); - gpio = gpio_chip_hwgpio(desc); - rc = gpio_do_set_config(gc, gpio, packed); - if (rc == -ENOTSUPP) { - dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", - gpio); - return 0; - } - - return rc; + return gpio_set_config_with_argument_optional(desc, + PIN_CONFIG_PERSIST_STATE, + !transitory); } EXPORT_SYMBOL_GPL(gpiod_set_transitory); @@ -3784,7 +3653,7 @@ struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags, label); - if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT)) + if (!gpiod_not_found(desc)) break; } @@ -3960,7 +3829,7 @@ 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 || desc == ERR_PTR(-ENOENT)) { + if (!desc || gpiod_not_found(desc)) { dev_dbg(dev, "using lookup tables for GPIO lookup\n"); desc = gpiod_find(dev, con_id, idx, &lookupflags); } @@ -3975,7 +3844,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * the device name as label */ ret = gpiod_request(desc, con_id ? con_id : devname); - if (ret < 0) { + if (ret) { if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { /* * This happens when there are several consumers for @@ -4095,10 +3964,8 @@ struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, struct gpio_desc *desc; desc = gpiod_get_index(dev, con_id, index, flags); - if (IS_ERR(desc)) { - if (PTR_ERR(desc) == -ENOENT) - return NULL; - } + if (gpiod_not_found(desc)) + return NULL; return desc; } @@ -4300,7 +4167,7 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev, struct gpio_descs *descs; descs = gpiod_get_array(dev, con_id, flags); - if (PTR_ERR(descs) == -ENOENT) + if (gpiod_not_found(descs)) return NULL; return descs; |