Merge tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Luinus Walleij:
 "Bulk GPIO changes for the v4.10 kernel cycle:

  Core changes:

   - Simplify threaded interrupt handling: instead of passing numbed
     parameters to gpiochip_irqchip_add_chained() we create a new call:
     gpiochip_irqchip_add_nested() so the two types are clearly
     semantically different. Also make sure that all nested chips call
     gpiochip_set_nested_irqchip() which is necessary for IRQ resend to
     work properly if it happens.

   - Return error on seek operations for the chardev.

   - Clamp values set as part of gpio[d]_direction_output() so that
     anything != 0 will be send down to the driver as "1" not the value
     passed in.

   - ACPI can now support naming of GPIO lines, hogs and holes in the
     GPIO lists.

  New drivers:

   - The SX150x driver was deemed unfit for the GPIO subsystem and was
     moved over to a combined GPIO+pinctrl driver in the pinctrl
     subsystem.

  New features:

   - Various cleanups to various drivers"

* tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (49 commits)
  gpio: merrifield: Implement gpio_get_direction callback
  gpio: merrifield: Add support for hardware debouncer
  gpio: chardev: Return error for seek operations
  gpio: arizona: Tidy up probe error path
  gpio: arizona: Remove pointless set of platform drvdata
  gpio: pl061: delete platform data handling
  gpio: pl061: move platform data into driver
  gpio: pl061: rename variable from chip to pl061
  gpio: pl061: rename state container struct
  gpio: pl061: use local state for parent IRQ storage
  gpio: set explicit nesting on drivers
  gpio: simplify adding threaded interrupts
  gpio: vf610: use builtin_platform_driver
  gpio: axp209: use correct register for GPIO input status
  gpio: stmpe: fix interrupt handling bug
  gpio: em: depnd on ARCH_SHMOBILE
  gpio: zx: depend on ARCH_ZX
  gpio: x86: update config dependencies for x86 specific hardware
  gpio: mb86s7x: use builtin_platform_driver
  gpio: etraxfs: use builtin_platform_driver
  ...
This commit is contained in:
Linus Torvalds
2016-12-13 07:54:57 -08:00
當前提交 061ad5038c
共有 44 個文件被更改,包括 2226 次插入1293 次删除

查看文件

