From 12f92ccc5baeb99e2f1d3ea9ae2e35441a56a100 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 9 Apr 2018 14:07:17 -0700 Subject: gpio: xra1403: Switch to a fixed upper bound for registers Geert Uytterhoeven pointed out that the number of register was a fixed upper bound so there's no need to use a dynamically allocated array in place of a VLA. Use the defined upper bound. Suggested-by: Geert Uytterhoeven Signed-off-by: Laura Abbott Reviewed-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xra1403.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index 8d4c8e99b251..8711a7907568 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -39,6 +39,7 @@ #define XRA_REIR 0x10 /* Input Rising Edge Interrupt Enable */ #define XRA_FEIR 0x12 /* Input Falling Edge Interrupt Enable */ #define XRA_IFR 0x14 /* Input Filter Enable/Disable */ +#define XRA_LAST 0x15 /* Bounds */ struct xra1403 { struct gpio_chip chip; @@ -50,7 +51,7 @@ static const struct regmap_config xra1403_regmap_cfg = { .pad_bits = 1, .val_bits = 8, - .max_register = XRA_IFR | 0x01, + .max_register = XRA_LAST, }; static unsigned int to_reg(unsigned int reg, unsigned int offset) @@ -126,21 +127,16 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) { int reg; struct xra1403 *xra = gpiochip_get_data(chip); - int *value; + int value[XRA_LAST]; int i; unsigned int gcr; unsigned int gsr; - value = kmalloc_array(xra1403_regmap_cfg.max_register, sizeof(*value), - GFP_KERNEL); - if (!value) - return; - seq_puts(s, "xra reg:"); - for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++) + for (reg = 0; reg <= XRA_LAST; reg++) seq_printf(s, " %2.2x", reg); seq_puts(s, "\n value:"); - for (reg = 0; reg < xra1403_regmap_cfg.max_register; reg++) { + for (reg = 0; reg < XRA_LAST; reg++) { regmap_read(xra->regmap, reg, &value[reg]); seq_printf(s, " %2.2x", value[reg]); } @@ -159,7 +155,6 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) (gcr & BIT(i)) ? "in" : "out", (gsr & BIT(i)) ? "hi" : "lo"); } - kfree(value); } #else #define xra1403_dbg_show NULL -- cgit v1.2.3 From 7bf0d7f62282fa315949106275ff5ed295aefac2 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 30 Mar 2018 15:02:37 +0800 Subject: gpio: eic: Add edge trigger emulation for EIC The Spreadtrum debounce EIC and latch EIC can not support edge trigger, but most GPIO users (like gpio-key driver) only use the edge trigger, thus the EIC driver need add some support to emulate the edge trigger to satisfy this requirement. Signed-off-by: Baolin Wang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-eic-sprd.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index de7dd939c043..e0d6a0a7bc69 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -300,6 +300,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct sprd_eic *sprd_eic = gpiochip_get_data(chip); u32 offset = irqd_to_hwirq(data); + int state; switch (sprd_eic->type) { case SPRD_EIC_DEBOUNCE: @@ -310,6 +311,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) case IRQ_TYPE_LEVEL_LOW: sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0); break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_BOTH: + state = sprd_eic_get(chip, offset); + if (state) + sprd_eic_update(chip, offset, + SPRD_EIC_DBNC_IEV, 0); + else + sprd_eic_update(chip, offset, + SPRD_EIC_DBNC_IEV, 1); + break; default: return -ENOTSUPP; } @@ -324,6 +336,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) case IRQ_TYPE_LEVEL_LOW: sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1); break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_BOTH: + state = sprd_eic_get(chip, offset); + if (state) + sprd_eic_update(chip, offset, + SPRD_EIC_LATCH_INTPOL, 0); + else + sprd_eic_update(chip, offset, + SPRD_EIC_LATCH_INTPOL, 1); + break; default: return -ENOTSUPP; } @@ -405,6 +428,55 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) return 0; } +static void sprd_eic_toggle_trigger(struct gpio_chip *chip, unsigned int irq, + unsigned int offset) +{ + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + struct irq_data *data = irq_get_irq_data(irq); + u32 trigger = irqd_get_trigger_type(data); + int state, post_state; + + /* + * The debounce EIC and latch EIC can only support level trigger, so we + * can toggle the level trigger to emulate the edge trigger. + */ + if ((sprd_eic->type != SPRD_EIC_DEBOUNCE && + sprd_eic->type != SPRD_EIC_LATCH) || + !(trigger & IRQ_TYPE_EDGE_BOTH)) + return; + + sprd_eic_irq_mask(data); + state = sprd_eic_get(chip, offset); + +retry: + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + if (state) + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0); + else + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1); + break; + case SPRD_EIC_LATCH: + if (state) + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0); + else + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1); + break; + default: + sprd_eic_irq_unmask(data); + return; + } + + post_state = sprd_eic_get(chip, offset); + if (state != post_state) { + dev_warn(chip->parent, "EIC level was changed.\n"); + state = post_state; + goto retry; + } + + sprd_eic_irq_unmask(data); +} + static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data) { enum sprd_eic_type type = *(enum sprd_eic_type *)data; @@ -448,6 +520,7 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip) bank * SPRD_EIC_PER_BANK_NR + n); generic_handle_irq(girq); + sprd_eic_toggle_trigger(chip, girq, n); } } } -- cgit v1.2.3 From 92da8b9deb8795c960e56412e724c3c3c431e06d Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 30 Mar 2018 15:02:38 +0800 Subject: gpio: pmic_eic: Add edge trigger emulation for PMIC EIC This patch will toggle the EIC level to emulate the edge trigger to support PMIC EIC egdge trigger function, which is required by gpio-keys driver. Signed-off-by: Baolin Wang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pmic-eic-sprd.c | 58 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index 66d68d991162..29e044ff4b17 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -178,6 +178,14 @@ static int sprd_pmic_eic_irq_set_type(struct irq_data *data, case IRQ_TYPE_LEVEL_LOW: pmic_eic->reg[REG_IEV] = 0; break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_BOTH: + /* + * Will set the trigger level according to current EIC level + * in irq_bus_sync_unlock() interface, so here nothing to do. + */ + break; default: return -ENOTSUPP; } @@ -197,11 +205,22 @@ static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 trigger = irqd_get_trigger_type(data); u32 offset = irqd_to_hwirq(data); + int state; /* Set irq type */ - sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, - pmic_eic->reg[REG_IEV]); + if (trigger & IRQ_TYPE_EDGE_BOTH) { + state = sprd_pmic_eic_get(chip, offset); + if (state) + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0); + else + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1); + } else { + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, + pmic_eic->reg[REG_IEV]); + } + /* Set irq unmask */ sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE, pmic_eic->reg[REG_IE]); @@ -212,6 +231,35 @@ static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data) mutex_unlock(&pmic_eic->buslock); } +static void sprd_pmic_eic_toggle_trigger(struct gpio_chip *chip, + unsigned int irq, unsigned int offset) +{ + u32 trigger = irq_get_trigger_type(irq); + int state, post_state; + + if (!(trigger & IRQ_TYPE_EDGE_BOTH)) + return; + + state = sprd_pmic_eic_get(chip, offset); +retry: + if (state) + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0); + else + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1); + + post_state = sprd_pmic_eic_get(chip, offset); + if (state != post_state) { + dev_warn(chip->parent, "PMIC EIC level was changed.\n"); + state = post_state; + goto retry; + } + + /* Set irq unmask */ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE, 1); + /* Generate trigger start pulse for debounce EIC */ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG, 1); +} + static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data) { struct sprd_pmic_eic *pmic_eic = data; @@ -233,6 +281,12 @@ static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data) girq = irq_find_mapping(chip->irq.domain, n); handle_nested_irq(girq); + + /* + * The PMIC EIC can only support level trigger, so we can + * toggle the level trigger to emulate the edge trigger. + */ + sprd_pmic_eic_toggle_trigger(chip, girq, n); } return IRQ_HANDLED; -- cgit v1.2.3 From 192a35b1348275c8decf42452d382be21add938c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 5 Apr 2018 13:00:12 +0100 Subject: gpio: 104-dio-48e: make array 'ports' static, shrinks object size Don't populate the const read-only array 'ports' on the stack but instead make it static. Makes the object code smaller by over 100 buytes: Before: text data bss dec hex filename 10959 4952 832 16743 4167 drivers/gpio/gpio-104-dio-48e.o After: text data bss dec hex filename 10790 5008 832 16630 40f6 drivers/gpio/gpio-104-dio-48e.o (gcc version 7.2.0 x86_64) Signed-off-by: Colin Ian King Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-dio-48e.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 31e22c93e844..9c4e07fcb74b 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -188,7 +188,7 @@ static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, { struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); size_t i; - const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; const unsigned int gpio_reg_size = 8; unsigned int bits_offset; size_t word_index; -- cgit v1.2.3 From a411e81e61df24023f40255145d8f023402002c9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 10 Apr 2018 22:30:28 +0200 Subject: gpiolib: add hogs support for machine code Board files constitute a significant part of the users of the legacy GPIO framework. In many cases they only export a line and set its desired value. We could use GPIO hogs for that like we do for DT and ACPI but there's no support for that in machine code. This patch proposes to extend the machine.h API with support for registering hog tables in board files. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- Documentation/driver-api/gpio/board.rst | 16 ++++++++ drivers/gpio/gpiolib.c | 67 +++++++++++++++++++++++++++++++++ include/linux/gpio/machine.h | 31 +++++++++++++++ 3 files changed, 114 insertions(+) (limited to 'drivers/gpio') diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst index 25d62b2e9fd0..2c112553df84 100644 --- a/Documentation/driver-api/gpio/board.rst +++ b/Documentation/driver-api/gpio/board.rst @@ -177,3 +177,19 @@ mapping and is thus transparent to GPIO consumers. A set of functions such as gpiod_set_value() is available to work with the new descriptor-oriented interface. + +Boards using platform data can also hog GPIO lines by defining GPIO hog tables. + +.. code-block:: c + + struct gpiod_hog gpio_hog_table[] = { + GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH), + { } + }; + +And the table can be added to the board code as follows:: + + gpiod_add_hogs(gpio_hog_table); + +The line will be hogged as soon as the gpiochip is created or - in case the +chip was created earlier - when the hog table is registered. diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 43aeb07343ec..547adc149b62 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -71,6 +71,9 @@ static DEFINE_MUTEX(gpio_lookup_lock); static LIST_HEAD(gpio_lookup_list); LIST_HEAD(gpio_devices); +static DEFINE_MUTEX(gpio_machine_hogs_mutex); +static LIST_HEAD(gpio_machine_hogs); + static void gpiochip_free_hogs(struct gpio_chip *chip); static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, struct lock_class_key *lock_key, @@ -1171,6 +1174,41 @@ err_remove_device: return status; } +static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) +{ + struct gpio_desc *desc; + int rv; + + desc = gpiochip_get_desc(chip, hog->chip_hwnum); + if (IS_ERR(desc)) { + pr_err("%s: unable to get GPIO desc: %ld\n", + __func__, PTR_ERR(desc)); + return; + } + + if (desc->flags & FLAG_IS_HOGGED) + return; + + rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags); + if (rv) + pr_err("%s: unable to hog GPIO line (%s:%u): %d\n", + __func__, chip->label, hog->chip_hwnum, rv); +} + +static void machine_gpiochip_add(struct gpio_chip *chip) +{ + struct gpiod_hog *hog; + + mutex_lock(&gpio_machine_hogs_mutex); + + list_for_each_entry(hog, &gpio_machine_hogs, list) { + if (!strcmp(chip->label, hog->chip_label)) + gpiochip_machine_hog(chip, hog); + } + + mutex_unlock(&gpio_machine_hogs_mutex); +} + static void gpiochip_setup_devs(void) { struct gpio_device *gdev; @@ -1326,6 +1364,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, acpi_gpiochip_add(chip); + machine_gpiochip_add(chip); + /* * By first adding the chardev, and then adding the device, * we get a device node entry in sysfs under @@ -3462,6 +3502,33 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) } EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table); +/** + * gpiod_add_hogs() - register a set of GPIO hogs from machine code + * @hogs: table of gpio hog entries with a zeroed sentinel at the end + */ +void gpiod_add_hogs(struct gpiod_hog *hogs) +{ + struct gpio_chip *chip; + struct gpiod_hog *hog; + + mutex_lock(&gpio_machine_hogs_mutex); + + for (hog = &hogs[0]; hog->chip_label; hog++) { + list_add_tail(&hog->list, &gpio_machine_hogs); + + /* + * The chip may have been registered earlier, so check if it + * exists and, if so, try to hog the line now. + */ + chip = find_chip_by_name(hog->chip_label); + if (chip) + gpiochip_machine_hog(chip, hog); + } + + mutex_unlock(&gpio_machine_hogs_mutex); +} +EXPORT_SYMBOL_GPL(gpiod_add_hogs); + static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index b2f2dc638463..daa44eac9241 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -39,6 +39,23 @@ struct gpiod_lookup_table { struct gpiod_lookup table[]; }; +/** + * struct gpiod_hog - GPIO line hog table + * @chip_label: name of the chip the GPIO belongs to + * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO + * @line_name: consumer name for the hogged line + * @lflags: mask of GPIO lookup flags + * @dflags: GPIO flags used to specify the direction and value + */ +struct gpiod_hog { + struct list_head list; + const char *chip_label; + u16 chip_hwnum; + const char *line_name; + enum gpio_lookup_flags lflags; + int dflags; +}; + /* * Simple definition of a single GPIO under a con_id */ @@ -59,10 +76,23 @@ struct gpiod_lookup_table { .flags = _flags, \ } +/* + * Simple definition of a single GPIO hog in an array. + */ +#define GPIO_HOG(_chip_label, _chip_hwnum, _line_name, _lflags, _dflags) \ +{ \ + .chip_label = _chip_label, \ + .chip_hwnum = _chip_hwnum, \ + .line_name = _line_name, \ + .lflags = _lflags, \ + .dflags = _dflags, \ +} + #ifdef CONFIG_GPIOLIB void gpiod_add_lookup_table(struct gpiod_lookup_table *table); void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n); void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); +void gpiod_add_hogs(struct gpiod_hog *hogs); #else static inline void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} @@ -70,6 +100,7 @@ static inline void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {} static inline void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} +static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {} #endif #endif /* __LINUX_GPIO_MACHINE_H */ -- cgit v1.2.3 From f105edf70011859b33c3309f9c5ea96395cb616c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 10:28:21 +0200 Subject: gpio: loongson: Use right include The driver includes which is wrong, rely on and remove to call to gpio_set_value() in favor of calling the internal function. Move functions around to avoid forward declarations. Cc: Keguang Zhang Cc: Jiaxun Yang Cc: Huacai Chen Cc: linux-mips@linux-mips.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-loongson.c | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-loongson.c b/drivers/gpio/gpio-loongson.c index 92c4fe7b2677..973d82a29442 100644 --- a/drivers/gpio/gpio-loongson.c +++ b/drivers/gpio/gpio-loongson.c @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include #define STLS2F_N_GPIO 4 #define STLS3A_N_GPIO 16 @@ -34,38 +34,6 @@ static DEFINE_SPINLOCK(gpio_lock); -static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) -{ - u32 temp; - u32 mask; - - spin_lock(&gpio_lock); - mask = 1 << gpio; - temp = LOONGSON_GPIOIE; - temp |= mask; - LOONGSON_GPIOIE = temp; - spin_unlock(&gpio_lock); - - return 0; -} - -static int loongson_gpio_direction_output(struct gpio_chip *chip, - unsigned gpio, int level) -{ - u32 temp; - u32 mask; - - gpio_set_value(gpio, level); - spin_lock(&gpio_lock); - mask = 1 << gpio; - temp = LOONGSON_GPIOIE; - temp &= (~mask); - LOONGSON_GPIOIE = temp; - spin_unlock(&gpio_lock); - - return 0; -} - static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { u32 val; @@ -97,6 +65,38 @@ static void loongson_gpio_set_value(struct gpio_chip *chip, spin_unlock(&gpio_lock); } +static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + u32 temp; + u32 mask; + + spin_lock(&gpio_lock); + mask = 1 << gpio; + temp = LOONGSON_GPIOIE; + temp |= mask; + LOONGSON_GPIOIE = temp; + spin_unlock(&gpio_lock); + + return 0; +} + +static int loongson_gpio_direction_output(struct gpio_chip *chip, + unsigned gpio, int level) +{ + u32 temp; + u32 mask; + + loongson_gpio_set_value(chip, gpio, level); + spin_lock(&gpio_lock); + mask = 1 << gpio; + temp = LOONGSON_GPIOIE; + temp &= (~mask); + LOONGSON_GPIOIE = temp; + spin_unlock(&gpio_lock); + + return 0; +} + static struct gpio_chip loongson_chip = { .label = "Loongson-gpio-chip", .direction_input = loongson_gpio_direction_input, -- cgit v1.2.3 From 70e703e7410c40b99499b214567c1b6c324e26c6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 12:05:36 +0200 Subject: gpio: loongson: Create a dynamic platform device It is pretty helpful to create some kind of device for backing the GPIO chips, especially when preparing the driver for using GENERIC_GPIO, so let's create a simple platform device and a simple platform device driver and create the gpiochip in the .probe() routine for the device driver. Keep all at the core initcall so the behaviour is the same as before. Cc: Keguang Zhang Cc: Jiaxun Yang Cc: Huacai Chen Cc: linux-mips@linux-mips.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-loongson.c | 47 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-loongson.c b/drivers/gpio/gpio-loongson.c index 973d82a29442..3c9d4f3ed550 100644 --- a/drivers/gpio/gpio-loongson.c +++ b/drivers/gpio/gpio-loongson.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -97,19 +98,45 @@ static int loongson_gpio_direction_output(struct gpio_chip *chip, return 0; } -static struct gpio_chip loongson_chip = { - .label = "Loongson-gpio-chip", - .direction_input = loongson_gpio_direction_input, - .get = loongson_gpio_get_value, - .direction_output = loongson_gpio_direction_output, - .set = loongson_gpio_set_value, - .base = 0, - .ngpio = LOONGSON_N_GPIO, - .can_sleep = false, +static int loongson_gpio_probe(struct platform_device *pdev) +{ + struct gpio_chip *gc; + struct device *dev = &pdev->dev; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = "loongson-gpio-chip"; + gc->base = 0; + gc->ngpio = LOONGSON_N_GPIO; + gc->get = loongson_gpio_get_value; + gc->set = loongson_gpio_set_value; + gc->direction_input = loongson_gpio_direction_input; + gc->direction_output = loongson_gpio_direction_output; + + return gpiochip_add_data(gc, NULL); +} + +static struct platform_driver loongson_gpio_driver = { + .driver = { + .name = "loongson-gpio", + }, + .probe = loongson_gpio_probe, }; static int __init loongson_gpio_setup(void) { - return gpiochip_add_data(&loongson_chip, NULL); + struct platform_device *pdev; + int ret; + + ret = platform_driver_register(&loongson_gpio_driver); + if (ret) { + pr_err("error registering loongson GPIO driver\n"); + return ret; + } + + pdev = platform_device_register_simple("loongson-gpio", -1, NULL, 0); + return PTR_ERR_OR_ZERO(pdev); } postcore_initcall(loongson_gpio_setup); -- cgit v1.2.3 From a4e5db831a1bff9ca8e987519537c27930154041 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 12:20:24 +0200 Subject: gpio: loongson: Use BIT() macros This switches the Loongson driver over to using the bitops BIT() macros and drops some local variables and make the code easier to read (in my opinion). Cc: Keguang Zhang Cc: Jiaxun Yang Cc: Huacai Chen Cc: linux-mips@linux-mips.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-loongson.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-loongson.c b/drivers/gpio/gpio-loongson.c index 3c9d4f3ed550..16cfbe9e72fe 100644 --- a/drivers/gpio/gpio-loongson.c +++ b/drivers/gpio/gpio-loongson.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,11 @@ #define LOONGSON_N_GPIO STLS2F_N_GPIO #endif +/* + * Offset into the register where we read lines, we write them from offset 0. + * This offset is the only thing that stand between us and using + * GPIO_GENERIC. + */ #define LOONGSON_GPIO_IN_OFFSET 16 static DEFINE_SPINLOCK(gpio_lock); @@ -38,30 +44,25 @@ static DEFINE_SPINLOCK(gpio_lock); static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { u32 val; - u32 mask; - mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET); spin_lock(&gpio_lock); val = LOONGSON_GPIODATA; spin_unlock(&gpio_lock); - return (val & mask) != 0; + return !!(val & BIT(gpio + LOONGSON_GPIO_IN_OFFSET)); } static void loongson_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) { u32 val; - u32 mask; - - mask = 1 << gpio; spin_lock(&gpio_lock); val = LOONGSON_GPIODATA; if (value) - val |= mask; + val |= BIT(gpio); else - val &= (~mask); + val &= ~BIT(gpio); LOONGSON_GPIODATA = val; spin_unlock(&gpio_lock); } @@ -69,12 +70,10 @@ static void loongson_gpio_set_value(struct gpio_chip *chip, static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { u32 temp; - u32 mask; spin_lock(&gpio_lock); - mask = 1 << gpio; temp = LOONGSON_GPIOIE; - temp |= mask; + temp |= BIT(gpio); LOONGSON_GPIOIE = temp; spin_unlock(&gpio_lock); @@ -85,13 +84,11 @@ static int loongson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) { u32 temp; - u32 mask; loongson_gpio_set_value(chip, gpio, level); spin_lock(&gpio_lock); - mask = 1 << gpio; temp = LOONGSON_GPIOIE; - temp &= (~mask); + temp &= ~BIT(gpio); LOONGSON_GPIOIE = temp; spin_unlock(&gpio_lock); -- cgit v1.2.3 From e92a5c61607f44bc40a38cb3262275b3eae34358 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 14:37:12 +0200 Subject: gpio: lp3943: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lp3943.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c index 6dc6725403ec..c3a3b9b7b553 100644 --- a/drivers/gpio/gpio-lp3943.c +++ b/drivers/gpio/gpio-lp3943.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 284ead59d3c3f5e22a957ddeb6dba21f606fc88d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 14:40:59 +0200 Subject: gpio: lp873x: Include the right header This is a driver so include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lp873x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lp873x.c b/drivers/gpio/gpio-lp873x.c index df0ad2cef0d2..801995dd9b26 100644 --- a/drivers/gpio/gpio-lp873x.c +++ b/drivers/gpio/gpio-lp873x.c @@ -14,7 +14,7 @@ * Based on the TPS65218 driver */ -#include +#include #include #include #include -- cgit v1.2.3 From 11975f9e08423343a0975c246ea3928162266066 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 14:47:59 +0200 Subject: gpio: lpc32xx: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lpc32xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 92b3ae2a6735..aa74cc4d8b14 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -20,9 +20,8 @@ #include #include #include -#include +#include #include -#include #include #include -- cgit v1.2.3 From cec93b024bfc442e3789539d51e9c16b4dcfa74d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:01:23 +0200 Subject: gpio: lynxpoint: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lynxpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 1e557b10d73e..b5b5e500e72c 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 25424b864b2fd3de7b4701b5458d21b713d07d41 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:05:59 +0200 Subject: gpio: max730x: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max730x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index 946d09195598..198a36b07773 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include /* -- cgit v1.2.3 From 03a3f19ce3361af9a1c6c1c925172780c2b2778e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:08:00 +0200 Subject: gpio: mc33880: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mc33880.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index 0f0df7956264..18a5a58d634a 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From 3dc1c92fb24408736a5689088e3711c814c3c5a9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:11:30 +0200 Subject: gpio: mc9s08dz60: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mc9s08dz60.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 2fcad5b9cca5..d8d846d2189a 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #define GPIO_GROUP_NUM 2 #define GPIO_NUM_PER_GROUP 8 -- cgit v1.2.3 From 85320ab6f9fa580b2a5e363597f142b4c68863e8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:17:11 +0200 Subject: gpio: ml_ioh: Include the right header This is a driver so include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ml-ioh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index b3678bd1c120..e2bee27eb526 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From 0cbbdcf903cefff23d909739e1faacbb939f50b6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:21:15 +0200 Subject: gpio: mm-lantiq: Include the right header This is a driver so include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mm-lantiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index b1cf76dd84ba..b0754fe69e77 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 99ef32adc5102d1fa5beabc3a88e6bf150ccab30 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:32:17 +0200 Subject: gpio: msic: Include the right header This is a driver so only include . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 6cb67595d15f..3b34dbecef99 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From ba78d83be7d04f03a7fe6133efb5b6f83b9b0e7c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Apr 2018 15:40:45 +0200 Subject: gpio: mvebu: Use the proper APIs The MVEBU driver is requesting GPIO descriptors from itself, which is fine, but we have proper APIs to do this in a controlled way, so stop calling into the private functions of the GPIO library and use the gpiochip_* functions instead. Only include and since we are both producers and consumers in this case. Cc: Gregory CLEMENT Cc: Thomas Petazzoni Cc: Jason Cooper Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 45c65f805fd6..6e02148c208b 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -36,7 +36,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -51,8 +52,6 @@ #include #include -#include "gpiolib.h" - /* * GPIO unit register offsets. */ @@ -608,19 +607,16 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) if (mvpwm->gpiod) { ret = -EBUSY; } else { - desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm); - if (!desc) { - ret = -ENODEV; + desc = gpiochip_request_own_desc(&mvchip->chip, + pwm->hwpwm, "mvebu-pwm"); + if (IS_ERR(desc)) { + ret = PTR_ERR(desc); goto out; } - ret = gpiod_request(desc, "mvebu-pwm"); - if (ret) - goto out; - ret = gpiod_direction_output(desc, 0); if (ret) { - gpiod_free(desc); + gpiochip_free_own_desc(desc); goto out; } @@ -637,7 +633,7 @@ static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) unsigned long flags; spin_lock_irqsave(&mvpwm->lock, flags); - gpiod_free(mvpwm->gpiod); + gpiochip_free_own_desc(mvpwm->gpiod); mvpwm->gpiod = NULL; spin_unlock_irqrestore(&mvpwm->lock, flags); } -- cgit v1.2.3 From 8d0bd9a5c2ce31942f71d5a831ee8cecda5201a8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 15 Apr 2018 22:25:00 +0200 Subject: gpio: mxc: Remove reliance on This is a driver so we should only include . However this driver was using gpio_get_value() to fetch the current value of a GPIO used as IRQ line to determine trigger direction, so we need a better way than looping over the global GPIO numberspace. Fix this by just calling the .get() function in the GPIO chip, as we don't want to end up creating a consumer dependency on ourselves. Cc: Vladimir Zapolskiy Cc: Fabio Estevam Acked-by: Shawn Guo Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 5245a2fe62ae..11ec7228ab08 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -30,8 +30,6 @@ #include #include #include -/* FIXME: for gpio_get_value() replace this with direct register read */ -#include #include #include #include @@ -174,7 +172,6 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) struct mxc_gpio_port *port = gc->private; u32 bit, val; u32 gpio_idx = d->hwirq; - u32 gpio = port->gc.base + gpio_idx; int edge; void __iomem *reg = port->base; @@ -190,13 +187,13 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) if (GPIO_EDGE_SEL >= 0) { edge = GPIO_INT_BOTH_EDGES; } else { - val = gpio_get_value(gpio); + val = port->gc.get(&port->gc, gpio_idx); if (val) { edge = GPIO_INT_LOW_LEV; - pr_debug("mxc: set GPIO %d to low trigger\n", gpio); + pr_debug("mxc: set GPIO %d to low trigger\n", gpio_idx); } else { edge = GPIO_INT_HIGH_LEV; - pr_debug("mxc: set GPIO %d to high trigger\n", gpio); + pr_debug("mxc: set GPIO %d to high trigger\n", gpio_idx); } port->both_edges |= 1 << gpio_idx; } -- cgit v1.2.3 From 413f9e991896a98c03da6b3c43dc7791a4d28d9a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 18 Apr 2018 18:26:34 +0100 Subject: gpio: make several const arrays static, shrinks object size Don't populate the const read-only arrays 'port' on the stack but instead make them static. Makes the object code smaller: Before: text data bss dec hex filename 8542 4088 672 13302 33f6 drivers/gpio/gpio-gpio-mm.o 10959 4952 832 16743 4167 drivers/gpio/gpio-104-dio-48e.o 9022 5064 1408 15494 3c86 drivers/gpio/gpio-104-idi-48.o After: text data bss dec hex filename 8372 4144 672 13188 3384 drivers/gpio/gpio-gpio-mm.o 10790 5008 832 16630 40f6 drivers/gpio/gpio-104-dio-48e.o 8853 5152 1408 15413 3c35 linux/drivers/gpio/gpio-104-idi-48.o (gcc version 7.2.0 x86_64) Signed-off-by: Colin Ian King Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idi-48.c | 2 +- drivers/gpio/gpio-gpio-mm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index f35632609379..2c9738adb3a6 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -94,7 +94,7 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, { struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip); size_t i; - const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; const unsigned int gpio_reg_size = 8; unsigned int bits_offset; size_t word_index; diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c index d496cc56c2a2..b56ff2efbf36 100644 --- a/drivers/gpio/gpio-gpio-mm.c +++ b/drivers/gpio/gpio-gpio-mm.c @@ -177,7 +177,7 @@ static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, { struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); size_t i; - const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; const unsigned int gpio_reg_size = 8; unsigned int bits_offset; size_t word_index; -- cgit v1.2.3 From e6ca26abd37606ba4864f20c85d3fe4a2173b93f Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Thu, 26 Apr 2018 17:19:47 +0100 Subject: gpio: dwapb: Add support for 1 interrupt per port A GPIO The DesignWare GPIO IP can be configured for either 1 interrupt or 1 per GPIO in port A, but the driver currently only supports 1 interrupt. See the DesignWare DW_apb_gpio Databook description of the 'GPIO_INTR_IO' parameter. This change allows the driver to work with up to 32 interrupts, it will get as many interrupts as specified in the DT 'interrupts' property. It doesn't do anything clever with the different interrupts, it just calls the same handler used for single interrupt hardware. ACPI companion code provided by Hoan Tran . This was tested on X-Gene by Hoan. Signed-off-by: Phil Edworthy Reviewed-by: Rob Herring Acked-by: Lee Jones Acked-by: Hoan Tran Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/snps-dwapb-gpio.txt | 9 ++++- drivers/gpio/gpio-dwapb.c | 46 +++++++++++++++++----- drivers/mfd/intel_quark_i2c_gpio.c | 3 +- include/linux/platform_data/gpio-dwapb.h | 3 +- 4 files changed, 48 insertions(+), 13 deletions(-) (limited to 'drivers/gpio') diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt index 4a75da7051bd..3c1118bc67f5 100644 --- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt +++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt @@ -26,8 +26,13 @@ controller. the second encodes the triger flags encoded as described in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt - interrupt-parent : The parent interrupt controller. -- interrupts : The interrupt to the parent controller raised when GPIOs - generate the interrupts. +- interrupts : The interrupts to the parent controller raised when GPIOs + generate the interrupts. If the controller provides one combined interrupt + for all GPIOs, specify a single interrupt. If the controller provides one + interrupt for each GPIO, provide a list of interrupts that correspond to each + of the GPIO pins. When specifying multiple interrupts, if any are unconnected, + use the interrupts-extended property to specify the interrupts and set the + interrupt controller handle for unused interrupts to 0. - snps,nr-gpios : The number of pins in the port, a single cell. - resets : Reset line for the controller. diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 226977f78482..7dcd06b11570 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, irq_gc->chip_types[1].handler = handle_edge_irq; if (!pp->irq_shared) { - irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler, - gpio); + int i; + + for (i = 0; i < pp->ngpio; i++) { + if (pp->irq[i]) + irq_set_chained_handler_and_data(pp->irq[i], + dwapb_irq_handler, gpio); + } } else { /* * Request a shared IRQ since where MFD would have devices * using the same irq pin */ - err = devm_request_irq(gpio->dev, pp->irq, + err = devm_request_irq(gpio->dev, pp->irq[0], dwapb_irq_handler_mfd, IRQF_SHARED, "gpio-dwapb-mfd", gpio); if (err) { @@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, if (pp->idx == 0) port->gc.set_config = dwapb_gpio_set_config; - if (pp->irq) + if (pp->has_irq) dwapb_configure_irqs(gpio, port, pp); err = gpiochip_add_data(&port->gc, port); @@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, port->is_registered = true; /* Add GPIO-signaled ACPI event support */ - if (pp->irq) + if (pp->has_irq) acpi_gpiochip_request_interrupts(&port->gc); return err; @@ -601,13 +606,36 @@ dwapb_gpio_get_pdata(struct device *dev) if (dev->of_node && pp->idx == 0 && fwnode_property_read_bool(fwnode, "interrupt-controller")) { - pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0); - if (!pp->irq) + struct device_node *np = to_of_node(fwnode); + unsigned int j; + + /* + * The IP has configuration options to allow a single + * combined interrupt or one per gpio. If one per gpio, + * some might not be used. + */ + for (j = 0; j < pp->ngpio; j++) { + int irq = of_irq_get(np, j); + if (irq < 0) + continue; + + pp->irq[j] = irq; + pp->has_irq = true; + } + + if (!pp->has_irq) dev_warn(dev, "no irq for port%d\n", pp->idx); } - if (has_acpi_companion(dev) && pp->idx == 0) - pp->irq = platform_get_irq(to_platform_device(dev), 0); + if (has_acpi_companion(dev) && pp->idx == 0) { + unsigned int j; + + for (j = 0; j < pp->ngpio; j++) { + pp->irq[j] = platform_get_irq(to_platform_device(dev), j); + if (pp->irq[j]) + pp->has_irq = true; + } + } pp->irq_shared = false; pp->gpio_base = -1; diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 90e35dec8648..5bddb84cfc1f 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) pdata->properties->idx = 0; pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO; pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE; - pdata->properties->irq = pdev->irq; + pdata->properties->irq[0] = pdev->irq; + pdata->properties->has_irq = true; pdata->properties->irq_shared = true; cell->platform_data = pdata; diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h index 2dc7f4a8ab09..5a52d69c13f3 100644 --- a/include/linux/platform_data/gpio-dwapb.h +++ b/include/linux/platform_data/gpio-dwapb.h @@ -19,7 +19,8 @@ struct dwapb_port_property { unsigned int idx; unsigned int ngpio; unsigned int gpio_base; - unsigned int irq; + unsigned int irq[32]; + bool has_irq; bool irq_shared; }; -- cgit v1.2.3 From 058de3486be466bfc7a9d82f5a712cac7e689199 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 26 Apr 2018 22:12:36 +0200 Subject: gpio: mockup: use the SPDX identifier and remove license boilerplate Use the SPDX license identifier for GPLv2.0 or later and remove the license boilerplate. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mockup.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 76c2fe91a901..d66b7a768ecd 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * GPIO Testing Device Driver * * Copyright (C) 2014 Kamlakant Patel * Copyright (C) 2015-2016 Bamvor Jian Zhang * Copyright (C) 2017 Bartosz Golaszewski - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include -- cgit v1.2.3 From a23ffcf253a34c608d8ca6f697dbb3c064b32ce8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:08 +0200 Subject: gpio: 74xx-mmio: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74xx-mmio.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c index 0475e8ec96d0..49616ec815ee 100644 --- a/drivers/gpio/gpio-74xx-mmio.c +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -105,27 +105,22 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int mmio_74xx_gpio_probe(struct platform_device *pdev) { - const struct of_device_id *of_id; struct mmio_74xx_gpio_priv *priv; struct resource *res; void __iomem *dat; int err; - of_id = of_match_device(mmio_74xx_gpio_ids, &pdev->dev); - if (!of_id) - return -ENODEV; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->flags = (uintptr_t)of_device_get_match_data(&pdev->dev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dat = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dat)) return PTR_ERR(dat); - priv->flags = (uintptr_t) of_id->data; - err = bgpio_init(&priv->gc, &pdev->dev, DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), dat, NULL, NULL, NULL, NULL, 0); -- cgit v1.2.3 From 7114b7bacbfea6325b7f81c99878df2691916503 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:09 +0200 Subject: gpio: dwapb: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 7dcd06b11570..494df023271e 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -712,13 +712,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev) gpio->flags = 0; if (dev->of_node) { - const struct of_device_id *of_devid; - - of_devid = of_match_device(dwapb_of_match, dev); - if (of_devid) { - if (of_devid->data) - gpio->flags = (uintptr_t)of_devid->data; - } + gpio->flags = (uintptr_t)of_device_get_match_data(dev); } else if (has_acpi_companion(dev)) { const struct acpi_device_id *acpi_id; -- cgit v1.2.3 From 490a887829378926973174fe95330091388f7f51 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:10 +0200 Subject: gpio: ge: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ge.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 1fe2d3418f2f..4c43562434cf 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -52,8 +52,6 @@ MODULE_DEVICE_TABLE(of, gef_gpio_ids); static int __init gef_gpio_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(gef_gpio_ids, &pdev->dev); struct gpio_chip *gc; void __iomem *regs; int ret; @@ -82,7 +80,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev) } gc->base = -1; - gc->ngpio = (u16)(uintptr_t)of_id->data; + gc->ngpio = (u16)of_device_get_match_data(&pdev->dev); gc->of_gpio_n_cells = 2; gc->of_node = pdev->dev.of_node; -- cgit v1.2.3 From d897738381b979995702fc80e2a9a902ec3896b0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:11 +0200 Subject: gpio: ingenic: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ingenic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ingenic.c b/drivers/gpio/gpio-ingenic.c index 15fb2bc796a8..e738e384a5ca 100644 --- a/drivers/gpio/gpio-ingenic.c +++ b/drivers/gpio/gpio-ingenic.c @@ -285,8 +285,6 @@ MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match); static int ingenic_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *of_id = of_match_device( - ingenic_gpio_of_match, dev); struct ingenic_gpio_chip *jzgc; u32 bank; int err; @@ -323,7 +321,7 @@ static int ingenic_gpio_probe(struct platform_device *pdev) jzgc->gc.parent = dev; jzgc->gc.of_node = dev->of_node; jzgc->gc.owner = THIS_MODULE; - jzgc->version = (enum jz_version)of_id->data; + jzgc->version = (enum jz_version)of_device_get_match_data(dev); jzgc->gc.set = ingenic_gpio_set; jzgc->gc.get = ingenic_gpio_get; -- cgit v1.2.3 From 1f2d357b9ebef5c7ca7e7ee07234c08ac057c386 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:12 +0200 Subject: gpio: mxs: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 435def22445d..5ad8d4db74db 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -290,8 +290,6 @@ MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids); static int mxs_gpio_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(mxs_gpio_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; struct device_node *parent; static void __iomem *base; @@ -306,7 +304,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) port->id = of_alias_get_id(np, "gpio"); if (port->id < 0) return port->id; - port->devid = (enum mxs_gpio_id) of_id->data; + port->devid = (enum mxs_gpio_id)of_device_get_match_data(&pdev->dev); port->dev = &pdev->dev; port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) -- cgit v1.2.3 From fd46d5c35066920b6c85d0379b5e2b6498d46bc1 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:13 +0200 Subject: gpio: palmas: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-palmas.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 3d818195e351..ceb2fef2c8ae 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -159,13 +159,9 @@ static int palmas_gpio_probe(struct platform_device *pdev) struct palmas_platform_data *palmas_pdata; struct palmas_gpio *palmas_gpio; int ret; - const struct of_device_id *match; const struct palmas_device_data *dev_data; - match = of_match_device(of_palmas_gpio_match, &pdev->dev); - if (!match) - return -ENODEV; - dev_data = match->data; + dev_data = of_device_get_match_data(&pdev->dev); if (!dev_data) dev_data = &palmas_dev_data; -- cgit v1.2.3 From 67bab9353391f65a497442b1f9f920d452790c5a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:14 +0200 Subject: gpio: pca953x: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d2ead4b1cf61..9a06b8a4f5be 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -810,13 +810,11 @@ static int pca953x_probe(struct i2c_client *client, chip->driver_data = i2c_id->driver_data; } else { const struct acpi_device_id *acpi_id; - const struct of_device_id *match; + struct device *dev = &client->dev; - match = of_match_device(pca953x_dt_ids, &client->dev); - if (match) { - chip->driver_data = (int)(uintptr_t)match->data; - } else { - acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev); + chip->driver_data = (uintptr_t)of_device_get_match_data(dev); + if (!chip->driver_data) { + acpi_id = acpi_match_device(pca953x_acpi_ids, dev); if (!acpi_id) { ret = -ENODEV; goto err_exit; -- cgit v1.2.3 From 8357759a4201f3b165b3240095268ebc63493cc2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:15 +0200 Subject: gpio: pxa: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index f480fb896963..3c1f65bc0fa8 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -579,15 +579,9 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev, struct pxa_gpio_chip *pchip) { int nr_gpios; - const struct of_device_id *of_id = - of_match_device(pxa_gpio_dt_ids, &pdev->dev); const struct pxa_gpio_id *gpio_id; - if (!of_id || !of_id->data) { - dev_err(&pdev->dev, "Failed to find gpio controller\n"); - return -EFAULT; - } - gpio_id = of_id->data; + gpio_id = of_device_get_match_data(&pdev->dev); gpio_type = gpio_id->type; nr_gpios = gpio_id->gpio_nums; -- cgit v1.2.3 From edf874ef2dc73ee2f99727bd0caf08b095e3492e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:16 +0200 Subject: gpio: syscon: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-syscon.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 537cec7583fc..2512acd99027 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -182,20 +182,15 @@ MODULE_DEVICE_TABLE(of, syscon_gpio_ids); static int syscon_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *of_id; struct syscon_gpio_priv *priv; struct device_node *np = dev->of_node; int ret; - of_id = of_match_device(syscon_gpio_ids, dev); - if (!of_id) - return -ENODEV; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->data = of_id->data; + priv->data = of_device_get_match_data(dev); if (priv->data->compatible) { priv->syscon = syscon_regmap_lookup_by_compatible( -- cgit v1.2.3 From 81317c5a08a32a3798f56e4f40bbb8a3efd81271 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:17 +0200 Subject: gpio: ts4900: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ts4900.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c index 5bd21725e604..1da8d0586329 100644 --- a/drivers/gpio/gpio-ts4900.c +++ b/drivers/gpio/gpio-ts4900.c @@ -128,15 +128,10 @@ MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table); static int ts4900_gpio_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct of_device_id *match; struct ts4900_gpio_priv *priv; u32 ngpio; int ret; - match = of_match_device(ts4900_gpio_of_match_table, &client->dev); - if (!match) - return -EINVAL; - if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio)) ngpio = DEFAULT_PIN_NUMBER; @@ -148,7 +143,7 @@ static int ts4900_gpio_probe(struct i2c_client *client, priv->gpio_chip.label = "ts4900-gpio"; priv->gpio_chip.ngpio = ngpio; priv->gpio_chip.parent = &client->dev; - priv->input_bit = (uintptr_t)match->data; + priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev); priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config); if (IS_ERR(priv->regmap)) { -- cgit v1.2.3 From 23e577ebee3c3c578a993f0a4fa094feeae6f300 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:18 +0200 Subject: gpio: vf610: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-vf610.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 4610cc2938ad..d4ad6d0e02a2 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -254,8 +254,6 @@ static struct irq_chip vf610_gpio_irq_chip = { static int vf610_gpio_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = of_match_device(vf610_gpio_dt_ids, - &pdev->dev); struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct vf610_gpio_port *port; @@ -267,7 +265,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - port->sdata = of_id->data; + port->sdata = of_device_get_match_data(dev); iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->base = devm_ioremap_resource(dev, iores); if (IS_ERR(port->base)) -- cgit v1.2.3 From 0c695e38d94f007f0820d9c46df6f6d1fc855a8a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Apr 2018 09:38:19 +0200 Subject: gpio: xlp: Use of_device_get_match_data() Use of_device_get_match_data() instead of open-coding it. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xlp.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index e74bd43a6974..8e4275eaa7d7 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -322,14 +322,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) return irq; if (pdev->dev.of_node) { - const struct of_device_id *of_id; - - of_id = of_match_device(xlp_gpio_of_ids, &pdev->dev); - if (!of_id) { - dev_err(&pdev->dev, "Unable to match OF ID\n"); - return -ENODEV; - } - soc_type = (uintptr_t) of_id->data; + soc_type = (uintptr_t)of_device_get_match_data(&pdev->dev); } else { const struct acpi_device_id *acpi_id; -- cgit v1.2.3 From ba3efdff2cd214e4133b73f4891f6255b610c19b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 1 May 2018 10:36:39 +0300 Subject: gpiolib: fix gpiochip_machine_hog() There is a shifter vs vanilla mask bug here. We want to test if 1 << 11 is set but we're testing if 0xb is set. Fixes: 9a6c505f7df1 ("gpiolib: add hogs support for machine code") Signed-off-by: Dan Carpenter Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 547adc149b62..d1171db66c30 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1186,7 +1186,7 @@ static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) return; } - if (desc->flags & FLAG_IS_HOGGED) + if (test_bit(FLAG_IS_HOGGED, &desc->flags)) return; rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags); -- cgit v1.2.3 From 668f06579e99762ec6ef4a97ba824bc812a9ab2f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 3 May 2018 14:46:24 +0200 Subject: gpio: ge: Fix build warning Casting a pointer to u16 can produce a compiler warning such as this: drivers/gpio/gpio-ge.c: In function 'gef_gpio_probe': drivers/gpio/gpio-ge.c:83:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] gc->ngpio = (u16)of_device_get_match_data(&pdev->dev); ^ Cast the pointer through a uintptr_t to avoid the warning. Reported-by: kbuild test robot Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 4c43562434cf..636952769bc8 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -80,7 +80,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev) } gc->base = -1; - gc->ngpio = (u16)of_device_get_match_data(&pdev->dev); + gc->ngpio = (u16)(uintptr_t)of_device_get_match_data(&pdev->dev); gc->of_gpio_n_cells = 2; gc->of_node = pdev->dev.of_node; -- cgit v1.2.3 From 0950c19acaaa8f899f715954e2918ff45e5b2fc8 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sat, 28 Apr 2018 18:31:31 +0200 Subject: gpio: pca953x: convert register constants to hex which makes it easier to match them with the data sheets. Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 9a06b8a4f5be..b68a8a240e4c 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -25,25 +25,25 @@ #include -#define PCA953X_INPUT 0 -#define PCA953X_OUTPUT 1 -#define PCA953X_INVERT 2 -#define PCA953X_DIRECTION 3 +#define PCA953X_INPUT 0x00 +#define PCA953X_OUTPUT 0x01 +#define PCA953X_INVERT 0x02 +#define PCA953X_DIRECTION 0x03 #define REG_ADDR_AI 0x80 -#define PCA957X_IN 0 -#define PCA957X_INVRT 1 -#define PCA957X_BKEN 2 -#define PCA957X_PUPD 3 -#define PCA957X_CFG 4 -#define PCA957X_OUT 5 -#define PCA957X_MSK 6 -#define PCA957X_INTS 7 - -#define PCAL953X_IN_LATCH 34 -#define PCAL953X_INT_MASK 37 -#define PCAL953X_INT_STAT 38 +#define PCA957X_IN 0x00 +#define PCA957X_INVRT 0x01 +#define PCA957X_BKEN 0x02 +#define PCA957X_PUPD 0x03 +#define PCA957X_CFG 0x04 +#define PCA957X_OUT 0x05 +#define PCA957X_MSK 0x06 +#define PCA957X_INTS 0x07 + +#define PCAL953X_IN_LATCH 0x22 +#define PCAL953X_INT_MASK 0x25 +#define PCAL953X_INT_STAT 0x26 #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 -- cgit v1.2.3 From 6315d231efdc6ff1f3344e2d3c66dabcf6e7c27f Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sat, 28 Apr 2018 18:31:32 +0200 Subject: gpio: pca953x: add more register definitions for pcal953x PCAL chips ("L" seems to stand for "latched") have additional registers starting at address 0x40 to control the latches, interrupt mask, pull-up and pull down etc. Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index b68a8a240e4c..ed58c000c72f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -41,9 +41,13 @@ #define PCA957X_MSK 0x06 #define PCA957X_INTS 0x07 +#define PCAL953X_OUT_STRENGTH 0x20 #define PCAL953X_IN_LATCH 0x22 +#define PCAL953X_PULL_EN 0x23 +#define PCAL953X_PULL_SEL 0x24 #define PCAL953X_INT_MASK 0x25 #define PCAL953X_INT_STAT 0x26 +#define PCAL953X_OUT_CONF 0x27 #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 -- cgit v1.2.3 From a0ecbcccb5478e55293424ec4a5515498b234bf2 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sat, 28 Apr 2018 18:31:33 +0200 Subject: gpio: pca953x: add more register definitions for pcal6524 The pcal6524 has another set of registers to fine control the interrupt handling. Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index ed58c000c72f..6e3ddeae127f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -49,6 +49,12 @@ #define PCAL953X_INT_STAT 0x26 #define PCAL953X_OUT_CONF 0x27 +#define PCAL6524_INT_EDGE 0x28 +#define PCAL6524_INT_CLR 0x2a +#define PCAL6524_IN_STATUS 0x2b +#define PCAL6524_OUT_INDCONF 0x2c +#define PCAL6524_DEBOUNCE 0x2d + #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 -- cgit v1.2.3 From 4b21f94a3001ba5326425d6b6d93bc63ddebdc97 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 3 May 2018 20:14:46 +0300 Subject: gpio: Convert to use match_string() helper The new helper returns index of the matching string in an array. We are going to use it here. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 586d15137c03..28d968088131 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -210,11 +210,8 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * if (!con_id) return ERR_PTR(-ENOENT); - for (i = 0; i < ARRAY_SIZE(whitelist); i++) - if (!strcmp(con_id, whitelist[i])) - break; - - if (i == ARRAY_SIZE(whitelist)) + i = match_string(whitelist, ARRAY_SIZE(whitelist), con_id); + if (i < 0) return ERR_PTR(-ENOENT); desc = of_get_named_gpiod_flags(np, con_id, 0, of_flags); -- cgit v1.2.3 From 5e3a8ecd7614d5432b2db4f59fd6b119439aa226 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 7 May 2018 16:06:54 +0530 Subject: gpio: zynq: Remove call to platform_get_irq Remove the call to platform_get_irq use the cached one instead. Signed-off-by: Shubhrajyoti Datta Reviewed-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 75ee877e5cd5..e20f9cfcdb88 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -666,9 +666,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) static int __maybe_unused zynq_gpio_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - int irq = platform_get_irq(pdev, 0); - struct irq_data *data = irq_get_irq_data(irq); struct zynq_gpio *gpio = platform_get_drvdata(pdev); + struct irq_data *data = irq_get_irq_data(gpio->irq); if (!irqd_is_wakeup_set(data)) { zynq_gpio_save_context(gpio); @@ -681,9 +680,8 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) static int __maybe_unused zynq_gpio_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - int irq = platform_get_irq(pdev, 0); - struct irq_data *data = irq_get_irq_data(irq); struct zynq_gpio *gpio = platform_get_drvdata(pdev); + struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; if (!irqd_is_wakeup_set(data)) { -- cgit v1.2.3 From a76e865eea9e892466700451ba0ac54b22c039ae Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 7 May 2018 17:06:00 +0530 Subject: gpio: zynq: simplifly getting drvdata Get the driver data directly by dev_get_drvdata. Signed-off-by: Shubhrajyoti Datta Reviewed-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index e20f9cfcdb88..6c61e15cf322 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -665,8 +665,7 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) static int __maybe_unused zynq_gpio_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct zynq_gpio *gpio = platform_get_drvdata(pdev); + struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); if (!irqd_is_wakeup_set(data)) { @@ -679,8 +678,7 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) static int __maybe_unused zynq_gpio_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct zynq_gpio *gpio = platform_get_drvdata(pdev); + struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; -- cgit v1.2.3 From aa1fdda8f7ebf83f678e8d3c2ab4f1638c94195f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 18 May 2018 11:52:04 +0800 Subject: gpio: syscon: allow fetching syscon from parent node Syscon nodes can be a simple-mfd and the syscon-users then be declared as children of this node. That way the parent-child structure can be better represented for devices that are fully embedded in the syscon. Therefore allow getting the syscon from the parent if neither a special compatible nor a gpio,syscon-dev property is defined. Signed-off-by: Heiko Stuebner Signed-off-by: Levin Du Signed-off-by: Linus Walleij --- drivers/gpio/gpio-syscon.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 2512acd99027..8b0a69c5ba88 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -200,6 +200,8 @@ static int syscon_gpio_probe(struct platform_device *pdev) } else { priv->syscon = syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev"); + if (IS_ERR(priv->syscon) && np->parent) + priv->syscon = syscon_node_to_regmap(np->parent); if (IS_ERR(priv->syscon)) return PTR_ERR(priv->syscon); -- cgit v1.2.3 From da069d5d2b814d9887989dcdb29fb0202eac8b38 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Wed, 23 May 2018 09:52:44 +0100 Subject: gpio: dwapb: Rework support for 1 interrupt per port A GPIO Treat DT and ACPI the same as much as possible. Note that we can't use platform_get_irq() to get the DT interrupts as they are in the port sub-node and hence do not have an associated platform device. This also fixes a problem introduced with error checking when calling platform_get_irq(). Signed-off-by: Phil Edworthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 53 ++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 494df023271e..7a2de3de6571 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -444,7 +444,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, int i; for (i = 0; i < pp->ngpio; i++) { - if (pp->irq[i]) + if (pp->irq[i] >= 0) irq_set_chained_handler_and_data(pp->irq[i], dwapb_irq_handler, gpio); } @@ -562,7 +562,7 @@ dwapb_gpio_get_pdata(struct device *dev) struct dwapb_platform_data *pdata; struct dwapb_port_property *pp; int nports; - int i; + int i, j; nports = device_get_child_node_count(dev); if (nports == 0) @@ -580,6 +580,8 @@ dwapb_gpio_get_pdata(struct device *dev) i = 0; device_for_each_child_node(dev, fwnode) { + struct device_node *np = NULL; + pp = &pdata->properties[i++]; pp->fwnode = fwnode; @@ -599,46 +601,35 @@ dwapb_gpio_get_pdata(struct device *dev) pp->ngpio = 32; } + pp->irq_shared = false; + pp->gpio_base = -1; + /* * Only port A can provide interrupts in all configurations of * the IP. */ - if (dev->of_node && pp->idx == 0 && - fwnode_property_read_bool(fwnode, - "interrupt-controller")) { - struct device_node *np = to_of_node(fwnode); - unsigned int j; - - /* - * The IP has configuration options to allow a single - * combined interrupt or one per gpio. If one per gpio, - * some might not be used. - */ - for (j = 0; j < pp->ngpio; j++) { - int irq = of_irq_get(np, j); - if (irq < 0) - continue; - - pp->irq[j] = irq; - pp->has_irq = true; - } + if (pp->idx != 0) + continue; - if (!pp->has_irq) - dev_warn(dev, "no irq for port%d\n", pp->idx); + if (dev->of_node && fwnode_property_read_bool(fwnode, + "interrupt-controller")) { + np = to_of_node(fwnode); } - if (has_acpi_companion(dev) && pp->idx == 0) { - unsigned int j; + for (j = 0; j < pp->ngpio; j++) { + pp->irq[j] = -ENXIO; - for (j = 0; j < pp->ngpio; j++) { + if (np) + pp->irq[j] = of_irq_get(np, j); + else if (has_acpi_companion(dev)) pp->irq[j] = platform_get_irq(to_platform_device(dev), j); - if (pp->irq[j]) - pp->has_irq = true; - } + + if (pp->irq[j] >= 0) + pp->has_irq = true; } - pp->irq_shared = false; - pp->gpio_base = -1; + if (!pp->has_irq) + dev_warn(dev, "no irq for port%d\n", pp->idx); } return pdata; -- cgit v1.2.3 From 060f3ebf6a9a4a92dd92149e6ebffae10679ed17 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 11 Apr 2018 15:55:01 +0200 Subject: gpio: zynq: Setup chip->base based on alias ID In past Xilinx gpio-zynq driver was setting up gpio chip->base as 0 which was chagned to autodetection when driver was upstreamed. Older systems, which were using this old version, setup SW stack which expects zynq gpio base as 0 and right now there is no way how to set this up. The patch is adding an option to setup chip->base based on aliases which is something what some other drivers are doing too. It means when gpio0 alias is setup then chip->base is 0. When gpio alias is not setup gpiochip_find_base() set it up properly which is current behavior. Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 6c61e15cf322..3f5fcdd5a429 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -827,7 +827,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) chip->free = zynq_gpio_free; chip->direction_input = zynq_gpio_dir_in; chip->direction_output = zynq_gpio_dir_out; - chip->base = -1; + chip->base = of_alias_get_id(pdev->dev.of_node, "gpio"); chip->ngpio = gpio->p_data->ngpio; /* Retrieve GPIO clock */ -- cgit v1.2.3 From 0a70fe00efea7c6ac087a10aa57131e59d63e194 Mon Sep 17 00:00:00 2001 From: Grigoryev Denis Date: Fri, 4 May 2018 16:53:18 +0000 Subject: gpio: pca953x: Clear irq trigger type on irq shutdown The driver stores the result of irq_set_type() in the internal variables irq_trig_raise and irq_trig_fall, which later are used to determine the GPIOs that must be re-configured as input. These variables retain their value between gpiolib's export / unexport, resulting in an incorrect state in some cases. The corresponding bits in the variables irq_trig_raise and irq_trig_fall should be cleared in irq_shutdown(). Signed-off-by: Denis Grigoryev Acked-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 6e3ddeae127f..d01e09d37573 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -532,6 +532,15 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) return 0; } +static void pca953x_irq_shutdown(struct irq_data *d) +{ + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + u8 mask = 1 << (d->hwirq % BANK_SZ); + + chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; + chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; +} + static struct irq_chip pca953x_irq_chip = { .name = "pca953x", .irq_mask = pca953x_irq_mask, @@ -539,6 +548,7 @@ static struct irq_chip pca953x_irq_chip = { .irq_bus_lock = pca953x_irq_bus_lock, .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, .irq_set_type = pca953x_irq_set_type, + .irq_shutdown = pca953x_irq_shutdown, }; static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) -- cgit v1.2.3 From 0cdf21b34e3062af8da0a2a1c419654263c21b87 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 17 May 2018 06:59:47 +0200 Subject: gpio: pca953x: set the PCA_PCAL flag also when matching by DT The of_device_table is missing the PCA_PCAL flag so the pcal6524 would be operated in tca6424 compatibility mode which does not handle the new interrupt mask registers. Suggested-by: Andy Shevchenko Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d01e09d37573..ae9b1ed76951 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -58,6 +58,7 @@ #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 +#define PCA_LATCH_INT (PCA_PCAL | PCA_INT) #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 #define PCA_TYPE_MASK 0xF000 @@ -954,8 +955,8 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, - { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_INT), }, - { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_INT), }, + { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), }, + { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), }, { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, -- cgit v1.2.3 From 394aeef83c7080c9fd850e3479e0cd58e510163b Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 17 May 2018 06:59:48 +0200 Subject: gpio: pca953x: define masks for addressing common and extended registers These mask bits are to be used to map the extended register addresses (which are defined for an unsupported 8-bit pcal chip) to 16 and 24 bit chips (pcal6524). Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index ae9b1ed76951..06ef9c36764e 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -56,6 +56,10 @@ #define PCAL6524_DEBOUNCE 0x2d #define PCA_GPIO_MASK 0x00FF + +#define PCAL_GPIO_MASK 0x1f +#define PCAL_PINCTRL_MASK 0xe0 + #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) -- cgit v1.2.3 From d5dbf9c266ccf632cdf259146e4ec62b381db655 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Thu, 17 May 2018 06:59:49 +0200 Subject: gpio: pca953x: fix address calculation for pcal6524 The register constants are so far defined in a way that they fit for the pcal9555a when shifted by the number of banks, i.e. are multiplied by 2 in the accessor function. Now, the pcal6524 has 3 banks which means the relative offset is multiplied by 4 for the standard registers. Simply applying the bit shift to the extended registers gives a wrong result, since the base offset is already included in the offset. Therefore, we have to add code to the 24 bit accessor functions that adjusts the register number for these exended registers. The formula finally used was developed and proposed by Andy Shevchenko . Suggested-by: Andy Shevchenko Signed-off-by: H. Nikolaus Schaller Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 06ef9c36764e..fb5cc1f80b10 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -222,9 +222,11 @@ static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int addr = (reg & PCAL_GPIO_MASK) << bank_shift; + int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; return i2c_smbus_write_i2c_block_data(chip->client, - (reg << bank_shift) | REG_ADDR_AI, + pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); } @@ -264,9 +266,11 @@ static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_read_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int addr = (reg & PCAL_GPIO_MASK) << bank_shift; + int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; return i2c_smbus_read_i2c_block_data(chip->client, - (reg << bank_shift) | REG_ADDR_AI, + pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); } -- cgit v1.2.3 From af7949284910a1f0b7814625051b8acf99af74d2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 17 May 2018 18:11:56 +1000 Subject: gpio: aspeed: Set output latch before changing direction In aspeed_gpio_dir_out(), we need to establish the new output value in the output latch *before* we change the direction to output in order to avoid a glitch on the output line if the previous value of the latch was different. Signed-off-by: Benjamin Herrenschmidt Reviewed-by: Christopher Bostic Reviewed-by: Andrew Jeffery Tested-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 77e485557498..f210bed83dd6 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -287,11 +287,10 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc, spin_lock_irqsave(&gpio->lock, flags); + __aspeed_gpio_set(gc, offset, val); reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)); iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR)); - __aspeed_gpio_set(gc, offset, val); - spin_unlock_irqrestore(&gpio->lock, flags); return 0; -- cgit v1.2.3 From ed5cab43f99d1629af0e34ff565aa14efe0a8ac9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 17 May 2018 18:12:02 +1000 Subject: gpio: aspeed: Use a cache of output data registers The current driver does a read/modify/write of the output registers when changing a bit in __aspeed_gpio_set(). This is sub-optimal for a couple of reasons: - If any of the neighbouring GPIOs (sharing the shared register) isn't (yet) configured as an output, it will read the current input value, and then apply it to the output latch, which may not be what the user expects. There should be no bug in practice as aspeed_gpio_dir_out() will establish a new value but it's not great either. - The GPIO block in the aspeed chip is clocked rather slowly (typically 25Mhz). That extra MMIO read halves the maximum speed at which we can toggle the GPIO. This provides a significant performance improvement to the GPIO based FSI master. Signed-off-by: Benjamin Herrenschmidt Reviewed-by: Christopher Bostic Reviewed-by: Andrew Jeffery Tested-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index f210bed83dd6..f579bec6e102 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -54,6 +54,8 @@ struct aspeed_gpio { u8 *offset_timer; unsigned int timer_users[4]; struct clk *clk; + + u32 *dcache; }; struct aspeed_gpio_bank { @@ -231,12 +233,13 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, u32 reg; addr = bank_val_reg(gpio, bank, GPIO_DATA); - reg = ioread32(addr); + reg = gpio->dcache[GPIO_BANK(offset)]; if (val) reg |= GPIO_BIT(offset); else reg &= ~GPIO_BIT(offset); + gpio->dcache[GPIO_BANK(offset)] = reg; iowrite32(reg, addr); } @@ -851,7 +854,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) const struct of_device_id *gpio_id; struct aspeed_gpio *gpio; struct resource *res; - int rc; + int rc, i, banks; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -892,6 +895,20 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->chip.base = -1; gpio->chip.irq.need_valid_mask = true; + /* Allocate a cache of the output registers */ + banks = gpio->config->nr_gpios >> 5; + gpio->dcache = devm_kzalloc(&pdev->dev, + sizeof(u32) * banks, GFP_KERNEL); + if (!gpio->dcache) + return -ENOMEM; + + /* Populate it with initial values read from the HW */ + for (i = 0; i < banks; i++) { + const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i]; + gpio->dcache[i] = ioread32(gpio->base + bank->val_regs + + GPIO_DATA); + } + rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); if (rc < 0) return rc; -- cgit v1.2.3 From 3027743f83f867d85662f5134e835c2e199cb9be Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 21 May 2018 10:57:07 -0700 Subject: gpio: Remove VLA from gpiolib The new challenge is to remove VLAs from the kernel (see https://lkml.org/lkml/2018/3/7/621) to eventually turn on -Wvla. Using a kmalloc array is the easy way to fix this but kmalloc is still more expensive than stack allocation. Introduce a fast path with a fixed size stack array to cover most chip with gpios below some fixed amount. The slow path dynamically allocates an array to cover those chips with a large number of gpios. Reviewed-by: Geert Uytterhoeven Reviewed-by: Phil Reid Reviewed-and-tested-by: Lukas Wunner Signed-off-by: Lukas Wunner Signed-off-by: Laura Abbott Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 12 +++++++ drivers/gpio/gpiolib.c | 76 +++++++++++++++++++++++++++++++++---------- drivers/gpio/gpiolib.h | 2 +- include/linux/gpio/consumer.h | 10 +++--- 4 files changed, 78 insertions(+), 22 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b960f6f35abd..71c0ab46f216 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -22,6 +22,18 @@ menuconfig GPIOLIB if GPIOLIB +config GPIOLIB_FASTPATH_LIMIT + int "Maximum number of GPIOs for fast path" + range 32 512 + default 512 + help + This adjusts the point at which certain APIs will switch from + using a stack allocated buffer to a dynamically allocated buffer. + + You shouldn't need to change this unless you really need to + optimize either stack space or performance. Change this carefully + since setting an incorrect value could cause stack corruption. + config OF_GPIO def_bool y depends on OF diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d1171db66c30..487edf188138 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -61,6 +61,11 @@ static struct bus_type gpio_bus_type = { .name = "gpio", }; +/* + * Number of GPIOs to use for the fast path in set array + */ +#define FASTPATH_NGPIO CONFIG_GPIOLIB_FASTPATH_LIMIT + /* gpio_lock prevents conflicts during gpio_desc[] table updates. * While any GPIO is requested, its gpio_chip is not removable; * each GPIO's "requested" flag serves as a lock and refcount. @@ -453,12 +458,11 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd, vals[i] = !!ghd.values[i]; /* Reuse the array setting function */ - gpiod_set_array_value_complex(false, + return gpiod_set_array_value_complex(false, true, lh->numdescs, lh->descs, vals); - return 0; } return -EINVAL; } @@ -1281,6 +1285,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, goto err_free_descs; } + if (chip->ngpio > FASTPATH_NGPIO) + chip_warn(chip, "line cnt %u is greater than fast path cnt %u\n", + chip->ngpio, FASTPATH_NGPIO); + gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL); if (!gdev->label) { status = -ENOMEM; @@ -2758,16 +2766,28 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *chip = desc_array[i]->gdev->chip; - unsigned long mask[BITS_TO_LONGS(chip->ngpio)]; - unsigned long bits[BITS_TO_LONGS(chip->ngpio)]; + unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + unsigned long *mask, *bits; int first, j, ret; + if (likely(chip->ngpio <= FASTPATH_NGPIO)) { + mask = fastpath; + } else { + mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio), + sizeof(*mask), + can_sleep ? GFP_KERNEL : GFP_ATOMIC); + if (!mask) + return -ENOMEM; + } + + bits = mask + BITS_TO_LONGS(chip->ngpio); + bitmap_zero(mask, chip->ngpio); + if (!can_sleep) WARN_ON(chip->can_sleep); /* collect all inputs belonging to the same chip */ first = i; - memset(mask, 0, sizeof(mask)); do { const struct gpio_desc *desc = desc_array[i]; int hwgpio = gpio_chip_hwgpio(desc); @@ -2778,8 +2798,11 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, (desc_array[i]->gdev->chip == chip)); ret = gpio_chip_get_multiple(chip, mask, bits); - if (ret) + if (ret) { + if (mask != fastpath) + kfree(mask); return ret; + } for (j = first; j < i; j++) { const struct gpio_desc *desc = desc_array[j]; @@ -2791,6 +2814,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, value_array[j] = value; trace_gpio_value(desc_to_gpio(desc), 1, value); } + + if (mask != fastpath) + kfree(mask); } return 0; } @@ -2974,7 +3000,7 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip, } } -void gpiod_set_array_value_complex(bool raw, bool can_sleep, +int gpiod_set_array_value_complex(bool raw, bool can_sleep, unsigned int array_size, struct gpio_desc **desc_array, int *value_array) @@ -2983,14 +3009,26 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *chip = desc_array[i]->gdev->chip; - unsigned long mask[BITS_TO_LONGS(chip->ngpio)]; - unsigned long bits[BITS_TO_LONGS(chip->ngpio)]; + unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + unsigned long *mask, *bits; int count = 0; + if (likely(chip->ngpio <= FASTPATH_NGPIO)) { + mask = fastpath; + } else { + mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio), + sizeof(*mask), + can_sleep ? GFP_KERNEL : GFP_ATOMIC); + if (!mask) + return -ENOMEM; + } + + bits = mask + BITS_TO_LONGS(chip->ngpio); + bitmap_zero(mask, chip->ngpio); + if (!can_sleep) WARN_ON(chip->can_sleep); - memset(mask, 0, sizeof(mask)); do { struct gpio_desc *desc = desc_array[i]; int hwgpio = gpio_chip_hwgpio(desc); @@ -3021,7 +3059,11 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep, /* push collected bits to outputs */ if (count != 0) gpio_chip_set_multiple(chip, mask, bits); + + if (mask != fastpath) + kfree(mask); } + return 0; } /** @@ -3096,13 +3138,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_value); * This function should be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ -void gpiod_set_raw_array_value(unsigned int array_size, +int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, int *value_array) { if (!desc_array) - return; - gpiod_set_array_value_complex(true, false, array_size, desc_array, - value_array); + return -EINVAL; + return gpiod_set_array_value_complex(true, false, array_size, + desc_array, value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value); @@ -3422,14 +3464,14 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); * * This function is to be called from contexts that can sleep. */ -void gpiod_set_raw_array_value_cansleep(unsigned int array_size, +int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, int *value_array) { might_sleep_if(extra_checks); if (!desc_array) - return; - gpiod_set_array_value_complex(true, true, array_size, desc_array, + return -EINVAL; + return gpiod_set_array_value_complex(true, true, array_size, desc_array, value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index ad456b6f9d8b..1a8e20363861 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -188,7 +188,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, unsigned int array_size, struct gpio_desc **desc_array, int *value_array); -void gpiod_set_array_value_complex(bool raw, bool can_sleep, +int gpiod_set_array_value_complex(bool raw, bool can_sleep, unsigned int array_size, struct gpio_desc **desc_array, int *value_array); diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index dbd065963296..243112c7fa7d 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -116,7 +116,7 @@ int gpiod_get_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, int *value_array); void gpiod_set_raw_value(struct gpio_desc *desc, int value); -void gpiod_set_raw_array_value(unsigned int array_size, +int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, int *value_array); @@ -134,7 +134,7 @@ int gpiod_get_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, int *value_array); void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); -void gpiod_set_raw_array_value_cansleep(unsigned int array_size, +int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, int *value_array); @@ -369,12 +369,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) /* GPIO can never have been requested */ WARN_ON(1); } -static inline void gpiod_set_raw_array_value(unsigned int array_size, +static inline int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, int *value_array) { /* GPIO can never have been requested */ WARN_ON(1); + return 0; } static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) @@ -423,12 +424,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, /* GPIO can never have been requested */ WARN_ON(1); } -static inline void gpiod_set_raw_array_value_cansleep(unsigned int array_size, +static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, int *value_array) { /* GPIO can never have been requested */ WARN_ON(1); + return 0; } static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) -- cgit v1.2.3 From 2808801aab8a595b5bb66c43e2f8b3f3a025cf79 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 22 May 2018 11:05:40 +0800 Subject: gpio: mxc: add clock operation Some i.MX SoCs have GPIO clock gates in CCM CCGR, such as i.MX6SLL, need to enable clocks before accessing GPIO registers, add optional clock operation for GPIO driver. Signed-off-by: Anson Huang Reviewed-by: Fabio Estevam Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 11ec7228ab08..f4dc31d88a04 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include #include @@ -60,6 +61,7 @@ struct mxc_gpio_hwdata { struct mxc_gpio_port { struct list_head node; void __iomem *base; + struct clk *clk; int irq; int irq_high; struct irq_domain *domain; @@ -434,6 +436,17 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (port->irq < 0) return port->irq; + /* the controller clock is optional */ + port->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(port->clk)) + port->clk = NULL; + + err = clk_prepare_enable(port->clk); + if (err) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return err; + } + /* disable the interrupt and clear the status */ writel(0, port->base + GPIO_IMR); writel(~0, port->base + GPIO_ISR); @@ -502,6 +515,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) out_irqdomain_remove: irq_domain_remove(port->domain); out_bgio: + clk_disable_unprepare(port->clk); dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); return err; } -- cgit v1.2.3 From 014e420d8ab5cc3cd8828a4ac2690048e1040754 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2018 23:32:54 -0300 Subject: gpio: mxc: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index f4dc31d88a04..2f2829966d4c 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -1,24 +1,11 @@ -/* - * MXC GPIO support. (c) 2008 Daniel Mack - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * Based on code from Freescale Semiconductor, - * Authors: Daniel Mack, Juergen Beisert. - * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * 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. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// MXC GPIO support. (c) 2008 Daniel Mack +// Copyright 2008 Juergen Beisert, kernel@pengutronix.de +// +// Based on code from Freescale Semiconductor, +// Authors: Daniel Mack, Juergen Beisert. +// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. #include #include -- cgit v1.2.3 From 97fe7bef56e60ef6efa186348908b954a236b2fb Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Wed, 28 Mar 2018 10:59:57 -0700 Subject: gpio: Remove VLA from stmpe driver The new challenge is to remove VLAs from the kernel (see https://lkml.org/lkml/2018/3/7/621) The number of GPIOs on the supported chips is fairly small so stack allocate to a known upper bound and spit out a warning if any new chips have more gpios. Signed-off-by: Laura Abbott Reviewed-by: Phil Reid Reviewed-by: Kees Cook Signed-off-by: Linus Walleij --- drivers/gpio/gpio-stmpe.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index f8d7d1cd8488..8d6a5a7e612d 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -363,13 +363,15 @@ static struct irq_chip stmpe_gpio_irq_chip = { .irq_set_type = stmpe_gpio_irq_set_type, }; +#define MAX_GPIOS 24 + static irqreturn_t stmpe_gpio_irq(int irq, void *dev) { struct stmpe_gpio *stmpe_gpio = dev; struct stmpe *stmpe = stmpe_gpio->stmpe; u8 statmsbreg; int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); - u8 status[num_banks]; + u8 status[DIV_ROUND_UP(MAX_GPIOS, 8)]; int ret; int i; @@ -434,6 +436,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev) struct stmpe_gpio *stmpe_gpio; int ret, irq; + if (stmpe->num_gpios > MAX_GPIOS) { + dev_err(&pdev->dev, "Need to increase maximum GPIO number\n"); + return -EINVAL; + } + stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL); if (!stmpe_gpio) return -ENOMEM; -- cgit v1.2.3 From 339e7730cba4ba9d599ab4e92fc0475965c757ce Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 May 2018 23:32:55 -0300 Subject: gpio: mxs: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 5ad8d4db74db..e2831ee70cdc 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -1,24 +1,10 @@ -/* - * MXC GPIO support. (c) 2008 Daniel Mack - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * Based on code from Freescale, - * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * 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. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// MXC GPIO support. (c) 2008 Daniel Mack +// Copyright 2008 Juergen Beisert, kernel@pengutronix.de +// +// Based on code from Freescale, +// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. #include #include -- cgit v1.2.3 From be1f20a41fdf591334f4343004564bc4b6dc78d2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:22:04 +0200 Subject: gpio: octeon: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-octeon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 96a8a8cb2729..1b19c88ea7bb 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From b7351b077e6832e50b7fa3125f939a42b616b806 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:24:00 +0200 Subject: gpio: omap: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 35971a341c40..d1afedf4dcbf 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From b11a0b3e72a8ef4de0fdd161418854cb379a4391 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:25:13 +0200 Subject: gpio: palmas: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-palmas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index ceb2fef2c8ae..05b0cd5dcf11 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -#include +#include #include #include #include -- cgit v1.2.3 From 644f3da0b42aa299554c9c09a96d23c03957c6b0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:26:20 +0200 Subject: gpio: pca953x: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index fb5cc1f80b10..c55ad157e820 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -12,7 +12,7 @@ */ #include -#include +#include #include #include #include -- cgit v1.2.3 From 12087fab9149fba529ff66dd283ed1090248de8e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:27:28 +0200 Subject: gpio: pcf857x: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pcf857x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 38fbb420c6cd..adf72dda25a2 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include #include #include #include -- cgit v1.2.3 From 5db1f87317b59bd708e3e8cd20deac6ac0d6bff9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:29:30 +0200 Subject: gpio: pch: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 68c6d0c5a6d1..ffce0ab912ed 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From dcc6ceef74fc27f0533b4957bf90e1a7f9c8909b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:30:26 +0200 Subject: gpio: pl061: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index b70974cb9ef1..2afd9de84a0d 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 84bf021ecee4e50b63ab5e5563a5202e69cb5623 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 May 2018 14:32:09 +0200 Subject: gpio: pxa: Include the right header This is a GPIO driver, include only . Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 3c1f65bc0fa8..1e66f808051c 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 6310b930ccbba55168f30b610fae681d73bd7bd2 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 29 May 2018 20:21:01 +0530 Subject: gpio: davinci: fix build warning when !CONFIG_OF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This nukes the following warning that is seen when building without OF support: drivers/gpio/gpio-davinci.c:437:25: warning: ‘keystone_gpio_get_irq_chip’ defined but not used [-Wunused-function] static struct irq_chip *keystone_gpio_get_irq_chip(unsigned int irq) ^~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Sekhar Nori Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 987126c4c6f6..b574ecff7761 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -610,14 +610,12 @@ done: return 0; } -#if IS_ENABLED(CONFIG_OF) static const struct of_device_id davinci_gpio_ids[] = { { .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip}, { .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip}, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, davinci_gpio_ids); -#endif static struct platform_driver davinci_gpio_driver = { .probe = davinci_gpio_probe, -- cgit v1.2.3