diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 396 |
1 files changed, 266 insertions, 130 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index aad84a6306c4..36ca5064486e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -73,7 +73,8 @@ LIST_HEAD(gpio_devices); static void gpiochip_free_hogs(struct gpio_chip *chip); static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, - struct lock_class_key *key); + struct lock_class_key *lock_key, + struct lock_class_key *request_key); static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); @@ -161,7 +162,7 @@ EXPORT_SYMBOL_GPL(desc_to_gpio); */ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) { - if (!desc || !desc->gdev || !desc->gdev->chip) + if (!desc || !desc->gdev) return NULL; return desc->gdev->chip; } @@ -195,7 +196,7 @@ static int gpiochip_find_base(int ngpio) * gpiod_get_direction - return the current direction of a GPIO * @desc: GPIO to get the direction of * - * Return GPIOF_DIR_IN or GPIOF_DIR_OUT, or an error code in case of error. + * Returns 0 for output, 1 for input, or an error code in case of error. * * This function may sleep if gpiod_cansleep() is true. */ @@ -459,6 +460,15 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) return -EINVAL; + /* + * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If + * the hardware actually supports enabling both at the same time the + * electrical result would be disastrous. + */ + if ((lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) && + (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) + return -EINVAL; + /* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */ if (!(lflags & GPIOHANDLE_REQUEST_OUTPUT) && ((lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) || @@ -505,6 +515,10 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE) set_bit(FLAG_OPEN_SOURCE, &desc->flags); + ret = gpiod_set_transitory(desc, false); + if (ret < 0) + goto out_free_descs; + /* * Lines have to be requested explicitly for input * or output, else the line will be treated "as is". @@ -587,6 +601,9 @@ out_free_lh: * @events: KFIFO for the GPIO events * @read_lock: mutex lock to protect reads from colliding with adding * new events to the FIFO + * @timestamp: cache for the timestamp storing it between hardirq + * and IRQ thread, used to bring the timestamp close to the actual + * event */ struct lineevent_state { struct gpio_device *gdev; @@ -597,17 +614,18 @@ struct lineevent_state { wait_queue_head_t wait; DECLARE_KFIFO(events, struct gpioevent_data, 16); struct mutex read_lock; + u64 timestamp; }; #define GPIOEVENT_REQUEST_VALID_FLAGS \ (GPIOEVENT_REQUEST_RISING_EDGE | \ GPIOEVENT_REQUEST_FALLING_EDGE) -static unsigned int lineevent_poll(struct file *filep, +static __poll_t lineevent_poll(struct file *filep, struct poll_table_struct *wait) { struct lineevent_state *le = filep->private_data; - unsigned int events = 0; + __poll_t events = 0; poll_wait(filep, &le->wait, wait); @@ -731,7 +749,10 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) struct gpioevent_data ge; int ret, level; - ge.timestamp = ktime_get_real_ns(); + /* Do not leak kernel stack to userspace */ + memset(&ge, 0, sizeof(ge)); + + ge.timestamp = le->timestamp; level = gpiod_get_value_cansleep(le->desc); if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE @@ -759,6 +780,19 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) return IRQ_HANDLED; } +static irqreturn_t lineevent_irq_handler(int irq, void *p) +{ + struct lineevent_state *le = p; + + /* + * Just store the timestamp in hardirq context so we get it as + * close in time as possible to the actual event. + */ + le->timestamp = ktime_get_real_ns(); + + return IRQ_WAKE_THREAD; +} + static int lineevent_create(struct gpio_device *gdev, void __user *ip) { struct gpioevent_request eventreq; @@ -851,7 +885,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) /* Request a thread to read the events */ ret = request_threaded_irq(le->irq, - NULL, + lineevent_irq_handler, lineevent_irq_thread, irqflags, le->label, @@ -1049,7 +1083,7 @@ static void gpiodevice_release(struct device *dev) list_del(&gdev->list); ida_simple_remove(&gpio_ida, gdev->id); - kfree(gdev->label); + kfree_const(gdev->label); kfree(gdev->descs); kfree(gdev); } @@ -1100,7 +1134,8 @@ static void gpiochip_setup_devs(void) } int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, - struct lock_class_key *key) + struct lock_class_key *lock_key, + struct lock_class_key *request_key) { unsigned long flags; int status = 0; @@ -1157,10 +1192,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, goto err_free_descs; } - if (chip->label) - gdev->label = kstrdup(chip->label, GFP_KERNEL); - else - gdev->label = kstrdup("unknown", GFP_KERNEL); + gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL); if (!gdev->label) { status = -ENOMEM; goto err_free_descs; @@ -1207,31 +1239,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, struct gpio_desc *desc = &gdev->descs[i]; desc->gdev = gdev; - /* - * REVISIT: most hardware initializes GPIOs as inputs - * (often with pullups enabled) so power usage is - * minimized. Linux code should set the gpio direction - * first thing; but until it does, and in case - * chip->get_direction is not set, we may expose the - * wrong direction in sysfs. - */ - - if (chip->get_direction) { - /* - * If we have .get_direction, set up the initial - * direction flag from the hardware. - */ - int dir = chip->get_direction(chip, i); - if (!dir) - set_bit(FLAG_IS_OUT, &desc->flags); - } else if (!chip->direction_input) { - /* - * If the chip lacks the .direction_input callback - * we logically assume all lines are outputs. - */ - set_bit(FLAG_IS_OUT, &desc->flags); - } + /* REVISIT: most hardware initializes GPIOs as inputs (often + * with pullups enabled) so power usage is minimized. Linux + * code should set the gpio direction first thing; but until + * it does, and in case chip->get_direction is not set, we may + * expose the wrong direction in sysfs. + */ + desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0; } #ifdef CONFIG_PINCTRL @@ -1246,7 +1261,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (status) goto err_remove_from_list; - status = gpiochip_add_irqchip(chip, key); + status = gpiochip_add_irqchip(chip, lock_key, request_key); if (status) goto err_remove_chip; @@ -1281,7 +1296,7 @@ err_remove_from_list: list_del(&gdev->list); spin_unlock_irqrestore(&gpio_lock, flags); err_free_label: - kfree(gdev->label); + kfree_const(gdev->label); err_free_descs: kfree(gdev->descs); err_free_gdev: @@ -1381,7 +1396,7 @@ static int devm_gpio_chip_match(struct device *dev, void *res, void *data) } /** - * devm_gpiochip_add_data() - Resource manager piochip_add_data() + * devm_gpiochip_add_data() - Resource manager gpiochip_add_data() * @dev: the device pointer on which irq_chip belongs to. * @chip: the chip to register, with chip->base initialized * @data: driver-private data associated with this chip @@ -1508,14 +1523,15 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) gpiochip->irq.valid_mask = NULL; } -static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, - unsigned int offset) +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, + unsigned int offset) { /* No mask means all valid */ if (likely(!gpiochip->irq.valid_mask)) return true; return test_bit(offset, gpiochip->irq.valid_mask); } +EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid); /** * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip @@ -1632,7 +1648,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. */ - irq_set_lockdep_class(irq, chip->irq.lock_key); + irq_set_lockdep_class(irq, chip->irq.lock_key, chip->irq.request_key); irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler); /* Chips that use nested thread handlers have them marked */ if (chip->irq.threaded) @@ -1712,10 +1728,12 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) /** * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip * @gpiochip: the GPIO chip to add the IRQ chip to - * @lock_key: lockdep class + * @lock_key: lockdep class for IRQ lock + * @request_key: lockdep class for IRQ request */ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, - struct lock_class_key *lock_key) + struct lock_class_key *lock_key, + struct lock_class_key *request_key) { struct irq_chip *irqchip = gpiochip->irq.chip; const struct irq_domain_ops *ops; @@ -1753,6 +1771,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, gpiochip->to_irq = gpiochip_to_irq; gpiochip->irq.default_type = type; gpiochip->irq.lock_key = lock_key; + gpiochip->irq.request_key = request_key; if (gpiochip->irq.domain_ops) ops = gpiochip->irq.domain_ops; @@ -1850,7 +1869,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * @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 + * @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 @@ -1872,7 +1892,8 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, irq_flow_handler_t handler, unsigned int type, bool threaded, - struct lock_class_key *lock_key) + struct lock_class_key *lock_key, + struct lock_class_key *request_key) { struct device_node *of_node; @@ -1913,6 +1934,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, gpiochip->irq.default_type = type; gpiochip->to_irq = gpiochip_to_irq; gpiochip->irq.lock_key = lock_key; + gpiochip->irq.request_key = request_key; gpiochip->irq.domain = irq_domain_add_simple(of_node, gpiochip->ngpio, first_irq, &gpiochip_domain_ops, gpiochip); @@ -1940,7 +1962,8 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key); #else /* CONFIG_GPIOLIB_IRQCHIP */ static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip, - struct lock_class_key *key) + struct lock_class_key *lock_key, + struct lock_class_key *request_key) { return 0; } @@ -2165,40 +2188,37 @@ done: * macro to avoid endless duplication. If the desc is NULL it is an * optional GPIO and calls should just bail out. */ +static int validate_desc(const struct gpio_desc *desc, const char *func) +{ + if (!desc) + return 0; + if (IS_ERR(desc)) { + pr_warn("%s: invalid GPIO (errorpointer)\n", func); + return PTR_ERR(desc); + } + if (!desc->gdev) { + pr_warn("%s: invalid GPIO (no device)\n", func); + return -EINVAL; + } + if (!desc->gdev->chip) { + dev_warn(&desc->gdev->dev, + "%s: backing chip is gone\n", func); + return 0; + } + return 1; +} + #define VALIDATE_DESC(desc) do { \ - if (!desc) \ - return 0; \ - if (IS_ERR(desc)) { \ - pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \ - return PTR_ERR(desc); \ - } \ - if (!desc->gdev) { \ - pr_warn("%s: invalid GPIO (no device)\n", __func__); \ - return -EINVAL; \ - } \ - if ( !desc->gdev->chip ) { \ - dev_warn(&desc->gdev->dev, \ - "%s: backing chip is gone\n", __func__); \ - return 0; \ - } } while (0) + int __valid = validate_desc(desc, __func__); \ + if (__valid <= 0) \ + return __valid; \ + } while (0) #define VALIDATE_DESC_VOID(desc) do { \ - if (!desc) \ - return; \ - if (IS_ERR(desc)) { \ - pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \ - return; \ - } \ - if (!desc->gdev) { \ - pr_warn("%s: invalid GPIO (no device)\n", __func__); \ + int __valid = validate_desc(desc, __func__); \ + if (__valid <= 0) \ return; \ - } \ - if (!desc->gdev->chip) { \ - dev_warn(&desc->gdev->dev, \ - "%s: backing chip is gone\n", __func__); \ - return; \ - } } while (0) - + } while (0) int gpiod_request(struct gpio_desc *desc, const char *label) { @@ -2447,7 +2467,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw); */ int gpiod_direction_output(struct gpio_desc *desc, int value) { - struct gpio_chip *gc = desc->gdev->chip; + struct gpio_chip *gc; int ret; VALIDATE_DESC(desc); @@ -2464,6 +2484,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) return -EIO; } + gc = desc->gdev->chip; if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { /* First see if we can enable open drain in hardware */ ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), @@ -2521,6 +2542,50 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) EXPORT_SYMBOL_GPL(gpiod_set_debounce); /** + * gpiod_set_transitory - Lose or retain GPIO state on suspend or reset + * @desc: descriptor of the GPIO for which to configure persistence + * @transitory: True to lose state on suspend or reset, false for persistence + * + * Returns: + * 0 on success, otherwise a negative error code. + */ +int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) +{ + struct gpio_chip *chip; + unsigned long packed; + int gpio; + int rc; + + VALIDATE_DESC(desc); + /* + * Handle FLAG_TRANSITORY first, enabling queries to gpiolib for + * persistence state. + */ + if (transitory) + set_bit(FLAG_TRANSITORY, &desc->flags); + else + clear_bit(FLAG_TRANSITORY, &desc->flags); + + /* If the driver supports it, set the persistence state now */ + chip = desc->gdev->chip; + if (!chip->set_config) + return 0; + + packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, + !transitory); + gpio = gpio_chip_hwgpio(desc); + rc = chip->set_config(chip, gpio, packed); + if (rc == -ENOTSUPP) { + dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", + gpio); + return 0; + } + + return rc; +} +EXPORT_SYMBOL_GPL(gpiod_set_transitory); + +/** * gpiod_is_active_low - test whether a GPIO is active-low or not * @desc: the gpio descriptor to test * @@ -2884,6 +2949,27 @@ void gpiod_set_raw_value(struct gpio_desc *desc, int value) EXPORT_SYMBOL_GPL(gpiod_set_raw_value); /** + * gpiod_set_value_nocheck() - set a GPIO line value without checking + * @desc: the descriptor to set the value on + * @value: value to set + * + * This sets the value of a GPIO line backing a descriptor, applying + * different semantic quirks like active low and open drain/source + * handling. + */ +static void gpiod_set_value_nocheck(struct gpio_desc *desc, int value) +{ + if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) + value = !value; + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + gpio_set_open_drain_value_commit(desc, value); + else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + gpio_set_open_source_value_commit(desc, value); + else + gpiod_set_raw_value_commit(desc, value); +} + +/** * gpiod_set_value() - assign a gpio's value * @desc: gpio whose value will be assigned * @value: value to assign @@ -2897,16 +2983,8 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_value); void gpiod_set_value(struct gpio_desc *desc, int value) { VALIDATE_DESC_VOID(desc); - /* Should be using gpiod_set_value_cansleep() */ WARN_ON(desc->gdev->chip->can_sleep); - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - value = !value; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - gpio_set_open_drain_value_commit(desc, value); - else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - gpio_set_open_source_value_commit(desc, value); - else - gpiod_set_raw_value_commit(desc, value); + gpiod_set_value_nocheck(desc, value); } EXPORT_SYMBOL_GPL(gpiod_set_value); @@ -3107,8 +3185,7 @@ bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset) if (offset >= chip->ngpio) return false; - return !test_bit(FLAG_SLEEP_MAY_LOSE_VALUE, - &chip->gpiodev->descs[offset].flags); + return !test_bit(FLAG_TRANSITORY, &chip->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent); @@ -3234,9 +3311,7 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) { might_sleep_if(extra_checks); VALIDATE_DESC_VOID(desc); - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - value = !value; - gpiod_set_raw_value_commit(desc, value); + gpiod_set_value_nocheck(desc, value); } EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); @@ -3545,8 +3620,10 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, if (lflags & GPIO_OPEN_SOURCE) set_bit(FLAG_OPEN_SOURCE, &desc->flags); - if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE) - set_bit(FLAG_SLEEP_MAY_LOSE_VALUE, &desc->flags); + + status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); + if (status < 0) + return status; /* No particular flag request, return here... */ if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { @@ -3586,6 +3663,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, struct gpio_desc *desc = NULL; int status; enum gpio_lookup_flags lookupflags = 0; + /* Maybe we have a device name, maybe not */ + const char *devname = dev ? dev_name(dev) : "?"; dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id); @@ -3614,7 +3693,11 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, return desc; } - status = gpiod_request(desc, con_id); + /* + * If a connection label was passed use that, else attempt to use + * the device name as label + */ + status = gpiod_request(desc, con_id ? con_id : devname); if (status < 0) return ERR_PTR(status); @@ -3630,17 +3713,88 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, EXPORT_SYMBOL_GPL(gpiod_get_index); /** + * gpiod_get_from_of_node() - obtain a GPIO from an OF node + * @node: handle of the OF node + * @propname: name of the DT property representing the GPIO + * @index: index of the GPIO to obtain for the consumer + * @dflags: GPIO initialization flags + * @label: label to attach to the requested GPIO + * + * Returns: + * On successful request the GPIO pin is configured in accordance with + * provided @dflags. If the node does not have the requested GPIO + * property, NULL is returned. + * + * In case of error an ERR_PTR() is returned. + */ +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + struct gpio_desc *desc; + unsigned long lflags = 0; + enum of_gpio_flags flags; + bool active_low = false; + bool single_ended = false; + bool open_drain = false; + bool transitory = false; + int ret; + + desc = of_get_named_gpiod_flags(node, propname, + index, &flags); + + if (!desc || IS_ERR(desc)) { + /* If it is not there, just return NULL */ + if (PTR_ERR(desc) == -ENOENT) + return NULL; + return desc; + } + + active_low = flags & OF_GPIO_ACTIVE_LOW; + single_ended = flags & OF_GPIO_SINGLE_ENDED; + open_drain = flags & OF_GPIO_OPEN_DRAIN; + transitory = flags & OF_GPIO_TRANSITORY; + + ret = gpiod_request(desc, label); + if (ret) + return ERR_PTR(ret); + + if (active_low) + lflags |= GPIO_ACTIVE_LOW; + + if (single_ended) { + if (open_drain) + lflags |= GPIO_OPEN_DRAIN; + else + lflags |= GPIO_OPEN_SOURCE; + } + + if (transitory) + lflags |= GPIO_TRANSITORY; + + ret = gpiod_configure_flags(desc, propname, lflags, dflags); + if (ret < 0) { + gpiod_put(desc); + return ERR_PTR(ret); + } + + return desc; +} +EXPORT_SYMBOL(gpiod_get_from_of_node); + +/** * fwnode_get_named_gpiod - obtain a GPIO from firmware node * @fwnode: handle of the firmware node * @propname: name of the firmware property representing the GPIO - * @index: index of the GPIO to obtain in the consumer + * @index: index of the GPIO to obtain for the consumer * @dflags: GPIO initialization flags * @label: label to attach to the requested GPIO * * This function can be used for drivers that get their configuration - * from firmware. + * from opaque firmware. * - * Function properly finds the corresponding GPIO using whatever is the + * The function properly finds the corresponding GPIO using whatever is the * underlying firmware interface and then makes sure that the GPIO * descriptor is requested before it is returned to the caller. * @@ -3657,53 +3811,35 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, { struct gpio_desc *desc = ERR_PTR(-ENODEV); unsigned long lflags = 0; - bool active_low = false; - bool single_ended = false; - bool open_drain = false; int ret; if (!fwnode) return ERR_PTR(-EINVAL); if (is_of_node(fwnode)) { - enum of_gpio_flags flags; - - desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname, - index, &flags); - if (!IS_ERR(desc)) { - active_low = flags & OF_GPIO_ACTIVE_LOW; - single_ended = flags & OF_GPIO_SINGLE_ENDED; - open_drain = flags & OF_GPIO_OPEN_DRAIN; - } + desc = gpiod_get_from_of_node(to_of_node(fwnode), + propname, index, + dflags, + label); + return desc; } else if (is_acpi_node(fwnode)) { struct acpi_gpio_info info; desc = acpi_node_get_gpiod(fwnode, propname, index, &info); - if (!IS_ERR(desc)) { - active_low = info.polarity == GPIO_ACTIVE_LOW; - ret = acpi_gpio_update_gpiod_flags(&dflags, info.flags); - if (ret) - pr_debug("Override GPIO initialization flags\n"); - } - } + if (IS_ERR(desc)) + return desc; - if (IS_ERR(desc)) - return desc; + acpi_gpio_update_gpiod_flags(&dflags, &info); + + if (info.polarity == GPIO_ACTIVE_LOW) + lflags |= GPIO_ACTIVE_LOW; + } + /* Currently only ACPI takes this path */ ret = gpiod_request(desc, label); if (ret) return ERR_PTR(ret); - if (active_low) - lflags |= GPIO_ACTIVE_LOW; - - if (single_ended) { - if (open_drain) - lflags |= GPIO_OPEN_DRAIN; - else - lflags |= GPIO_OPEN_SOURCE; - } - ret = gpiod_configure_flags(desc, propname, lflags, dflags); if (ret < 0) { gpiod_put(desc); |