@@ -986,7 +986,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp)
return -ENODEV;
get_device(&gdev->dev);
filp->private_data = gdev;
return 0;
return nonseekable_open(inode, filp);
}
/**
@@ -1011,7 +1012,7 @@ static const struct file_operations gpio_fileops = {
.release = gpio_chrdev_release,
.open = gpio_chrdev_open,
.owner = THIS_MODULE,
.llseek = noop_llseek,
.llseek = no_llseek,
.unlocked_ioctl = gpio_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = gpio_ioctl_compat,
@@ -1512,7 +1513,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
}
/**
* gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
* gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
* @gpiochip: the gpiochip to set the irqchip chain to
* @irqchip: the irqchip to chain to the gpiochip
* @parent_irq: the irq number corresponding to the parent IRQ for this
@@ -1521,10 +1522,10 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
* coming out of the gpiochip. If the interrupt is nested rather than
* cascaded, pass NULL in this handler argument
*/
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
irq_flow_handler_t parent_handler)
static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
irq_flow_handler_t parent_handler)
{
unsigned int offset;
@@ -1548,7 +1549,7 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
irq_set_chained_handler_and_data(parent_irq, parent_handler,
gpiochip);
gpiochip->irq_parent = parent_irq;
gpiochip->irq_chained_parent = parent_irq;
}
/* Set the parent IRQ for all affected IRQs */
@@ -1559,8 +1560,47 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
parent_irq);
}
}
/**
* gpiochip_set_chained_irqchip() - connects a chained irqchip to a gpiochip
* @gpiochip: the gpiochip to set the irqchip chain to
* @irqchip: the irqchip to chain to the gpiochip
* @parent_irq: the irq number corresponding to the parent IRQ for this
* chained 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
*/
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
irq_flow_handler_t parent_handler)
{
gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
parent_handler);
}
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
/**
* gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip
* @gpiochip: 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 *gpiochip,
struct irq_chip *irqchip,
int parent_irq)
{
if (!gpiochip->irq_nested) {
chip_err(gpiochip, "tried to nest a chained gpiochip\n");
return;
}
gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
NULL);
}
EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
/**
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
* @d: the irqdomain used by this irqchip
@@ -1583,8 +1623,8 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
*/
irq_set_lockdep_class(irq, chip->lock_key);
irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
/* Chips that can sleep need nested thread handlers */
if (chip->can_sleep && !chip->irq_not_threaded)
/* Chips that use nested thread handlers have them marked */
if (chip->irq_nested)
irq_set_nested_thread(irq, 1);
irq_set_noprobe(irq);
@@ -1602,7 +1642,7 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
{
struct gpio_chip *chip = d->host_data;
if (chip->can_sleep)
if (chip->irq_nested)
irq_set_nested_thread(irq, 0);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
@@ -1657,9 +1697,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
acpi_gpiochip_free_interrupts(gpiochip);
if (gpiochip->irq_parent) {
irq_set_chained_handler(gpiochip->irq_parent, NULL);
irq_set_handler_data(gpiochip->irq_parent, NULL);
if (gpiochip->irq_chained_parent) {
irq_set_chained_handler(gpiochip->irq_chained_parent, NULL);
irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
}
/* Remove all IRQ mappings and delete the domain */
@@ -1683,7 +1723,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
}
/**
* gpiochip_irqchip_add() - adds an irqchip to a gpiochip
* _gpiochip_irqchip_add() - adds an irqchip to a gpiochip
* @gpiochip: 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
@@ -1691,6 +1731,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
* @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.
* @nested: whether this is a nested irqchip calling handle_nested_irq()
* in its IRQ handler
* @lock_key: lockdep class
*
* This function closely associates a certain irqchip with a certain
@@ -1712,6 +1754,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
unsigned int first_irq,
irq_flow_handler_t handler,
unsigned int type,
bool nested,
struct lock_class_key *lock_key)
{
struct device_node *of_node;
@@ -1726,6 +1769,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
pr_err("missing gpiochip .dev parent pointer\n");
return -EINVAL;
}
gpiochip->irq_nested = nested;
of_node = gpiochip->parent->of_node;
#ifdef CONFIG_OF_GPIO
/*
@@ -2223,6 +2267,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
struct gpio_chip *gc = desc->gdev->chip;
int val = !!value;
int ret;
/* GPIOs used for IRQs shall not be set as output */
@@ -2242,7 +2287,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
goto set_output_value;
}
/* Emulate open drain by not actively driving the line high */
if (value)
if (val)
return gpiod_direction_input(desc);
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
@@ -2253,7 +2298,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
goto set_output_value;
}
/* Emulate open source by not actively driving the line low */
if (!value)
if (!val)
return gpiod_direction_input(desc);
} else {
/* Make sure to disable open drain/source hardware, if any */
@@ -2271,10 +2316,10 @@ set_output_value:
return -EIO;
}
ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value);
ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), val);
if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_value(desc_to_gpio(desc), 0, value);
trace_gpio_value(desc_to_gpio(desc), 0, val);
trace_gpio_direction(desc_to_gpio(desc), 0, ret);
return ret;
}
@@ -2314,6 +2359,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
VALIDATE_DESC(desc);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
else
value = !!value;
return _gpiod_direction_output_raw(desc, value);
}
EXPORT_SYMBOL_GPL(gpiod_direction_output);
@@ -2758,6 +2805,15 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
}
set_bit(FLAG_USED_AS_IRQ, &desc->flags);
/*
* If the consumer has not set up a label (such as when the
* IRQ is referenced from .to_irq()) we set up a label here
* so it is clear this is used as an interrupt.
*/
if (!desc->label)
desc_set_label(desc, "interrupt");
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
@@ -2772,10 +2828,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
*/
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
if (offset >= chip->ngpio)
struct gpio_desc *desc;
desc = gpiochip_get_desc(chip, offset);
if (IS_ERR(desc))
return;
clear_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
/* If we only had this marking, erase it */
if (desc->label && !strcmp(desc->label, "interrupt"))
desc_set_label(desc, NULL);
}
EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
@@ -3170,7 +3233,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
/* Process flags */
if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
status = gpiod_direction_output(desc,
dflags & GPIOD_FLAGS_BIT_DIR_VAL);
!!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
else
status = gpiod_direction_input(desc);