diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpio/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
| -rw-r--r-- | drivers/gpio/devres.c | 11 | ||||
| -rw-r--r-- | drivers/gpio/gpio-davinci.c | 177 | ||||
| -rw-r--r-- | drivers/gpio/gpio-gemini.c | 236 | ||||
| -rw-r--r-- | drivers/gpio/gpio-intel-mid.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mm-lantiq.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mockup.c | 23 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mvebu.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pca953x.c | 9 | ||||
| -rw-r--r-- | drivers/gpio/gpio-rcar.c | 21 | ||||
| -rw-r--r-- | drivers/gpio/gpio-stp-xway.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 5 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-of.c | 31 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 22 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.h | 3 |
16 files changed, 405 insertions, 151 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d5d36549ecc1..701809b1a105 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -197,6 +197,15 @@ config GPIO_GE_FPGA and write pin state) for GPIO implemented in a number of GE single board computers. +config GPIO_GEMINI + bool "Gemini GPIO" + depends on ARCH_GEMINI + depends on OF_GPIO + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Support for common GPIOs found in Cortina systems Gemini platforms. + config GPIO_GENERIC_PLATFORM tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" select GPIO_GENERIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a7676b82de6f..de45957b9b62 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o +obj-$(CONFIG_GPIO_GEMINI) += gpio-gemini.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 89969e887e5d..d196be7ac352 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -11,7 +11,7 @@ * * This file is based on kernel/irq/devres.c * - * Copyright (c) 2011 John Crispin <blogic@openwrt.org> + * Copyright (c) 2011 John Crispin <john@phrozen.org> */ #include <linux/module.h> @@ -21,6 +21,8 @@ #include <linux/device.h> #include <linux/gfp.h> +#include "gpiolib.h" + static void devm_gpiod_release(struct device *dev, void *res) { struct gpio_desc **desc = res; @@ -141,7 +143,6 @@ struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, enum gpiod_flags flags, const char *label) { - static const char * const suffixes[] = { "gpios", "gpio" }; char prop_name[32]; /* 32 is max size of property name */ struct gpio_desc **dr; struct gpio_desc *desc; @@ -152,13 +153,13 @@ struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, if (!dr) return ERR_PTR(-ENOMEM); - for (i = 0; i < ARRAY_SIZE(suffixes); i++) { + for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { if (con_id) snprintf(prop_name, sizeof(prop_name), "%s-%s", - con_id, suffixes[i]); + con_id, gpio_suffixes[i]); else snprintf(prop_name, sizeof(prop_name), "%s", - suffixes[i]); + gpio_suffixes[i]); desc = fwnode_get_named_gpiod(child, prop_name, flags, label); if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT)) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 9191056548fe..72f49d1e110d 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -43,25 +43,7 @@ typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq); #define MAX_LABEL_SIZE 20 static void __iomem *gpio_base; - -static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio) -{ - void __iomem *ptr; - - if (gpio < 32 * 1) - ptr = gpio_base + 0x10; - else if (gpio < 32 * 2) - ptr = gpio_base + 0x38; - else if (gpio < 32 * 3) - ptr = gpio_base + 0x60; - else if (gpio < 32 * 4) - ptr = gpio_base + 0x88; - else if (gpio < 32 * 5) - ptr = gpio_base + 0xb0; - else - ptr = NULL; - return ptr; -} +static unsigned int offset_array[5] = {0x10, 0x38, 0x60, 0x88, 0xb0}; static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d) { @@ -81,11 +63,13 @@ static inline int __davinci_direction(struct gpio_chip *chip, unsigned offset, bool out, int value) { struct davinci_gpio_controller *d = gpiochip_get_data(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g; unsigned long flags; u32 temp; - u32 mask = 1 << offset; + int bank = offset / 32; + u32 mask = __gpio_mask(offset); + g = d->regs[bank]; spin_lock_irqsave(&d->lock, flags); temp = readl_relaxed(&g->dir); if (out) { @@ -121,9 +105,12 @@ davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio_controller *d = gpiochip_get_data(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g; + int bank = offset / 32; - return !!((1 << offset) & readl_relaxed(&g->in_data)); + g = d->regs[bank]; + + return !!(__gpio_mask(offset) & readl_relaxed(&g->in_data)); } /* @@ -133,9 +120,13 @@ static void davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct davinci_gpio_controller *d = gpiochip_get_data(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g; + int bank = offset / 32; - writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data); + g = d->regs[bank]; + + writel_relaxed(__gpio_mask(offset), + value ? &g->set_data : &g->clr_data); } static struct davinci_gpio_platform_data * @@ -172,34 +163,13 @@ of_err: return NULL; } -#ifdef CONFIG_OF_GPIO -static int davinci_gpio_of_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags) -{ - struct davinci_gpio_controller *chips = dev_get_drvdata(gc->parent); - struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->parent); - - if (gpiospec->args[0] > pdata->ngpio) - return -EINVAL; - - if (gc != &chips[gpiospec->args[0] / 32].chip) - return -EINVAL; - - if (flags) - *flags = gpiospec->args[1]; - - return gpiospec->args[0] % 32; -} -#endif - static int davinci_gpio_probe(struct platform_device *pdev) { - int i, base; + static int ctrl_num, bank_base; + int gpio, bank; unsigned ngpio, nbank; struct davinci_gpio_controller *chips; struct davinci_gpio_platform_data *pdata; - struct davinci_gpio_regs __iomem *regs; struct device *dev = &pdev->dev; struct resource *res; char label[MAX_LABEL_SIZE]; @@ -238,41 +208,31 @@ static int davinci_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio_base)) return PTR_ERR(gpio_base); - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i); - chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL); - if (!chips[i].chip.label) + snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++); + chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL); + if (!chips->chip.label) return -ENOMEM; - chips[i].chip.direction_input = davinci_direction_in; - chips[i].chip.get = davinci_gpio_get; - chips[i].chip.direction_output = davinci_direction_out; - chips[i].chip.set = davinci_gpio_set; + chips->chip.direction_input = davinci_direction_in; + chips->chip.get = davinci_gpio_get; + chips->chip.direction_output = davinci_direction_out; + chips->chip.set = davinci_gpio_set; - chips[i].chip.base = base; - chips[i].chip.ngpio = ngpio - base; - if (chips[i].chip.ngpio > 32) - chips[i].chip.ngpio = 32; + chips->chip.ngpio = ngpio; + chips->chip.base = bank_base; #ifdef CONFIG_OF_GPIO - chips[i].chip.of_gpio_n_cells = 2; - chips[i].chip.of_xlate = davinci_gpio_of_xlate; - chips[i].chip.parent = dev; - chips[i].chip.of_node = dev->of_node; + chips->chip.of_gpio_n_cells = 2; + chips->chip.parent = dev; + chips->chip.of_node = dev->of_node; #endif - spin_lock_init(&chips[i].lock); - - regs = gpio2regs(base); - if (!regs) - return -ENXIO; - chips[i].regs = regs; - chips[i].set_data = ®s->set_data; - chips[i].clr_data = ®s->clr_data; - chips[i].in_data = ®s->in_data; + spin_lock_init(&chips->lock); + bank_base += ngpio; - gpiochip_add_data(&chips[i].chip, &chips[i]); - } + for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++) + chips->regs[bank] = gpio_base + offset_array[bank]; + gpiochip_add_data(&chips->chip, chips); platform_set_drvdata(pdev, chips); davinci_gpio_irq_setup(pdev); return 0; @@ -333,16 +293,19 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(struct irq_desc *desc) { - unsigned int irq = irq_desc_get_irq(desc); struct davinci_gpio_regs __iomem *g; u32 mask = 0xffff; + int bank_num; struct davinci_gpio_controller *d; + struct davinci_gpio_irq_data *irqdata; - d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc); - g = (struct davinci_gpio_regs __iomem *)d->regs; + irqdata = (struct davinci_gpio_irq_data *)irq_desc_get_handler_data(desc); + bank_num = irqdata->bank_num; + g = irqdata->regs; + d = irqdata->chip; /* we only care about one bank */ - if (irq & 1) + if ((bank_num % 2) == 1) mask <<= 16; /* temporarily mask (level sensitive) parent IRQ */ @@ -350,6 +313,7 @@ static void gpio_irq_handler(struct irq_desc *desc) while (1) { u32 status; int bit; + irq_hw_number_t hw_irq; /* ack any irqs */ status = readl_relaxed(&g->intstat) & mask; @@ -362,9 +326,13 @@ static void gpio_irq_handler(struct irq_desc *desc) while (status) { bit = __ffs(status); status &= ~BIT(bit); + /* Max number of gpios per controller is 144 so + * hw_irq will be in [0..143] + */ + hw_irq = (bank_num / 2) * 32 + bit; + generic_handle_irq( - irq_find_mapping(d->irq_domain, - d->chip.base + bit)); + irq_find_mapping(d->irq_domain, hw_irq)); } } chained_irq_exit(irq_desc_get_chip(desc), desc); @@ -376,7 +344,7 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) struct davinci_gpio_controller *d = gpiochip_get_data(chip); if (d->irq_domain) - return irq_create_mapping(d->irq_domain, d->chip.base + offset); + return irq_create_mapping(d->irq_domain, offset); else return -ENXIO; } @@ -390,7 +358,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). */ if (offset < d->gpio_unbanked) - return d->gpio_irq + offset; + return d->base_irq + offset; else return -ENODEV; } @@ -403,7 +371,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data); g = (struct davinci_gpio_regs __iomem *)d->regs; - mask = __gpio_mask(data->irq - d->gpio_irq); + mask = __gpio_mask(data->irq - d->base_irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) return -EINVAL; @@ -420,7 +388,9 @@ static int davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - struct davinci_gpio_regs __iomem *g = gpio2regs(hw); + struct davinci_gpio_controller *chips = + (struct davinci_gpio_controller *)d->host_data; + struct davinci_gpio_regs __iomem *g = chips->regs[hw / 32]; irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_irq, "davinci_gpio"); @@ -478,6 +448,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) struct irq_domain *irq_domain = NULL; const struct of_device_id *match; struct irq_chip *irq_chip; + struct davinci_gpio_irq_data *irqdata; gpio_get_irq_chip_cb_t gpio_get_irq_chip; /* @@ -533,10 +504,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * IRQs, while the others use banked IRQs, would need some setup * tweaks to recognize hardware which can do that. */ - for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { - chips[bank].chip.to_irq = gpio_to_irq_banked; - chips[bank].irq_domain = irq_domain; - } + chips->chip.to_irq = gpio_to_irq_banked; + chips->irq_domain = irq_domain; /* * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO @@ -545,9 +514,9 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) */ if (pdata->gpio_unbanked) { /* pass "bank 0" GPIO IRQs to AINTC */ - chips[0].chip.to_irq = gpio_to_irq_unbanked; - chips[0].gpio_irq = bank_irq; - chips[0].gpio_unbanked = pdata->gpio_unbanked; + chips->chip.to_irq = gpio_to_irq_unbanked; + chips->base_irq = bank_irq; + chips->gpio_unbanked = pdata->gpio_unbanked; binten = GENMASK(pdata->gpio_unbanked / 16, 0); /* AINTC handles mask/unmask; GPIO handles triggering */ @@ -557,14 +526,14 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) irq_chip->irq_set_type = gpio_irq_type_unbanked; /* default trigger: both edges */ - g = gpio2regs(0); + g = chips->regs[0]; writel_relaxed(~0, &g->set_falling); writel_relaxed(~0, &g->set_rising); /* set the direct IRQs up to use that irqchip */ for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { irq_set_chip(irq, irq_chip); - irq_set_handler_data(irq, &chips[gpio / 32]); + irq_set_handler_data(irq, chips); irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); } @@ -576,8 +545,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * then chain through our own handler. */ for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) { - /* disabled by default, enabled only as needed */ - g = gpio2regs(gpio); + /* disabled by default, enabled only as needed + * There are register sets for 32 GPIOs. 2 banks of 16 + * GPIOs are covered by each set of registers hence divide by 2 + */ + g = chips->regs[bank / 2]; writel_relaxed(~0, &g->clr_falling); writel_relaxed(~0, &g->clr_rising); @@ -586,8 +558,19 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * gpio irqs. Pass the irq bank's corresponding controller to * the chained irq handler. */ + irqdata = devm_kzalloc(&pdev->dev, + sizeof(struct + davinci_gpio_irq_data), + GFP_KERNEL); + if (!irqdata) + return -ENOMEM; + + irqdata->regs = g; + irqdata->bank_num = bank; + irqdata->chip = chips; + irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, - &chips[gpio / 32]); + irqdata); binten |= BIT(bank); } diff --git a/drivers/gpio/gpio-gemini.c b/drivers/gpio/gpio-gemini.c new file mode 100644 index 000000000000..962485163b7f --- /dev/null +++ b/drivers/gpio/gpio-gemini.c @@ -0,0 +1,236 @@ +/* + * Gemini gpiochip and interrupt routines + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> + * + * Based on arch/arm/mach-gemini/gpio.c: + * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> + * + * Based on plat-mxc/gpio.c: + * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + */ +#include <linux/gpio/driver.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/of_gpio.h> +#include <linux/bitops.h> + +/* GPIO registers definition */ +#define GPIO_DATA_OUT 0x00 +#define GPIO_DATA_IN 0x04 +#define GPIO_DIR 0x08 +#define GPIO_DATA_SET 0x10 +#define GPIO_DATA_CLR 0x14 +#define GPIO_PULL_EN 0x18 +#define GPIO_PULL_TYPE 0x1C +#define GPIO_INT_EN 0x20 +#define GPIO_INT_STAT 0x24 +#define GPIO_INT_MASK 0x2C +#define GPIO_INT_CLR 0x30 +#define GPIO_INT_TYPE 0x34 +#define GPIO_INT_BOTH_EDGE 0x38 +#define GPIO_INT_LEVEL 0x3C +#define GPIO_DEBOUNCE_EN 0x40 +#define GPIO_DEBOUNCE_PRESCALE 0x44 + +/** + * struct gemini_gpio - Gemini GPIO state container + * @dev: containing device for this instance + * @gc: gpiochip for this instance + */ +struct gemini_gpio { + struct device *dev; + struct gpio_chip gc; + void __iomem *base; +}; + +static void gemini_gpio_ack_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gemini_gpio *g = gpiochip_get_data(gc); + + writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR); +} + +static void gemini_gpio_mask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gemini_gpio *g = gpiochip_get_data(gc); + u32 val; + + val = readl(g->base + GPIO_INT_EN); + val &= ~BIT(irqd_to_hwirq(d)); + writel(val, g->base + GPIO_INT_EN); +} + +static void gemini_gpio_unmask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gemini_gpio *g = gpiochip_get_data(gc); + u32 val; + + val = readl(g->base + GPIO_INT_EN); + val |= BIT(irqd_to_hwirq(d)); + writel(val, g->base + GPIO_INT_EN); +} + +static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gemini_gpio *g = gpiochip_get_data(gc); + u32 mask = BIT(irqd_to_hwirq(d)); + u32 reg_both, reg_level, reg_type; + + reg_type = readl(g->base + GPIO_INT_TYPE); + reg_level = readl(g->base + GPIO_INT_LEVEL); + reg_both = readl(g->base + GPIO_INT_BOTH_EDGE); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both |= mask; + break; + case IRQ_TYPE_EDGE_RISING: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both &= ~mask; + reg_level &= ~mask; + break; + case IRQ_TYPE_EDGE_FALLING: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both &= ~mask; + reg_level |= mask; + break; + case IRQ_TYPE_LEVEL_HIGH: + irq_set_handler_locked(d, handle_level_irq); + reg_type |= mask; + reg_level &= ~mask; + break; + case IRQ_TYPE_LEVEL_LOW: + irq_set_handler_locked(d, handle_level_irq); + reg_type |= mask; + reg_level |= mask; + break; + default: + irq_set_handler_locked(d, handle_bad_irq); + return -EINVAL; + } + + writel(reg_type, g->base + GPIO_INT_TYPE); + writel(reg_level, g->base + GPIO_INT_LEVEL); + writel(reg_both, g->base + GPIO_INT_BOTH_EDGE); + + gemini_gpio_ack_irq(d); + + return 0; +} + +static struct irq_chip gemini_gpio_irqchip = { + .name = "GPIO", + .irq_ack = gemini_gpio_ack_irq, + .irq_mask = gemini_gpio_mask_irq, + .irq_unmask = gemini_gpio_unmask_irq, + .irq_set_type = gemini_gpio_set_irq_type, +}; + +static void gemini_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct gemini_gpio *g = gpiochip_get_data(gc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + int offset; + unsigned long stat; + + chained_irq_enter(irqchip, desc); + + stat = readl(g->base + GPIO_INT_STAT); + if (stat) + for_each_set_bit(offset, &stat, gc->ngpio) + generic_handle_irq(irq_find_mapping(gc->irqdomain, + offset)); + + chained_irq_exit(irqchip, desc); +} + +static int gemini_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct gemini_gpio *g; + int irq; + int ret; + + g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); + if (!g) + return -ENOMEM; + + g->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + g->base = devm_ioremap_resource(dev, res); + if (IS_ERR(g->base)) + return PTR_ERR(g->base); + + irq = platform_get_irq(pdev, 0); + if (!irq) + return -EINVAL; + + ret = bgpio_init(&g->gc, dev, 4, + g->base + GPIO_DATA_IN, + g->base + GPIO_DATA_SET, + g->base + GPIO_DATA_CLR, + g->base + GPIO_DIR, + NULL, + 0); + if (ret) { + dev_err(dev, "unable to init generic GPIO\n"); + return ret; + } + g->gc.label = "Gemini"; + g->gc.base = -1; + g->gc.parent = dev; + g->gc.owner = THIS_MODULE; + /* ngpio is set by bgpio_init() */ + + ret = devm_gpiochip_add_data(dev, &g->gc, g); + if (ret) + return ret; + + /* Disable, unmask and clear all interrupts */ + writel(0x0, g->base + GPIO_INT_EN); + writel(0x0, g->base + GPIO_INT_MASK); + writel(~0x0, g->base + GPIO_INT_CLR); + + ret = gpiochip_irqchip_add(&g->gc, &gemini_gpio_irqchip, + 0, handle_bad_irq, + IRQ_TYPE_NONE); + if (ret) { + dev_info(dev, "could not add irqchip\n"); + return ret; + } + gpiochip_set_chained_irqchip(&g->gc, &gemini_gpio_irqchip, + irq, gemini_gpio_irq_handler); + + dev_info(dev, "Gemini GPIO @%p registered\n", g->base); + + return 0; +} + +static const struct of_device_id gemini_gpio_of_match[] = { + { + .compatible = "cortina,gemini-gpio", + }, + {}, +}; + +static struct platform_driver gemini_gpio_driver = { + .driver = { + .name = "gemini-gpio", + .of_match_table = of_match_ptr(gemini_gpio_of_match), + }, + .probe = gemini_gpio_probe, +}; +builtin_platform_driver(gemini_gpio_driver); diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index a1e44c221f66..b76ecee82c3f 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -321,7 +321,7 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv) } } -static int intel_gpio_runtime_idle(struct device *dev) +static int __maybe_unused intel_gpio_runtime_idle(struct device *dev) { int err = pm_schedule_suspend(dev, 500); return err ?: -EBUSY; diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index 54e5d8257d34..b1cf76dd84ba 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin <blogic@openwrt.org> + * Copyright (C) 2012 John Crispin <john@phrozen.org> */ #include <linux/init.h> diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 1ef85b0c2b1f..82a9efd021db 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -43,7 +43,7 @@ static int gpio_mockup_ranges[MAX_GC << 1]; static int gpio_mockup_params_nr; module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400); -const char pins_name_start = 'A'; +static const char pins_name_start = 'A'; static int mockup_gpio_get(struct gpio_chip *gc, unsigned int offset) { @@ -120,13 +120,10 @@ err: static int mockup_gpio_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; struct mockup_gpio_controller *cntr; - int ret; - int i; - int base; - int ngpio; - char chip_name[sizeof(GPIO_NAME) + 3]; + struct device *dev = &pdev->dev; + int ret, i, base, ngpio; + char *chip_name; if (gpio_mockup_params_nr < 2) return -EINVAL; @@ -146,8 +143,12 @@ static int mockup_gpio_probe(struct platform_device *pdev) ngpio = gpio_mockup_ranges[i * 2 + 1] - base; if (ngpio >= 0) { - sprintf(chip_name, "%s-%c", GPIO_NAME, - pins_name_start + i); + chip_name = devm_kasprintf(dev, GFP_KERNEL, + "%s-%c", GPIO_NAME, + pins_name_start + i); + if (!chip_name) + return -ENOMEM; + ret = mockup_gpio_add(dev, &cntr[i], chip_name, base, ngpio); } else { @@ -170,8 +171,8 @@ static int mockup_gpio_probe(struct platform_device *pdev) static struct platform_driver mockup_gpio_driver = { .driver = { - .name = GPIO_NAME, - }, + .name = GPIO_NAME, + }, .probe = mockup_gpio_probe, }; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 1ed6132b993c..a649556ac3ca 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -659,7 +659,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) match = of_match_device(mvebu_gpio_of_match, &pdev->dev); if (match) - soc_variant = (int) match->data; + soc_variant = (unsigned long) match->data; else soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d5d72d84b719..d44232aadb6c 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/platform_data/pca953x.h> @@ -754,8 +755,16 @@ static int pca953x_probe(struct i2c_client *client, invert = pdata->invert; chip->names = pdata->names; } else { + struct gpio_desc *reset_gpio; + chip->gpio_start = -1; irq_base = 0; + + /* See if we need to de-assert a reset pin */ + reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); } chip->client = client; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 2be48f5eba36..31ad288846af 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -242,11 +242,24 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset) { - return pinctrl_request_gpio(chip->base + offset); + struct gpio_rcar_priv *p = gpiochip_get_data(chip); + int error; + + error = pm_runtime_get_sync(&p->pdev->dev); + if (error < 0) + return error; + + error = pinctrl_request_gpio(chip->base + offset); + if (error) + pm_runtime_put(&p->pdev->dev); + + return error; } static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset) { + struct gpio_rcar_priv *p = gpiochip_get_data(chip); + pinctrl_free_gpio(chip->base + offset); /* @@ -254,6 +267,8 @@ static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset) * drive the GPIO pin as an output. */ gpio_rcar_config_general_input_output_mode(chip, offset, false); + + pm_runtime_put(&p->pdev->dev); } static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset) @@ -426,7 +441,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) } pm_runtime_enable(dev); - pm_runtime_get_sync(dev); io = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -460,6 +474,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip = &p->irq_chip; irq_chip->name = name; + irq_chip->parent_device = dev; irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; @@ -494,7 +509,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) err1: gpiochip_remove(gpio_chip); err0: - pm_runtime_put(dev); pm_runtime_disable(dev); return ret; } @@ -505,7 +519,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) gpiochip_remove(&p->gpio_chip); - pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; } diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 19e654f88b3a..c07385b71403 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin <blogic@openwrt.org> + * Copyright (C) 2012 John Crispin <john@phrozen.org> * */ diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index a3faefa44f68..9b37a3692b3f 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -416,9 +416,8 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; /* - * ActiveLow is only specified for GpioInt resource. If - * GpioIo is used then the only way to set the flag is - * to use _DSD "gpios" property. + * Polarity and triggering are only specified for GpioInt + * resource. * Note: we expect here: * - ACPI_ACTIVE_LOW == GPIO_ACTIVE_LOW * - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 92b185f19232..975b9f6cf408 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -160,6 +160,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API * @np: device node to get GPIO from * @chip: GPIO chip whose hog is parsed + * @idx: Index of the GPIO to parse * @name: GPIO line name * @lflags: gpio_lookup_flags - returned from of_find_gpio() or * of_parse_own_gpio() @@ -170,7 +171,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, */ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, struct gpio_chip *chip, - const char **name, + unsigned int idx, const char **name, enum gpio_lookup_flags *lflags, enum gpiod_flags *dflags) { @@ -178,6 +179,7 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, enum of_gpio_flags xlate_flags; struct of_phandle_args gpiospec; struct gpio_desc *desc; + unsigned int i; u32 tmp; int ret; @@ -196,9 +198,12 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, gpiospec.np = chip_np; gpiospec.args_count = tmp; - ret = of_property_read_u32_array(np, "gpios", gpiospec.args, tmp); - if (ret) - return ERR_PTR(ret); + for (i = 0; i < tmp; i++) { + ret = of_property_read_u32_index(np, "gpios", idx * tmp + i, + &gpiospec.args[i]); + if (ret) + return ERR_PTR(ret); + } desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags); if (IS_ERR(desc)) @@ -240,20 +245,24 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) const char *name; enum gpio_lookup_flags lflags; enum gpiod_flags dflags; + unsigned int i; int ret; for_each_available_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; - desc = of_parse_own_gpio(np, chip, &name, &lflags, &dflags); - if (IS_ERR(desc)) - continue; + for (i = 0;; i++) { + desc = of_parse_own_gpio(np, chip, i, &name, &lflags, + &dflags); + if (IS_ERR(desc)) + break; - ret = gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) { - of_node_put(np); - return ret; + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret < 0) { + of_node_put(np); + return ret; + } } } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20c6c51cbe10..14ee088c80dd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1,3 +1,4 @@ +#include <linux/bitops.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> @@ -982,7 +983,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) struct gpio_device, chrdev); /* Fail on open if the backing gpiochip is gone */ - if (!gdev || !gdev->chip) + if (!gdev->chip) return -ENODEV; get_device(&gdev->dev); filp->private_data = gdev; @@ -1001,8 +1002,6 @@ static int gpio_chrdev_release(struct inode *inode, struct file *filp) struct gpio_device *gdev = container_of(inode->i_cdev, struct gpio_device, chrdev); - if (!gdev) - return -ENODEV; put_device(&gdev->dev); return 0; } @@ -2570,18 +2569,11 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip, if (chip->set_multiple) { chip->set_multiple(chip, mask, bits); } else { - int i; - for (i = 0; i < chip->ngpio; i++) { - if (mask[BIT_WORD(i)] == 0) { - /* no more set bits in this mask word; - * skip ahead to the next word */ - i = (BIT_WORD(i) + 1) * BITS_PER_LONG - 1; - continue; - } - /* set outputs if the corresponding mask bit is set */ - if (__test_and_clear_bit(i, mask)) - chip->set(chip, i, test_bit(i, bits)); - } + unsigned int i; + + /* set outputs if the corresponding mask bit is set */ + for_each_set_bit(i, mask, chip->ngpio) + chip->set(chip, i, test_bit(i, bits)); } } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index d10eaf520860..2495b7ee1b42 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -76,7 +76,8 @@ struct gpio_device { /** * struct acpi_gpio_info - ACPI GPIO specific information * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo - * @active_low: in case of @gpioint, the pin is active low + * @polarity: interrupt polarity as provided by ACPI + * @triggering: triggering type as provided by ACPI */ struct acpi_gpio_info { bool gpioint; |
