From fd7337fdb9bce420033c28af4c07b73e34e692c1 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 14 Aug 2015 16:10:58 +0200 Subject: gpiolib-of: Rename gpio_hog functions to be generic The gpio hogging functions are currently only used for gpio-hogging. But these functions are widely generic ones which parse gpio device nodes in the DT. Signed-off-by: Markus Pargmann Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index fa6e3c8..5fe34a9 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -119,20 +119,20 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, EXPORT_SYMBOL(of_get_named_gpio_flags); /** - * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API + * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API * @np: device node to get GPIO from * @name: GPIO line name * @lflags: gpio_lookup_flags - returned from of_find_gpio() or - * of_get_gpio_hog() + * of_parse_own_gpio() * @dflags: gpiod_flags - optional GPIO initialization flags * * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno * value on the error condition. */ -static struct gpio_desc *of_get_gpio_hog(struct device_node *np, - const char **name, - enum gpio_lookup_flags *lflags, - enum gpiod_flags *dflags) +static struct gpio_desc *of_parse_own_gpio(struct device_node *np, + const char **name, + enum gpio_lookup_flags *lflags, + enum gpiod_flags *dflags) { struct device_node *chip_np; enum of_gpio_flags xlate_flags; @@ -196,13 +196,13 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np, } /** - * of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested + * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on * * This is only used by of_gpiochip_add to request/set GPIO initial * configuration. */ -static void of_gpiochip_scan_hogs(struct gpio_chip *chip) +static void of_gpiochip_scan_gpios(struct gpio_chip *chip) { struct gpio_desc *desc = NULL; struct device_node *np; @@ -214,7 +214,7 @@ static void of_gpiochip_scan_hogs(struct gpio_chip *chip) if (!of_property_read_bool(np, "gpio-hog")) continue; - desc = of_get_gpio_hog(np, &name, &lflags, &dflags); + desc = of_parse_own_gpio(np, &name, &lflags, &dflags); if (IS_ERR(desc)) continue; @@ -440,7 +440,7 @@ int of_gpiochip_add(struct gpio_chip *chip) of_node_get(chip->of_node); - of_gpiochip_scan_hogs(chip); + of_gpiochip_scan_gpios(chip); return 0; } -- cgit v0.10.2 From c0017ed71966a19ec40c7bc900d4338ddfbc4105 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 14 Aug 2015 16:10:59 +0200 Subject: gpio: Introduce gpio descriptor 'name' The latest gpio hogging mechanism assigns each gpio a 'line-name' in the devicetree. The 'name' field is different from the 'label' field. 'label' is only used for requested GPIOs to describe its current use by driver or userspace. The 'name' field describes the GPIO itself, not the use. This is most likely identical to the label in the schematic on the GPIO line and should help to find this particular GPIO. This is equivalent to the gpiochip->names array. However names should be stored in the GPIO descriptor. We will use gpiochip->names in the future only as initializer for the GPIO descriptors for drivers that assign GPIO names hardcoded. All other GPIO names will be parsed from DT and directly assigned to the GPIO descriptor. This patch adds a helper function to find gpio descriptors by name instead of gpio number. Signed-off-by: Markus Pargmann Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5db3445..697c409 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -90,6 +90,38 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) EXPORT_SYMBOL_GPL(gpio_to_desc); /** + * Convert a GPIO name to its descriptor + */ +struct gpio_desc *gpio_name_to_desc(const char * const name) +{ + struct gpio_chip *chip; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + list_for_each_entry(chip, &gpio_chips, list) { + int i; + + for (i = 0; i != chip->ngpio; ++i) { + struct gpio_desc *gpio = &chip->desc[i]; + + if (!gpio->name) + continue; + + if (!strcmp(gpio->name, name)) { + spin_unlock_irqrestore(&gpio_lock, flags); + return gpio; + } + } + } + + spin_unlock_irqrestore(&gpio_lock, flags); + + return NULL; +} +EXPORT_SYMBOL_GPL(gpio_name_to_desc); + +/** * Get the GPIO descriptor corresponding to the given hw number for this chip. */ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index bf34300..78e634d 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -89,7 +89,10 @@ struct gpio_desc { #define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */ #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ + /* Connection label */ const char *label; + /* Name of the GPIO */ + const char *name; }; int gpiod_request(struct gpio_desc *desc, const char *label); diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 14cac67..366a3fd 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -130,6 +130,7 @@ int gpiod_to_irq(const struct gpio_desc *desc); /* Convert between the old gpio_ and new gpiod_ interfaces */ struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); +struct gpio_desc *gpio_name_to_desc(const char *name); /* Child properties interface */ struct fwnode_handle; @@ -400,6 +401,12 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio) { return ERR_PTR(-EINVAL); } + +static inline struct gpio_desc *gpio_name_to_desc(const char *name) +{ + return ERR_PTR(-EINVAL); +} + static inline int desc_to_gpio(const struct gpio_desc *desc) { /* GPIO can never have been requested */ -- cgit v0.10.2 From 5f3ca7329b049b40667a190ddf14b69afdb91576 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 14 Aug 2015 16:11:00 +0200 Subject: gpiolib: Use GPIO name from names array for gpio descriptor This patch adds GPIO names to the GPIO descriptors when initializing the gpiochip. It also introduces a check whether any of the new names will conflict with an existing GPIO name. Signed-off-by: Markus Pargmann Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 697c409..2341bfc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -250,6 +250,38 @@ static int gpiochip_add_to_list(struct gpio_chip *chip) return err; } +/* + * Takes the names from gc->names and checks if they are all unique. If they + * are, they are assigned to their gpio descriptors. + * + * Returns -EEXIST if one of the names is already used for a different GPIO. + */ +static int gpiochip_set_desc_names(struct gpio_chip *gc) +{ + int i; + + if (!gc->names) + return 0; + + /* First check all names if they are unique */ + for (i = 0; i != gc->ngpio; ++i) { + struct gpio_desc *gpio; + + gpio = gpio_name_to_desc(gc->names[i]); + if (gpio) { + dev_err(gc->dev, "Detected name collision for GPIO name '%s'\n", + gc->names[i]); + return -EEXIST; + } + } + + /* Then add all names to the GPIO descriptors */ + for (i = 0; i != gc->ngpio; ++i) + gc->desc[i].name = gc->names[i]; + + return 0; +} + /** * gpiochip_add() - register a gpio_chip * @chip: the chip to register, with chip->base initialized @@ -322,6 +354,10 @@ int gpiochip_add(struct gpio_chip *chip) if (!chip->owner && chip->dev && chip->dev->driver) chip->owner = chip->dev->driver->owner; + status = gpiochip_set_desc_names(chip); + if (status) + goto err_remove_from_list; + status = of_gpiochip_add(chip); if (status) goto err_remove_chip; @@ -342,6 +378,7 @@ err_remove_chip: acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); +err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&chip->list); spin_unlock_irqrestore(&gpio_lock, flags); -- cgit v0.10.2 From ddd5404007b8496f20ad2efe1147e102e6226634 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 14 Aug 2015 16:11:01 +0200 Subject: gpio-sysfs: Use gpio descriptor name instead of gpiochip names array The name is now stored in the gpio descriptor as well, for example to allow to store names from DT. This patch changes the sysfs gpio files to use the gpio descriptor name. Signed-off-by: Markus Pargmann Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index b57ed8e..3e81f28 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -550,9 +550,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) struct gpiod_data *data; unsigned long flags; int status; - const char *ioname = NULL; struct device *dev; - int offset; /* can't export until sysfs is available ... */ if (!gpio_class.p) { @@ -601,13 +599,9 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) else data->direction_can_change = false; - offset = gpio_chip_hwgpio(desc); - if (chip->names && chip->names[offset]) - ioname = chip->names[offset]; - dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0), data, gpio_groups, - ioname ? ioname : "gpio%u", + desc->name ? desc->name : "gpio%u", desc_to_gpio(desc)); if (IS_ERR(dev)) { status = PTR_ERR(dev); -- cgit v0.10.2 From ced433e2a4a0f11362c149daf802157ffb65ee20 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 14 Aug 2015 16:11:02 +0200 Subject: gpiolib: Add gpio name information to /sys/kernel/debug/gpio Add some information about gpio names to the debugfs gpio file. name and label of a GPIO are then displayed next to each other. This way it is easy to see what the real name of GPIO is and what the driver requested it for. Signed-off-by: Markus Pargmann [Dropped unsolicited sysfs ABI patch hunk] Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2341bfc..09b7316 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2378,14 +2378,19 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) int is_irq; for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { - if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) + if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) { + if (gdesc->name) { + seq_printf(s, " gpio-%-3d (%-20.20s)\n", + gpio, gdesc->name); + } continue; + } gpiod_get_direction(gdesc); is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags); - seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s", - gpio, gdesc->label, + seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s", + gpio, gdesc->name ? gdesc->name : "", gdesc->label, is_out ? "out" : "in ", chip->get ? (chip->get(chip, i) ? "hi" : "lo") -- cgit v0.10.2 From f881bab038c9667deab19a85d8666029cbfa6f2c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 23 Sep 2015 16:20:43 -0700 Subject: gpio: keep the GPIO line names internal This refactors the changes to the GPIO line naming mechanism to not have so widespread effects, instead we conclude the patch series by having created a name attribute in the GPIO descriptor, that need not be globally unique, and it will be initialized from the old .names array in struct gpio_chip if it exists, then used in the legacy sysfs code like the array was used previously. The associated changes to name lines from the device tree are controversial and need to stand alone from this. Resulting changes: 1. Remove the export and the header for the gpio_name_to_desc() as so far the only use is inside gpiolib.c. Staticize gpio_name_to_desc() and move it above the only function using it. 2. Only print a warning if there are two GPIO lines with the same name. The reason is to preserve current behaviour: before the previous changes to the naming mechanism this would not reject probing the driver, instead the error would occur when trying to export the line in sysfs, so restore this behaviour, but print a friendly warning if names collide. Cc: Johan Hovold Cc: Markus Pargmann Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 09b7316..7c7c39c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -90,38 +90,6 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) EXPORT_SYMBOL_GPL(gpio_to_desc); /** - * Convert a GPIO name to its descriptor - */ -struct gpio_desc *gpio_name_to_desc(const char * const name) -{ - struct gpio_chip *chip; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - list_for_each_entry(chip, &gpio_chips, list) { - int i; - - for (i = 0; i != chip->ngpio; ++i) { - struct gpio_desc *gpio = &chip->desc[i]; - - if (!gpio->name) - continue; - - if (!strcmp(gpio->name, name)) { - spin_unlock_irqrestore(&gpio_lock, flags); - return gpio; - } - } - } - - spin_unlock_irqrestore(&gpio_lock, flags); - - return NULL; -} -EXPORT_SYMBOL_GPL(gpio_name_to_desc); - -/** * Get the GPIO descriptor corresponding to the given hw number for this chip. */ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, @@ -250,6 +218,37 @@ static int gpiochip_add_to_list(struct gpio_chip *chip) return err; } +/** + * Convert a GPIO name to its descriptor + */ +static struct gpio_desc *gpio_name_to_desc(const char * const name) +{ + struct gpio_chip *chip; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + list_for_each_entry(chip, &gpio_chips, list) { + int i; + + for (i = 0; i != chip->ngpio; ++i) { + struct gpio_desc *gpio = &chip->desc[i]; + + if (!gpio->name) + continue; + + if (!strcmp(gpio->name, name)) { + spin_unlock_irqrestore(&gpio_lock, flags); + return gpio; + } + } + } + + spin_unlock_irqrestore(&gpio_lock, flags); + + return NULL; +} + /* * Takes the names from gc->names and checks if they are all unique. If they * are, they are assigned to their gpio descriptors. @@ -268,11 +267,10 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) struct gpio_desc *gpio; gpio = gpio_name_to_desc(gc->names[i]); - if (gpio) { - dev_err(gc->dev, "Detected name collision for GPIO name '%s'\n", - gc->names[i]); - return -EEXIST; - } + if (gpio) + dev_warn(gc->dev, "Detected name collision for " + "GPIO name '%s'\n", + gc->names[i]); } /* Then add all names to the GPIO descriptors */ diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 366a3fd..fb0fde6 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -130,7 +130,6 @@ int gpiod_to_irq(const struct gpio_desc *desc); /* Convert between the old gpio_ and new gpiod_ interfaces */ struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); -struct gpio_desc *gpio_name_to_desc(const char *name); /* Child properties interface */ struct fwnode_handle; @@ -402,11 +401,6 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio) return ERR_PTR(-EINVAL); } -static inline struct gpio_desc *gpio_name_to_desc(const char *name) -{ - return ERR_PTR(-EINVAL); -} - static inline int desc_to_gpio(const struct gpio_desc *desc) { /* GPIO can never have been requested */ -- cgit v0.10.2 From 1dbf7f299f90dc4b45e2322a3af843ad65e1501b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 17 Sep 2015 14:21:25 +0200 Subject: gpio: pl061: detail IRQ trigger handling I couldn't follow this code flow. Make it dirt simple to figure out what is going on and get proper debug prints. Warn if we set up an IRQ without any trigger. Should make no semantic difference. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 229ef65..5b1461f 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -158,24 +158,63 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpiois = readb(chip->base + GPIOIS); gpioibe = readb(chip->base + GPIOIBE); + if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) && + (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) + { + dev_err(gc->dev, + "trying to configure line %d for both level and edge " + "detection, choose one!\n", + offset); + return -EINVAL; + } + if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH; + + /* Disable edge detection */ + gpioibe &= ~bit; + /* Enable level detection */ gpiois |= bit; - if (trigger & IRQ_TYPE_LEVEL_HIGH) + /* Select polarity */ + if (polarity) gpioiev |= bit; else gpioiev &= ~bit; - } else - gpiois &= ~bit; - if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - /* Setting this makes GPIOEV be ignored */ + dev_dbg(gc->dev, "line %d: IRQ on %s level\n", + offset, + polarity ? "HIGH" : "LOW"); + } else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { + /* Disable level detection */ + gpiois &= ~bit; + /* Select both edges, setting this makes GPIOEV be ignored */ gpioibe |= bit; - else { + + dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset); + } else if ((trigger & IRQ_TYPE_EDGE_RISING) || + (trigger & IRQ_TYPE_EDGE_FALLING)) { + bool rising = trigger & IRQ_TYPE_EDGE_RISING; + + /* Disable level detection */ + gpiois &= ~bit; + /* Clear detection on both edges */ gpioibe &= ~bit; - if (trigger & IRQ_TYPE_EDGE_RISING) + /* Select edge */ + if (rising) gpioiev |= bit; - else if (trigger & IRQ_TYPE_EDGE_FALLING) + else gpioiev &= ~bit; + + dev_dbg(gc->dev, "line %d: IRQ on %s edge\n", + offset, + rising ? "RISING" : "FALLING"); + } else { + /* No trigger: disable everything */ + gpiois &= ~bit; + gpioibe &= ~bit; + gpioiev &= ~bit; + dev_warn(gc->dev, "no trigger selected for line %d\n", + offset); } writeb(gpiois, chip->base + GPIOIS); -- cgit v0.10.2 From 4843289e60e16bed00b7c3b910e67fb06214631a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Aug 2015 10:40:23 +0200 Subject: gpio: etraxfs: use container_of() to get state container The state container of the etraxfs GPIO driver is extracted from the gpio_chip exploiting the fact that offsetof() the struct gpio_chip inside the struct bgpio_chip are both 0, so the container_of() is in practice a noop. However if a member is added to struct etraxfs_gpio_chip in front of struct bgpio_chip, things will break. Using proper container_of() avoids this problem. Semantically this is a noop, the compiler will optimize it away, but syntactically it makes me happier. Acked-by: Rabin Vincent Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index 2ffcd9f..5c15dd1 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -176,6 +176,11 @@ static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = { .rw_intr_pins = ARTPEC3_rw_intr_pins, }; +static struct etraxfs_gpio_chip *to_etraxfs(struct gpio_chip *gc) +{ + return container_of(gc, struct etraxfs_gpio_chip, bgc.gc); +} + static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc) { return gc->label[0] - 'A'; @@ -220,7 +225,8 @@ static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip, static void etraxfs_gpio_irq_ack(struct irq_data *d) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); @@ -229,7 +235,8 @@ static void etraxfs_gpio_irq_ack(struct irq_data *d) static void etraxfs_gpio_irq_mask(struct irq_data *d) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); @@ -241,7 +248,8 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d) static void etraxfs_gpio_irq_unmask(struct irq_data *d) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); @@ -253,7 +261,8 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d) static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); u32 cfg; @@ -289,7 +298,8 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) static int etraxfs_gpio_irq_request_resources(struct irq_data *d) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); int ret = -EBUSY; @@ -319,7 +329,8 @@ out: static void etraxfs_gpio_irq_release_resources(struct irq_data *d) { - struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct etraxfs_gpio_chip *chip = + to_etraxfs(irq_data_get_irq_chip_data(d)); struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); -- cgit v0.10.2 From 231d51b8a4d5b24e72112bbc73fdcc38759a26e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Aug 2015 10:54:12 +0200 Subject: gpio: altera: use container_of() to get state container The state container of the Altera GPIO driver is extracted from the gpio_chip exploiting the fact that offsetof() the struct gpio_chip inside the struct of_mm_gpio_chip are both 0, so the container_of() is in practice a noop. However if a member is added to struct altera_gpio_chip in front of struct of_mm_gpio_chip, things will break. Using proper container_of() avoids this problem. Semantically this is a noop, the compiler will optimize it away, but syntactically it makes me happier. Cc: Tien Hock Loh Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 1b44941..3e6661b 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -42,6 +42,11 @@ struct altera_gpio_chip { int mapped_irq; }; +static struct altera_gpio_chip *to_altera(struct gpio_chip *gc) +{ + return container_of(gc, struct altera_gpio_chip, mmchip.gc); +} + static void altera_gpio_irq_unmask(struct irq_data *d) { struct altera_gpio_chip *altera_gc; @@ -49,7 +54,7 @@ static void altera_gpio_irq_unmask(struct irq_data *d) unsigned long flags; u32 intmask; - altera_gc = irq_data_get_irq_chip_data(d); + altera_gc = to_altera(irq_data_get_irq_chip_data(d)); mm_gc = &altera_gc->mmchip; spin_lock_irqsave(&altera_gc->gpio_lock, flags); @@ -67,7 +72,7 @@ static void altera_gpio_irq_mask(struct irq_data *d) unsigned long flags; u32 intmask; - altera_gc = irq_data_get_irq_chip_data(d); + altera_gc = to_altera(irq_data_get_irq_chip_data(d)); mm_gc = &altera_gc->mmchip; spin_lock_irqsave(&altera_gc->gpio_lock, flags); @@ -87,7 +92,7 @@ static int altera_gpio_irq_set_type(struct irq_data *d, { struct altera_gpio_chip *altera_gc; - altera_gc = irq_data_get_irq_chip_data(d); + altera_gc = to_altera(irq_data_get_irq_chip_data(d)); if (type == IRQ_TYPE_NONE) return 0; @@ -210,7 +215,7 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc) unsigned long status; int i; - altera_gc = irq_desc_get_handler_data(desc); + altera_gc = to_altera(irq_desc_get_handler_data(desc)); chip = irq_desc_get_chip(desc); mm_gc = &altera_gc->mmchip; irqdomain = altera_gc->mmchip.gc.irqdomain; @@ -239,7 +244,7 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc) unsigned long status; int i; - altera_gc = irq_desc_get_handler_data(desc); + altera_gc = to_altera(irq_desc_get_handler_data(desc)); chip = irq_desc_get_chip(desc); mm_gc = &altera_gc->mmchip; irqdomain = altera_gc->mmchip.gc.irqdomain; -- cgit v0.10.2 From 218f1f8b50aef5438fd95a4e3d64549bf9c459c3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Aug 2015 11:26:04 +0200 Subject: gpio: sx150x: use container_of() to get state container The state container of the sx150x GPIO driver is sometimes extracted from the gpio_chip exploiting the fact that offsetof() the struct gpio_chip inside the struct sx150x_chip is 0, so the container_of() is in practice a noop. However if a member is added to struct sx150_chip in front of struct gpio_chip, things will break. Using proper container_of() avoids this problem. Semantically this is a noop, the compiler will optimize it away, but syntactically it makes me happier. Cc: Wei Chen Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index 9c6b967..76f9201 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -160,6 +160,11 @@ static const struct of_device_id sx150x_of_match[] = { }; MODULE_DEVICE_TABLE(of, sx150x_of_match); +struct sx150x_chip *to_sx150x(struct gpio_chip *gc) +{ + return container_of(gc, struct sx150x_chip, gpio_chip); +} + static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) { s32 err = i2c_smbus_write_byte_data(client, reg, val); @@ -296,11 +301,9 @@ static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) { - struct sx150x_chip *chip; + struct sx150x_chip *chip = to_sx150x(gc); int status = -EINVAL; - chip = container_of(gc, struct sx150x_chip, gpio_chip); - if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_get_io(chip, offset); @@ -312,9 +315,7 @@ static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) { - struct sx150x_chip *chip; - - chip = container_of(gc, struct sx150x_chip, gpio_chip); + struct sx150x_chip *chip = to_sx150x(gc); mutex_lock(&chip->lock); if (offset_is_oscio(chip, offset)) @@ -326,11 +327,9 @@ static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { - struct sx150x_chip *chip; + struct sx150x_chip *chip = to_sx150x(gc); int status = -EINVAL; - chip = container_of(gc, struct sx150x_chip, gpio_chip); - if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_io_input(chip, offset); @@ -343,11 +342,9 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int val) { - struct sx150x_chip *chip; + struct sx150x_chip *chip = to_sx150x(gc); int status = 0; - chip = container_of(gc, struct sx150x_chip, gpio_chip); - if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_io_output(chip, offset, val); @@ -358,7 +355,7 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc, static void sx150x_irq_mask(struct irq_data *d) { - struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); + struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d)); unsigned n = d->hwirq; chip->irq_masked |= (1 << n); @@ -367,7 +364,7 @@ static void sx150x_irq_mask(struct irq_data *d) static void sx150x_irq_unmask(struct irq_data *d) { - struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); + struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d)); unsigned n = d->hwirq; chip->irq_masked &= ~(1 << n); @@ -376,7 +373,7 @@ static void sx150x_irq_unmask(struct irq_data *d) static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) { - struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); + struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d)); unsigned n, val = 0; if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) @@ -431,14 +428,14 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) static void sx150x_irq_bus_lock(struct irq_data *d) { - struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); + struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d)); mutex_lock(&chip->lock); } static void sx150x_irq_bus_sync_unlock(struct irq_data *d) { - struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); + struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d)); unsigned n; if (chip->irq_update == NO_UPDATE_PENDING) -- cgit v0.10.2 From 2f930643c581f3fe45568f24a8aba93af46ff287 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Aug 2015 14:13:46 +0200 Subject: gpio: vf610: use container_of() to get state container The state container of the vf610 GPIO driver is sometimes extracted from the gpio_chip exploiting the fact that offsetof() the struct gpio_chip inside the struct vf610_gpio_port is 0, so the container_of() is in practice a noop. However if a member is added to struct vf610_gpio_port in front of struct gpio_chip, things will break. Using proper container_of() avoids this problem. Semantically this is a noop, the compiler will optimize it away, but syntactically it makes me happier. Also replace some explicit container_of() calls with the helper function. Acked-by: Stefan Agner Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 069f9e4..e1a3971 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -62,6 +62,11 @@ struct vf610_gpio_port { static struct irq_chip vf610_gpio_irq_chip; +static struct vf610_gpio_port *to_vf610_gp(struct gpio_chip *gc) +{ + return container_of(gc, struct vf610_gpio_port, gc); +} + static const struct of_device_id vf610_gpio_dt_ids[] = { { .compatible = "fsl,vf610-gpio" }, { /* sentinel */ } @@ -89,16 +94,14 @@ static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset) static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct vf610_gpio_port *port = - container_of(gc, struct vf610_gpio_port, gc); + struct vf610_gpio_port *port = to_vf610_gp(gc); return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio)); } static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct vf610_gpio_port *port = - container_of(gc, struct vf610_gpio_port, gc); + struct vf610_gpio_port *port = to_vf610_gp(gc); unsigned long mask = BIT(gpio); if (val) @@ -122,7 +125,8 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, static void vf610_gpio_irq_handler(struct irq_desc *desc) { - struct vf610_gpio_port *port = irq_desc_get_handler_data(desc); + struct vf610_gpio_port *port = + to_vf610_gp(irq_desc_get_handler_data(desc)); struct irq_chip *chip = irq_desc_get_chip(desc); int pin; unsigned long irq_isfr; @@ -142,7 +146,8 @@ static void vf610_gpio_irq_handler(struct irq_desc *desc) static void vf610_gpio_irq_ack(struct irq_data *d) { - struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d); + struct vf610_gpio_port *port = + to_vf610_gp(irq_data_get_irq_chip_data(d)); int gpio = d->hwirq; vf610_gpio_writel(BIT(gpio), port->base + PORT_ISFR); @@ -150,7 +155,8 @@ static void vf610_gpio_irq_ack(struct irq_data *d) static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type) { - struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d); + struct vf610_gpio_port *port = + to_vf610_gp(irq_data_get_irq_chip_data(d)); u8 irqc; switch (type) { @@ -185,7 +191,8 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type) static void vf610_gpio_irq_mask(struct irq_data *d) { - struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d); + struct vf610_gpio_port *port = + to_vf610_gp(irq_data_get_irq_chip_data(d)); void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq); vf610_gpio_writel(0, pcr_base); @@ -193,7 +200,8 @@ static void vf610_gpio_irq_mask(struct irq_data *d) static void vf610_gpio_irq_unmask(struct irq_data *d) { - struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d); + struct vf610_gpio_port *port = + to_vf610_gp(irq_data_get_irq_chip_data(d)); void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq); vf610_gpio_writel(port->irqc[d->hwirq] << PORT_PCR_IRQC_OFFSET, @@ -202,7 +210,8 @@ static void vf610_gpio_irq_unmask(struct irq_data *d) static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable) { - struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d); + struct vf610_gpio_port *port = + to_vf610_gp(irq_data_get_irq_chip_data(d)); if (enable) enable_irq_wake(port->irq); -- cgit v0.10.2 From fa9795d1121e18a6ee2d0f8b2e837f51d63d4b00 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Aug 2015 14:26:46 +0200 Subject: gpio: zynq: use container_of() to get state container The state container of the Zynq GPIO driver is sometimes extracted from the gpio_chip exploiting the fact that offsetof() the struct gpio_chip inside the struct zynq_gpio is 0, so the container_of() is in practice a noop. However if a member is added to struct zynq_gpio in front of struct gpio_chip, things will break. Using proper container_of() avoids this problem. Semantically this is a noop, the compiler will optimize it away, but syntactically it makes me happier. Also replace some explicit container_of() calls with the helper function. Cc: Lars-Peter Clausen Cc: Ezra Savard Cc: Michal Simek Acked-by: Harini Katakam Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 1d1a586..8abeaca 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -130,6 +130,12 @@ struct zynq_platform_data { static struct irq_chip zynq_gpio_level_irqchip; static struct irq_chip zynq_gpio_edge_irqchip; + +static struct zynq_gpio *to_zynq_gpio(struct gpio_chip *gc) +{ + return container_of(gc, struct zynq_gpio, chip); +} + /** * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank * for a given pin in the GPIO device @@ -177,7 +183,7 @@ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin) { u32 data; unsigned int bank_num, bank_pin_num; - struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip); + struct zynq_gpio *gpio = to_zynq_gpio(chip); zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); @@ -201,7 +207,7 @@ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin, int state) { unsigned int reg_offset, bank_num, bank_pin_num; - struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip); + struct zynq_gpio *gpio = to_zynq_gpio(chip); zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); @@ -238,7 +244,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin) { u32 reg; unsigned int bank_num, bank_pin_num; - struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip); + struct zynq_gpio *gpio = to_zynq_gpio(chip); zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); @@ -271,7 +277,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, { u32 reg; unsigned int bank_num, bank_pin_num; - struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip); + struct zynq_gpio *gpio = to_zynq_gpio(chip); zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); @@ -301,7 +307,8 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, static void zynq_gpio_irq_mask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; - struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_data_get_irq_chip_data(irq_data)); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); @@ -321,7 +328,8 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data) static void zynq_gpio_irq_unmask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; - struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_data_get_irq_chip_data(irq_data)); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); @@ -340,7 +348,8 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data) static void zynq_gpio_irq_ack(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; - struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_data_get_irq_chip_data(irq_data)); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); @@ -390,7 +399,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { u32 int_type, int_pol, int_any; unsigned int device_pin_num, bank_num, bank_pin_num; - struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_data_get_irq_chip_data(irq_data)); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); @@ -453,7 +463,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) { - struct zynq_gpio *gpio = irq_data_get_irq_chip_data(data); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_data_get_irq_chip_data(data)); irq_set_irq_wake(gpio->irq, on); @@ -518,7 +529,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc) { u32 int_sts, int_enb; unsigned int bank_num; - struct zynq_gpio *gpio = irq_desc_get_handler_data(desc); + struct zynq_gpio *gpio = + to_zynq_gpio(irq_desc_get_handler_data(desc)); struct irq_chip *irqchip = irq_desc_get_chip(desc); chained_irq_enter(irqchip, desc); -- cgit v0.10.2 From 9f3538280301bb953bf159d5ce9fc1f41482aa4c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 28 Aug 2015 14:48:56 -0700 Subject: gpio: msm: Remove unused driver Remove this driver now that Bjorn has introduced a pinctrl driver for msm8660 and the dts files have been updated with the pinctrl compatibles. Cc: Andy Gross Reviewed-by: Bjorn Andersson Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-msm.txt b/Documentation/devicetree/bindings/gpio/gpio-msm.txt deleted file mode 100644 index ac20e68..0000000 --- a/Documentation/devicetree/bindings/gpio/gpio-msm.txt +++ /dev/null @@ -1,26 +0,0 @@ -MSM GPIO controller bindings - -Required properties: -- compatible: - - "qcom,msm-gpio" for MSM controllers -- #gpio-cells : Should be two. - - first cell is the pin number - - second cell is used to specify optional parameters (unused) -- gpio-controller : Marks the device node as a GPIO controller. -- #interrupt-cells : Should be 2. -- interrupt-controller: Mark the device node as an interrupt controller -- interrupts : Specify the TLMM summary interrupt number -- ngpio : Specify the number of MSM GPIOs - -Example: - - msmgpio: gpio@fd510000 { - compatible = "qcom,msm-gpio"; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - reg = <0xfd510000 0x4000>; - interrupts = <0 208 0>; - ngpio = <150>; - }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8949b3f..2026034 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -297,14 +297,6 @@ config GPIO_MPC8XXX Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. -config GPIO_MSM_V2 - tristate "Qualcomm MSM GPIO v2" - depends on GPIOLIB && OF && ARCH_QCOM - help - Say yes here to support the GPIO interface on ARM v7 based - Qualcomm MSM chips. Most of the pins on the MSM can be - selected for GPIO, and are controlled by this driver. - config GPIO_MVEBU def_bool y depends on PLAT_ORION diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index f79a7c4..0d30b64 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o -obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c deleted file mode 100644 index 4b42221..0000000 --- a/drivers/gpio/gpio-msm-v2.c +++ /dev/null @@ -1,453 +0,0 @@ -/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_NR_GPIO 300 - -/* Bits of interest in the GPIO_IN_OUT register. - */ -enum { - GPIO_IN = 0, - GPIO_OUT = 1 -}; - -/* Bits of interest in the GPIO_INTR_STATUS register. - */ -enum { - INTR_STATUS = 0, -}; - -/* Bits of interest in the GPIO_CFG register. - */ -enum { - GPIO_OE = 9, -}; - -/* Bits of interest in the GPIO_INTR_CFG register. - * When a GPIO triggers, two separate decisions are made, controlled - * by two separate flags. - * - * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS - * register for that GPIO will be updated to reflect the triggering of that - * gpio. If this bit is 0, this register will not be updated. - * - Second, INTR_ENABLE controls whether an interrupt is triggered. - * - * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt - * can be triggered but the status register will not reflect it. - */ -enum { - INTR_ENABLE = 0, - INTR_POL_CTL = 1, - INTR_DECT_CTL = 2, - INTR_RAW_STATUS_EN = 3, -}; - -/* Codes of interest in GPIO_INTR_CFG_SU. - */ -enum { - TARGET_PROC_SCORPION = 4, - TARGET_PROC_NONE = 7, -}; - -/** - * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure - * - * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By - * keeping track of which gpios are unmasked as irq sources, we avoid - * having to do readl calls on hundreds of iomapped registers each time - * the summary interrupt fires in order to locate the active interrupts. - * - * @wake_irqs: a bitmap for tracking which interrupt lines are enabled - * as wakeup sources. When the device is suspended, interrupts which are - * not wakeup sources are disabled. - * - * @dual_edge_irqs: a bitmap used to track which irqs are configured - * as dual-edge, as this is not supported by the hardware and requires - * some special handling in the driver. - */ -struct msm_gpio_dev { - struct gpio_chip gpio_chip; - DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO); - DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO); - DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO); - struct irq_domain *domain; - int summary_irq; - void __iomem *msm_tlmm_base; -}; - -static struct msm_gpio_dev msm_gpio; - -#define GPIO_INTR_CFG_SU(gpio) (msm_gpio.msm_tlmm_base + 0x0400 + \ - (0x04 * (gpio))) -#define GPIO_CONFIG(gpio) (msm_gpio.msm_tlmm_base + 0x1000 + \ - (0x10 * (gpio))) -#define GPIO_IN_OUT(gpio) (msm_gpio.msm_tlmm_base + 0x1004 + \ - (0x10 * (gpio))) -#define GPIO_INTR_CFG(gpio) (msm_gpio.msm_tlmm_base + 0x1008 + \ - (0x10 * (gpio))) -#define GPIO_INTR_STATUS(gpio) (msm_gpio.msm_tlmm_base + 0x100c + \ - (0x10 * (gpio))) - -static DEFINE_SPINLOCK(tlmm_lock); - -static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip) -{ - return container_of(chip, struct msm_gpio_dev, gpio_chip); -} - -static inline void set_gpio_bits(unsigned n, void __iomem *reg) -{ - writel(readl(reg) | n, reg); -} - -static inline void clear_gpio_bits(unsigned n, void __iomem *reg) -{ - writel(readl(reg) & ~n, reg); -} - -static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN); -} - -static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset)); -} - -static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - unsigned long irq_flags; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset)); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); - return 0; -} - -static int msm_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, - int val) -{ - unsigned long irq_flags; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - msm_gpio_set(chip, offset, val); - set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset)); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); - return 0; -} - -static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return 0; -} - -static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - return; -} - -static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip); - struct irq_domain *domain = g_dev->domain; - - return irq_create_mapping(domain, offset); -} - -/* For dual-edge interrupts in software, since the hardware has no - * such support: - * - * At appropriate moments, this function may be called to flip the polarity - * settings of both-edge irq lines to try and catch the next edge. - * - * The attempt is considered successful if: - * - the status bit goes high, indicating that an edge was caught, or - * - the input value of the gpio doesn't change during the attempt. - * If the value changes twice during the process, that would cause the first - * test to fail but would force the second, as two opposite - * transitions would cause a detection no matter the polarity setting. - * - * The do-loop tries to sledge-hammer closed the timing hole between - * the initial value-read and the polarity-write - if the line value changes - * during that window, an interrupt is lost, the new polarity setting is - * incorrect, and the first success test will fail, causing a retry. - * - * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c. - */ -static void msm_gpio_update_dual_edge_pos(unsigned gpio) -{ - int loop_limit = 100; - unsigned val, val2, intstat; - - do { - val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); - if (val) - clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); - else - set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); - val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); - intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS); - if (intstat || val == val2) - return; - } while (loop_limit-- > 0); - pr_err("%s: dual-edge irq failed to stabilize, " - "interrupts dropped. %#08x != %#08x\n", - __func__, val, val2); -} - -static void msm_gpio_irq_ack(struct irq_data *d) -{ - int gpio = d->hwirq; - - writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio)); - if (test_bit(gpio, msm_gpio.dual_edge_irqs)) - msm_gpio_update_dual_edge_pos(gpio); -} - -static void msm_gpio_irq_mask(struct irq_data *d) -{ - unsigned long irq_flags; - int gpio = d->hwirq; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); - clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio)); - __clear_bit(gpio, msm_gpio.enabled_irqs); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); -} - -static void msm_gpio_irq_unmask(struct irq_data *d) -{ - unsigned long irq_flags; - int gpio = d->hwirq; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - __set_bit(gpio, msm_gpio.enabled_irqs); - set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio)); - writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio)); - spin_unlock_irqrestore(&tlmm_lock, irq_flags); -} - -static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - unsigned long irq_flags; - int gpio = d->hwirq; - uint32_t bits; - - spin_lock_irqsave(&tlmm_lock, irq_flags); - - bits = readl(GPIO_INTR_CFG(gpio)); - - if (flow_type & IRQ_TYPE_EDGE_BOTH) { - bits |= BIT(INTR_DECT_CTL); - irq_set_handler_locked(d, handle_edge_irq); - if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - __set_bit(gpio, msm_gpio.dual_edge_irqs); - else - __clear_bit(gpio, msm_gpio.dual_edge_irqs); - } else { - bits &= ~BIT(INTR_DECT_CTL); - irq_set_handler_locked(d, handle_level_irq); - __clear_bit(gpio, msm_gpio.dual_edge_irqs); - } - - if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) - bits |= BIT(INTR_POL_CTL); - else - bits &= ~BIT(INTR_POL_CTL); - - writel(bits, GPIO_INTR_CFG(gpio)); - - if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) - msm_gpio_update_dual_edge_pos(gpio); - - spin_unlock_irqrestore(&tlmm_lock, irq_flags); - - return 0; -} - -/* - * When the summary IRQ is raised, any number of GPIO lines may be high. - * It is the job of the summary handler to find all those GPIO lines - * which have been set as summary IRQ lines and which are triggered, - * and to call their interrupt handlers. - */ -static void msm_summary_irq_handler(struct irq_desc *desc) -{ - unsigned long i; - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - for_each_set_bit(i, msm_gpio.enabled_irqs, MAX_NR_GPIO) { - if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS)) - generic_handle_irq(irq_find_mapping(msm_gpio.domain, - i)); - } - - chained_irq_exit(chip, desc); -} - -static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) -{ - int gpio = d->hwirq; - - if (on) { - if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO)) - irq_set_irq_wake(msm_gpio.summary_irq, 1); - set_bit(gpio, msm_gpio.wake_irqs); - } else { - clear_bit(gpio, msm_gpio.wake_irqs); - if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO)) - irq_set_irq_wake(msm_gpio.summary_irq, 0); - } - - return 0; -} - -static struct irq_chip msm_gpio_irq_chip = { - .name = "msmgpio", - .irq_mask = msm_gpio_irq_mask, - .irq_unmask = msm_gpio_irq_unmask, - .irq_ack = msm_gpio_irq_ack, - .irq_set_type = msm_gpio_irq_set_type, - .irq_set_wake = msm_gpio_irq_set_wake, -}; - -static struct lock_class_key msm_gpio_lock_class; - -static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - irq_set_lockdep_class(irq, &msm_gpio_lock_class); - irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, - handle_level_irq); - - return 0; -} - -static const struct irq_domain_ops msm_gpio_irq_domain_ops = { - .xlate = irq_domain_xlate_twocell, - .map = msm_gpio_irq_domain_map, -}; - -static int msm_gpio_probe(struct platform_device *pdev) -{ - int ret, ngpio; - struct resource *res; - - if (of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio)) { - dev_err(&pdev->dev, "%s: ngpio property missing\n", __func__); - return -EINVAL; - } - - if (ngpio > MAX_NR_GPIO) - WARN(1, "ngpio exceeds the MAX_NR_GPIO. Increase MAX_NR_GPIO\n"); - - bitmap_zero(msm_gpio.enabled_irqs, MAX_NR_GPIO); - bitmap_zero(msm_gpio.wake_irqs, MAX_NR_GPIO); - bitmap_zero(msm_gpio.dual_edge_irqs, MAX_NR_GPIO); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - msm_gpio.msm_tlmm_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(msm_gpio.msm_tlmm_base)) - return PTR_ERR(msm_gpio.msm_tlmm_base); - - msm_gpio.gpio_chip.ngpio = ngpio; - msm_gpio.gpio_chip.label = pdev->name; - msm_gpio.gpio_chip.dev = &pdev->dev; - msm_gpio.gpio_chip.base = 0; - msm_gpio.gpio_chip.direction_input = msm_gpio_direction_input; - msm_gpio.gpio_chip.direction_output = msm_gpio_direction_output; - msm_gpio.gpio_chip.get = msm_gpio_get; - msm_gpio.gpio_chip.set = msm_gpio_set; - msm_gpio.gpio_chip.to_irq = msm_gpio_to_irq; - msm_gpio.gpio_chip.request = msm_gpio_request; - msm_gpio.gpio_chip.free = msm_gpio_free; - - ret = gpiochip_add(&msm_gpio.gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "gpiochip_add failed with error %d\n", ret); - return ret; - } - - msm_gpio.summary_irq = platform_get_irq(pdev, 0); - if (msm_gpio.summary_irq < 0) { - dev_err(&pdev->dev, "No Summary irq defined for msmgpio\n"); - return msm_gpio.summary_irq; - } - - msm_gpio.domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, - &msm_gpio_irq_domain_ops, - &msm_gpio); - if (!msm_gpio.domain) - return -ENODEV; - - irq_set_chained_handler(msm_gpio.summary_irq, msm_summary_irq_handler); - - return 0; -} - -static const struct of_device_id msm_gpio_of_match[] = { - { .compatible = "qcom,msm-gpio", }, - { }, -}; -MODULE_DEVICE_TABLE(of, msm_gpio_of_match); - -static int msm_gpio_remove(struct platform_device *dev) -{ - gpiochip_remove(&msm_gpio.gpio_chip); - - irq_set_handler(msm_gpio.summary_irq, NULL); - - return 0; -} - -static struct platform_driver msm_gpio_driver = { - .probe = msm_gpio_probe, - .remove = msm_gpio_remove, - .driver = { - .name = "msmgpio", - .of_match_table = msm_gpio_of_match, - }, -}; - -module_platform_driver(msm_gpio_driver) - -MODULE_AUTHOR("Gregory Bean "); -MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:msmgpio"); -- cgit v0.10.2 From 49a5bd880cb63fba9f4589a89d68b8a255062a5f Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Tue, 1 Sep 2015 11:38:02 +0200 Subject: gpio: ath79: Convert to the state container design pattern Turn the ath79 driver into a true driver supporting multiple instances. While at it also removed unneed includes and make use of the BIT() macro. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 03b9953..e5827a5 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -12,61 +12,51 @@ * by the Free Software Foundation. */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include #include -static void __iomem *ath79_gpio_base; -static u32 ath79_gpio_count; -static DEFINE_SPINLOCK(ath79_gpio_lock); +struct ath79_gpio_ctrl { + struct gpio_chip chip; + void __iomem *base; + spinlock_t lock; +}; + +#define to_ath79_gpio_ctrl(c) container_of(c, struct ath79_gpio_ctrl, chip) -static void __ath79_gpio_set_value(unsigned gpio, int value) +static void ath79_gpio_set_value(struct gpio_chip *chip, + unsigned gpio, int value) { - void __iomem *base = ath79_gpio_base; + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); if (value) - __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET); + __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET); else - __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR); + __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR); } -static int __ath79_gpio_get_value(unsigned gpio) +static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { - return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1; -} + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); -static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset) -{ - return __ath79_gpio_get_value(offset); -} - -static void ath79_gpio_set_value(struct gpio_chip *chip, - unsigned offset, int value) -{ - __ath79_gpio_set_value(offset, value); + return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1; } static int ath79_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - void __iomem *base = ath79_gpio_base; + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); unsigned long flags; - spin_lock_irqsave(&ath79_gpio_lock, flags); + spin_lock_irqsave(&ctrl->lock, flags); - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), - base + AR71XX_GPIO_REG_OE); + __raw_writel( + __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset), + ctrl->base + AR71XX_GPIO_REG_OE); - spin_unlock_irqrestore(&ath79_gpio_lock, flags); + spin_unlock_irqrestore(&ctrl->lock, flags); return 0; } @@ -74,35 +64,37 @@ static int ath79_gpio_direction_input(struct gpio_chip *chip, static int ath79_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - void __iomem *base = ath79_gpio_base; + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); unsigned long flags; - spin_lock_irqsave(&ath79_gpio_lock, flags); + spin_lock_irqsave(&ctrl->lock, flags); if (value) - __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); + __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); else - __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); + __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), - base + AR71XX_GPIO_REG_OE); + __raw_writel( + __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), + ctrl->base + AR71XX_GPIO_REG_OE); - spin_unlock_irqrestore(&ath79_gpio_lock, flags); + spin_unlock_irqrestore(&ctrl->lock, flags); return 0; } static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - void __iomem *base = ath79_gpio_base; + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); unsigned long flags; - spin_lock_irqsave(&ath79_gpio_lock, flags); + spin_lock_irqsave(&ctrl->lock, flags); - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), - base + AR71XX_GPIO_REG_OE); + __raw_writel( + __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), + ctrl->base + AR71XX_GPIO_REG_OE); - spin_unlock_irqrestore(&ath79_gpio_lock, flags); + spin_unlock_irqrestore(&ctrl->lock, flags); return 0; } @@ -110,25 +102,26 @@ static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - void __iomem *base = ath79_gpio_base; + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); unsigned long flags; - spin_lock_irqsave(&ath79_gpio_lock, flags); + spin_lock_irqsave(&ctrl->lock, flags); if (value) - __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); + __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); else - __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); + __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), - base + AR71XX_GPIO_REG_OE); + __raw_writel( + __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset), + ctrl->base + AR71XX_GPIO_REG_OE); - spin_unlock_irqrestore(&ath79_gpio_lock, flags); + spin_unlock_irqrestore(&ctrl->lock, flags); return 0; } -static struct gpio_chip ath79_gpio_chip = { +static const struct gpio_chip ath79_gpio_chip = { .label = "ath79", .get = ath79_gpio_get_value, .set = ath79_gpio_set_value, @@ -147,10 +140,16 @@ static int ath79_gpio_probe(struct platform_device *pdev) { struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data; struct device_node *np = pdev->dev.of_node; + struct ath79_gpio_ctrl *ctrl; struct resource *res; + u32 ath79_gpio_count; bool oe_inverted; int err; + ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); if (err) { @@ -171,19 +170,21 @@ static int ath79_gpio_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ath79_gpio_base = devm_ioremap_nocache( + ctrl->base = devm_ioremap_nocache( &pdev->dev, res->start, resource_size(res)); - if (!ath79_gpio_base) + if (!ctrl->base) return -ENOMEM; - ath79_gpio_chip.dev = &pdev->dev; - ath79_gpio_chip.ngpio = ath79_gpio_count; + spin_lock_init(&ctrl->lock); + memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip)); + ctrl->chip.dev = &pdev->dev; + ctrl->chip.ngpio = ath79_gpio_count; if (oe_inverted) { - ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; - ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; + ctrl->chip.direction_input = ar934x_gpio_direction_input; + ctrl->chip.direction_output = ar934x_gpio_direction_output; } - err = gpiochip_add(&ath79_gpio_chip); + err = gpiochip_add(&ctrl->chip); if (err) { dev_err(&pdev->dev, "cannot add AR71xx GPIO chip, error=%d", err); -- cgit v0.10.2 From c75a37720480819291ebca0db7fab4e87c46f73d Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Wed, 26 Aug 2015 17:52:19 -0400 Subject: gpio: Fix error checking in the function device_pca957x_init This fixes error checking in the function device_pca957x_init to properly check and return error code values from the calls to the function pca953x_write_regs if they fail as to properly signal callers when a error occurs due a failure when writing registers for this gpio based device. Signed-off-by: Nicholas Krause Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 50caeb1..4e5745d 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -635,11 +635,15 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) memset(val, 0xFF, NBANK(chip)); else memset(val, 0, NBANK(chip)); - pca953x_write_regs(chip, PCA957X_INVRT, val); + ret = pca953x_write_regs(chip, PCA957X_INVRT, val); + if (ret) + goto out; /* To enable register 6, 7 to control pull up and pull down */ memset(val, 0x02, NBANK(chip)); - pca953x_write_regs(chip, PCA957X_BKEN, val); + ret = pca953x_write_regs(chip, PCA957X_BKEN, val); + if (ret) + goto out; return 0; out: -- cgit v0.10.2 From 633a5065939ae75a07bc37c110399a3faf065147 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 10 Sep 2015 16:59:01 +0100 Subject: gpio: arizona: add support for WM8998 and WM1814 Signed-off-by: Richard Fitzgerald Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index 052fbc8..ca00273 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -118,6 +118,8 @@ static int arizona_gpio_probe(struct platform_device *pdev) case WM5110: case WM8280: case WM8997: + case WM8998: + case WM1814: arizona_gpio->gpio_chip.ngpio = 5; break; default: -- cgit v0.10.2 From 48b5953ed826224a1332f2fd784d37d5f084ca9c Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Tue, 18 Aug 2015 18:02:32 +0200 Subject: gpio: gpiolib: don't compare an unsigned for >= 0 The parameter offset is an unsigned, so it makes no sense to compare it for >= 0. Fix the compiler warning regarding this by removing this comparison. As the macro GPIO_OFFSET_VALID is only used at this single place, simplify the code by dropping the macro completely and dropping the invert, too. No functional change. Signed-off-by: Dirk Behme Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7c7c39c..8f18077 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -47,8 +47,6 @@ */ DEFINE_SPINLOCK(gpio_lock); -#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio) - static DEFINE_MUTEX(gpio_lookup_lock); static LIST_HEAD(gpio_lookup_list); LIST_HEAD(gpio_chips); @@ -995,7 +993,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) { struct gpio_desc *desc; - if (!GPIO_OFFSET_VALID(chip, offset)) + if (offset >= chip->ngpio) return NULL; desc = &chip->desc[offset]; -- cgit v0.10.2 From b8664924e8071b67b99f05b13e669e20104d7709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Mon, 21 Sep 2015 18:24:24 +0200 Subject: gpio: add GPIO support for IT87xx, replacing gpio-it8761e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for the GPIOs found on the ITE super-I/O chips IT87xx. Signed-off-by: Diego Elio Pettenò Signed-off-by: Christophe Vu-Brugier Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2026034..63000b1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -235,11 +235,17 @@ config GPIO_IOP If unsure, say N. -config GPIO_IT8761E - tristate "IT8761E GPIO support" - depends on X86 # unconditional access to IO space. +config GPIO_IT87 + tristate "IT87xx GPIO support" + depends on X86 # unconditional access to IO space. help - Say yes here to support GPIO functionality of IT8761E super I/O chip. + Say yes here to support GPIO functionality of IT87xx Super I/O chips. + + This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and + supports the IT8761E Super I/O chip as well. + + To compile this driver as a module, choose M here: the module will + be called gpio_it87 config GPIO_LOONGSON bool "Loongson-2/3 GPIO support" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0d30b64..77a07e9 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o -obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o +obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c new file mode 100644 index 0000000..21f6f7c --- /dev/null +++ b/drivers/gpio/gpio-it87.c @@ -0,0 +1,411 @@ +/* + * GPIO interface for IT87xx Super I/O chips + * + * Author: Diego Elio Pettenò + * + * Based on it87_wdt.c by Oliver Schuster + * gpio-it8761e.c by Denis Turischev + * gpio-stmpe.c by Rabin Vincent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Chip Id numbers */ +#define NO_DEV_ID 0xffff +#define IT8728_ID 0x8728 +#define IT8732_ID 0x8732 +#define IT8761_ID 0x8761 + +/* IO Ports */ +#define REG 0x2e +#define VAL 0x2f + +/* Logical device Numbers LDN */ +#define GPIO 0x07 + +/* Configuration Registers and Functions */ +#define LDNREG 0x07 +#define CHIPID 0x20 +#define CHIPREV 0x22 + +/** + * struct it87_gpio - it87-specific GPIO chip + * @chip the underlying gpio_chip structure + * @lock a lock to avoid races between operations + * @io_base base address for gpio ports + * @io_size size of the port rage starting from io_base. + * @output_base Super I/O register address for Output Enable register + * @simple_base Super I/O 'Simple I/O' Enable register + * @simple_size Super IO 'Simple I/O' Enable register size; this is + * required because IT87xx chips might only provide Simple I/O + * switches on a subset of lines, whereas the others keep the + * same status all time. + */ +struct it87_gpio { + struct gpio_chip chip; + spinlock_t lock; + u16 io_base; + u16 io_size; + u8 output_base; + u8 simple_base; + u8 simple_size; +}; + +static struct it87_gpio it87_gpio_chip = { + .lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock), +}; + +static inline struct it87_gpio *to_it87_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct it87_gpio, chip); +} + +/* Superio chip access functions; copied from wdt_it87 */ + +static inline int superio_enter(void) +{ + /* + * Try to reserve REG and REG + 1 for exclusive access. + */ + if (!request_muxed_region(REG, 2, KBUILD_MODNAME)) + return -EBUSY; + + outb(0x87, REG); + outb(0x01, REG); + outb(0x55, REG); + outb(0x55, REG); + return 0; +} + +static inline void superio_exit(void) +{ + outb(0x02, REG); + outb(0x02, VAL); + release_region(REG, 2); +} + +static inline void superio_select(int ldn) +{ + outb(LDNREG, REG); + outb(ldn, VAL); +} + +static inline int superio_inb(int reg) +{ + outb(reg, REG); + return inb(VAL); +} + +static inline void superio_outb(int val, int reg) +{ + outb(reg, REG); + outb(val, VAL); +} + +static inline int superio_inw(int reg) +{ + int val; + + outb(reg++, REG); + val = inb(VAL) << 8; + outb(reg, REG); + val |= inb(VAL); + return val; +} + +static inline void superio_outw(int val, int reg) +{ + outb(reg++, REG); + outb(val >> 8, VAL); + outb(reg, REG); + outb(val, VAL); +} + +static inline void superio_set_mask(int mask, int reg) +{ + u8 curr_val = superio_inb(reg); + u8 new_val = curr_val | mask; + + if (curr_val != new_val) + superio_outb(new_val, reg); +} + +static inline void superio_clear_mask(int mask, int reg) +{ + u8 curr_val = superio_inb(reg); + u8 new_val = curr_val & ~mask; + + if (curr_val != new_val) + superio_outb(new_val, reg); +} + +static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num) +{ + u8 mask, group; + int rc = 0; + struct it87_gpio *it87_gpio = to_it87_gpio(chip); + + mask = 1 << (gpio_num % 8); + group = (gpio_num / 8); + + spin_lock(&it87_gpio->lock); + + rc = superio_enter(); + if (rc) + goto exit; + + /* not all the IT87xx chips support Simple I/O and not all of + * them allow all the lines to be set/unset to Simple I/O. + */ + if (group < it87_gpio->simple_size) + superio_set_mask(mask, group + it87_gpio->simple_base); + + /* clear output enable, setting the pin to input, as all the + * newly-exported GPIO interfaces are set to input. + */ + superio_clear_mask(mask, group + it87_gpio->output_base); + + superio_exit(); + +exit: + spin_unlock(&it87_gpio->lock); + return rc; +} + +static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num) +{ + u16 reg; + u8 mask; + struct it87_gpio *it87_gpio = to_it87_gpio(chip); + + mask = 1 << (gpio_num % 8); + reg = (gpio_num / 8) + it87_gpio->io_base; + + return !!(inb(reg) & mask); +} + +static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num) +{ + u8 mask, group; + int rc = 0; + struct it87_gpio *it87_gpio = to_it87_gpio(chip); + + mask = 1 << (gpio_num % 8); + group = (gpio_num / 8); + + spin_lock(&it87_gpio->lock); + + rc = superio_enter(); + if (rc) + goto exit; + + /* clear the output enable bit */ + superio_clear_mask(mask, group + it87_gpio->output_base); + + superio_exit(); + +exit: + spin_unlock(&it87_gpio->lock); + return rc; +} + +static void it87_gpio_set(struct gpio_chip *chip, + unsigned gpio_num, int val) +{ + u8 mask, curr_vals; + u16 reg; + struct it87_gpio *it87_gpio = to_it87_gpio(chip); + + mask = 1 << (gpio_num % 8); + reg = (gpio_num / 8) + it87_gpio->io_base; + + curr_vals = inb(reg); + if (val) + outb(curr_vals | mask, reg); + else + outb(curr_vals & ~mask, reg); +} + +static int it87_gpio_direction_out(struct gpio_chip *chip, + unsigned gpio_num, int val) +{ + u8 mask, group; + int rc = 0; + struct it87_gpio *it87_gpio = to_it87_gpio(chip); + + mask = 1 << (gpio_num % 8); + group = (gpio_num / 8); + + spin_lock(&it87_gpio->lock); + + rc = superio_enter(); + if (rc) + goto exit; + + /* set the output enable bit */ + superio_set_mask(mask, group + it87_gpio->output_base); + + it87_gpio_set(chip, gpio_num, val); + + superio_exit(); + +exit: + spin_unlock(&it87_gpio->lock); + return rc; +} + +static struct gpio_chip it87_template_chip = { + .label = KBUILD_MODNAME, + .owner = THIS_MODULE, + .request = it87_gpio_request, + .get = it87_gpio_get, + .direction_input = it87_gpio_direction_in, + .set = it87_gpio_set, + .direction_output = it87_gpio_direction_out, + .base = -1 +}; + +static int __init it87_gpio_init(void) +{ + int rc = 0, i; + u16 chip_type; + u8 chip_rev, gpio_ba_reg; + char *labels, **labels_table; + + struct it87_gpio *it87_gpio = &it87_gpio_chip; + + rc = superio_enter(); + if (rc) + return rc; + + chip_type = superio_inw(CHIPID); + chip_rev = superio_inb(CHIPREV) & 0x0f; + superio_exit(); + + it87_gpio->chip = it87_template_chip; + + switch (chip_type) { + case IT8728_ID: + case IT8732_ID: + gpio_ba_reg = 0x62; + it87_gpio->io_size = 8; + it87_gpio->output_base = 0xc8; + it87_gpio->simple_base = 0xc0; + it87_gpio->simple_size = 5; + it87_gpio->chip.ngpio = 64; + break; + case IT8761_ID: + gpio_ba_reg = 0x60; + it87_gpio->io_size = 4; + it87_gpio->output_base = 0xf0; + it87_gpio->simple_size = 0; + it87_gpio->chip.ngpio = 16; + break; + case NO_DEV_ID: + pr_err("no device\n"); + return -ENODEV; + default: + pr_err("Unknown Chip found, Chip %04x Revision %x\n", + chip_type, chip_rev); + return -ENODEV; + } + + rc = superio_enter(); + if (rc) + return rc; + + superio_select(GPIO); + + /* fetch GPIO base address */ + it87_gpio->io_base = superio_inw(gpio_ba_reg); + + superio_exit(); + + pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n", + chip_type, chip_rev, it87_gpio->chip.ngpio, + it87_gpio->io_base); + + if (!request_region(it87_gpio->io_base, it87_gpio->io_size, + KBUILD_MODNAME)) + return -EBUSY; + + /* Set up aliases for the GPIO connection. + * + * ITE documentation for recent chips such as the IT8728F + * refers to the GPIO lines as GPxy, with a coordinates system + * where x is the GPIO group (starting from 1) and y is the + * bit within the group. + * + * By creating these aliases, we make it easier to understand + * to which GPIO pin we're referring to. + */ + labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"), + GFP_KERNEL); + labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *), + GFP_KERNEL); + + if (!labels || !labels_table) { + rc = -ENOMEM; + goto labels_free; + } + + for (i = 0; i < it87_gpio->chip.ngpio; i++) { + char *label = &labels[i * sizeof("it87_gpXY")]; + + sprintf(label, "it87_gp%u%u", 1+(i/8), i%8); + labels_table[i] = label; + } + + it87_gpio->chip.names = (const char *const*)labels_table; + + rc = gpiochip_add(&it87_gpio->chip); + if (rc) + goto labels_free; + + return 0; + +labels_free: + kfree(labels_table); + kfree(labels); + release_region(it87_gpio->io_base, it87_gpio->io_size); + return rc; +} + +static void __exit it87_gpio_exit(void) +{ + struct it87_gpio *it87_gpio = &it87_gpio_chip; + + gpiochip_remove(&it87_gpio->chip); + release_region(it87_gpio->io_base, it87_gpio->io_size); + kfree(it87_gpio->chip.names[0]); + kfree(it87_gpio->chip.names); +} + +module_init(it87_gpio_init); +module_exit(it87_gpio_exit); + +MODULE_AUTHOR("Diego Elio Pettenò "); +MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/gpio-it8761e.c deleted file mode 100644 index 30a8f24..0000000 --- a/drivers/gpio/gpio-it8761e.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * GPIO interface for IT8761E Super I/O chip - * - * Author: Denis Turischev - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 2 as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define SIO_CHIP_ID 0x8761 -#define CHIP_ID_HIGH_BYTE 0x20 -#define CHIP_ID_LOW_BYTE 0x21 - -static u8 ports[2] = { 0x2e, 0x4e }; -static u8 port; - -static DEFINE_SPINLOCK(sio_lock); - -#define GPIO_NAME "it8761-gpio" -#define GPIO_BA_HIGH_BYTE 0x60 -#define GPIO_BA_LOW_BYTE 0x61 -#define GPIO_IOSIZE 4 -#define GPIO1X_IO 0xf0 -#define GPIO2X_IO 0xf1 - -static u16 gpio_ba; - -static u8 read_reg(u8 addr, u8 port) -{ - outb(addr, port); - return inb(port + 1); -} - -static void write_reg(u8 data, u8 addr, u8 port) -{ - outb(addr, port); - outb(data, port + 1); -} - -static void enter_conf_mode(u8 port) -{ - outb(0x87, port); - outb(0x61, port); - outb(0x55, port); - outb((port == 0x2e) ? 0x55 : 0xaa, port); -} - -static void exit_conf_mode(u8 port) -{ - outb(0x2, port); - outb(0x2, port + 1); -} - -static void enter_gpio_mode(u8 port) -{ - write_reg(0x2, 0x7, port); -} - -static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) -{ - u16 reg; - u8 bit; - - bit = gpio_num % 8; - reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; - - return !!(inb(reg) & (1 << bit)); -} - -static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) -{ - u8 curr_dirs; - u8 io_reg, bit; - - bit = gpio_num % 8; - io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; - - spin_lock(&sio_lock); - - enter_conf_mode(port); - enter_gpio_mode(port); - - curr_dirs = read_reg(io_reg, port); - - if (curr_dirs & (1 << bit)) - write_reg(curr_dirs & ~(1 << bit), io_reg, port); - - exit_conf_mode(port); - - spin_unlock(&sio_lock); - return 0; -} - -static void it8761e_gpio_set(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_vals, bit; - u16 reg; - - bit = gpio_num % 8; - reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; - - spin_lock(&sio_lock); - - curr_vals = inb(reg); - if (val) - outb(curr_vals | (1 << bit), reg); - else - outb(curr_vals & ~(1 << bit), reg); - - spin_unlock(&sio_lock); -} - -static int it8761e_gpio_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) -{ - u8 curr_dirs, io_reg, bit; - - bit = gpio_num % 8; - io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; - - it8761e_gpio_set(gc, gpio_num, val); - - spin_lock(&sio_lock); - - enter_conf_mode(port); - enter_gpio_mode(port); - - curr_dirs = read_reg(io_reg, port); - - if (!(curr_dirs & (1 << bit))) - write_reg(curr_dirs | (1 << bit), io_reg, port); - - exit_conf_mode(port); - - spin_unlock(&sio_lock); - return 0; -} - -static struct gpio_chip it8761e_gpio_chip = { - .label = GPIO_NAME, - .owner = THIS_MODULE, - .get = it8761e_gpio_get, - .direction_input = it8761e_gpio_direction_in, - .set = it8761e_gpio_set, - .direction_output = it8761e_gpio_direction_out, -}; - -static int __init it8761e_gpio_init(void) -{ - int i, id, err; - - /* chip and port detection */ - for (i = 0; i < ARRAY_SIZE(ports); i++) { - spin_lock(&sio_lock); - enter_conf_mode(ports[i]); - - id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) + - read_reg(CHIP_ID_LOW_BYTE, ports[i]); - - exit_conf_mode(ports[i]); - spin_unlock(&sio_lock); - - if (id == SIO_CHIP_ID) { - port = ports[i]; - break; - } - } - - if (!port) - return -ENODEV; - - /* fetch GPIO base address */ - enter_conf_mode(port); - enter_gpio_mode(port); - gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) + - read_reg(GPIO_BA_LOW_BYTE, port); - exit_conf_mode(port); - - if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME)) - return -EBUSY; - - it8761e_gpio_chip.base = -1; - it8761e_gpio_chip.ngpio = 16; - - err = gpiochip_add(&it8761e_gpio_chip); - if (err < 0) - goto gpiochip_add_err; - - return 0; - -gpiochip_add_err: - release_region(gpio_ba, GPIO_IOSIZE); - gpio_ba = 0; - return err; -} - -static void __exit it8761e_gpio_exit(void) -{ - if (gpio_ba) { - gpiochip_remove(&it8761e_gpio_chip); - release_region(gpio_ba, GPIO_IOSIZE); - gpio_ba = 0; - } -} -module_init(it8761e_gpio_init); -module_exit(it8761e_gpio_exit); - -MODULE_AUTHOR("Denis Turischev "); -MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip"); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 69d301fdd19635a39cb2b78e53fdd625b7a27924 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Sep 2015 15:05:45 -0700 Subject: gpio: add DT bindings for existing consumer flags It is customary for GPIO controllers to support open drain/collector and open source/emitter configurations. Add standard GPIO line flags to account for this and augment the documentation to say that these are the most generic bindings. Several people approached me to add new flags to the lines, and this makes sense, but let's first bind up the most common cases before we start to add exotic stuff. Thanks to H. Nikolaus Schaller for ideas on how to encode single-ended wiring such as open drain/source and open collector/emitter. Cc: Tony Lindgren Cc: Grygorii Strashko Cc: H. Nikolaus Schaller Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 5788d5c..63b1b90 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -52,9 +52,13 @@ only uses one. gpio-specifier may encode: bank, pin position inside the bank, whether pin is open-drain and whether pin is logically inverted. + Exact meaning of each specifier cell is controller specific, and must -be documented in the device tree binding for the device. Use the macros -defined in include/dt-bindings/gpio/gpio.h whenever possible: +be documented in the device tree binding for the device. + +Most controllers are however specifying a generic flag bitfield +in the last cell, so for these, use the macros defined in +include/dt-bindings/gpio/gpio.h whenever possible: Example of a node using GPIOs: @@ -65,6 +69,15 @@ Example of a node using GPIOs: GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller. +Optional standard bitfield specifiers for the last cell: + +- Bit 0: 0 means active high, 1 means active low +- Bit 1: 1 means single-ended wiring, see: + https://en.wikipedia.org/wiki/Single-ended_triode + When used with active-low, this means open drain/collector, see: + https://en.wikipedia.org/wiki/Open_collector + When used with active-high, this means open source/emitter + 1.1) GPIO specifier best practices ---------------------------------- diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index e6b1e0a..c673d2c 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -9,7 +9,19 @@ #ifndef _DT_BINDINGS_GPIO_GPIO_H #define _DT_BINDINGS_GPIO_GPIO_H +/* Bit 0 express polarity */ #define GPIO_ACTIVE_HIGH 0 #define GPIO_ACTIVE_LOW 1 +/* Bit 1 express single-endedness */ +#define GPIO_PUSH_PULL 0 +#define GPIO_SINGLE_ENDED 2 + +/* + * Open Drain/Collector is the combination of single-ended active low, + * Open Source/Emitter is the combination of single-ended active high. + */ +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW) +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH) + #endif -- cgit v0.10.2 From aca82d1cbb49af34b69ecd4571a0fe48ad9247c1 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 25 Sep 2015 12:28:02 -0700 Subject: gpio: omap: move pm runtime in irq_chip.irq_bus_lock/sync_unlock The PM runtime API can't be used in atomic contex on -RT even if it's configured as irqsafe. As result, below error report can be seen when PM runtime API called from IRQ chip's callbacks irq_startup/irq_shutdown/irq_set_type, because they are protected by RAW spinlock: BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917 in_atomic(): 1, irqs_disabled(): 128, pid: 96, name: insmod 3 locks held by insmod/96: #0: (&dev->mutex){......}, at: [] __driver_attach+0x54/0xa0 #1: (&dev->mutex){......}, at: [] __driver_attach+0x60/0xa0 #2: (class){......}, at: [] __irq_get_desc_lock+0x60/0xa4 irq event stamp: 1834 hardirqs last enabled at (1833): [] _raw_spin_unlock_irqrestore+0x88/0x90 hardirqs last disabled at (1834): [] _raw_spin_lock_irqsave+0x2c/0x64 softirqs last enabled at (0): [] copy_process.part.52+0x410/0x19d8 softirqs last disabled at (0): [< (null)>] (null) Preemption disabled at:[< (null)>] (null) CPU: 1 PID: 96 Comm: insmod Tainted: G W O 4.1.3-rt3-00618-g57e2387-dirty #184 Hardware name: Generic DRA74X (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [] (show_stack) from [] (dump_stack+0x88/0xdc) [] (dump_stack) from [] (___might_sleep+0x198/0x2a8) [] (___might_sleep) from [] (rt_spin_lock+0x30/0x70) [] (rt_spin_lock) from [] (__pm_runtime_resume+0x68/0xa4) [] (__pm_runtime_resume) from [] (omap_gpio_irq_type+0x188/0x1d8) [] (omap_gpio_irq_type) from [] (__irq_set_trigger+0x68/0x130) [] (__irq_set_trigger) from [] (irq_set_irq_type+0x44/0x6c) [] (irq_set_irq_type) from [] (irq_create_of_mapping+0x120/0x174) [] (irq_create_of_mapping) from [] (of_irq_get+0x48/0x58) [] (of_irq_get) from [] (i2c_device_probe+0x54/0x15c) [] (i2c_device_probe) from [] (driver_probe_device+0x184/0x2c8) [] (driver_probe_device) from [] (__driver_attach+0x9c/0xa0) [] (__driver_attach) from [] (bus_for_each_dev+0x7c/0xb0) [] (bus_for_each_dev) from [] (driver_attach+0x28/0x30) [] (driver_attach) from [] (bus_add_driver+0x154/0x200) [] (bus_add_driver) from [] (driver_register+0x88/0x108) [] (driver_register) from [] (i2c_register_driver+0x3c/0x90) [] (i2c_register_driver) from [] (pcf857x_init+0x18/0x24 [gpio_pcf857x]) [] (pcf857x_init [gpio_pcf857x]) from [] (do_one_initcall+0x128/0x1e8) [] (do_one_initcall) from [] (do_init_module+0x6c/0x1bc) [] (do_init_module) from [] (load_module+0x18e8/0x21c4) [] (load_module) from [] (SyS_init_module+0xfc/0x158) [] (SyS_init_module) from [] (ret_fast_syscall+0x0/0x54) The IRQ chip interface defines only two callbacks which are executed in non-atomic contex - irq_bus_lock/irq_bus_sync_unlock, so lets move PM runtime calls there. Tested-by: Tony Lindgren Tested-by: Austin Schuh Signed-off-by: Grygorii Strashko Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 5236db1..a254691 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -496,9 +496,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) return -EINVAL; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - raw_spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); if (retval) { @@ -521,8 +518,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) return 0; error: - if (!BANK_USED(bank)) - pm_runtime_put(bank->dev); return retval; } @@ -797,9 +792,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) unsigned long flags; unsigned offset = d->hwirq; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - raw_spin_lock_irqsave(&bank->lock, flags); if (!LINE_USED(bank->mod_usage, offset)) @@ -815,8 +807,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) return 0; err: raw_spin_unlock_irqrestore(&bank->lock, flags); - if (!BANK_USED(bank)) - pm_runtime_put(bank->dev); return -EINVAL; } @@ -835,6 +825,19 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) omap_clear_gpio_debounce(bank, offset); omap_disable_gpio_module(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); +} + +static void omap_gpio_irq_bus_lock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); + + if (!BANK_USED(bank)) + pm_runtime_get_sync(bank->dev); +} + +static void gpio_irq_bus_sync_unlock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); /* * If this is the last IRQ to be freed in the bank, @@ -1183,6 +1186,8 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_unmask = omap_gpio_unmask_irq, irqc->irq_set_type = omap_gpio_irq_type, irqc->irq_set_wake = omap_gpio_wake_enable, + irqc->irq_bus_lock = omap_gpio_irq_bus_lock, + irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); bank->irq = platform_get_irq(pdev, 0); -- cgit v0.10.2 From 450fa54cfd66e3dda6eda26256637ee8928af12a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 25 Sep 2015 12:28:03 -0700 Subject: gpio: omap: convert to use generic irq handler This patch converts TI OMAP GPIO driver to use generic irq handler instead of chained IRQ handler. This way OMAP GPIO driver will be compatible with RT kernel where it will be forced thread IRQ handler while in non-RT kernel it still will be executed in HW IRQ context. As part of this change the IRQ wakeup configuration is applied to GPIO Bank IRQ as it now will be under control of IRQ PM Core during suspend. There are also additional benefits: - on-RT kernel there will be no complains any more about PM runtime usage in atomic context "BUG: sleeping function called from invalid context"; - GPIO bank IRQs will appear in /proc/interrupts and its usage statistic will be visible; - GPIO bank IRQs could be configured through IRQ proc_fs interface and, as result, could be a part of IRQ balancing process if needed; - GPIO bank IRQs will be under control of IRQ PM Core during suspend to RAM. Disadvantage: - additional runtime overhed as call chain till omap_gpio_irq_handler() will be longer now - necessity to use wa_lock in omap_gpio_irq_handler() to W/A warning in handle_irq_event_percpu() WARNING: CPU: 1 PID: 35 at kernel/irq/handle.c:149 handle_irq_event_percpu+0x51c/0x638() This patch doesn't fully follows recommendations provided by Sebastian Andrzej Siewior [1], because It's required to go through and check all GPIO IRQ pin states as fast as possible and pass control to handle_level_irq or handle_edge_irq. handle_level_irq or handle_edge_irq will perform actions specific for IRQ triggering type and wakeup corresponding registered threaded IRQ handler (at least it's expected to be threaded). IRQs can be lost if handle_nested_irq() will be used, because excecution time of some pin specific GPIO IRQ handler can be very significant and require accessing ext. devices (I2C). Idea of such kind reworking was also discussed in [2]. [1] http://www.spinics.net/lists/linux-omap/msg120665.html [2] http://www.spinics.net/lists/linux-omap/msg119516.html Tested-by: Tony Lindgren Tested-by: Austin Schuh Signed-off-by: Grygorii Strashko Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a254691..376827f 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -59,6 +59,7 @@ struct gpio_bank { u32 level_mask; u32 toggle_mask; raw_spinlock_t lock; + raw_spinlock_t wa_lock; struct gpio_chip chip; struct clk *dbck; u32 mod_usage; @@ -649,8 +650,13 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) { struct gpio_bank *bank = omap_irq_data_get_bank(d); unsigned offset = d->hwirq; + int ret; + + ret = omap_set_gpio_wakeup(bank, offset, enable); + if (!ret) + ret = irq_set_irq_wake(bank->irq, enable); - return omap_set_gpio_wakeup(bank, offset, enable); + return ret; } static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -704,26 +710,21 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) * line's interrupt handler has been run, we may miss some nested * interrupts. */ -static void omap_gpio_irq_handler(struct irq_desc *desc) +static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) { void __iomem *isr_reg = NULL; u32 isr; unsigned int bit; - struct gpio_bank *bank; - int unmasked = 0; - struct irq_chip *irqchip = irq_desc_get_chip(desc); - struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct gpio_bank *bank = gpiobank; + unsigned long wa_lock_flags; unsigned long lock_flags; - chained_irq_enter(irqchip, desc); - - bank = container_of(chip, struct gpio_bank, chip); isr_reg = bank->base + bank->regs->irqstatus; - pm_runtime_get_sync(bank->dev); - if (WARN_ON(!isr_reg)) goto exit; + pm_runtime_get_sync(bank->dev); + while (1) { u32 isr_saved, level_mask = 0; u32 enabled; @@ -745,13 +746,6 @@ static void omap_gpio_irq_handler(struct irq_desc *desc) raw_spin_unlock_irqrestore(&bank->lock, lock_flags); - /* if there is only edge sensitive GPIO pin interrupts - configured, we could unmask GPIO bank interrupt immediately */ - if (!level_mask && !unmasked) { - unmasked = 1; - chained_irq_exit(irqchip, desc); - } - if (!isr) break; @@ -772,18 +766,18 @@ static void omap_gpio_irq_handler(struct irq_desc *desc) raw_spin_unlock_irqrestore(&bank->lock, lock_flags); + raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags); + generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit)); + + raw_spin_unlock_irqrestore(&bank->wa_lock, + wa_lock_flags); } } - /* if bank has any level sensitive GPIO pin interrupt - configured, we must unmask the bank interrupt only after - handler(s) are executed in order to avoid spurious bank - interrupt */ exit: - if (!unmasked) - chained_irq_exit(irqchip, desc); pm_runtime_put(bank->dev); + return IRQ_HANDLED; } static unsigned int omap_gpio_irq_startup(struct irq_data *d) @@ -1135,7 +1129,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) } ret = gpiochip_irqchip_add(&bank->chip, irqc, - irq_base, omap_gpio_irq_handler, + irq_base, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { @@ -1144,10 +1138,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) return -ENODEV; } - gpiochip_set_chained_irqchip(&bank->chip, irqc, - bank->irq, omap_gpio_irq_handler); + gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL); - return 0; + ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler, + 0, dev_name(bank->dev), bank); + if (ret) + gpiochip_remove(&bank->chip); + + return ret; } static const struct of_device_id omap_gpio_match[]; @@ -1229,6 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->set_dataout = omap_set_gpio_dataout_mask; raw_spin_lock_init(&bank->lock); + raw_spin_lock_init(&bank->wa_lock); /* Static mapping, never released */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v0.10.2 From 7474f23dd05713dacc5f22d309913c96bce1c92b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 26 Sep 2015 22:18:20 +0200 Subject: gpio: max730x: eliminate double free The function __max730x_remove is called from the remove functions of drivers/gpio/gpio-max7300.c and drivers/gpio/gpio-max7301.c. In both cases, the probe function allocates ts using devm_kzalloc. Explicitly freeing such a value with kfree will cause a double free. Signed-off-by: Julia Lawall Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index 18ab89e..0f57d2d 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -236,7 +236,6 @@ int __max730x_remove(struct device *dev) ts->write(dev, 0x04, 0x00); gpiochip_remove(&ts->chip); mutex_destroy(&ts->lock); - kfree(ts); return 0; } EXPORT_SYMBOL_GPL(__max730x_remove); -- cgit v0.10.2 From 2db8aba860c70478f6af18c410a3e513a2d2f541 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Sep 2015 12:55:44 +0200 Subject: gpio: pca953x: Add TI TCA9539 support The TCA9539 is almost identical to the PCA9555 and software-compatible with this driver. It exposes 16 general purpose I/O pins in two 8-bit configurations. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index b9a42f2..13df993 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt @@ -24,6 +24,7 @@ Required properties: ti,tca6408 ti,tca6416 ti,tca6424 + ti,tca9539 exar,xra1202 Example: diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 4e5745d..ae70630 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -67,6 +67,7 @@ static const struct i2c_device_id pca953x_id[] = { { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, + { "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, { "xra1202", 8 | PCA953X_TYPE }, { } }; -- cgit v0.10.2 From cf3f2a2c8bae0db72233629c9da9d9f617b3f8af Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Sep 2015 23:50:20 +0200 Subject: gpio: generic: improve error handling in bgpio_map If bgpio_map returns NULL then err should always be set. Signed-off-by: Heiner Kallweit Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index a3f0753..eefff1a 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -591,8 +591,10 @@ static void __iomem *bgpio_map(struct platform_device *pdev, *err = 0; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!r) + if (!r) { + *err = -EINVAL; return NULL; + } sz = resource_size(r); if (sz != sane_sz) { @@ -637,8 +639,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev) sz = resource_size(r); dat = bgpio_map(pdev, "dat", sz, &err); - if (!dat) - return err ? err : -EINVAL; + if (err) + return err; set = bgpio_map(pdev, "set", sz, &err); if (err) -- cgit v0.10.2 From 43960b4731d3450fe82105c40ee19d487622e427 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Sep 2015 23:51:08 +0200 Subject: gpio: generic: modernize remapping Replace devm_request_mem_region / devm_ioremap with devm_ioremap_resource. Signed-off-by: Heiner Kallweit Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index eefff1a..0cdbe10 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -582,9 +582,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev, resource_size_t sane_sz, int *err) { - struct device *dev = &pdev->dev; struct resource *r; - resource_size_t start; resource_size_t sz; void __iomem *ret; @@ -602,15 +600,9 @@ static void __iomem *bgpio_map(struct platform_device *pdev, return NULL; } - start = r->start; - if (!devm_request_mem_region(dev, start, sz, r->name)) { - *err = -EBUSY; - return NULL; - } - - ret = devm_ioremap(dev, start, sz); - if (!ret) { - *err = -ENOMEM; + ret = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(ret)) { + *err = PTR_ERR(ret); return NULL; } -- cgit v0.10.2 From 8d2402605b85be860808961cd82fdc4bd8bc1704 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Sep 2015 23:52:36 +0200 Subject: gpio: generic: use error pointers Use the ERRPTR standard way to return an error code in a pointer thus simplifiying the code. Signed-off-by: Heiner Kallweit Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 0cdbe10..d8b1700 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -579,34 +579,20 @@ EXPORT_SYMBOL_GPL(bgpio_init); static void __iomem *bgpio_map(struct platform_device *pdev, const char *name, - resource_size_t sane_sz, - int *err) + resource_size_t sane_sz) { struct resource *r; resource_size_t sz; - void __iomem *ret; - - *err = 0; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!r) { - *err = -EINVAL; - return NULL; - } + if (!r) + return IOMEM_ERR_PTR(-EINVAL); sz = resource_size(r); - if (sz != sane_sz) { - *err = -EINVAL; - return NULL; - } + if (sz != sane_sz) + return IOMEM_ERR_PTR(-EINVAL); - ret = devm_ioremap_resource(&pdev->dev, r); - if (IS_ERR(ret)) { - *err = PTR_ERR(ret); - return NULL; - } - - return ret; + return devm_ioremap_resource(&pdev->dev, r); } static int bgpio_pdev_probe(struct platform_device *pdev) @@ -630,25 +616,25 @@ static int bgpio_pdev_probe(struct platform_device *pdev) sz = resource_size(r); - dat = bgpio_map(pdev, "dat", sz, &err); - if (err) - return err; + dat = bgpio_map(pdev, "dat", sz); + if (IS_ERR(dat)) + return PTR_ERR(dat); - set = bgpio_map(pdev, "set", sz, &err); - if (err) - return err; + set = bgpio_map(pdev, "set", sz); + if (IS_ERR(set)) + return PTR_ERR(set); - clr = bgpio_map(pdev, "clr", sz, &err); - if (err) - return err; + clr = bgpio_map(pdev, "clr", sz); + if (IS_ERR(clr)) + return PTR_ERR(clr); - dirout = bgpio_map(pdev, "dirout", sz, &err); - if (err) - return err; + dirout = bgpio_map(pdev, "dirout", sz); + if (IS_ERR(dirout)) + return PTR_ERR(dirout); - dirin = bgpio_map(pdev, "dirin", sz, &err); - if (err) - return err; + dirin = bgpio_map(pdev, "dirin", sz); + if (IS_ERR(dirin)) + return PTR_ERR(dirin); bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); if (!bgc) -- cgit v0.10.2 From c6664149af2939b8bbaef0711b3ca5469bed33fb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Oct 2015 14:20:27 +0300 Subject: gpio: pca953x: store driver_data for future use Instead of using id->driver_data directly we copied it to the internal structure. This will help to adapt driver for ACPI use. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index ae70630..27c96ce 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -42,6 +42,9 @@ #define PCA_INT 0x0100 #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 +#define PCA_TYPE_MASK 0xF000 + +#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) static const struct i2c_device_id pca953x_id[] = { { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, @@ -96,6 +99,7 @@ struct pca953x_chip { struct gpio_chip gpio_chip; const char *const *names; int chip_type; + unsigned long driver_data; }; static inline struct pca953x_chip *to_pca(struct gpio_chip *gc) @@ -518,14 +522,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) } static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id, int irq_base) { struct i2c_client *client = chip->client; int ret, i, offset = 0; if (client->irq && irq_base != -1 - && (id->driver_data & PCA_INT)) { + && (chip->driver_data & PCA_INT)) { switch (chip->chip_type) { case PCA953X_TYPE: @@ -582,12 +585,11 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, #else /* CONFIG_GPIO_PCA953X_IRQ */ static int pca953x_irq_setup(struct pca953x_chip *chip, - const struct i2c_device_id *id, int irq_base) { struct i2c_client *client = chip->client; - if (irq_base != -1 && (id->driver_data & PCA_INT)) + if (irq_base != -1 && (chip->driver_data & PCA_INT)) dev_warn(&client->dev, "interrupt support not compiled in\n"); return 0; @@ -678,14 +680,15 @@ static int pca953x_probe(struct i2c_client *client, chip->client = client; - chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE); + chip->driver_data = id->driver_data; + chip->chip_type = PCA_CHIP_TYPE(chip->driver_data); mutex_init(&chip->i2c_lock); /* initialize cached registers from their original values. * we can't share this chip with another i2c master. */ - pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK); + pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); if (chip->chip_type == PCA953X_TYPE) ret = device_pca953x_init(chip, invert); @@ -698,7 +701,7 @@ static int pca953x_probe(struct i2c_client *client, if (ret) return ret; - ret = pca953x_irq_setup(chip, id, irq_base); + ret = pca953x_irq_setup(chip, irq_base); if (ret) return ret; -- cgit v0.10.2 From f32517bf1ae0a2de72b3f27200233bd3ad65bfeb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Oct 2015 14:20:28 +0300 Subject: gpio: pca953x: support ACPI devices found on Galileo Gen2 This patch adds a support of the expandes found on Intel Galileo Gen2 board. The platform information comes from ACPI. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 27c96ce..2d4892c 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -21,6 +21,7 @@ #ifdef CONFIG_OF_GPIO #include #endif +#include #define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 @@ -76,6 +77,12 @@ static const struct i2c_device_id pca953x_id[] = { }; MODULE_DEVICE_TABLE(i2c, pca953x_id); +static const struct acpi_device_id pca953x_acpi_ids[] = { + { "INT3491", 16 | PCA953X_TYPE | PCA_INT, }, + { } +}; +MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); + #define MAX_BANK 5 #define BANK_SZ 8 @@ -680,7 +687,18 @@ static int pca953x_probe(struct i2c_client *client, chip->client = client; - chip->driver_data = id->driver_data; + if (id) { + chip->driver_data = id->driver_data; + } else { + const struct acpi_device_id *id; + + id = acpi_match_device(pca953x_acpi_ids, &client->dev); + if (!id) + return -ENODEV; + + chip->driver_data = id->driver_data; + } + chip->chip_type = PCA_CHIP_TYPE(chip->driver_data); mutex_init(&chip->i2c_lock); @@ -773,6 +791,7 @@ static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", .of_match_table = pca953x_dt_ids, + .acpi_match_table = ACPI_PTR(pca953x_acpi_ids), }, .probe = pca953x_probe, .remove = pca953x_remove, -- cgit v0.10.2 From 78856ac0dd33036ae08a18b644e9fa40b30ee011 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 5 Oct 2015 13:07:47 +0200 Subject: Revert "gpio-sysfs: Use gpio descriptor name instead of gpiochip names array" This reverts commit ddd5404007b8496f20ad2efe1147e102e6226634. We need to preserve only using this naming strategy for names coming from chip->names[], the descripor->name field is for the new interface. diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 3e81f28..b57ed8e 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -550,7 +550,9 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) struct gpiod_data *data; unsigned long flags; int status; + const char *ioname = NULL; struct device *dev; + int offset; /* can't export until sysfs is available ... */ if (!gpio_class.p) { @@ -599,9 +601,13 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) else data->direction_can_change = false; + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; + dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0), data, gpio_groups, - desc->name ? desc->name : "gpio%u", + ioname ? ioname : "gpio%u", desc_to_gpio(desc)); if (IS_ERR(dev)) { status = PTR_ERR(dev); -- cgit v0.10.2 From 21d4de1469a1da20a14a745c5f49488bba417ea7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 8 Oct 2015 10:12:01 +0300 Subject: gpio: pl061: returning with lock held in pl061_irq_type() We were returning with "chip->lock" held by mistake. It's safe to move the return to before we take the spinlock. Fixes: 1dbf7f299f90 ('gpio: pl061: detail IRQ trigger handling') Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 5b1461f..1793397 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -152,12 +152,6 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) if (offset < 0 || offset >= PL061_GPIO_NR) return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); - - gpioiev = readb(chip->base + GPIOIEV); - gpiois = readb(chip->base + GPIOIS); - gpioibe = readb(chip->base + GPIOIBE); - if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) && (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) { @@ -168,6 +162,13 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) return -EINVAL; } + + spin_lock_irqsave(&chip->lock, flags); + + gpioiev = readb(chip->base + GPIOIEV); + gpiois = readb(chip->base + GPIOIS); + gpioibe = readb(chip->base + GPIOIBE); + if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH; -- cgit v0.10.2 From 26ba9cd48fc0c2ff741de913270e9469506f3666 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Sep 2015 17:52:52 -0700 Subject: gpio: pl061: assign the apropriate handler for irqs The PL061 can handle level IRQs and edge IRQs, however it is just utilizing handle_simple_irq() for all IRQs. Inspired by Stefan Agners patch to vf610, this assigns the right handler depending on what type is set up, and after this handle_bad_irq() is only used as default and if the type is not specified, as is done in the OMAP driver: defining the IRQ type is really not optional for this driver. The interrupt handler was just writing the interrupt clearing register for all lines that were high when entering the handling loop, this is wrong: that register is only supposed to be written (on a per-line basis) for edge IRQs, so this ACK was moved to the .irq_ack() callback as is proper. Tested with PL061 on the ARM RealView PB11MPCore and the MMC/SC card detect GPIO. Cc: Jonas Gorski Cc: Stefan Agner Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 1793397..e154999 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -181,7 +181,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpioiev |= bit; else gpioiev &= ~bit; - + irq_set_handler_locked(d, handle_level_irq); dev_dbg(gc->dev, "line %d: IRQ on %s level\n", offset, polarity ? "HIGH" : "LOW"); @@ -190,7 +190,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpiois &= ~bit; /* Select both edges, setting this makes GPIOEV be ignored */ gpioibe |= bit; - + irq_set_handler_locked(d, handle_edge_irq); dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset); } else if ((trigger & IRQ_TYPE_EDGE_RISING) || (trigger & IRQ_TYPE_EDGE_FALLING)) { @@ -205,7 +205,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpioiev |= bit; else gpioiev &= ~bit; - + irq_set_handler_locked(d, handle_edge_irq); dev_dbg(gc->dev, "line %d: IRQ on %s edge\n", offset, rising ? "RISING" : "FALLING"); @@ -214,6 +214,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) gpiois &= ~bit; gpioibe &= ~bit; gpioiev &= ~bit; + irq_set_handler_locked(d, handle_bad_irq); dev_warn(gc->dev, "no trigger selected for line %d\n", offset); } @@ -238,7 +239,6 @@ static void pl061_irq_handler(struct irq_desc *desc) chained_irq_enter(irqchip, desc); pending = readb(chip->base + GPIOMIS); - writeb(pending, chip->base + GPIOIC); if (pending) { for_each_set_bit(offset, &pending, PL061_GPIO_NR) generic_handle_irq(irq_find_mapping(gc->irqdomain, @@ -274,8 +274,28 @@ static void pl061_irq_unmask(struct irq_data *d) spin_unlock(&chip->lock); } +/** + * pl061_irq_ack() - ACK an edge IRQ + * @d: IRQ data for this IRQ + * + * This gets called from the edge IRQ handler to ACK the edge IRQ + * in the GPIOIC (interrupt-clear) register. For level IRQs this is + * not needed: these go away when the level signal goes away. + */ +static void pl061_irq_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); + u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); + + spin_lock(&chip->lock); + writeb(mask, chip->base + GPIOIC); + spin_unlock(&chip->lock); +} + static struct irq_chip pl061_irqchip = { .name = "pl061", + .irq_ack = pl061_irq_ack, .irq_mask = pl061_irq_mask, .irq_unmask = pl061_irq_unmask, .irq_set_type = pl061_irq_type, @@ -338,7 +358,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) } ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip, - irq_base, handle_simple_irq, + irq_base, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_info(&adev->dev, "could not add irqchip\n"); -- cgit v0.10.2 From 30cefeacec3e289c00128f28b831fb251650eea6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 25 Sep 2015 12:06:02 -0700 Subject: gpio: omap: fix static checker warning This patch fixes below static checker warning by changing type of irq field in struct gpio_bank from u16 to int. drivers/gpio/gpio-omap.c:1191 omap_gpio_probe() warn: assigning (-6) to unsigned variable 'bank->irq' drivers/gpio/gpio-omap.c 1188 bank->irq = platform_get_irq(pdev, 0); 1189 if (bank->irq <= 0) { bank->irq is u16. 1190 if (!bank->irq) 1191 bank->irq = -ENXIO; Does not work. 1192 if (bank->irq != -EPROBE_DEFER) Does not work. 1193 dev_err(dev, 1194 "can't get irq resource ret=%d\n", bank->irq); 1195 return bank->irq; 1196 } Fixes: commit 89d18e3af8b9: "gpio: omap: switch to use platform_get_irq" Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 376827f..56d2d02 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -51,7 +51,7 @@ struct gpio_regs { struct gpio_bank { struct list_head node; void __iomem *base; - u16 irq; + int irq; u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; -- cgit v0.10.2 From c771c2f484857f3b1fc81d180485e96b7cb67c17 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 11 Oct 2015 17:34:15 +0200 Subject: gpiolib: provide generic request/free implementations Provide generic request/free implementations that pinctrl aware gpio drivers can use instead of open coding if they use a 1:1 pin to gpio signal mapping. Signed-off-by: Jonas Gorski Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8f18077..8eba02d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "gpiolib.h" @@ -745,6 +746,28 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} #endif /* CONFIG_GPIOLIB_IRQCHIP */ +/** + * gpiochip_generic_request() - request the gpio function for a pin + * @chip: the gpiochip owning the GPIO + * @offset: the offset of the GPIO to request for GPIO function + */ +int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(chip->base + offset); +} +EXPORT_SYMBOL_GPL(gpiochip_generic_request); + +/** + * gpiochip_generic_free() - free the gpio function from a pin + * @chip: 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 *chip, unsigned offset) +{ + pinctrl_free_gpio(chip->base + offset); +} +EXPORT_SYMBOL_GPL(gpiochip_generic_free); + #ifdef CONFIG_PINCTRL /** diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 1aed31c..d1baebf 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -206,6 +206,9 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, #endif /* CONFIG_GPIOLIB_IRQCHIP */ +int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); +void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); + #ifdef CONFIG_PINCTRL /** -- cgit v0.10.2 From 203f0daafdf228a7e4e90a714a2a085884d91ea4 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 11 Oct 2015 17:34:16 +0200 Subject: gpio: replace trivial implementations of request/free with generic one Replace all trivial request/free callbacks that do nothing but call into pinctrl code with the generic versions. Signed-off-by: Jonas Gorski Reviewed-by: Thomas Petazzoni Acked-by: James Hogan Acked-by: Stefan Agner Acked-by: Joachim Eastwood Acked-by: Gregory CLEMENT Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index eb68603..e39dcb0 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -36,16 +36,6 @@ static inline struct lpc18xx_gpio_chip *to_lpc18xx_gpio(struct gpio_chip *chip) return container_of(chip, struct lpc18xx_gpio_chip, gpio); } -static int lpc18xx_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(offset); -} - -static void lpc18xx_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(offset); -} - static void lpc18xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct lpc18xx_gpio_chip *gc = to_lpc18xx_gpio(chip); @@ -95,8 +85,8 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip, static struct gpio_chip lpc18xx_chip = { .label = "lpc18xx/43xx-gpio", - .request = lpc18xx_gpio_request, - .free = lpc18xx_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = lpc18xx_gpio_direction_input, .direction_output = lpc18xx_gpio_direction_output, .set = lpc18xx_gpio_set, diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index abd8676..d3355a6 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -29,16 +29,6 @@ #define GPIO_DATA_IN 0x04 #define GPIO_PIN_DIRECTION 0x08 -static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(offset); -} - -static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(offset); -} - static int moxart_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -66,8 +56,8 @@ static int moxart_gpio_probe(struct platform_device *pdev) } bgc->gc.label = "moxart-gpio"; - bgc->gc.request = moxart_gpio_request; - bgc->gc.free = moxart_gpio_free; + bgc->gc.request = gpiochip_generic_request; + bgc->gc.free = gpiochip_generic_free; bgc->data = bgc->read_reg(bgc->reg_set); bgc->gc.base = 0; bgc->gc.ngpio = 32; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index df418b8..d428b97 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -185,16 +185,6 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) * Functions implementing the gpio_chip methods */ -static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) -{ - return pinctrl_request_gpio(chip->base + pin); -} - -static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) -{ - pinctrl_free_gpio(chip->base + pin); -} - static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value) { struct mvebu_gpio_chip *mvchip = @@ -709,8 +699,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->soc_variant = soc_variant; mvchip->chip.label = dev_name(&pdev->dev); mvchip->chip.dev = &pdev->dev; - mvchip->chip.request = mvebu_gpio_request; - mvchip->chip.free = mvebu_gpio_free; + mvchip->chip.request = gpiochip_generic_request; + mvchip->chip.free = gpiochip_generic_free; mvchip->chip.direction_input = mvebu_gpio_direction_input; mvchip->chip.get = mvebu_gpio_get; mvchip->chip.direction_output = mvebu_gpio_direction_output; diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 12c99d9..4356e6c 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -138,16 +138,6 @@ static int tb10x_gpio_direction_out(struct gpio_chip *chip, return 0; } -static int tb10x_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void tb10x_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); @@ -213,8 +203,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) tb10x_gpio->gc.get = tb10x_gpio_get; tb10x_gpio->gc.direction_output = tb10x_gpio_direction_out; tb10x_gpio->gc.set = tb10x_gpio_set; - tb10x_gpio->gc.request = tb10x_gpio_request; - tb10x_gpio->gc.free = tb10x_gpio_free; + tb10x_gpio->gc.request = gpiochip_generic_request; + tb10x_gpio->gc.free = gpiochip_generic_free; tb10x_gpio->gc.base = -1; tb10x_gpio->gc.ngpio = ngpio; tb10x_gpio->gc.can_sleep = false; diff --git a/drivers/gpio/gpio-tz1090-pdc.c b/drivers/gpio/gpio-tz1090-pdc.c index ede7e40..3623d00 100644 --- a/drivers/gpio/gpio-tz1090-pdc.c +++ b/drivers/gpio/gpio-tz1090-pdc.c @@ -137,16 +137,6 @@ static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset, __global_unlock2(lstat); } -static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) { struct tz1090_pdc_gpio *priv = to_pdc(chip); @@ -203,8 +193,8 @@ static int tz1090_pdc_gpio_probe(struct platform_device *pdev) priv->chip.direction_output = tz1090_pdc_gpio_direction_output; priv->chip.get = tz1090_pdc_gpio_get; priv->chip.set = tz1090_pdc_gpio_set; - priv->chip.free = tz1090_pdc_gpio_free; - priv->chip.request = tz1090_pdc_gpio_request; + priv->chip.free = gpiochip_generic_free; + priv->chip.request = gpiochip_generic_request; priv->chip.to_irq = tz1090_pdc_gpio_to_irq; priv->chip.of_node = np; diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index e1a3971..87b950c 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -82,16 +82,6 @@ static inline u32 vf610_gpio_readl(void __iomem *reg) return readl_relaxed(reg); } -static int vf610_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct vf610_gpio_port *port = to_vf610_gp(gc); @@ -264,8 +254,8 @@ static int vf610_gpio_probe(struct platform_device *pdev) gc->ngpio = VF610_GPIO_PER_PORT; gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT; - gc->request = vf610_gpio_request; - gc->free = vf610_gpio_free; + gc->request = gpiochip_generic_request; + gc->free = gpiochip_generic_free; gc->direction_input = vf610_gpio_direction_input; gc->get = vf610_gpio_get; gc->direction_output = vf610_gpio_direction_output; -- cgit v0.10.2 From da4002ee901205df4238dd9a63e5598064a0cd17 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 11 Oct 2015 17:34:17 +0200 Subject: gpio: gpio-xz: use the generic request/free implementations Instead of storing in the chip data whether the chip uses pinctrl and conditionally call pinctrl_{request,free}_gpio, just don't populate request/free in that case. This makes the implementations trivial and the same as the generic implementations, thus we can just use them. Signed-off-by: Jonas Gorski Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 4b8a269..1dcf7a6 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -41,7 +41,6 @@ struct zx_gpio { void __iomem *base; struct gpio_chip gc; - bool uses_pinctrl; }; static inline struct zx_gpio *to_zx(struct gpio_chip *gc) @@ -49,25 +48,6 @@ static inline struct zx_gpio *to_zx(struct gpio_chip *gc) return container_of(gc, struct zx_gpio, gc); } -static int zx_gpio_request(struct gpio_chip *gc, unsigned offset) -{ - struct zx_gpio *chip = to_zx(gc); - int gpio = gc->base + offset; - - if (chip->uses_pinctrl) - return pinctrl_request_gpio(gpio); - return 0; -} - -static void zx_gpio_free(struct gpio_chip *gc, unsigned offset) -{ - struct zx_gpio *chip = to_zx(gc); - int gpio = gc->base + offset; - - if (chip->uses_pinctrl) - pinctrl_free_gpio(gpio); -} - static int zx_direction_input(struct gpio_chip *gc, unsigned offset) { struct zx_gpio *chip = to_zx(gc); @@ -252,12 +232,12 @@ static int zx_gpio_probe(struct platform_device *pdev) return PTR_ERR(chip->base); spin_lock_init(&chip->lock); - if (of_property_read_bool(dev->of_node, "gpio-ranges")) - chip->uses_pinctrl = true; + if (of_property_read_bool(dev->of_node, "gpio-ranges")) { + chip->gc.request = gpiochip_generic_request; + chip->gc.free = gpiochip_generic_free; + } id = of_alias_get_id(dev->of_node, "gpio"); - chip->gc.request = zx_gpio_request; - chip->gc.free = zx_gpio_free; chip->gc.direction_input = zx_direction_input; chip->gc.direction_output = zx_direction_output; chip->gc.get = zx_get_value; -- cgit v0.10.2 From 31831f41bfd1e340bad66014a1b7ccd761ee51cf Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 11 Oct 2015 17:34:18 +0200 Subject: gpio: pl061: use the generic request/free implementations Instead of storing in the chip data whether the chip uses pinctrl and conditionally call pinctrl_{request,free}_gpio, just don't populate request/free in that case. This makes the implementations trivial and the same as the generic implementations, thus we can just use them. Signed-off-by: Jonas Gorski Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index e154999..4d4b376 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -52,36 +52,12 @@ struct pl061_gpio { void __iomem *base; struct gpio_chip gc; - bool uses_pinctrl; #ifdef CONFIG_PM struct pl061_context_save_regs csave_regs; #endif }; -static int pl061_gpio_request(struct gpio_chip *gc, unsigned offset) -{ - /* - * Map back to global GPIO space and request muxing, the direction - * parameter does not matter for this controller. - */ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - int gpio = gc->base + offset; - - if (chip->uses_pinctrl) - return pinctrl_request_gpio(gpio); - return 0; -} - -static void pl061_gpio_free(struct gpio_chip *gc, unsigned offset) -{ - struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - int gpio = gc->base + offset; - - if (chip->uses_pinctrl) - pinctrl_free_gpio(gpio); -} - static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) { struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); @@ -329,11 +305,11 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(chip->base); spin_lock_init(&chip->lock); - if (of_property_read_bool(dev->of_node, "gpio-ranges")) - chip->uses_pinctrl = true; + if (of_property_read_bool(dev->of_node, "gpio-ranges")) { + chip->gc.request = gpiochip_generic_request; + chip->gc.free = gpiochip_generic_free; + } - chip->gc.request = pl061_gpio_request; - chip->gc.free = pl061_gpio_free; chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value; -- cgit v0.10.2 From 98c85d583a5dee70d75faed3eb79851dd0a2e2fe Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 11 Oct 2015 17:34:19 +0200 Subject: pinctrl: replace trivial implementations of gpio_chip request/free Replace all trivial request/free callbacks that do nothing but call into pinctrl code with the generic versions. Signed-off-by: Jonas Gorski Acked-by: Bjorn Andersson Acked-by: Heiko Stuebner Acked-by: Eric Anholt Acked-by: Mika Westerberg Acked-by: Andrew Bresticker Acked-by: Baruch Siach Acked-by: Matthias Brugger Acked-by: Lee Jones Acked-by: Laxman Dewangan Acked-by: Maxime Ripard Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 8efa235..a1ea565 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -330,16 +330,6 @@ static inline void bcm2835_pinctrl_fsel_set( bcm2835_gpio_wr(pc, FSEL_REG(pin), val); } -static int bcm2835_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void bcm2835_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { return pinctrl_gpio_direction_input(chip->base + offset); @@ -375,8 +365,8 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static struct gpio_chip bcm2835_gpio_chip = { .label = MODULE_NAME, .owner = THIS_MODULE, - .request = bcm2835_gpio_request, - .free = bcm2835_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = bcm2835_gpio_direction_input, .direction_output = bcm2835_gpio_direction_output, .get = bcm2835_gpio_get, diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 270c127..84936ba 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1149,16 +1149,6 @@ static struct pinctrl_desc chv_pinctrl_desc = { .owner = THIS_MODULE, }; -static int chv_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void chv_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static unsigned chv_gpio_offset_to_pin(struct chv_pinctrl *pctrl, unsigned offset) { @@ -1238,8 +1228,8 @@ static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static const struct gpio_chip chv_gpio_chip = { .owner = THIS_MODULE, - .request = chv_gpio_request, - .free = chv_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get_direction = chv_gpio_get_direction, .direction_input = chv_gpio_direction_input, .direction_output = chv_gpio_direction_output, diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 54848b8..928a00b 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -597,16 +597,6 @@ static const struct pinctrl_desc intel_pinctrl_desc = { .owner = THIS_MODULE, }; -static int intel_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void intel_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int intel_gpio_get(struct gpio_chip *chip, unsigned offset) { struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(chip); @@ -654,8 +644,8 @@ static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static const struct gpio_chip intel_gpio_chip = { .owner = THIS_MODULE, - .request = intel_gpio_request, - .free = intel_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = intel_gpio_direction_input, .direction_output = intel_gpio_direction_output, .get = intel_gpio_get, diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 1b22f96..f8fafc1 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -723,16 +723,6 @@ static const struct pinmux_ops mtk_pmx_ops = { .gpio_set_direction = mtk_pmx_gpio_set_direction, }; -static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void mtk_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { @@ -1005,8 +995,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static struct gpio_chip mtk_gpio_chip = { .owner = THIS_MODULE, - .request = mtk_gpio_request, - .free = mtk_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = mtk_gpio_direction_input, .direction_output = mtk_gpio_direction_output, .get = mtk_gpio_get, diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 97681fa..b59fbb4 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -654,25 +654,11 @@ static inline void abx500_gpio_dbg_show_one(struct seq_file *s, #define abx500_gpio_dbg_show NULL #endif -static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - return pinctrl_request_gpio(gpio); -} - -static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - static struct gpio_chip abx500gpio_chip = { .label = "abx500-gpio", .owner = THIS_MODULE, - .request = abx500_gpio_request, - .free = abx500_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = abx500_gpio_direction_input, .get = abx500_gpio_get, .direction_output = abx500_gpio_direction_output, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 96cf039..eebfae0 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -884,24 +884,6 @@ static void nmk_gpio_latent_irq_handler(struct irq_desc *desc) /* I/O Functions */ -static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - /* - * Map back to global GPIO space and request muxing, the direction - * parameter does not matter for this controller. - */ - int gpio = chip->base + offset; - - return pinctrl_request_gpio(gpio); -} - -static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) { struct nmk_gpio_chip *nmk_chip = @@ -1267,8 +1249,8 @@ static int nmk_gpio_probe(struct platform_device *dev) spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; - chip->request = nmk_gpio_request; - chip->free = nmk_gpio_free; + chip->request = gpiochip_generic_request; + chip->free = gpiochip_generic_free; chip->direction_input = nmk_gpio_make_input; chip->get = nmk_gpio_get_input; chip->direction_output = nmk_gpio_make_output; diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c index f6be685..fd342df 100644 --- a/drivers/pinctrl/pinctrl-adi2.c +++ b/drivers/pinctrl/pinctrl-adi2.c @@ -713,16 +713,6 @@ static struct pinctrl_desc adi_pinmux_desc = { .owner = THIS_MODULE, }; -static int adi_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void adi_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct gpio_port *port; @@ -994,8 +984,8 @@ static int adi_gpio_probe(struct platform_device *pdev) port->chip.get = adi_gpio_get_value; port->chip.direction_output = adi_gpio_direction_output; port->chip.set = adi_gpio_set_value; - port->chip.request = adi_gpio_request; - port->chip.free = adi_gpio_free; + port->chip.request = gpiochip_generic_request, + port->chip.free = gpiochip_generic_free, port->chip.to_irq = adi_gpio_to_irq; if (pdata->port_gpio_base > 0) port->chip.base = pdata->port_gpio_base; diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index 4747e08..56af28b 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -536,21 +536,11 @@ static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return as3722_irq_get_virq(as_pci->as3722, offset); } -static int as3722_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void as3722_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static const struct gpio_chip as3722_gpio_chip = { .label = "as3722-gpio", .owner = THIS_MODULE, - .request = as3722_gpio_request, - .free = as3722_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get = as3722_gpio_get, .set = as3722_gpio_set, .direction_input = as3722_gpio_direction_input, diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index b0fde0f..ce6e589 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1277,28 +1277,6 @@ static int at91_pinctrl_remove(struct platform_device *pdev) return 0; } -static int at91_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - /* - * Map back to global GPIO space and request muxing, the direction - * parameter does not matter for this controller. - */ - int gpio = chip->base + offset; - int bank = chip->base / chip->ngpio; - - dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__, - 'A' + bank, offset, gpio); - - return pinctrl_request_gpio(gpio); -} - -static void at91_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); @@ -1684,8 +1662,8 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev, /* This structure is replicated for each GPIO block allocated at probe time */ static struct gpio_chip at91_gpio_template = { - .request = at91_gpio_request, - .free = at91_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get_direction = at91_gpio_get_direction, .direction_input = at91_gpio_direction_input, .get = at91_gpio_get, diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index 9c9b889..813eb7c 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -217,24 +217,6 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip) return container_of(chip, struct u300_gpio, chip); } -static int u300_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - /* - * Map back to global GPIO space and request muxing, the direction - * parameter does not matter for this controller. - */ - int gpio = chip->base + offset; - - return pinctrl_request_gpio(gpio); -} - -static void u300_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) { struct u300_gpio *gpio = to_u300_gpio(chip); @@ -417,8 +399,8 @@ int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset, static struct gpio_chip u300_gpio_chip = { .label = "u300-gpio-chip", .owner = THIS_MODULE, - .request = u300_gpio_request, - .free = u300_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get = u300_gpio_get, .set = u300_gpio_set, .direction_input = u300_gpio_direction_input, diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c index 11f8b83..38a7799 100644 --- a/drivers/pinctrl/pinctrl-digicolor.c +++ b/drivers/pinctrl/pinctrl-digicolor.c @@ -169,16 +169,6 @@ static struct pinmux_ops dc_pmxops = { .gpio_request_enable = dc_pmx_request_gpio, }; -static int dc_gpio_request(struct gpio_chip *chip, unsigned gpio) -{ - return pinctrl_request_gpio(chip->base + gpio); -} - -static void dc_gpio_free(struct gpio_chip *chip, unsigned gpio) -{ - pinctrl_free_gpio(chip->base + gpio); -} - static int dc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip); @@ -255,8 +245,8 @@ static int dc_gpiochip_add(struct dc_pinmap *pmap, struct device_node *np) chip->label = DRIVER_NAME; chip->dev = pmap->dev; - chip->request = dc_gpio_request; - chip->free = dc_gpio_free; + chip->request = gpiochip_generic_request; + chip->free = gpiochip_generic_free; chip->direction_input = dc_gpio_direction_input; chip->direction_output = dc_gpio_direction_output; chip->get = dc_gpio_get; diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index 952b1c6..85c9046 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1171,16 +1171,6 @@ static struct pinctrl_desc pistachio_pinctrl_desc = { .confops = &pistachio_pinconf_ops, }; -static int pistachio_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void pistachio_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct pistachio_gpio_bank *bank = gc_to_bank(chip); @@ -1332,8 +1322,8 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc) .npins = _npins, \ .gpio_chip = { \ .label = "GPIO" #_bank, \ - .request = pistachio_gpio_request, \ - .free = pistachio_gpio_free, \ + .request = gpiochip_generic_request, \ + .free = gpiochip_generic_free, \ .get_direction = pistachio_gpio_get_direction, \ .direction_input = pistachio_gpio_direction_input, \ .direction_output = pistachio_gpio_direction_output, \ diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 88bb707..d79889a 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1374,16 +1374,6 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, * GPIO handling */ -static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) { struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); @@ -1461,8 +1451,8 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) } static const struct gpio_chip rockchip_gpiolib_chip = { - .request = rockchip_gpio_request, - .free = rockchip_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .set = rockchip_gpio_set, .get = rockchip_gpio_get, .direction_input = rockchip_gpio_direction_input, diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 389526e..b58d3f2 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -742,16 +742,6 @@ static void st_gpio_direction(struct st_gpio_bank *bank, } } -static int st_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void st_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int st_gpio_get(struct gpio_chip *chip, unsigned offset) { struct st_gpio_bank *bank = gpio_chip_to_bank(chip); @@ -1490,8 +1480,8 @@ static void st_gpio_irqmux_handler(struct irq_desc *desc) } static struct gpio_chip st_gpio_template = { - .request = st_gpio_request, - .free = st_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get = st_gpio_get, .set = st_gpio_set, .direction_input = st_gpio_direction_input, diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index 779950c..ae724bd 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -682,28 +682,14 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val) return 0; } -static int xway_gpio_req(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - return pinctrl_request_gpio(gpio); -} - -static void xway_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - static struct gpio_chip xway_chip = { .label = "gpio-xway", .direction_input = xway_gpio_dir_in, .direction_output = xway_gpio_dir_out, .get = xway_gpio_get, .set = xway_gpio_set, - .request = xway_gpio_req, - .free = xway_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .base = -1, }; diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index a0c7407..146264a 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -458,18 +458,6 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&pctrl->lock, flags); } -static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - return pinctrl_request_gpio(gpio); -} - -static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - return pinctrl_free_gpio(gpio); -} - #ifdef CONFIG_DEBUG_FS #include @@ -527,8 +515,8 @@ static struct gpio_chip msm_gpio_template = { .direction_output = msm_gpio_direction_output, .get = msm_gpio_get, .set = msm_gpio_set, - .request = msm_gpio_request, - .free = msm_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .dbg_show = msm_gpio_dbg_show, }; diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index bd1e245..6c42ca1 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -546,16 +546,6 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value) pmic_gpio_config_set(state->ctrl, pin, &config, 1); } -static int pmic_gpio_request(struct gpio_chip *chip, unsigned base) -{ - return pinctrl_request_gpio(chip->base + base); -} - -static void pmic_gpio_free(struct gpio_chip *chip, unsigned base) -{ - pinctrl_free_gpio(chip->base + base); -} - static int pmic_gpio_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *gpio_desc, u32 *flags) @@ -595,8 +585,8 @@ static const struct gpio_chip pmic_gpio_gpio_template = { .direction_output = pmic_gpio_direction_output, .get = pmic_gpio_get, .set = pmic_gpio_set, - .request = pmic_gpio_request, - .free = pmic_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .of_xlate = pmic_gpio_of_xlate, .to_irq = pmic_gpio_to_irq, .dbg_show = pmic_gpio_dbg_show, diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c index e3be3ce..9ce0e30 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c @@ -604,16 +604,6 @@ static void pmic_mpp_set(struct gpio_chip *chip, unsigned pin, int value) pmic_mpp_config_set(state->ctrl, pin, &config, 1); } -static int pmic_mpp_request(struct gpio_chip *chip, unsigned base) -{ - return pinctrl_request_gpio(chip->base + base); -} - -static void pmic_mpp_free(struct gpio_chip *chip, unsigned base) -{ - pinctrl_free_gpio(chip->base + base); -} - static int pmic_mpp_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *gpio_desc, u32 *flags) @@ -653,8 +643,8 @@ static const struct gpio_chip pmic_mpp_gpio_template = { .direction_output = pmic_mpp_direction_output, .get = pmic_mpp_get, .set = pmic_mpp_set, - .request = pmic_mpp_request, - .free = pmic_mpp_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .of_xlate = pmic_mpp_of_xlate, .to_irq = pmic_mpp_to_irq, .dbg_show = pmic_mpp_dbg_show, diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index c760bf4..3f622cc 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -888,19 +888,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev, return 0; } -static int samsung_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void samsung_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static const struct gpio_chip samsung_gpiolib_chip = { - .request = samsung_gpio_request, - .free = samsung_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .set = samsung_gpio_set, .get = samsung_gpio_get, .direction_input = samsung_gpio_direction_input, diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 38e0c7b..f9c7a05 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -446,16 +446,6 @@ static const struct pinmux_ops sunxi_pmx_ops = { .gpio_set_direction = sunxi_pmx_gpio_set_direction, }; -static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { @@ -956,8 +946,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev, last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number; pctl->chip->owner = THIS_MODULE; - pctl->chip->request = sunxi_pinctrl_gpio_request, - pctl->chip->free = sunxi_pinctrl_gpio_free, + pctl->chip->request = gpiochip_generic_request, + pctl->chip->free = gpiochip_generic_free, pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input, pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output, pctl->chip->get = sunxi_pinctrl_gpio_get, diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index c15316b..fb22d3f 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -486,16 +486,6 @@ static struct pinctrl_desc wmt_desc = { .confops = &wmt_pinconf_ops, }; -static int wmt_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_request_gpio(chip->base + offset); -} - -static void wmt_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - pinctrl_free_gpio(chip->base + offset); -} - static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev); @@ -560,8 +550,8 @@ static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static struct gpio_chip wmt_gpio_chip = { .label = "gpio-wmt", .owner = THIS_MODULE, - .request = wmt_gpio_request, - .free = wmt_gpio_free, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .get_direction = wmt_gpio_get_direction, .direction_input = wmt_gpio_direction_input, .direction_output = wmt_gpio_direction_output, -- cgit v0.10.2 From 923b93e451db876d1479d3e4458fce14fec31d1c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 13 Oct 2015 00:20:20 +0300 Subject: gpiolib: Split GPIO flags parsing and GPIO configuration When requesting a GPIO through the legacy or the gpiod_* API the gpiochip request operation is first called and then the GPIO flags are parsed and the GPIO is configured. This prevents the gpiochip from rejecting the request if the flags are not supported by the device. To fix this split the parse-and-configure operation in two and parse flags before requesting the GPIO. Signed-off-by: Laurent Pinchart Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c index 8b83099..3a5c701 100644 --- a/drivers/gpio/gpiolib-legacy.c +++ b/drivers/gpio/gpiolib-legacy.c @@ -28,10 +28,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (!desc && gpio_is_valid(gpio)) return -EPROBE_DEFER; - err = gpiod_request(desc, label); - if (err) - return err; - if (flags & GPIOF_OPEN_DRAIN) set_bit(FLAG_OPEN_DRAIN, &desc->flags); @@ -41,6 +37,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (flags & GPIOF_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); + err = gpiod_request(desc, label); + if (err) + return err; + if (flags & GPIOF_DIR_IN) err = gpiod_direction_input(desc); else diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8eba02d..1615cc9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -927,6 +927,14 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label) spin_lock_irqsave(&gpio_lock, flags); } done: + if (status < 0) { + /* Clear flags that might have been set by the caller before + * requesting the GPIO. + */ + clear_bit(FLAG_ACTIVE_LOW, &desc->flags); + clear_bit(FLAG_OPEN_DRAIN, &desc->flags); + clear_bit(FLAG_OPEN_SOURCE, &desc->flags); + } spin_unlock_irqrestore(&gpio_lock, flags); return status; } @@ -2041,13 +2049,28 @@ struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, } EXPORT_SYMBOL_GPL(gpiod_get_optional); +/** + * gpiod_parse_flags - helper function to parse GPIO lookup flags + * @desc: gpio to be setup + * @lflags: gpio_lookup_flags - returned from of_find_gpio() or + * of_get_gpio_hog() + * + * Set the GPIO descriptor flags based on the given GPIO lookup flags. + */ +static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags) +{ + if (lflags & GPIO_ACTIVE_LOW) + set_bit(FLAG_ACTIVE_LOW, &desc->flags); + if (lflags & GPIO_OPEN_DRAIN) + set_bit(FLAG_OPEN_DRAIN, &desc->flags); + if (lflags & GPIO_OPEN_SOURCE) + set_bit(FLAG_OPEN_SOURCE, &desc->flags); +} /** * gpiod_configure_flags - helper function to configure a given GPIO * @desc: gpio whose value will be assigned * @con_id: function within the GPIO consumer - * @lflags: gpio_lookup_flags - returned from of_find_gpio() or - * of_get_gpio_hog() * @dflags: gpiod_flags - optional GPIO initialization flags * * Return 0 on success, -ENOENT if no GPIO has been assigned to the @@ -2055,17 +2078,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional); * occurred while trying to acquire the GPIO. */ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, - unsigned long lflags, enum gpiod_flags dflags) + enum gpiod_flags dflags) { int status; - if (lflags & GPIO_ACTIVE_LOW) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - if (lflags & GPIO_OPEN_DRAIN) - set_bit(FLAG_OPEN_DRAIN, &desc->flags); - if (lflags & GPIO_OPEN_SOURCE) - set_bit(FLAG_OPEN_SOURCE, &desc->flags); - /* No particular flag request, return here... */ if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { pr_debug("no flags found for %s\n", con_id); @@ -2132,11 +2148,13 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, return desc; } + gpiod_parse_flags(desc, lookupflags); + status = gpiod_request(desc, con_id); if (status < 0) return ERR_PTR(status); - status = gpiod_configure_flags(desc, con_id, lookupflags, flags); + status = gpiod_configure_flags(desc, con_id, flags); if (status < 0) { dev_dbg(dev, "setup of GPIO %s failed\n", con_id); gpiod_put(desc); @@ -2190,14 +2208,14 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, if (IS_ERR(desc)) return desc; - ret = gpiod_request(desc, NULL); - if (ret) - return ERR_PTR(ret); - /* Only value flag can be set from both DT and ACPI is active_low */ if (active_low) set_bit(FLAG_ACTIVE_LOW, &desc->flags); + ret = gpiod_request(desc, NULL); + if (ret) + return ERR_PTR(ret); + return desc; } EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); @@ -2250,6 +2268,8 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, chip = gpiod_to_chip(desc); hwnum = gpio_chip_hwgpio(desc); + gpiod_parse_flags(desc, lflags); + local_desc = gpiochip_request_own_desc(chip, hwnum, name); if (IS_ERR(local_desc)) { pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n", @@ -2257,7 +2277,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, return PTR_ERR(local_desc); } - status = gpiod_configure_flags(desc, name, lflags, dflags); + status = gpiod_configure_flags(desc, name, dflags); if (status < 0) { pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n", name, chip->label, hwnum); -- cgit v0.10.2 From 90b665f627b18822a7bbebeff44ce730ccf74275 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 13 Oct 2015 00:20:21 +0300 Subject: gpiolib: Add and use OF_GPIO_SINGLE_ENDED flag The flag matches the DT GPIO_SINGLE_ENDED flag and allows drivers to parse and use the DT flag to handle single-ended (open-drain or open-source) GPIOs. Signed-off-by: Laurent Pinchart Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1615cc9..6798355 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1831,6 +1831,13 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, if (of_flags & OF_GPIO_ACTIVE_LOW) *flags |= GPIO_ACTIVE_LOW; + if (of_flags & OF_GPIO_SINGLE_ENDED) { + if (of_flags & OF_GPIO_ACTIVE_LOW) + *flags |= GPIO_OPEN_DRAIN; + else + *flags |= GPIO_OPEN_SOURCE; + } + return desc; } @@ -2184,6 +2191,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, { struct gpio_desc *desc = ERR_PTR(-ENODEV); bool active_low = false; + bool single_ended = false; int ret; if (!fwnode) @@ -2194,8 +2202,10 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname, 0, &flags); - if (!IS_ERR(desc)) + if (!IS_ERR(desc)) { active_low = flags & OF_GPIO_ACTIVE_LOW; + single_ended = flags & OF_GPIO_SINGLE_ENDED; + } } else if (is_acpi_node(fwnode)) { struct acpi_gpio_info info; @@ -2208,10 +2218,16 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, if (IS_ERR(desc)) return desc; - /* Only value flag can be set from both DT and ACPI is active_low */ if (active_low) set_bit(FLAG_ACTIVE_LOW, &desc->flags); + if (single_ended) { + if (active_low) + set_bit(FLAG_OPEN_DRAIN, &desc->flags); + else + set_bit(FLAG_OPEN_SOURCE, &desc->flags); + } + ret = gpiod_request(desc, NULL); if (ret) return ERR_PTR(ret); diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index f319182..87d6d16 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -29,6 +29,7 @@ struct device_node; */ enum of_gpio_flags { OF_GPIO_ACTIVE_LOW = 0x1, + OF_GPIO_SINGLE_ENDED = 0x2, }; #ifdef CONFIG_OF_GPIO -- cgit v0.10.2 From 85001089a764d6d12b47f33a8c9b49cf06cfe045 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Wed, 14 Oct 2015 13:51:54 +0100 Subject: gpio/xilinx: enable for MIPS MIPSfpga uses the axi gpio controller. Enable the driver for MIPS. Signed-off-by: Zubair Lutfullah Kakakhel Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63000b1..597b8d4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -506,7 +506,7 @@ config GPIO_XGENE_SB config GPIO_XILINX tristate "Xilinx GPIO support" - depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86) + depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86 || MIPS) help Say yes here to support the Xilinx FPGA GPIO device -- cgit v0.10.2 From 677b2ff4afd9996eabefc9472c701211b4b49e87 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 2 Oct 2015 14:26:05 -0700 Subject: gpio: add a real time compliance checklist Add some information about real time compliance to the driver document. Inspired by Grygorii Strashko's real time compliance patches. Cc: Grygorii Strashko Signed-off-by: Linus Walleij diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index 90d0f6a..9d79851 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -93,22 +93,37 @@ GPIO irqchips usually fall in one of two categories: Chained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks. -* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any - other GPIO irqchip residing on the other side of a sleeping bus. Of course - such drivers that need slow bus traffic to read out IRQ status and similar, - traffic which may in turn incur other IRQs to happen, cannot be handled - in a quick IRQ handler with IRQs disabled. Instead they need to spawn a - thread and then mask the parent IRQ line until the interrupt is handled - by the driver. The hallmark of this driver is to call something like - this in its interrupt handler: + NOTE: chained IRQ handlers are usually not good for real time. If you + are submitting a new driver or refactoring a driver for real time compliance, + consider using creating a nested/threaded irqchip instead, see below. + +* NESTED THREADED GPIO irqchips: these are traditionally off-chip GPIO + expanders and any other GPIO irqchip residing on the other side of a + sleeping bus. Of course such drivers that need slow bus traffic to read + out IRQ status and similar, traffic which may in turn incur other IRQs to + happen, cannot be handled in a quick IRQ handler with IRQs disabled. + + With the introduction of real time support in the Linux kernel, also other + GPIO irqchips are encouraged to use a nested and threaded IRQ handler. + Doing so makes the interrupts naturally preemptible on a real time + setup, which means the system can easily be configured for real time with + a (usually negligable) performance loss. + + These drivers spawn a thread and then mask the parent IRQ line until the + interrupt is handled by the driver. The hallmark of this driver is to call + something like this in its interrupt handler: static irqreturn_t tc3589x_gpio_irq(int irq, void *data) ... handle_nested_irq(irq); + OR + generic_handle_irq(irq); - The hallmark of threaded GPIO irqchips is that they set the .can_sleep - flag on struct gpio_chip to true, indicating that this chip may sleep - when accessing the GPIOs. + Threaded GPIO irqchips should set the .can_sleep flag on struct gpio_chip + to true if they are e.g. accessing the chip over I2C or SPI, indicating that + this chip may sleep when accessing the GPIOs. irqchips that are just made + threaded to be preemptible and thus real time compliant need not do this: + preemption is not sleeping. To help out in handling the set-up and management of GPIO irqchips and the associated irqdomain and resource allocation callbacks, the gpiolib has @@ -125,7 +140,7 @@ symbol: gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler data. (Notice handler data, since the irqchip data is likely used by the parent irqchip!) This is for the chained type of chip. This is also used - to set up a nested irqchip if NULL is passed as handler. + to set up a threaded/nested irqchip if NULL is passed as handler. To use the helpers please keep the following in mind: @@ -170,6 +185,39 @@ typically be called in the .startup() and .shutdown() callbacks from the irqchip. +Real-Time compliance for GPIO IRQ chips +--------------------------------------- + +Any provider of irqchips needs to be carefully tailored to support Real Time +preemption. It is desireable that all irqchips in the GPIO subsystem keep this +in mind and does the proper testing to assure they are real time-enabled. The +following is a checklist to follow when preparing a driver for real +time-compliance: + +- Nominally use raw_spinlock_t in the IRQ context path of the IRQ handler as + we do not want these sections to be preempted. + +- Do NOT use chained_irq_enter() or chained_irq_exit() in the IRQ handler, + as we want the hotpath to be preemptible. + +- Instead use nested IRQs and generic handlers such as handle_bad_irq(), + handle_level_irq() and handle_edge_irq(). Consequentally the handler + argument of gpiochip_set_chained_irqchip() should be NULL when using the + gpiolib irqchip helpers. + +- Nominally set all handlers to handle_bad_irq() in the setup call, then + set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip + .set_type() callback depending on what your controller supports. + +- If you need to use the pm_runtime_get*()/pm_runtime_put*() callbacks in some + of the irqchip callbacks, these should be moved to the .irq_bus_lock() + and .irq_bus_unlock() callbacks respectively, as these are the only + slowpath callbacks on an irqchip. Create the callbacks if need be. + +- Test your driver with the apropriate in-kernel real time test cases for both + level and edge IRQs. + + Requesting self-owned GPIO pins ------------------------------- -- cgit v0.10.2 From 83ea24fd45f8793706b9a259842ab3f144661e25 Mon Sep 17 00:00:00 2001 From: Kamlakant Patel Date: Thu, 15 Oct 2015 18:23:32 +0530 Subject: gpio: xlp: Convert to use gpiolib irqchip helpers commit "325f0a (MIPS: Netlogic: Use chip_data for irq_chip methods)" Updates "mips/netlogic/common/irq.c" to use chip_data to store interrupt controller data pointer. Before this commit handler_data was used to store interrupt controller data which caused errors while using gpiochip_set_chained_irqchip. Update XLP GPIO driver to use the gpiolib irqchip helpers. And add missing depends on OF_GPIO in Kconfig. Signed-off-by: Kamlakant Patel Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 597b8d4..77a796d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -512,7 +512,7 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on CPU_XLP + depends on CPU_XLP && OF_GPIO select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index e02499a..bc06a2c 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -18,6 +18,7 @@ #include #include #include +#include /* * XLP GPIO has multiple 32 bit registers for each feature where each register @@ -208,25 +209,28 @@ static struct irq_chip xlp_gpio_irq_chip = { .flags = IRQCHIP_ONESHOT_SAFE, }; -static irqreturn_t xlp_gpio_generic_handler(int irq, void *data) +static void xlp_gpio_generic_handler(struct irq_desc *desc) { - struct xlp_gpio_priv *priv = data; + struct xlp_gpio_priv *priv = irq_desc_get_handler_data(desc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); int gpio, regoff; u32 gpio_stat; regoff = -1; gpio_stat = 0; + + chained_irq_enter(irqchip, desc); for_each_set_bit(gpio, priv->gpio_enabled_mask, XLP_MAX_NR_GPIO) { if (regoff != gpio / XLP_GPIO_REGSZ) { regoff = gpio / XLP_GPIO_REGSZ; gpio_stat = readl(priv->gpio_intr_stat + regoff * 4); } + if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ)) generic_handle_irq(irq_find_mapping( priv->chip.irqdomain, gpio)); } - - return IRQ_HANDLED; + chained_irq_exit(irqchip, desc); } static int xlp_gpio_dir_output(struct gpio_chip *gc, unsigned gpio, int state) @@ -378,12 +382,6 @@ static int xlp_gpio_probe(struct platform_device *pdev) gc->get = xlp_gpio_get; spin_lock_init(&priv->lock); - - err = devm_request_irq(&pdev->dev, irq, xlp_gpio_generic_handler, - IRQ_TYPE_NONE, pdev->name, priv); - if (err) - return err; - irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); if (irq_base < 0) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); @@ -401,6 +399,9 @@ static int xlp_gpio_probe(struct platform_device *pdev) goto out_gpio_remove; } + gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq, + xlp_gpio_generic_handler); + dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio); return 0; -- cgit v0.10.2 From 6057d40f41a30f234533e5cf28810dd3fd2b6995 Mon Sep 17 00:00:00 2001 From: YD Tseng Date: Mon, 19 Oct 2015 11:07:37 +0800 Subject: gpio: driver for AMD Promontory This patch adds a new GPIO driver for AMD Promontory chip. This GPIO controller is enumerated by ACPI and the ACPI compliant hardware ID is AMDF030. Change history: v2: 1. fix coding style 2. registers renaming v3: 1. change include file 2. fix coding style 3. remove module_init/exit, add module_platform_driver 4. remove MODULE_ALIAS v4: 1. change TOTAL_GPIO_PINS to PT_TOTAL_GPIO 2. remove PCI dependency in Kconfig 3. fix subject line Signed-off-by: YD Tseng Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 77a796d..6fed6fc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -119,6 +119,13 @@ config GPIO_ALTERA If driver is built as a module it will be called gpio-altera. +config GPIO_AMDPT + tristate "AMD Promontory GPIO support" + depends on ACPI + help + driver for GPIO functionality on Promontory IOHub + Require ACPI ASL code to enumerate as a platform device. + config GPIO_BCM_KONA bool "Broadcom Kona GPIO" depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 77a07e9..43f4b3c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o +obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c new file mode 100644 index 0000000..cbbb966 --- /dev/null +++ b/drivers/gpio/gpio-amdpt.c @@ -0,0 +1,261 @@ +/* + * AMD Promontory GPIO driver + * + * Copyright (C) 2015 ASMedia Technology Inc. + * Author: YD Tseng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#define PT_TOTAL_GPIO 8 + +/* PCI-E MMIO register offsets */ +#define PT_DIRECTION_REG 0x00 +#define PT_INPUTDATA_REG 0x04 +#define PT_OUTPUTDATA_REG 0x08 +#define PT_CLOCKRATE_REG 0x0C +#define PT_SYNC_REG 0x28 + +struct pt_gpio_chip { + struct gpio_chip gc; + void __iomem *reg_base; + spinlock_t lock; +}; + +#define to_pt_gpio(c) container_of(c, struct pt_gpio_chip, gc) + +static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 using_pins; + + dev_dbg(gc->dev, "pt_gpio_request offset=%x\n", offset); + + spin_lock_irqsave(&pt_gpio->lock, flags); + + using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); + if (using_pins & BIT(offset)) { + dev_warn(gc->dev, "PT GPIO pin %x reconfigured\n", + offset); + spin_unlock_irqrestore(&pt_gpio->lock, flags); + return -EINVAL; + } + + writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); + + return 0; +} + +static void pt_gpio_free(struct gpio_chip *gc, unsigned offset) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 using_pins; + + spin_lock_irqsave(&pt_gpio->lock, flags); + + using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); + using_pins &= ~BIT(offset); + writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); + + dev_dbg(gc->dev, "pt_gpio_free offset=%x\n", offset); +} + +static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 data; + + dev_dbg(gc->dev, "pt_gpio_set_value offset=%x, value=%x\n", + offset, value); + + spin_lock_irqsave(&pt_gpio->lock, flags); + + data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); + data &= ~BIT(offset); + if (value) + data |= BIT(offset); + writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); +} + +static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&pt_gpio->lock, flags); + + data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); + + /* configure as output */ + if (data & BIT(offset)) + data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); + else /* configure as input */ + data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); + + data >>= offset; + data &= 1; + + dev_dbg(gc->dev, "pt_gpio_get_value offset=%x, value=%x\n", + offset, data); + + return data; +} + +static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 data; + + dev_dbg(gc->dev, "pt_gpio_dirction_input offset=%x\n", offset); + + spin_lock_irqsave(&pt_gpio->lock, flags); + + data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); + data &= ~BIT(offset); + writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); + + return 0; +} + +static int pt_gpio_direction_output(struct gpio_chip *gc, + unsigned offset, int value) +{ + struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc); + unsigned long flags; + u32 data; + + dev_dbg(gc->dev, "pt_gpio_direction_output offset=%x, value=%x\n", + offset, value); + + spin_lock_irqsave(&pt_gpio->lock, flags); + + data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); + if (value) + data |= BIT(offset); + else + data &= ~BIT(offset); + writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); + + data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); + data |= BIT(offset); + writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); + + spin_unlock_irqrestore(&pt_gpio->lock, flags); + + return 0; +} + +static int pt_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acpi_device *acpi_dev; + acpi_handle handle = ACPI_HANDLE(dev); + struct pt_gpio_chip *pt_gpio; + struct resource *res_mem; + int ret = 0; + + if (acpi_bus_get_device(handle, &acpi_dev)) { + dev_err(dev, "PT GPIO device node not found\n"); + return -ENODEV; + } + + pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL); + if (!pt_gpio) + return -ENOMEM; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res_mem) { + dev_err(&pdev->dev, "Failed to get MMIO resource for PT GPIO.\n"); + return -EINVAL; + } + pt_gpio->reg_base = devm_ioremap_resource(dev, res_mem); + if (IS_ERR(pt_gpio->reg_base)) { + dev_err(&pdev->dev, "Failed to map MMIO resource for PT GPIO.\n"); + return PTR_ERR(pt_gpio->reg_base); + } + + spin_lock_init(&pt_gpio->lock); + + pt_gpio->gc.label = pdev->name; + pt_gpio->gc.owner = THIS_MODULE; + pt_gpio->gc.dev = dev; + pt_gpio->gc.request = pt_gpio_request; + pt_gpio->gc.free = pt_gpio_free; + pt_gpio->gc.direction_input = pt_gpio_direction_input; + pt_gpio->gc.direction_output = pt_gpio_direction_output; + pt_gpio->gc.get = pt_gpio_get_value; + pt_gpio->gc.set = pt_gpio_set_value; + pt_gpio->gc.base = -1; + pt_gpio->gc.ngpio = PT_TOTAL_GPIO; +#if defined(CONFIG_OF_GPIO) + pt_gpio->gc.of_node = pdev->dev.of_node; +#endif + ret = gpiochip_add(&pt_gpio->gc); + if (ret) { + dev_err(&pdev->dev, "Failed to register GPIO lib\n"); + return ret; + } + + platform_set_drvdata(pdev, pt_gpio); + + /* initialize register setting */ + writel(0, pt_gpio->reg_base + PT_SYNC_REG); + writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG); + + dev_dbg(&pdev->dev, "PT GPIO driver loaded\n"); + return ret; +} + +static int pt_gpio_remove(struct platform_device *pdev) +{ + struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&pt_gpio->gc); + + return 0; +} + +static const struct acpi_device_id pt_gpio_acpi_match[] = { + { "AMDF030", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match); + +static struct platform_driver pt_gpio_driver = { + .driver = { + .name = "pt-gpio", + .acpi_match_table = ACPI_PTR(pt_gpio_acpi_match), + }, + .probe = pt_gpio_probe, + .remove = pt_gpio_remove, +}; + +module_platform_driver(pt_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("YD Tseng "); +MODULE_DESCRIPTION("AMD Promontory GPIO Driver"); -- cgit v0.10.2 From 1ceacea220c36e7933216e79b0ca21e1318b7c8d Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Mon, 19 Oct 2015 12:59:14 -0400 Subject: gpio: Add GPIO support for the ACCES 104-IDIO-16 The ACCES 104-IDIO-16 family of PC/104 utility boards feature 16 optically isolated inputs and 16 optically isolated FET solid state outputs. This driver provides GPIO support for these 32 channels of digital I/O. Change-of-State detection interrupts are not supported. GPIO 0-15 correspond to digital outputs 0-15, while GPIO 16-31 correspond to digital inputs 0-15. The base port address for the device may be set via the idio_16_base module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6fed6fc..27ce2ec 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -689,6 +689,16 @@ config GPIO_SX150X endmenu +menu "ISA GPIO drivers" + +config GPIO_104_IDIO_16 + tristate "ACCES 104-IDIO-16 GPIO support" + depends on X86 + help + Enables GPIO support for the ACCES 104-IDIO-16 family. + +endmenu + menu "MFD GPIO expanders" config GPIO_ADP5520 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 43f4b3c..986dbd8 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o +obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c new file mode 100644 index 0000000..5400d7d --- /dev/null +++ b/drivers/gpio/gpio-104-idio-16.c @@ -0,0 +1,216 @@ +/* + * GPIO driver for the ACCES 104-IDIO-16 family + * Copyright (C) 2015 William Breathitt Gray + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned idio_16_base; +module_param(idio_16_base, uint, 0); +MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address"); + +/** + * struct idio_16_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @lock: synchronization lock to prevent gpio_set race conditions + * @base: base port address of the GPIO device + * @extent: extent of port address region of the GPIO device + * @out_state: output bits state + */ +struct idio_16_gpio { + struct gpio_chip chip; + spinlock_t lock; + unsigned base; + unsigned extent; + unsigned out_state; +}; + +static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 15) + return 1; + + return 0; +} + +static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return 0; +} + +static int idio_16_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + chip->set(chip, offset, value); + return 0; +} + +static struct idio_16_gpio *to_idio16gpio(struct gpio_chip *gc) +{ + return container_of(gc, struct idio_16_gpio, chip); +} + +static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip); + const unsigned BIT_MASK = 1U << (offset-16); + + if (offset < 16) + return -EINVAL; + + if (offset < 24) + return !!(inb(idio16gpio->base + 1) & BIT_MASK); + + return !!(inb(idio16gpio->base + 5) & (BIT_MASK>>8)); +} + +static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip); + const unsigned BIT_MASK = 1U << offset; + unsigned long flags; + + if (offset > 15) + return; + + spin_lock_irqsave(&idio16gpio->lock, flags); + + if (value) + idio16gpio->out_state |= BIT_MASK; + else + idio16gpio->out_state &= ~BIT_MASK; + + if (offset > 7) + outb(idio16gpio->out_state >> 8, idio16gpio->base + 4); + else + outb(idio16gpio->out_state, idio16gpio->base); + + spin_unlock_irqrestore(&idio16gpio->lock, flags); +} + +static int __init idio_16_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct idio_16_gpio *idio16gpio; + int err; + + const unsigned BASE = idio_16_base; + const unsigned EXTENT = 8; + const char *const NAME = dev_name(dev); + + idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); + if (!idio16gpio) + return -ENOMEM; + + if (!request_region(BASE, EXTENT, NAME)) { + dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", + NAME, BASE, BASE + EXTENT); + err = -EBUSY; + goto err_lock_io_port; + } + + idio16gpio->chip.label = NAME; + idio16gpio->chip.dev = dev; + idio16gpio->chip.owner = THIS_MODULE; + idio16gpio->chip.base = -1; + idio16gpio->chip.ngpio = 32; + idio16gpio->chip.get_direction = idio_16_gpio_get_direction; + idio16gpio->chip.direction_input = idio_16_gpio_direction_input; + idio16gpio->chip.direction_output = idio_16_gpio_direction_output; + idio16gpio->chip.get = idio_16_gpio_get; + idio16gpio->chip.set = idio_16_gpio_set; + idio16gpio->base = BASE; + idio16gpio->extent = EXTENT; + idio16gpio->out_state = 0xFFFF; + + spin_lock_init(&idio16gpio->lock); + + dev_set_drvdata(dev, idio16gpio); + + err = gpiochip_add(&idio16gpio->chip); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + goto err_gpio_register; + } + + return 0; + +err_gpio_register: + release_region(BASE, EXTENT); +err_lock_io_port: + return err; +} + +static int idio_16_remove(struct platform_device *pdev) +{ + struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&idio16gpio->chip); + release_region(idio16gpio->base, idio16gpio->extent); + + return 0; +} + +static struct platform_device *idio_16_device; + +static struct platform_driver idio_16_driver = { + .driver = { + .name = "104-idio-16" + }, + .remove = idio_16_remove +}; + +static void __exit idio_16_exit(void) +{ + platform_device_unregister(idio_16_device); + platform_driver_unregister(&idio_16_driver); +} + +static int __init idio_16_init(void) +{ + int err; + + idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1); + if (!idio_16_device) + return -ENOMEM; + + err = platform_device_add(idio_16_device); + if (err) + goto err_platform_device; + + err = platform_driver_probe(&idio_16_driver, idio_16_probe); + if (err) + goto err_platform_driver; + + return 0; + +err_platform_driver: + platform_device_del(idio_16_device); +err_platform_device: + platform_device_put(idio_16_device); + return err; +} + +module_init(idio_16_init); +module_exit(idio_16_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 4aa50b87f1e99164a93314c25ed3a827c24bc54f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 27 Oct 2015 11:13:18 +0100 Subject: Revert "gpio: add a real time compliance checklist" This reverts commit 677b2ff4afd9996eabefc9472c701211b4b49e87. diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index 9d79851..90d0f6a 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -93,37 +93,22 @@ GPIO irqchips usually fall in one of two categories: Chained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks. - NOTE: chained IRQ handlers are usually not good for real time. If you - are submitting a new driver or refactoring a driver for real time compliance, - consider using creating a nested/threaded irqchip instead, see below. - -* NESTED THREADED GPIO irqchips: these are traditionally off-chip GPIO - expanders and any other GPIO irqchip residing on the other side of a - sleeping bus. Of course such drivers that need slow bus traffic to read - out IRQ status and similar, traffic which may in turn incur other IRQs to - happen, cannot be handled in a quick IRQ handler with IRQs disabled. - - With the introduction of real time support in the Linux kernel, also other - GPIO irqchips are encouraged to use a nested and threaded IRQ handler. - Doing so makes the interrupts naturally preemptible on a real time - setup, which means the system can easily be configured for real time with - a (usually negligable) performance loss. - - These drivers spawn a thread and then mask the parent IRQ line until the - interrupt is handled by the driver. The hallmark of this driver is to call - something like this in its interrupt handler: +* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any + other GPIO irqchip residing on the other side of a sleeping bus. Of course + such drivers that need slow bus traffic to read out IRQ status and similar, + traffic which may in turn incur other IRQs to happen, cannot be handled + in a quick IRQ handler with IRQs disabled. Instead they need to spawn a + thread and then mask the parent IRQ line until the interrupt is handled + by the driver. The hallmark of this driver is to call something like + this in its interrupt handler: static irqreturn_t tc3589x_gpio_irq(int irq, void *data) ... handle_nested_irq(irq); - OR - generic_handle_irq(irq); - Threaded GPIO irqchips should set the .can_sleep flag on struct gpio_chip - to true if they are e.g. accessing the chip over I2C or SPI, indicating that - this chip may sleep when accessing the GPIOs. irqchips that are just made - threaded to be preemptible and thus real time compliant need not do this: - preemption is not sleeping. + The hallmark of threaded GPIO irqchips is that they set the .can_sleep + flag on struct gpio_chip to true, indicating that this chip may sleep + when accessing the GPIOs. To help out in handling the set-up and management of GPIO irqchips and the associated irqdomain and resource allocation callbacks, the gpiolib has @@ -140,7 +125,7 @@ symbol: gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler data. (Notice handler data, since the irqchip data is likely used by the parent irqchip!) This is for the chained type of chip. This is also used - to set up a threaded/nested irqchip if NULL is passed as handler. + to set up a nested irqchip if NULL is passed as handler. To use the helpers please keep the following in mind: @@ -185,39 +170,6 @@ typically be called in the .startup() and .shutdown() callbacks from the irqchip. -Real-Time compliance for GPIO IRQ chips ---------------------------------------- - -Any provider of irqchips needs to be carefully tailored to support Real Time -preemption. It is desireable that all irqchips in the GPIO subsystem keep this -in mind and does the proper testing to assure they are real time-enabled. The -following is a checklist to follow when preparing a driver for real -time-compliance: - -- Nominally use raw_spinlock_t in the IRQ context path of the IRQ handler as - we do not want these sections to be preempted. - -- Do NOT use chained_irq_enter() or chained_irq_exit() in the IRQ handler, - as we want the hotpath to be preemptible. - -- Instead use nested IRQs and generic handlers such as handle_bad_irq(), - handle_level_irq() and handle_edge_irq(). Consequentally the handler - argument of gpiochip_set_chained_irqchip() should be NULL when using the - gpiolib irqchip helpers. - -- Nominally set all handlers to handle_bad_irq() in the setup call, then - set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip - .set_type() callback depending on what your controller supports. - -- If you need to use the pm_runtime_get*()/pm_runtime_put*() callbacks in some - of the irqchip callbacks, these should be moved to the .irq_bus_lock() - and .irq_bus_unlock() callbacks respectively, as these are the only - slowpath callbacks on an irqchip. Create the callbacks if need be. - -- Test your driver with the apropriate in-kernel real time test cases for both - level and edge IRQs. - - Requesting self-owned GPIO pins ------------------------------- -- cgit v0.10.2 From c307b002548590c5d8c32b964831de671ad4affe Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 20 Oct 2015 17:22:15 +0300 Subject: gpio: add a real time compliance notes Put in a compliance checklist. Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index 90d0f6a..12a6194 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -62,6 +62,11 @@ Any debugfs dump method should normally ignore signals which haven't been requested as GPIOs. They can use gpiochip_is_requested(), which returns either NULL or the label associated with that GPIO when it was requested. +RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs +(like PM runtime) in its gpio_chip implementation (.get/.set and direction +control callbacks) if it is expected to call GPIO APIs from atomic context +on -RT (inside hard IRQ handlers and similar contexts). Normally this should +not be required. GPIO drivers providing IRQs --------------------------- @@ -73,6 +78,13 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using the header . So basically such a driver is utilizing two sub- systems simultaneously: gpio and irq. +RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs +(like PM runtime) as part of its irq_chip implementation on -RT. +- spinlock_t should be replaced with raw_spinlock_t [1]. +- If sleepable APIs have to be used, these can be done from the .irq_bus_lock() + and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks + on an irqchip. Create the callbacks if needed [2]. + GPIO irqchips usually fall in one of two categories: * CHAINED GPIO irqchips: these are usually the type that is embedded on @@ -93,6 +105,38 @@ GPIO irqchips usually fall in one of two categories: Chained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks. + RT_FULL: Note, chained IRQ handlers will not be forced threaded on -RT. + As result, spinlock_t or any sleepable APIs (like PM runtime) can't be used + in chained IRQ handler. + if required (and if it can't be converted to the nested threaded GPIO irqchip) + - chained IRQ handler can be converted to generic irq handler and this way + it will be threaded IRQ handler on -RT and hard IRQ handler on non-RT + (for example, see [3]). + Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled, + so IRQ core will complain if it will be called from IRQ handler wich is forced + thread. The "fake?" raw lock can be used to W/A this problem: + + raw_spinlock_t wa_lock; + static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) + unsigned long wa_lock_flags; + raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags); + generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit)); + raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags); + +* GENERIC CHAINED GPIO irqchips: these are the same as "CHAINED GPIO irqchips", + but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is + performed by generic IRQ handler which is configured using request_irq(). + The GPIO irqchip will then end up calling something like this sequence in + its interrupt handler: + + static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) + for each detected GPIO IRQ + generic_handle_irq(...); + + RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ + core will complain that generic_handle_irq() is called with IRQ enabled and + the same W/A as for "CHAINED GPIO irqchips" can be applied. + * NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any other GPIO irqchip residing on the other side of a sleeping bus. Of course such drivers that need slow bus traffic to read out IRQ status and similar, @@ -133,6 +177,13 @@ To use the helpers please keep the following in mind: the irqchip can initialize. E.g. .dev and .can_sleep shall be set up properly. +- Nominally set all handlers to handle_bad_irq() in the setup call and pass + handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is + expected for GPIO driver that irqchip .set_type() callback have to be called + before using/enabling GPIO IRQ. Then set the handler to handle_level_irq() + and/or handle_edge_irq() in the irqchip .set_type() callback depending on + what your controller supports. + It is legal for any IRQ consumer to request an IRQ from any irqchip no matter if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and irq_chip are orthogonal, and offering their services independent of each @@ -169,6 +220,31 @@ When implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .startup() and .shutdown() callbacks from the irqchip. +Real-Time compliance for GPIO IRQ chips +--------------------------------------- + +Any provider of irqchips needs to be carefully tailored to support Real Time +preemption. It is desireable that all irqchips in the GPIO subsystem keep this +in mind and does the proper testing to assure they are real time-enabled. +So, pay attention on above " RT_FULL:" notes, please. +The following is a checklist to follow when preparing a driver for real +time-compliance: + +- ensure spinlock_t is not used as part irq_chip implementation; +- ensure that sleepable APIs are not used as part irq_chip implementation. + If sleepable APIs have to be used, these can be done from the .irq_bus_lock() + and .irq_bus_unlock() callbacks; +- Chained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used + from chained IRQ handler; +- Generic chained GPIO irqchips: take care about generic_handle_irq() calls and + apply corresponding W/A; +- Chained GPIO irqchips: get rid of chained IRQ handler and use generic irq + handler if possible :) +- regmap_mmio: Sry, but you are in trouble :( if MMIO regmap is used as for + GPIO IRQ chip implementation; +- Test your driver with the appropriate in-kernel real time test cases for both + level and edge IRQs. + Requesting self-owned GPIO pins ------------------------------- @@ -190,3 +266,7 @@ gpiochip_free_own_desc(). These functions must be used with care since they do not affect module use count. Do not use the functions to request gpio descriptors not owned by the calling driver. + +[1] http://www.spinics.net/lists/linux-omap/msg120425.html +[2] https://lkml.org/lkml/2015/9/25/494 +[3] https://lkml.org/lkml/2015/9/25/495 -- cgit v0.10.2 From b2f68b6306dbdbfd9b8cf46c697b52efa78f9ad6 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 21 Oct 2015 00:12:00 -0700 Subject: gpio: generic: Revert to old error handling in bgpio_map Returning an error instead of NULL in bgpio_map if platform_get_resource_byname does not find a resource was introduced with commit cf3f2a2c8bae ("gpio: generic: improve error handling in bgpio_map"). This results in several qemu runtime failures with default and non-default configurations, if attempts are made to boot from mmcblk0. Examples for failures with multi_v7_defconfig are Machine: vexpress-a9 dtb: vexpress-v2p-ca9 Machine: vexpress-a15 dtb: vexpress-v2p-ca15-tc1 Crash: VFS: Cannot open root device "mmcblk0" or unknown-block(0,0): error -6 Please append a correct "root=" boot option; here are the available partitions: Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) Looking into the code, always returning an error if bgpio_map fails does not appear to make much sense, since the code in bgpio_setup_io specifically supports some of the resources to be NULL. Fixes: cf3f2a2c8bae ("gpio: generic: improve error handling in bgpio_map") Cc: Heiner Kallweit Signed-off-by: Guenter Roeck Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index d8b1700..bd5193c 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -586,7 +586,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev, r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); if (!r) - return IOMEM_ERR_PTR(-EINVAL); + return NULL; sz = resource_size(r); if (sz != sane_sz) -- cgit v0.10.2 From 79786721c29ff8fecf2903ba080479476015553d Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 22 Oct 2015 21:51:18 -0700 Subject: gpio: xilinx: Drop architecture dependencies The driver does not have any real architecture dependencies. To avoid listing each architecture that might use this driver on some FPGA-enabled platform, drop these dependencies. Signed-off-by: Soren Brinkmann Acked-by: Moritz Fischer Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 27ce2ec..dbb171d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -513,7 +513,7 @@ config GPIO_XGENE_SB config GPIO_XILINX tristate "Xilinx GPIO support" - depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86 || MIPS) + depends on OF_GPIO help Say yes here to support the Xilinx FPGA GPIO device -- cgit v0.10.2 From 787dfbb294b25b37211d0749e7cdbb20d443c680 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 23 Oct 2015 09:25:30 -0700 Subject: gpio: zynq: Document interrupt-controller DT binding HW and driver support the GPIO as interrupt-controller. Document that in the DT binding. Signed-off-by: Soren Brinkmann Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt index db4c6a6..7b54265 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt @@ -12,6 +12,13 @@ Required properties: - interrupts : Interrupt specifier (see interrupt bindings for details) - interrupt-parent : Must be core interrupt controller +- interrupt-controller : Marks the device node as an interrupt controller. +- #interrupt-cells : Should be 2. The first cell is the GPIO number. + The second cell bits[3:0] is used to specify trigger type and level flags: + 1 = low-to-high edge triggered. + 2 = high-to-low edge triggered. + 4 = active high level-sensitive. + 8 = active low level-sensitive. - reg : Address and length of the register set for the device Example: @@ -22,5 +29,7 @@ Example: gpio-controller; interrupt-parent = <&intc>; interrupts = <0 20 4>; + interrupt-controller; + #interrupt-cells = <2>; reg = <0xe000a000 0x1000>; }; -- cgit v0.10.2 From e25589894e24b07a33b143b9bfd95fe8d2c0a353 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 28 Oct 2015 17:24:16 -0400 Subject: gpio: Add ACCES 104-IDIO-16 driver maintainer entry Add William Breathitt Gray as the maintainer of the ACCES 104-IDIO-16 GPIO driver. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij diff --git a/MAINTAINERS b/MAINTAINERS index 274f854..b1d18dd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,12 @@ L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/abituguru3.c +ACCES 104-IDIO-16 GPIO DRIVER +M: "William Breathitt Gray" +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-104-idio-16.c + ACENIC DRIVER M: Jes Sorensen L: linux-acenic@sunsite.dk -- cgit v0.10.2 From bc6a73bbfba5d8325b0e659545ce2f3ad983829b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2015 10:32:19 +0100 Subject: gpio: group port-mapped I/O drivers in a menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a Kconfig submenu for drivers using X86 port-mapped I/O and depend on X86 for this. Suggested-by: Mika Westerberg Cc: William Breathitt Gray Cc: Andreas Bofjall Cc: Diego Elio Pettenò Cc: Daniel Krueger Cc: Bruno Randolf Cc: Vivien Didelot Acked-by: Simon Guinot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index dbb171d..d20644b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -183,16 +183,6 @@ config GPIO_ETRAXFS help Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. -config GPIO_F7188X - tristate "F71869, F71869A, F71882FG and F71889F GPIO support" - depends on X86 - help - This option enables support for GPIOs found on Fintek Super-I/O - chips F71869, F71869A, F71882FG and F71889F. - - To compile this driver as a module, choose M here: the module will - be called f7188x-gpio. - config GPIO_GE_FPGA bool "GE FPGA based GPIO" depends on GE_FPGA @@ -242,18 +232,6 @@ config GPIO_IOP If unsure, say N. -config GPIO_IT87 - tristate "IT87xx GPIO support" - depends on X86 # unconditional access to IO space. - help - Say yes here to support GPIO functionality of IT87xx Super I/O chips. - - This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and - supports the IT8761E Super I/O chip as well. - - To compile this driver as a module, choose M here: the module will - be called gpio_it87 - config GPIO_LOONGSON bool "Loongson-2/3 GPIO support" depends on CPU_LOONGSON2 || CPU_LOONGSON3 @@ -373,42 +351,6 @@ config GPIO_SAMSUNG Legacy GPIO support. Use only for platforms without support for pinctrl. -config GPIO_SCH - tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO" - depends on PCI && X86 - select MFD_CORE - select LPC_SCH - help - Say yes here to support GPIO interface on Intel Poulsbo SCH, - Intel Tunnel Creek processor, Intel Centerton processor or - Intel Quark X1000 SoC. - - The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are - powered by the core power rail and are turned off during sleep - modes (S3 and higher). The remaining four GPIOs are powered by - the Intel SCH suspend power supply. These GPIOs remain - active during S3. The suspend powered GPIOs can be used to wake the - system from the Suspend-to-RAM state. - - The Intel Tunnel Creek processor has 5 GPIOs powered by the - core power rail and 9 from suspend power supply. - - The Intel Centerton processor has a total of 30 GPIO pins. - Twenty-one are powered by the core power rail and 9 from the - suspend power supply. - - The Intel Quark X1000 SoC has 2 GPIOs powered by the core - power well and 6 from the suspend power well. - -config GPIO_SCH311X - tristate "SMSC SCH311x SuperI/O GPIO" - help - Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and - SCH3116 "Super I/O" chipsets. - - To compile this driver as a module, choose M here: the module will - be called gpio-sch311x. - config GPIO_SPEAR_SPICS bool "ST SPEAr13xx SPI Chip Select as GPIO support" depends on PLAT_SPEAR @@ -445,15 +387,6 @@ config GPIO_TB10X select GENERIC_IRQ_CHIP select OF_GPIO -config GPIO_TS5500 - tristate "TS-5500 DIO blocks and compatibles" - depends on TS5500 || COMPILE_TEST - help - This driver supports Digital I/O exposed by pin blocks found on some - Technologic Systems platforms. It includes, but is not limited to, 3 - blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 - LCD port. - config GPIO_TZ1090 bool "Toumaz Xenif TZ1090 GPIO support" depends on SOC_TZ1090 @@ -552,6 +485,84 @@ config GPIO_ZYNQ endmenu +menu "Port-mapped I/O GPIO drivers" + depends on X86 + +config GPIO_104_IDIO_16 + tristate "ACCES 104-IDIO-16 GPIO support" + depends on X86 + help + Enables GPIO support for the ACCES 104-IDIO-16 family. + +config GPIO_F7188X + tristate "F71869, F71869A, F71882FG and F71889F GPIO support" + depends on X86 + help + This option enables support for GPIOs found on Fintek Super-I/O + chips F71869, F71869A, F71882FG and F71889F. + + To compile this driver as a module, choose M here: the module will + be called f7188x-gpio. + +config GPIO_IT87 + tristate "IT87xx GPIO support" + depends on X86 # unconditional access to IO space. + help + Say yes here to support GPIO functionality of IT87xx Super I/O chips. + + This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and + supports the IT8761E Super I/O chip as well. + + To compile this driver as a module, choose M here: the module will + be called gpio_it87 + +config GPIO_SCH + tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO" + depends on PCI && X86 + select MFD_CORE + select LPC_SCH + help + Say yes here to support GPIO interface on Intel Poulsbo SCH, + Intel Tunnel Creek processor, Intel Centerton processor or + Intel Quark X1000 SoC. + + The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are + powered by the core power rail and are turned off during sleep + modes (S3 and higher). The remaining four GPIOs are powered by + the Intel SCH suspend power supply. These GPIOs remain + active during S3. The suspend powered GPIOs can be used to wake the + system from the Suspend-to-RAM state. + + The Intel Tunnel Creek processor has 5 GPIOs powered by the + core power rail and 9 from suspend power supply. + + The Intel Centerton processor has a total of 30 GPIO pins. + Twenty-one are powered by the core power rail and 9 from the + suspend power supply. + + The Intel Quark X1000 SoC has 2 GPIOs powered by the core + power well and 6 from the suspend power well. + +config GPIO_SCH311X + tristate "SMSC SCH311x SuperI/O GPIO" + help + Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and + SCH3116 "Super I/O" chipsets. + + To compile this driver as a module, choose M here: the module will + be called gpio-sch311x. + +config GPIO_TS5500 + tristate "TS-5500 DIO blocks and compatibles" + depends on TS5500 || COMPILE_TEST + help + This driver supports Digital I/O exposed by pin blocks found on some + Technologic Systems platforms. It includes, but is not limited to, 3 + blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 + LCD port. + +endmenu + menu "I2C GPIO expanders" depends on I2C @@ -689,16 +700,6 @@ config GPIO_SX150X endmenu -menu "ISA GPIO drivers" - -config GPIO_104_IDIO_16 - tristate "ACCES 104-IDIO-16 GPIO support" - depends on X86 - help - Enables GPIO support for the ACCES 104-IDIO-16 family. - -endmenu - menu "MFD GPIO expanders" config GPIO_ADP5520 -- cgit v0.10.2 From c103a10f690cc49054c52f493eeeff143d5f59e7 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 30 Oct 2015 12:02:05 +0200 Subject: gpio / ACPI: Allow shared GPIO event to be read via operation region In Microsoft Surface3 the GPIO detecting lid state is shared between GPIO event and operation region. Below is simplied version of the DSDT from Surface3 including relevant parts: Scope (GPO0) { Name (_AEI, ResourceTemplate () { GpioInt (Edge, ActiveBoth, Shared, PullNone, 0x0000, "\\_SB.GPO0", 0x00, ResourceConsumer, , ) { // Pin list 0x004C } }) OperationRegion (GPOR, GeneralPurposeIo, Zero, One) Field (GPOR, ByteAcc, NoLock, Preserve) { Connection ( GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone, "\\_SB.GPO0", 0x00, ResourceConsumer,,) { // Pin list 0x004C } ), HELD, 1 } Method (_E4C, 0, Serialized) // _Exx: Edge-Triggered GPE { If ((HELD == One)) { ^^LID.LIDB = One } Else { ^^LID.LIDB = Zero Notify (LID, 0x80) // Status Change } Notify (^^PCI0.SPI1.NTRG, One) // Device Check } } When GPIO 0x4c changes we call ASL method _E4C which tries to read HELD field (the same GPIO). This triggers following error on the console: ACPI Error: Method parse/execution failed [\_SB.GPO0._E4C] (Node ffff88013f4b4438), AE_ERROR (20150930/psparse-542) The error happens because ACPI GPIO operation region handler (acpi_gpio_adr_space_handler()) tries to acquire the very same GPIO which returns an error (-EBUSY) because the GPIO is already reserved for the GPIO event. Fix this so that we "borrow" the event GPIO if we find the GPIO belongs to an event. Allow this only for GPIOs that are read. To be able to go through acpi_gpio->events list for operation region access we need to make sure the list is properly initialized whenever GPIO chip is registered. Link: https://bugzilla.kernel.org/show_bug.cgi?id=106571 Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 143a9bd..bbcac3a 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -304,7 +304,6 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) if (ACPI_FAILURE(status)) return; - INIT_LIST_HEAD(&acpi_gpio->events); acpi_walk_resources(handle, "_AEI", acpi_gpiochip_request_interrupt, acpi_gpio); } @@ -603,6 +602,25 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, break; } } + + /* + * The same GPIO can be shared between operation region and + * event but only if the access here is ACPI_READ. In that + * case we "borrow" the event GPIO instead. + */ + if (!found && agpio->sharable == ACPI_SHARED && + function == ACPI_READ) { + struct acpi_gpio_event *event; + + list_for_each_entry(event, &achip->events, node) { + if (event->pin == pin) { + desc = event->desc; + found = true; + break; + } + } + } + if (!found) { desc = gpiochip_request_own_desc(chip, pin, "ACPI:OpRegion"); @@ -719,6 +737,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip) } acpi_gpio->chip = chip; + INIT_LIST_HEAD(&acpi_gpio->events); status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio); if (ACPI_FAILURE(status)) { -- cgit v0.10.2 From aad7a2119965a4a504ddf1d8374968135e9a8780 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Fri, 30 Oct 2015 11:36:29 +0100 Subject: gpio: MAINTAINERS: Add an entry for the ATH79 GPIO driver Add an entry for the ATH79 GPIO driver with myself as maintainer. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij diff --git a/MAINTAINERS b/MAINTAINERS index b1d18dd..6ad9d5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1779,6 +1779,14 @@ S: Supported F: Documentation/aoe/ F: drivers/block/aoe/ +ATHEROS 71XX/9XXX GPIO DRIVER +M: Alban Bedel +W: https://github.com/AlbanBedel/linux +T: git git://github.com/AlbanBedel/linux +S: Maintained +F: drivers/gpio/gpio-ath79.c +F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt + ATHEROS ATH GENERIC UTILITIES M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org -- cgit v0.10.2 From aacaffd1d9a6f8e2c7369d83c21d41c3b53e2edc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2015 11:58:28 +0100 Subject: gpio: dt-bindings: document the official use of "ngpios" There are a bunch of drivers that utilize the "ngpios" DT property without any vendor prefix. Try to start cleaning up the mess by defining what we mean by this property. Cc: devicetree@vger.kernel.org Cc: Pramod Kumar Cc: Jonas Gorski Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 63b1b90..e9c49dc 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -129,6 +129,30 @@ Every GPIO controller node must contain both an empty "gpio-controller" property, and a #gpio-cells integer property, which indicates the number of cells in a gpio-specifier. +Optionally, a GPIO controller may have a "ngpios" property. This property +indicates the number of in-use slots of available slots for GPIOs. The +typical example is something like this: the hardware register is 32 bits +wide, but only 18 of the bits have a physical counterpart. The driver is +generally written so that all 32 bits can be used, but the IP block is reused +in a lot of designs, some using all 32 bits, some using 18 and some using +12. In this case, setting "ngpios = <18>;" informs the driver that only the +first 18 GPIOs, at local offset 0 .. 17, are in use. + +If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an +additional bitmask is needed to specify which GPIOs are actually in use, +and which are dummies. The bindings for this case has not yet been +specified, but should be specified if/when such hardware appears. + +Example: + +gpio-controller@00000000 { + compatible = "foo"; + reg = <0x00000000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <18>; +} + The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism providing automatic GPIO request and configuration as part of the gpio-controller's driver probe function. -- cgit v0.10.2 From 7768feb0f56d4ba6c1ae1395e144e168e41f1900 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 1 Nov 2015 10:39:07 +0100 Subject: gpio: drop surplus X86 dependencies Port-mapped I/O depends on X86 already, so individual drivers need not specify this dependency. Suggested-by: Vivien Didelot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d20644b..777f401 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -486,17 +486,15 @@ config GPIO_ZYNQ endmenu menu "Port-mapped I/O GPIO drivers" - depends on X86 + depends on X86 # Unconditional I/O space access config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" - depends on X86 help Enables GPIO support for the ACCES 104-IDIO-16 family. config GPIO_F7188X tristate "F71869, F71869A, F71882FG and F71889F GPIO support" - depends on X86 help This option enables support for GPIOs found on Fintek Super-I/O chips F71869, F71869A, F71882FG and F71889F. @@ -506,7 +504,6 @@ config GPIO_F7188X config GPIO_IT87 tristate "IT87xx GPIO support" - depends on X86 # unconditional access to IO space. help Say yes here to support GPIO functionality of IT87xx Super I/O chips. @@ -518,7 +515,7 @@ config GPIO_IT87 config GPIO_SCH tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO" - depends on PCI && X86 + depends on PCI select MFD_CORE select LPC_SCH help -- cgit v0.10.2 From 269a46f80bd9c77b6f862a92ccb52eb8a68d3997 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 1 Nov 2015 10:43:16 +0100 Subject: gpio: drop surplus I2C dependencies The I2C expander menu already depends on I2C, drop subdependecies on individual drivers. Keep the instances of depends on I2C=y though, so these are still restricted to the compiled-in case. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 777f401..a8dcc99 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -565,7 +565,6 @@ menu "I2C GPIO expanders" config GPIO_ADP5588 tristate "ADP5588 I2C GPIO expander" - depends on I2C help This option enables support for 18 GPIOs found on Analog Devices ADP5588 GPIO Expanders. @@ -579,7 +578,7 @@ config GPIO_ADP5588_IRQ config GPIO_ADNP tristate "Avionic Design N-bit GPIO expander" - depends on I2C && OF_GPIO + depends on OF_GPIO select GPIOLIB_IRQCHIP help This option enables support for N GPIOs found on Avionic Design @@ -591,14 +590,12 @@ config GPIO_ADNP config GPIO_MAX7300 tristate "Maxim MAX7300 GPIO expander" - depends on I2C select GPIO_MAX730X help GPIO driver for Maxim MAX7300 I2C-based GPIO expander. config GPIO_MAX732X tristate "MAX7319, MAX7320-7327 I2C Port Expanders" - depends on I2C help Say yes here to support the MAX7319, MAX7320-7327 series of I2C Port Expanders. Each IO port on these chips has a fixed role of @@ -631,7 +628,6 @@ config GPIO_MC9S08DZ60 config GPIO_PCA953X tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports" - depends on I2C help Say yes here to provide access to several register-oriented SMBus I/O expanders, made mostly by NXP or TI. Compatible @@ -659,7 +655,6 @@ config GPIO_PCA953X_IRQ config GPIO_PCF857X tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" - depends on I2C select GPIOLIB_IRQCHIP select IRQ_DOMAIN help -- cgit v0.10.2 From 0963670aeaec2287aa263daa0d41384d4dcd5292 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 1 Nov 2015 10:50:19 +0100 Subject: gpio: fix up SPI submenu - Relax dependencies on SPI_MASTER for drivers in the SPI menu that already has this dependency. - Move out the expander that would be hidden for I2C access if SPI_MASTER was not selected. Tentatively create a separate menu for this. - Move the ZX SoC driver to memory-mapped drivers, this must be a mistake and only worked because the system has an SPI master enabled at the same time. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a8dcc99..b18bea0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -483,6 +483,12 @@ config GPIO_ZYNQ help Say yes here to support Xilinx Zynq GPIO controller. +config GPIO_ZX + bool "ZTE ZX GPIO support" + select GPIOLIB_IRQCHIP + help + Say yes here to support the GPIO device on ZTE ZX SoCs. + endmenu menu "Port-mapped I/O GPIO drivers" @@ -984,7 +990,7 @@ menu "SPI GPIO expanders" config GPIO_74X164 tristate "74x164 serial-in/parallel-out 8-bits shift register" - depends on SPI_MASTER && OF + depends on OF help Driver for 74x164 compatible serial-in/parallel-out 8-outputs shift registers. This driver can be used to provide access @@ -992,32 +998,28 @@ config GPIO_74X164 config GPIO_MAX7301 tristate "Maxim MAX7301 GPIO expander" - depends on SPI_MASTER select GPIO_MAX730X help GPIO driver for Maxim MAX7301 SPI-based GPIO expander. -config GPIO_MCP23S08 - tristate "Microchip MCP23xxx I/O expander" - depends on (SPI_MASTER && !I2C) || I2C - help - SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 - I/O expanders. - This provides a GPIO interface supporting inputs and outputs. - The I2C versions of the chips can be used as interrupt-controller. - config GPIO_MC33880 tristate "Freescale MC33880 high-side/low-side switch" - depends on SPI_MASTER help SPI driver for Freescale MC33880 high-side/low-side switch. This provides GPIO interface supporting inputs and outputs. -config GPIO_ZX - bool "ZTE ZX GPIO support" - select GPIOLIB_IRQCHIP +endmenu + +menu "SPI or I2C GPIO expanders" + depends on (SPI_MASTER && !I2C) || I2C + +config GPIO_MCP23S08 + tristate "Microchip MCP23xxx I/O expander" help - Say yes here to support the GPIO device on ZTE ZX SoCs. + SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 + I/O expanders. + This provides a GPIO interface supporting inputs and outputs. + The I2C versions of the chips can be used as interrupt-controller. endmenu -- cgit v0.10.2