From 86d3f367686852cde028cf6c12cb0e944f28a784 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 Mar 2016 20:39:57 +0800 Subject: gpio: menz127: Drop *mdev field from struct men_z127_gpio No need to store *medv in struct men_z127_gpio. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index a68e199..8c1ab8e 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -35,7 +35,6 @@ struct men_z127_gpio { struct gpio_chip gc; void __iomem *reg_base; - struct mcb_device *mdev; struct resource *mem; spinlock_t lock; }; @@ -44,7 +43,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, unsigned debounce) { struct men_z127_gpio *priv = gpiochip_get_data(gc); - struct device *dev = &priv->mdev->dev; + struct device *dev = gc->parent; unsigned int rnd; u32 db_en, db_cnt; @@ -136,7 +135,6 @@ static int men_z127_probe(struct mcb_device *mdev, goto err_release; } - men_z127_gpio->mdev = mdev; mcb_set_drvdata(mdev, men_z127_gpio); ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4, -- cgit v0.10.2 From f85834229b1808781b0b56a9d637e19312916300 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 Mar 2016 20:48:15 +0800 Subject: gpio: mb86s7x: Remove redundant platform_set_drvdata() call Set it once is enough, so remove the second platform_set_drvdata() call. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 7fffc1d..d23a942 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -185,8 +185,6 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) gchip->gc.parent = &pdev->dev; gchip->gc.base = -1; - platform_set_drvdata(pdev, gchip); - ret = gpiochip_add_data(&gchip->gc, gchip); if (ret) { dev_err(&pdev->dev, "couldn't register gpio driver\n"); -- cgit v0.10.2 From dbb763b8ea5d8eb0ce3e45e289969f6f1f418921 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:21:44 +0100 Subject: gpio: rcar: Implement gpiochip.set_multiple() This allows to set multiple outputs using a single register write. Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d9ab0cd..3fe8e77 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -336,6 +336,25 @@ static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&p->lock, flags); } +static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct gpio_rcar_priv *p = gpiochip_get_data(chip); + unsigned long flags; + u32 val, bankmask; + + bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); + if (!bankmask) + return; + + spin_lock_irqsave(&p->lock, flags); + val = gpio_rcar_read(p, OUTDT); + val &= ~bankmask; + val |= (bankmask & bits[0]); + gpio_rcar_write(p, OUTDT, val); + spin_unlock_irqrestore(&p->lock, flags); +} + static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -476,6 +495,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) gpio_chip->get = gpio_rcar_get; gpio_chip->direction_output = gpio_rcar_direction_output; gpio_chip->set = gpio_rcar_set; + gpio_chip->set_multiple = gpio_rcar_set_multiple; gpio_chip->label = name; gpio_chip->parent = dev; gpio_chip->owner = THIS_MODULE; -- cgit v0.10.2 From d46ab6823963de2165f5a2af7600ce830e990e53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:19:18 +0100 Subject: gpio: 74x164: Implement gpiochip.set_multiple() This allows to set multiple outputs using a single SPI transfer. Signed-off-by: Geert Uytterhoeven Reviewed-by: Phil Reid Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index c81224f..62291a8 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -75,6 +75,29 @@ static void gen_74x164_set_value(struct gpio_chip *gc, mutex_unlock(&chip->lock); } +static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + struct gen_74x164_chip *chip = gpiochip_get_data(gc); + unsigned int i, idx, shift; + u8 bank, bankmask; + + mutex_lock(&chip->lock); + for (i = 0, bank = chip->registers - 1; i < chip->registers; + i++, bank--) { + idx = i / sizeof(*mask); + shift = i % sizeof(*mask) * BITS_PER_BYTE; + bankmask = mask[idx] >> shift; + if (!bankmask) + continue; + + chip->buffer[bank] &= ~bankmask; + chip->buffer[bank] |= bankmask & (bits[idx] >> shift); + } + __gen_74x164_write_config(chip); + mutex_unlock(&chip->lock); +} + static int gen_74x164_direction_output(struct gpio_chip *gc, unsigned offset, int val) { @@ -114,6 +137,7 @@ static int gen_74x164_probe(struct spi_device *spi) chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; + chip->gpio_chip.set_multiple = gen_74x164_set_multiple; chip->gpio_chip.base = -1; chip->registers = nregs; -- cgit v0.10.2 From dad3d272957b006b9069486597610840f7063350 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Fri, 18 Mar 2016 16:07:06 +0800 Subject: gpio: mcp23s08: switch to use gpiolib irqchip helpers This switches the mcp23s08 driver to use the gpiolib irqchip helpers. Signed-off-by: Phil Reid Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5f3429f..927be87 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1091,6 +1091,7 @@ menu "SPI or I2C GPIO expanders" config GPIO_MCP23S08 tristate "Microchip MCP23xxx I/O expander" + select GPIOLIB_IRQCHIP help SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 I/O expanders. diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 47e4869..ae61bc2 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,6 @@ struct mcp23s08 { /* lock protects the cached values */ struct mutex lock; struct mutex irq_lock; - struct irq_domain *irq_domain; struct gpio_chip chip; @@ -96,11 +95,6 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - /*----------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_I2C) @@ -369,7 +363,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) if ((BIT(i) & mcp->cache[MCP_INTF]) && ((BIT(i) & intcap & mcp->irq_rise) || (mcp->irq_fall & ~intcap & BIT(i)))) { - child_irq = irq_find_mapping(mcp->irq_domain, i); + child_irq = irq_find_mapping(mcp->chip.irqdomain, i); handle_nested_irq(child_irq); } } @@ -377,16 +371,10 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) return IRQ_HANDLED; } -static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct mcp23s08 *mcp = gpiochip_get_data(chip); - - return irq_find_mapping(mcp->irq_domain, offset); -} - static void mcp23s08_irq_mask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] &= ~BIT(pos); @@ -394,7 +382,8 @@ static void mcp23s08_irq_mask(struct irq_data *data) static void mcp23s08_irq_unmask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] |= BIT(pos); @@ -402,7 +391,8 @@ static void mcp23s08_irq_unmask(struct irq_data *data) static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; int status = 0; @@ -426,14 +416,16 @@ static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) static void mcp23s08_irq_bus_lock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->irq_lock); } static void mcp23s08_irq_bus_unlock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->lock); mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); @@ -445,7 +437,8 @@ static void mcp23s08_irq_bus_unlock(struct irq_data *data) static int mcp23s08_irq_reqres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) { dev_err(mcp->chip.parent, @@ -459,7 +452,8 @@ static int mcp23s08_irq_reqres(struct irq_data *data) static void mcp23s08_irq_relres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); gpiochip_unlock_as_irq(&mcp->chip, data->hwirq); } @@ -478,17 +472,11 @@ static struct irq_chip mcp23s08_irq_chip = { static int mcp23s08_irq_setup(struct mcp23s08 *mcp) { struct gpio_chip *chip = &mcp->chip; - int err, irq, j; + int err; unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED; mutex_init(&mcp->irq_lock); - mcp->irq_domain = irq_domain_add_linear(chip->parent->of_node, - chip->ngpio, - &irq_domain_simple_ops, mcp); - if (!mcp->irq_domain) - return -ENODEV; - if (mcp->irq_active_high) irqflags |= IRQF_TRIGGER_HIGH; else @@ -503,30 +491,23 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) return err; } - chip->to_irq = mcp23s08_gpio_to_irq; - - for (j = 0; j < mcp->chip.ngpio; j++) { - irq = irq_create_mapping(mcp->irq_domain, j); - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_data(irq, mcp); - irq_set_chip(irq, &mcp23s08_irq_chip); - irq_set_nested_thread(irq, true); - irq_set_noprobe(irq); + err = gpiochip_irqchip_add(chip, + &mcp23s08_irq_chip, + 0, + handle_simple_irq, + IRQ_TYPE_NONE); + if (err) { + dev_err(chip->parent, + "could not connect irqchip to gpiochip: %d\n", err); + return err; } - return 0; -} -static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) -{ - unsigned int irq, i; + gpiochip_set_chained_irqchip(chip, + &mcp23s08_irq_chip, + mcp->irq, + NULL); - for (i = 0; i < mcp->chip.ngpio; i++) { - irq = irq_find_mapping(mcp->irq_domain, i); - if (irq > 0) - irq_dispose_mapping(irq); - } - - irq_domain_remove(mcp->irq_domain); + return 0; } /*----------------------------------------------------------------------*/ @@ -721,7 +702,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, if (mcp->irq && mcp->irq_controller) { status = mcp23s08_irq_setup(mcp); if (status) { - mcp23s08_irq_teardown(mcp); goto fail; } } @@ -847,9 +827,6 @@ static int mcp230xx_remove(struct i2c_client *client) { struct mcp23s08 *mcp = i2c_get_clientdata(client); - if (client->irq && mcp->irq_controller) - mcp23s08_irq_teardown(mcp); - gpiochip_remove(&mcp->chip); kfree(mcp); @@ -1017,8 +994,6 @@ static int mcp23s08_remove(struct spi_device *spi) if (!data->mcp[addr]) continue; - if (spi->irq && data->mcp[addr]->irq_controller) - mcp23s08_irq_teardown(data->mcp[addr]); gpiochip_remove(&data->mcp[addr]->chip); } -- cgit v0.10.2 From f7aed67d632f6e316b9a9e2fe2818a07bfa42e81 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 22 Mar 2016 14:28:34 +0100 Subject: gpio: mcp23s08: delete req/rel_resource callbacks When using the GPIOLIB_IRQCHIP the gpiolib provides a straight-forward implementation of request/release resources, rely on that instead. Cc: Phil Reid Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ae61bc2..c882c2b 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -435,29 +435,6 @@ static void mcp23s08_irq_bus_unlock(struct irq_data *data) mutex_unlock(&mcp->irq_lock); } -static int mcp23s08_irq_reqres(struct irq_data *data) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); - struct mcp23s08 *mcp = gpiochip_get_data(gc); - - if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) { - dev_err(mcp->chip.parent, - "unable to lock HW IRQ %lu for IRQ usage\n", - data->hwirq); - return -EINVAL; - } - - return 0; -} - -static void mcp23s08_irq_relres(struct irq_data *data) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); - struct mcp23s08 *mcp = gpiochip_get_data(gc); - - gpiochip_unlock_as_irq(&mcp->chip, data->hwirq); -} - static struct irq_chip mcp23s08_irq_chip = { .name = "gpio-mcp23xxx", .irq_mask = mcp23s08_irq_mask, @@ -465,8 +442,6 @@ static struct irq_chip mcp23s08_irq_chip = { .irq_set_type = mcp23s08_irq_set_type, .irq_bus_lock = mcp23s08_irq_bus_lock, .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, - .irq_request_resources = mcp23s08_irq_reqres, - .irq_release_resources = mcp23s08_irq_relres, }; static int mcp23s08_irq_setup(struct mcp23s08 *mcp) -- cgit v0.10.2 From 574b782e7b632974e85e8629842746d0229c4aed Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Feb 2016 22:00:01 +0800 Subject: gpio: amdpt: Convert to use gpio-generic Use gpio-generic to simplify this driver. Signed-off-by: Axel Lin Tested-by: YD Tseng Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 927be87..6d6015f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -122,6 +122,7 @@ config GPIO_ALTERA config GPIO_AMDPT tristate "AMD Promontory GPIO support" depends on ACPI + select GPIO_GENERIC help driver for GPIO functionality on Promontory IOHub Require ACPI ASL code to enumerate as a platform device. diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index c248404..569b424 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -28,7 +28,6 @@ struct pt_gpio_chip { struct gpio_chip gc; void __iomem *reg_base; - spinlock_t lock; }; static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) @@ -39,19 +38,19 @@ static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset); - spin_lock_irqsave(&pt_gpio->lock, flags); + spin_lock_irqsave(&gc->bgpio_lock, flags); using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); if (using_pins & BIT(offset)) { dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n", offset); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); return -EINVAL; } writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); return 0; } @@ -62,111 +61,17 @@ static void pt_gpio_free(struct gpio_chip *gc, unsigned offset) unsigned long flags; u32 using_pins; - spin_lock_irqsave(&pt_gpio->lock, flags); + spin_lock_irqsave(&gc->bgpio_lock, flags); using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); using_pins &= ~BIT(offset); writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset); } -static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_set_value offset=%x, value=%x\n", - offset, value); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - data &= ~BIT(offset); - if (value) - data |= BIT(offset); - writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); -} - -static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - - /* configure as output */ - if (data & BIT(offset)) - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - else /* configure as input */ - data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - data >>= offset; - data &= 1; - - dev_dbg(gc->parent, "pt_gpio_get_value offset=%x, value=%x\n", - offset, data); - - return data; -} - -static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_dirction_input offset=%x\n", offset); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - data &= ~BIT(offset); - writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - return 0; -} - -static int pt_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, int value) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_direction_output offset=%x, value=%x\n", - offset, value); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - if (value) - data |= BIT(offset); - else - data &= ~BIT(offset); - writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - data |= BIT(offset); - writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - return 0; -} - static int pt_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -196,18 +101,19 @@ static int pt_gpio_probe(struct platform_device *pdev) return PTR_ERR(pt_gpio->reg_base); } - spin_lock_init(&pt_gpio->lock); + ret = bgpio_init(&pt_gpio->gc, dev, 4, + pt_gpio->reg_base + PT_INPUTDATA_REG, + pt_gpio->reg_base + PT_OUTPUTDATA_REG, NULL, + pt_gpio->reg_base + PT_DIRECTION_REG, NULL, + BGPIOF_READ_OUTPUT_REG_SET); + if (ret) { + dev_err(&pdev->dev, "bgpio_init failed\n"); + return ret; + } - pt_gpio->gc.label = pdev->name; pt_gpio->gc.owner = THIS_MODULE; - pt_gpio->gc.parent = dev; pt_gpio->gc.request = pt_gpio_request; pt_gpio->gc.free = pt_gpio_free; - pt_gpio->gc.direction_input = pt_gpio_direction_input; - pt_gpio->gc.direction_output = pt_gpio_direction_output; - pt_gpio->gc.get = pt_gpio_get_value; - pt_gpio->gc.set = pt_gpio_set_value; - pt_gpio->gc.base = -1; pt_gpio->gc.ngpio = PT_TOTAL_GPIO; #if defined(CONFIG_OF_GPIO) pt_gpio->gc.of_node = pdev->dev.of_node; -- cgit v0.10.2 From 592569de4c247fe4f25db8369dc0c63860f9560b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 18 Mar 2016 21:05:16 +0800 Subject: gpio: octeon: Convert to use devm_ioremap_resource Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 47aead1..9373d4e 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -83,6 +83,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) struct octeon_gpio *gpio; struct gpio_chip *chip; struct resource *res_mem; + void __iomem *reg_base; int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,21 +92,11 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip = &gpio->chip; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem == NULL) { - dev_err(&pdev->dev, "found no memory resource\n"); - err = -ENXIO; - goto out; - } - if (!devm_request_mem_region(&pdev->dev, res_mem->start, - resource_size(res_mem), - res_mem->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - err = -ENXIO; - goto out; - } - gpio->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start, - resource_size(res_mem)); + reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + gpio->register_base = (u64)reg_base; pdev->dev.platform_data = chip; chip->label = "octeon-gpio"; chip->parent = &pdev->dev; @@ -119,11 +110,10 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip->set = octeon_gpio_set; err = devm_gpiochip_add_data(&pdev->dev, chip, gpio); if (err) - goto out; + return err; dev_info(&pdev->dev, "OCTEON GPIO driver probed.\n"); -out: - return err; + return 0; } static struct of_device_id octeon_gpio_match[] = { -- cgit v0.10.2 From b6d055b198b70c430a0b7e78280e8ef35e44f319 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 18 Mar 2016 21:06:06 +0800 Subject: gpio: octeon: Constify octeon_gpio_match table Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 9373d4e..96a8a8c 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -116,7 +116,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) return 0; } -static struct of_device_id octeon_gpio_match[] = { +static const struct of_device_id octeon_gpio_match[] = { { .compatible = "cavium,octeon-3860-gpio", }, -- cgit v0.10.2 From ca27379f5d2956e08558fbfc0d35b3ba64abbe0c Mon Sep 17 00:00:00 2001 From: YD Tseng Date: Thu, 17 Mar 2016 11:35:57 +0800 Subject: gpio: amdpt: Add a new ACPI HID This patch adds a new ACPI HID, AMDIF030, in the pt_gpio_acpi_match. Signed-off-by: YD Tseng Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 569b424..9b78dc8 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -145,6 +145,7 @@ static int pt_gpio_remove(struct platform_device *pdev) static const struct acpi_device_id pt_gpio_acpi_match[] = { { "AMDF030", 0 }, + { "AMDIF030", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match); -- cgit v0.10.2 From e99190cea39022690193938ff3e80d2faa98f389 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 14:49:42 +0100 Subject: powerpc: mpc52xx_gpt: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 3048e34..22645a7 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -278,14 +278,9 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) * GPIOLIB hooks */ #if defined(CONFIG_GPIOLIB) -static inline struct mpc52xx_gpt_priv *gc_to_mpc52xx_gpt(struct gpio_chip *gc) -{ - return container_of(gc, struct mpc52xx_gpt_priv, gc); -} - static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); return (in_be32(&gpt->regs->status) >> 8) & 1; } @@ -293,7 +288,7 @@ static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); unsigned long flags; u32 r; @@ -307,7 +302,7 @@ mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v) static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); unsigned long flags; dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio); @@ -354,9 +349,9 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, MPC52xx_GPT_MODE_MS_GPIO); - rc = gpiochip_add(&gpt->gc); + rc = gpiochip_add_data(&gpt->gc, gpt); if (rc) - dev_err(gpt->dev, "gpiochip_add() failed; rc=%i\n", rc); + dev_err(gpt->dev, "gpiochip_add_data() failed; rc=%i\n", rc); dev_dbg(gpt->dev, "%s() complete.\n", __func__); } -- cgit v0.10.2 From da5f767ef66a4c71109fdb8577b36864abc3263c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 14:54:45 +0100 Subject: powerpc: mpc8349emitx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 15e8021..dbcd030 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -99,7 +99,7 @@ static void mcu_power_off(void) static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct mcu *mcu = container_of(gc, struct mcu, gc); + struct mcu *mcu = gpiochip_get_data(gc); u8 bit = 1 << (4 + gpio); mutex_lock(&mcu->lock); @@ -136,7 +136,7 @@ static int mcu_gpiochip_add(struct mcu *mcu) gc->direction_output = mcu_gpio_dir_out; gc->of_node = np; - return gpiochip_add(gc); + return gpiochip_add_data(gc, mcu); } static int mcu_gpiochip_remove(struct mcu *mcu) -- cgit v0.10.2 From e65078f1f3490c753f8c223b088e8a482968b891 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:00:49 +0100 Subject: powerpc: sysdev: cpm1: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 8ed6536..6c11099 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -532,15 +532,9 @@ struct cpm1_gpio16_chip { u16 cpdata; }; -static inline struct cpm1_gpio16_chip * -to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc); -} - static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; cpm1_gc->cpdata = in_be16(&iop->dat); @@ -560,7 +554,7 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, int value) { - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; if (value) @@ -574,7 +568,7 @@ static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -588,7 +582,7 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -606,7 +600,7 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -642,7 +636,7 @@ int cpm1_gpiochip_add16(struct device_node *np) gc->get = cpm1_gpio16_get; gc->set = cpm1_gpio16_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc); } struct cpm1_gpio32_chip { @@ -653,15 +647,9 @@ struct cpm1_gpio32_chip { u32 cpdata; }; -static inline struct cpm1_gpio32_chip * -to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc); -} - static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; cpm1_gc->cpdata = in_be32(&iop->dat); @@ -681,7 +669,7 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, int value) { - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; if (value) @@ -695,7 +683,7 @@ static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -709,7 +697,7 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -727,7 +715,7 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -763,7 +751,7 @@ int cpm1_gpiochip_add32(struct device_node *np) gc->get = cpm1_gpio32_get; gc->set = cpm1_gpio32_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc); } static int cpm_init_par_io(void) -- cgit v0.10.2 From a14a2d484b386972f9027246dbe5d066519edb9f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:05:43 +0100 Subject: powerpc: cpm_common: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 9d32465..0ac12e5 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -80,15 +80,9 @@ struct cpm2_gpio32_chip { u32 cpdata; }; -static inline struct cpm2_gpio32_chip * -to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc); -} - static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; cpm2_gc->cpdata = in_be32(&iop->dat); @@ -108,7 +102,7 @@ static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, int value) { - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; if (value) @@ -122,7 +116,7 @@ static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -136,7 +130,7 @@ static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -154,7 +148,7 @@ static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -190,6 +184,6 @@ int cpm2_gpiochip_add32(struct device_node *np) gc->get = cpm2_gpio32_get; gc->set = cpm2_gpio32_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm2_gc); } #endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */ -- cgit v0.10.2 From 0d36fe65f58391712e11a6621075f373216e5f00 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:34:12 +0100 Subject: powerpc: ppc4xx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c index d7a7ef13..4ab83cd 100644 --- a/arch/powerpc/sysdev/ppc4xx_gpio.c +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -67,12 +67,6 @@ struct ppc4xx_gpio_chip { * There are a maximum of 32 gpios in each gpio controller. */ -static inline struct ppc4xx_gpio_chip * -to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc); -} - static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); @@ -97,7 +91,7 @@ static void ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&chip->lock, flags); @@ -112,7 +106,7 @@ ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); struct ppc4xx_gpio __iomem *regs = mm_gc->regs; unsigned long flags; @@ -142,7 +136,7 @@ static int ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); struct ppc4xx_gpio __iomem *regs = mm_gc->regs; unsigned long flags; @@ -200,7 +194,7 @@ static int __init ppc4xx_add_gpiochips(void) gc->get = ppc4xx_gpio_get; gc->set = ppc4xx_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc); if (ret) goto err; continue; -- cgit v0.10.2 From 1e714e54b5ca5bfc75bc43ed41f8217242e831fe Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:49:10 +0100 Subject: powerpc: qe_lib-gpio: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 6584571..333eb22 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -18,6 +18,8 @@ #include #include #include +#include +/* FIXME: needed for gpio_to_chip() get rid of this */ #include #include #include @@ -37,15 +39,9 @@ struct qe_gpio_chip { struct qe_pio_regs saved_regs; }; -static inline struct qe_gpio_chip * -to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct qe_gpio_chip, mm_gc); -} - static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(&mm_gc->gc); struct qe_pio_regs __iomem *regs = mm_gc->regs; qe_gc->cpdata = in_be32(®s->cpdata); @@ -69,7 +65,7 @@ static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); struct qe_pio_regs __iomem *regs = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); @@ -89,7 +85,7 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); @@ -104,7 +100,7 @@ static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; qe_gpio_set(gc, gpio, val); @@ -165,7 +161,7 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) } mm_gc = to_of_mm_gpio_chip(gc); - qe_gc = to_qe_gpio_chip(mm_gc); + qe_gc = gpiochip_get_data(gc); spin_lock_irqsave(&qe_gc->lock, flags); @@ -302,7 +298,7 @@ static int __init qe_add_gpiochips(void) gc->get = qe_gpio_get; gc->set = qe_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc); if (ret) goto err; continue; -- cgit v0.10.2 From 937daafca774b05633f436c19885c8cb3cbdcc8a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:53:29 +0100 Subject: powerpc: simple-gpio: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anton Vorontsov Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c index 56ce8ca..ef470b4 100644 --- a/arch/powerpc/sysdev/simple_gpio.c +++ b/arch/powerpc/sysdev/simple_gpio.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include "simple_gpio.h" @@ -32,11 +32,6 @@ struct u8_gpio_chip { u8 data; }; -static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct u8_gpio_chip, mm_gc); -} - static u8 u8_pin2mask(unsigned int pin) { return 1 << (8 - 1 - pin); @@ -52,7 +47,7 @@ static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); + struct u8_gpio_chip *u8_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&u8_gc->lock, flags); @@ -80,7 +75,7 @@ static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); + struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc); u8_gc->data = in_8(mm_gc->regs); } @@ -108,7 +103,7 @@ static int __init u8_simple_gpiochip_add(struct device_node *np) gc->get = u8_gpio_get; gc->set = u8_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, u8_gc); if (ret) goto err; return 0; -- cgit v0.10.2 From a8cb826aeab84553a30af22ca6d6b95a6513adb2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:58:33 +0100 Subject: sh: sdk7786-gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Linus Walleij diff --git a/arch/sh/boards/mach-sdk7786/gpio.c b/arch/sh/boards/mach-sdk7786/gpio.c index f71ce09..4799701 100644 --- a/arch/sh/boards/mach-sdk7786/gpio.c +++ b/arch/sh/boards/mach-sdk7786/gpio.c @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include #include #include @@ -44,6 +44,6 @@ static struct gpio_chip usrgpir_gpio_chip = { static int __init usrgpir_gpio_setup(void) { - return gpiochip_add(&usrgpir_gpio_chip); + return gpiochip_add_data(&usrgpir_gpio_chip, NULL); } device_initcall(usrgpir_gpio_setup); -- cgit v0.10.2 From efed58f1c574a31c03447afffe69440e83fdf84d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:02:00 +0100 Subject: sh: x3proto-gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Linus Walleij diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c index 1fb2cbe..cea88b0 100644 --- a/arch/sh/boards/mach-x3proto/gpio.c +++ b/arch/sh/boards/mach-x3proto/gpio.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include @@ -107,7 +107,7 @@ int __init x3proto_gpio_setup(void) if (unlikely(ilsel < 0)) return ilsel; - ret = gpiochip_add(&x3proto_gpio_chip); + ret = gpiochip_add_data(&x3proto_gpio_chip, NULL); if (unlikely(ret)) goto err_gpio; -- cgit v0.10.2 From fd19f534ab7660883191d5f3c9d01f0c6f444aea Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:07:09 +0100 Subject: unicore32: gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Acked-by: Guan Xuetao Signed-off-by: Linus Walleij diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c index 5ab2379..49347a0 100644 --- a/arch/unicore32/kernel/gpio.c +++ b/arch/unicore32/kernel/gpio.c @@ -14,6 +14,8 @@ #include #include +#include +/* FIXME: needed for gpio_set_value() - convert to use descriptors or hogs */ #include #include @@ -118,5 +120,5 @@ void __init puv3_init_gpio(void) * gpio_set_value(GPO_SET_V2, 1); */ #endif - gpiochip_add(&puv3_gpio_chip); + gpiochip_add_data(&puv3_gpio_chip, NULL); } -- cgit v0.10.2 From 839850f4fb76b56fcad3cabe27fc9f1a03821a2c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:32:08 +0100 Subject: input: adp5589-keys: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index c01a1d6..32d94c6 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -387,7 +387,7 @@ static int adp5589_write(struct i2c_client *client, u8 reg, u8 val) #ifdef CONFIG_GPIOLIB static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); @@ -399,7 +399,7 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) static void adp5589_gpio_set_value(struct gpio_chip *chip, unsigned off, int val) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); @@ -418,7 +418,7 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); int ret; @@ -438,7 +438,7 @@ static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) static int adp5589_gpio_direction_output(struct gpio_chip *chip, unsigned off, int val) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); int ret; @@ -525,9 +525,9 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad) mutex_init(&kpad->gpio_lock); - error = gpiochip_add(&kpad->gc); + error = gpiochip_add_data(&kpad->gc, kpad); if (error) { - dev_err(dev, "gpiochip_add failed, err: %d\n", error); + dev_err(dev, "gpiochip_add_data() failed, err: %d\n", error); return error; } -- cgit v0.10.2 From d94780444bf3da8fc35e281aec6bbffa54a4a01a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:35:27 +0100 Subject: input: ad7879: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 69d299d..e4bf110 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -379,7 +379,7 @@ static const struct attribute_group ad7879_attr_group = { static int ad7879_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); int err; mutex_lock(&ts->mutex); @@ -393,7 +393,7 @@ static int ad7879_gpio_direction_input(struct gpio_chip *chip, static int ad7879_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); int err; mutex_lock(&ts->mutex); @@ -412,7 +412,7 @@ static int ad7879_gpio_direction_output(struct gpio_chip *chip, static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); u16 val; mutex_lock(&ts->mutex); @@ -425,7 +425,7 @@ static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio) static void ad7879_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); mutex_lock(&ts->mutex); if (value) @@ -456,7 +456,7 @@ static int ad7879_gpio_add(struct ad7879 *ts, ts->gc.owner = THIS_MODULE; ts->gc.parent = ts->dev; - ret = gpiochip_add(&ts->gc); + ret = gpiochip_add_data(&ts->gc, ts); if (ret) dev_err(ts->dev, "failed to register gpio %d\n", ts->gc.base); -- cgit v0.10.2 From ab503238ff6974b9a51d328c2a55c505064c64f7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 31 Mar 2016 09:09:12 +0200 Subject: powerpc: ppc4xx: drop unused variable commit 0d36fe65f58391712e11a6621075f373216e5f00 "powerpc: ppc4xx: use gpiochip data pointer" made the mm_gc local variable in ppc4xx_gpio_set() redundant, and when GCC treats warnings as errors this happens: arch/powerpc/sysdev/ppc4xx_gpio.c: In function 'ppc4xx_gpio_set': arch/powerpc/sysdev/ppc4xx_gpio.c:93:26: error: unused variable 'mm_gc' [-Werror=unused-variable] struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); ^ cc1: all warnings being treated as errors Reported-by: kbuild test robot Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Linus Walleij diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c index 4ab83cd..5382d04 100644 --- a/arch/powerpc/sysdev/ppc4xx_gpio.c +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -90,7 +90,6 @@ __ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); unsigned long flags; -- cgit v0.10.2 From 63cc787e71ae12976b2116f09677d1f2805df83e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Mar 2016 12:00:31 +0800 Subject: irqdomain: Export irq_domain_free_irqs_common Export irq_domain_free_irqs_common so it can be used by modules. Signed-off-by: Axel Lin Acked-by: Thomas Gleixner Acked-by: Marc Zyngier Signed-off-by: Linus Walleij diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3a519a0..245a485 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1099,6 +1099,7 @@ void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, } irq_domain_free_irqs_parent(domain, virq, nr_irqs); } +EXPORT_SYMBOL_GPL(irq_domain_free_irqs_common); /** * irq_domain_free_irqs_top - Clear handler and handler data, clear irqdata and free parent -- cgit v0.10.2 From c6cc75fec020eda0df04aff21f6cd6f4bfc1eea5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Mar 2016 12:01:43 +0800 Subject: gpio: xgene-sb: Use irq_domain_free_irqs_common() Current code calls irq_domain_alloc_irqs_parent() in .alloc, so it should call irq_domain_free_irqs_parent() accordingly in .free. Fix it by switching to use irq_domain_free_irqs_common() instead. Signed-off-by: Axel Lin Acked-by: Marc Zyngier Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 31cbcb8..0332586 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -216,23 +216,10 @@ static int xgene_gpio_sb_domain_alloc(struct irq_domain *domain, &parent_fwspec); } -static void xgene_gpio_sb_domain_free(struct irq_domain *domain, - unsigned int virq, - unsigned int nr_irqs) -{ - struct irq_data *d; - unsigned int i; - - for (i = 0; i < nr_irqs; i++) { - d = irq_domain_get_irq_data(domain, virq + i); - irq_domain_reset_irq_data(d); - } -} - static const struct irq_domain_ops xgene_gpio_sb_domain_ops = { .translate = xgene_gpio_sb_domain_translate, .alloc = xgene_gpio_sb_domain_alloc, - .free = xgene_gpio_sb_domain_free, + .free = irq_domain_free_irqs_common, .activate = xgene_gpio_sb_domain_activate, .deactivate = xgene_gpio_sb_domain_deactivate, }; -- cgit v0.10.2 From 80018bd9cb590c3d7fea9b51730e4a251cb1bb42 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Mon, 14 Mar 2016 23:32:10 +0000 Subject: gpio: 74x164: add dt support for nxp's 74x594 The chip is also an 8 bit shift register which works out of the box as a GPO expander with this patch Signed-off-by: Nicolas Saenz Julienne Acked-by: Rob Herring Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt index cc26080..ce1b223 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt @@ -1,7 +1,9 @@ * Generic 8-bits shift register GPIO driver Required properties: -- compatible : Should be "fairchild,74hc595" +- compatible: Should contain one of the following: + "fairchild,74hc595" + "nxp,74lvc594" - reg : chip select number - gpio-controller : Marks the device node as a gpio controller. - #gpio-cells : Should be two. The first cell is the pin number and diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 62291a8..80f9ddf 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -177,6 +177,7 @@ static int gen_74x164_remove(struct spi_device *spi) static const struct of_device_id gen_74x164_dt_ids[] = { { .compatible = "fairchild,74hc595" }, + { .compatible = "nxp,74lvc594" }, {}, }; MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids); -- cgit v0.10.2 From 1418f9e6e02da2ad0a6aacc8645e6ad7496105e9 Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Wed, 23 Mar 2016 17:47:19 +0800 Subject: gpio: mpc8xxx: Add new platforms GPIO DT node description Update the NXP GPIO node dt-binding file for QorIQ and Layerscape platforms, and add one more example with ls2080a GPIO node. Signed-off-by: Liu Gang Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index 120bc49..4b6cc63 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -1,9 +1,10 @@ -* Freescale MPC512x/MPC8xxx/Layerscape GPIO controller +* Freescale MPC512x/MPC8xxx/QorIQ/Layerscape GPIO controller Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: - mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq. + mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, + ls1021a, ls1043a, ls2080a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -15,7 +16,7 @@ Optional properties: - little-endian : GPIO registers are used as little endian. If not present registers are used as big endian by default. -Example: +Example of gpio-controller node for a mpc5125 SoC: gpio0: gpio@1100 { compatible = "fsl,mpc5125-gpio"; @@ -24,3 +25,16 @@ gpio0: gpio@1100 { interrupts = <78 0x8>; status = "okay"; }; + +Example of gpio-controller node for a ls2080a SoC: + +gpio0: gpio@2300000 { + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = <0 36 0x4>; /* Level high type */ + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +}; -- cgit v0.10.2 From 16fe1ad289019d78a8f8fdb65f08d298ee921cb3 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 23 Mar 2016 18:01:27 +0100 Subject: gpio: mcp23s08: Add support for level triggered interrupts The interrupt for the corresponding pin is configured to trigger when the pin state changes compared to a preconfigured state (Bit set in INTCON). This state is set by setting/clearing the bit in DEFVAL. In the interrupt handler we need also to check if the bit in INTCON is set for level triggered interrupts. Signed-off-by: Alexander Stein Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index c882c2b..ac22efc 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -362,7 +362,8 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) for (i = 0; i < mcp->chip.ngpio; i++) { if ((BIT(i) & mcp->cache[MCP_INTF]) && ((BIT(i) & intcap & mcp->irq_rise) || - (mcp->irq_fall & ~intcap & BIT(i)))) { + (mcp->irq_fall & ~intcap & BIT(i)) || + (BIT(i) & mcp->cache[MCP_INTCON]))) { child_irq = irq_find_mapping(mcp->chip.irqdomain, i); handle_nested_irq(child_irq); } @@ -408,6 +409,12 @@ static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) mcp->cache[MCP_INTCON] &= ~BIT(pos); mcp->irq_rise &= ~BIT(pos); mcp->irq_fall |= BIT(pos); + } else if (type & IRQ_TYPE_LEVEL_HIGH) { + mcp->cache[MCP_INTCON] |= BIT(pos); + mcp->cache[MCP_DEFVAL] &= ~BIT(pos); + } else if (type & IRQ_TYPE_LEVEL_LOW) { + mcp->cache[MCP_INTCON] |= BIT(pos); + mcp->cache[MCP_DEFVAL] |= BIT(pos); } else return -EINVAL; -- cgit v0.10.2 From dd98756d78153dbb43685f0f0e618dda235aee00 Mon Sep 17 00:00:00 2001 From: Kamlakant Patel Date: Thu, 24 Mar 2016 15:01:40 +0530 Subject: gpio: xlp: Add GPIO driver support for Broadcom Vulcan ARM64 - Add GPIO support for Broadcom Vulcan ARM64. - Add depends on ARCH_VULCAN to Kconfig to enable gpio controller driver for Broadcom Vulcan ARM64 SoCs. Signed-off-by: Kamlakant Patel Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-xlp.txt b/Documentation/devicetree/bindings/gpio/gpio-xlp.txt index 262ee4d..28662d8 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-xlp.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-xlp.txt @@ -3,6 +3,8 @@ Netlogic XLP Family GPIO This GPIO driver is used for following Netlogic XLP SoCs: XLP832, XLP316, XLP208, XLP980, XLP532 +This GPIO driver is also compatible with GPIO controller found on +Broadcom Vulcan ARM64. Required properties: ------------------- @@ -13,6 +15,7 @@ Required properties: - "netlogic,xlp208-gpio": For Netlogic XLP208 - "netlogic,xlp980-gpio": For Netlogic XLP980 - "netlogic,xlp532-gpio": For Netlogic XLP532 + - "brcm,vulcan-gpio": For Broadcom Vulcan ARM64 - reg: Physical base address and length of the controller's registers. - #gpio-cells: Should be two. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6d6015f..7889836 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -474,7 +474,7 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on CPU_XLP && OF_GPIO + depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST) select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index aa5813d..08897dc 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -85,7 +85,8 @@ enum { XLP_GPIO_VARIANT_XLP316, XLP_GPIO_VARIANT_XLP208, XLP_GPIO_VARIANT_XLP980, - XLP_GPIO_VARIANT_XLP532 + XLP_GPIO_VARIANT_XLP532, + GPIO_VARIANT_VULCAN }; struct xlp_gpio_priv { @@ -285,6 +286,10 @@ static const struct of_device_id xlp_gpio_of_ids[] = { .compatible = "netlogic,xlp532-gpio", .data = (void *)XLP_GPIO_VARIANT_XLP532, }, + { + .compatible = "brcm,vulcan-gpio", + .data = (void *)GPIO_VARIANT_VULCAN, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); @@ -347,6 +352,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) break; case XLP_GPIO_VARIANT_XLP980: case XLP_GPIO_VARIANT_XLP532: + case GPIO_VARIANT_VULCAN: priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN; priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV; priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT; @@ -354,7 +360,12 @@ static int xlp_gpio_probe(struct platform_device *pdev) priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL; priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00; - ngpio = (soc_type == XLP_GPIO_VARIANT_XLP980) ? 66 : 67; + if (soc_type == XLP_GPIO_VARIANT_XLP980) + ngpio = 66; + else if (soc_type == XLP_GPIO_VARIANT_XLP532) + ngpio = 67; + else + ngpio = 70; break; default: dev_err(&pdev->dev, "Unknown Processor type!\n"); @@ -377,10 +388,14 @@ static int xlp_gpio_probe(struct platform_device *pdev) gc->get = xlp_gpio_get; spin_lock_init(&priv->lock); - irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); - if (irq_base < 0) { + /* XLP has fixed IRQ range for GPIO interrupts */ + if (soc_type == GPIO_VARIANT_VULCAN) + irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0); + else + irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); + if (IS_ERR_VALUE(irq_base)) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); - return -ENODEV; + return irq_base; } err = gpiochip_add_data(gc, priv); -- cgit v0.10.2 From 75c004df525e3bda38dfac1f0e8eff7fe515a0ab Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 31 Mar 2016 11:09:11 +0200 Subject: gpio: dt-bindings: document the concept of GPIO banks Cc: devicetree@vger.kernel.org Cc: Neil Armstrong Cc: Rob Herring Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 069cdf6..f509ecf 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -131,6 +131,19 @@ Every GPIO controller node must contain both an empty "gpio-controller" property, and a #gpio-cells integer property, which indicates the number of cells in a gpio-specifier. +Some system-on-chips (SoCs) use the concept of GPIO banks. A GPIO bank is an +instance of a hardware IP core on a silicon die, usually exposed to the +programmer as a coherent range of I/O addresses. Usually each such bank is +exposed in the device tree as an individual gpio-controller node, reflecting +the fact that the hardware was synthesized by reusing the same IP block a +few times over. + +A GPIO controller may specify a bank ID. This is a hardware index that +indicate the logical order of the GPIO controller in the hardware architecture, +usually in the sequence 0, 1, 2 .. n. The hardware index may be different +from the order of register ranges and related to the backplane of how this +one bank is connected to the outside through a pin controller for example. + Optionally, a GPIO controller may have a "ngpios" property. This property indicates the number of in-use slots of available slots for GPIOs. The typical example is something like this: the hardware register is 32 bits @@ -152,6 +165,7 @@ gpio-controller@00000000 { reg = <0x00000000 0x1000>; gpio-controller; #gpio-cells = <2>; + gpio-bank = <0>; ngpios = <18>; } -- cgit v0.10.2 From f6a49e5a3f5562855f9e4b9b81916b06ef673771 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 25 Mar 2016 13:36:29 +0100 Subject: tools/gpio: Enable compiler optimization to catch more bugs Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 4d198d5..c155d6b 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -1,5 +1,5 @@ CC = $(CROSS_COMPILE)gcc -CFLAGS += -Wall -g -D_GNU_SOURCE +CFLAGS += -O2 -Wall -g -D_GNU_SOURCE all: lsgpio -- cgit v0.10.2 From 691998fac6f50c9117e279c3fbfa63a23cf7ce2e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 25 Mar 2016 13:36:30 +0100 Subject: tools/gpio: Add missing initialization of device_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lsgpio.c: In function ‘main’: lsgpio.c:166:7: warning: ‘device_name’ may be used uninitialized in this functio n [-Wmaybe-uninitialized] ret = list_device(device_name); ^ Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c index 1124da3..eb3f56e 100644 --- a/tools/gpio/lsgpio.c +++ b/tools/gpio/lsgpio.c @@ -147,7 +147,7 @@ void print_usage(void) int main(int argc, char **argv) { - const char *device_name; + const char *device_name = NULL; int ret; int c; -- cgit v0.10.2 From 8fccdb580ebec0f5b081d824797911a4c5d91891 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 27 Mar 2016 17:43:02 +0200 Subject: gpio: gpio-it87: Add support for IT8620 and IT8628 These chips seem to have a 9th GPIO block (thus supporting 72 GPIOs) which is configured through SuperIO register 0xd2 (output enable) and 0xd3 (simple I/O). This is also the reason why io_size is larger than on IT8728 / IT8732. Unfortunately I don't have hardware to test this 9th GPIO block. I am also not sure about not configuring the Simple I/O registers as the hardware I have only uses GPIO block 8. Reading back the values of 0xc0-0xc7 (as configured by the BIOS/EFI on my board) shows that all have 0xff set. Signed-off-by: Martin Blumenstingl Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7889836..08a93e0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -558,7 +558,7 @@ config GPIO_IT87 Say yes here to support GPIO functionality of IT87xx Super I/O chips. This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and - supports the IT8761E Super I/O chip as well. + supports the IT8761E, IT8620E and IT8628E Super I/O chip as well. To compile this driver as a module, choose M here: the module will be called gpio_it87 diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c index b219c82..63a962d 100644 --- a/drivers/gpio/gpio-it87.c +++ b/drivers/gpio/gpio-it87.c @@ -34,6 +34,8 @@ /* Chip Id numbers */ #define NO_DEV_ID 0xffff +#define IT8620_ID 0x8620 +#define IT8628_ID 0x8628 #define IT8728_ID 0x8728 #define IT8732_ID 0x8732 #define IT8761_ID 0x8761 @@ -302,6 +304,14 @@ static int __init it87_gpio_init(void) it87_gpio->chip = it87_template_chip; switch (chip_type) { + case IT8620_ID: + case IT8628_ID: + gpio_ba_reg = 0x62; + it87_gpio->io_size = 11; + it87_gpio->output_base = 0xc8; + it87_gpio->simple_size = 0; + it87_gpio->chip.ngpio = 64; + break; case IT8728_ID: case IT8732_ID: gpio_ba_reg = 0x62; -- cgit v0.10.2 From 8f3e19fae04a0c85d137dbb6f3c49de63b60cfc2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:41 -0400 Subject: gpio: bcm-kona: make explicitly non-modular The Kconfig currently controlling compilation of this code is: config GPIO_BCM_KONA bool "Broadcom Kona GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Ray Jui Cc: Alexandre Courbot Cc: bcm-kernel-feedback-list@broadcom.com Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 2fd38d5..9aabc48 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -1,4 +1,7 @@ /* + * Broadcom Kona GPIO Driver + * + * Author: Broadcom Corporation * Copyright (C) 2012-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or @@ -17,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -502,8 +505,6 @@ static struct of_device_id const bcm_kona_gpio_of_match[] = { {} }; -MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match); - /* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. @@ -659,9 +660,4 @@ static struct platform_driver bcm_kona_gpio_driver = { }, .probe = bcm_kona_gpio_probe, }; - -module_platform_driver(bcm_kona_gpio_driver); - -MODULE_AUTHOR("Broadcom Corporation "); -MODULE_DESCRIPTION("Broadcom Kona GPIO Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(bcm_kona_gpio_driver); -- cgit v0.10.2 From d5610e514e92144d19bd5e39e5cf3804bbf85f3e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:42 -0400 Subject: gpio: mb86s7x: make explicitly non-modular The Kconfig for this driver is currently: config GPIO_MB86S7X bool "GPIO support for Fujitsu MB86S7x Platforms" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index d23a942..d55af50 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -208,7 +207,6 @@ static const struct of_device_id mb86s70_gpio_dt_ids[] = { { .compatible = "fujitsu,mb86s70-gpio" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids); static struct platform_driver mb86s70_gpio_driver = { .driver = { @@ -223,8 +221,4 @@ static int __init mb86s70_gpio_init(void) { return platform_driver_register(&mb86s70_gpio_driver); } -module_init(mb86s70_gpio_init); - -MODULE_DESCRIPTION("MB86S7x GPIO Driver"); -MODULE_ALIAS("platform:mb86s70-gpio"); -MODULE_LICENSE("GPL"); +device_initcall(mb86s70_gpio_init); -- cgit v0.10.2 From 0de6a80de1425905f9fe8f3df8c455ec56250107 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:43 -0400 Subject: gpio: mc9s08dz60: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MC9S08DZ60 drivers/gpio/Kconfig: bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_i2c_driver() uses the same init level priority as builtin_i2c_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Wu Guoxing Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 14f252f..2fcad5b 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include #include @@ -111,8 +111,6 @@ static const struct i2c_device_id mc9s08dz60_id[] = { {}, }; -MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id); - static struct i2c_driver mc9s08dz60_i2c_driver = { .driver = { .name = "mc9s08dz60", @@ -120,10 +118,4 @@ static struct i2c_driver mc9s08dz60_i2c_driver = { .probe = mc9s08dz60_probe, .id_table = mc9s08dz60_id, }; - -module_i2c_driver(mc9s08dz60_i2c_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc. " - "Wu Guoxing "); -MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board"); -MODULE_LICENSE("GPL v2"); +builtin_i2c_driver(mc9s08dz60_i2c_driver); -- cgit v0.10.2 From 4bb9f7251cf2c922e46a9059dc4d70028469275a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:44 -0400 Subject: gpio: moxart: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MOXART drivers/gpio/Kconfig: bool "MOXART GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular references so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. We don't replace module.h with init.h since the file already has that. Cc: Jonas Jensen Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index f02d0b4..d58d389 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -82,8 +81,4 @@ static struct platform_driver moxart_gpio_driver = { }, .probe = moxart_gpio_probe, }; -module_platform_driver(moxart_gpio_driver); - -MODULE_DESCRIPTION("MOXART GPIO chip driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jonas Jensen "); +builtin_platform_driver(moxart_gpio_driver); -- cgit v0.10.2 From ed329f3a6483ad4825be2f731aa08b34731ecfcb Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:45 -0400 Subject: gpio: mvebu: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MVEBU drivers/gpio/Kconfig: def_bool y ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 11c6582..cd5dc27 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -34,7 +34,7 @@ */ #include -#include +#include #include #include #include @@ -557,7 +557,6 @@ static const struct of_device_id mvebu_gpio_of_match[] = { /* sentinel */ }, }; -MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) { @@ -838,4 +837,4 @@ static struct platform_driver mvebu_gpio_driver = { .suspend = mvebu_gpio_suspend, .resume = mvebu_gpio_resume, }; -module_platform_driver(mvebu_gpio_driver); +builtin_platform_driver(mvebu_gpio_driver); -- cgit v0.10.2 From ef3e7100e06a8788d89555e0a4926ab85f689583 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:46 -0400 Subject: gpio: pl061: make explicitly non-modular The Kconfig for this driver is currently: config GPIO_PL061 bool "PrimeCell PL061 GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Acked-by: Baruch Siach Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 5cb3821..9afb415 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2008, 2009 Provigent Ltd. * + * Author: Baruch Siach + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -11,7 +13,7 @@ */ #include #include -#include +#include #include #include #include @@ -429,8 +431,6 @@ static struct amba_id pl061_ids[] = { { 0, 0 }, }; -MODULE_DEVICE_TABLE(amba, pl061_ids); - static struct amba_driver pl061_gpio_driver = { .drv = { .name = "pl061_gpio", @@ -446,8 +446,4 @@ static int __init pl061_gpio_init(void) { return amba_driver_register(&pl061_gpio_driver); } -module_init(pl061_gpio_init); - -MODULE_AUTHOR("Baruch Siach "); -MODULE_DESCRIPTION("PL061 GPIO driver"); -MODULE_LICENSE("GPL"); +device_initcall(pl061_gpio_init); -- cgit v0.10.2 From 3c90c6d60b4184cd08bc2b8c1db0b507c3a1c84e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:47 -0400 Subject: gpio: sta2x11: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_STA2X11 drivers/gpio/Kconfig: bool "STA2x11/ConneXt GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 0d5b8c5..853ca23 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -20,7 +20,7 @@ * */ -#include +#include #include #include #include @@ -432,8 +432,4 @@ static struct platform_driver sta2x11_gpio_platform_driver = { }, .probe = gsta_probe, }; - -module_platform_driver(sta2x11_gpio_platform_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("sta2x11_gpio GPIO driver"); +builtin_platform_driver(sta2x11_gpio_platform_driver); -- cgit v0.10.2 From b33d12d3d72df3272c9c017cd93577ba1c9b24bb Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:48 -0400 Subject: gpio: xgene: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_XGENE drivers/gpio/Kconfig: bool "APM X-Gene GPIO controller support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Feng Kan Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index c0aa387..4193502 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -17,7 +17,6 @@ * along with this program. If not, see . */ -#include #include #include #include @@ -211,7 +210,6 @@ static const struct of_device_id xgene_gpio_of_match[] = { { .compatible = "apm,xgene-gpio", }, {}, }; -MODULE_DEVICE_TABLE(of, xgene_gpio_of_match); static struct platform_driver xgene_gpio_driver = { .driver = { @@ -221,9 +219,4 @@ static struct platform_driver xgene_gpio_driver = { }, .probe = xgene_gpio_probe, }; - -module_platform_driver(xgene_gpio_driver); - -MODULE_AUTHOR("Feng Kan "); -MODULE_DESCRIPTION("APM X-Gene GPIO driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(xgene_gpio_driver); -- cgit v0.10.2 From 18fb0a981e18b91c6eb1a00f8b06f2fb5be2e9aa Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:49 -0400 Subject: gpio: zx: make explicitly non-modular The Kconfig currently controlling compilation of this code is: config GPIO_ZX bool "ZTE ZX GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Jun Nie Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 47c79fa..93de8be 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -1,4 +1,8 @@ /* + * ZTE ZX296702 GPIO driver + * + * Author: Jun Nie + * * Copyright (C) 2015 Linaro Ltd. * * This program is free software; you can redistribute it and/or modify @@ -10,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -282,7 +286,6 @@ static const struct of_device_id zx_gpio_match[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, zx_gpio_match); static struct platform_driver zx_gpio_driver = { .probe = zx_gpio_probe, @@ -291,9 +294,4 @@ static struct platform_driver zx_gpio_driver = { .of_match_table = of_match_ptr(zx_gpio_match), }, }; - -module_platform_driver(zx_gpio_driver) - -MODULE_AUTHOR("Jun Nie "); -MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(zx_gpio_driver) -- cgit v0.10.2 From 6e66a6599a813abfc9ebe2e295c9d557c434812a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 Mar 2016 19:49:41 +0800 Subject: gpio: tpic2810: Make sure cached buffer has consistent status with h/w status i2c_smbus_write_byte_data() can fail. To ensure the cached buffer has consistent status with h/w status, don't update the cached gpio->buffer if write fails. Also refactor the code a bit by adding a tpic2810_set_mask_bits() helper and use it to simplify the code. Signed-off-by: Axel Lin Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c index 9f020aa..cace79c 100644 --- a/drivers/gpio/gpio-tpic2810.c +++ b/drivers/gpio/gpio-tpic2810.c @@ -57,39 +57,34 @@ static int tpic2810_direction_output(struct gpio_chip *chip, return 0; } -static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +static void tpic2810_set_mask_bits(struct gpio_chip *chip, u8 mask, u8 bits) { struct tpic2810 *gpio = gpiochip_get_data(chip); + u8 buffer; + int err; mutex_lock(&gpio->lock); - if (value) - gpio->buffer |= BIT(offset); - else - gpio->buffer &= ~BIT(offset); + buffer = gpio->buffer & ~mask; + buffer |= (mask & bits); - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); + err = i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, + buffer); + if (!err) + gpio->buffer = buffer; mutex_unlock(&gpio->lock); } +static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +{ + tpic2810_set_mask_bits(chip, BIT(offset), value ? BIT(offset) : 0); +} + static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { - struct tpic2810 *gpio = gpiochip_get_data(chip); - - mutex_lock(&gpio->lock); - - /* clear bits under mask */ - gpio->buffer &= ~(*mask); - /* set bits under mask */ - gpio->buffer |= ((*mask) & (*bits)); - - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); - - mutex_unlock(&gpio->lock); + tpic2810_set_mask_bits(chip, *mask, *bits); } static struct gpio_chip template_chip = { -- cgit v0.10.2 From c663e5f56737757db4d0b317c510ab505f93cecb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 22 Mar 2016 10:51:16 +0100 Subject: gpio: support native single-ended hardware drivers Some GPIO controllers has a special hardware bit we can flip to support open drain / source. This means that on these hardwares we do not need to emulate OD/OS by setting the line to input instead of actively driving it high/low. Add an optional vtable callback to the driver set_single_ended() so that driver can implement this in hardware if they have it. We may need a pinctrl_gpio_set_config() call at some point to propagate this down to a backing pin control device on systems with split GPIO/pin control. Reported-by: Michael Hennerich Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7206553..1edc830 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1509,8 +1509,8 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) { - struct gpio_chip *chip; - int status = -EINVAL; + struct gpio_chip *gc = desc->gdev->chip; + int ret; /* GPIOs used for IRQs shall not be set as output */ if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { @@ -1520,28 +1520,50 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) return -EIO; } - /* Open drain pin should not be driven to 1 */ - if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - return gpiod_direction_input(desc); - - /* Open source pin should not be driven to 0 */ - if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - return gpiod_direction_input(desc); + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { + /* First see if we can enable open drain in hardware */ + if (gc->set_single_ended) { + ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), + LINE_MODE_OPEN_DRAIN); + if (!ret) + goto set_output_value; + } + /* Emulate open drain by not actively driving the line high */ + if (value) + return gpiod_direction_input(desc); + } + else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { + if (gc->set_single_ended) { + ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), + LINE_MODE_OPEN_SOURCE); + if (!ret) + goto set_output_value; + } + /* Emulate open source by not actively driving the line low */ + if (!value) + return gpiod_direction_input(desc); + } else { + /* Make sure to disable open drain/source hardware, if any */ + if (gc->set_single_ended) + gc->set_single_ended(gc, + gpio_chip_hwgpio(desc), + LINE_MODE_PUSH_PULL); + } - chip = desc->gdev->chip; - if (!chip->set || !chip->direction_output) { +set_output_value: + if (!gc->set || !gc->direction_output) { gpiod_warn(desc, "%s: missing set() or direction_output() operations\n", __func__); return -EIO; } - status = chip->direction_output(chip, gpio_chip_hwgpio(desc), value); - if (status == 0) + ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value); + if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); trace_gpio_value(desc_to_gpio(desc), 0, value); - trace_gpio_direction(desc_to_gpio(desc), 0, status); - return status; + trace_gpio_direction(desc_to_gpio(desc), 0, ret); + return ret; } /** diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index bee976f..50882e0 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -20,6 +20,18 @@ struct gpio_device; #ifdef CONFIG_GPIOLIB /** + * enum single_ended_mode - mode for single ended operation + * @LINE_MODE_PUSH_PULL: normal mode for a GPIO line, drive actively high/low + * @LINE_MODE_OPEN_DRAIN: set line to be open drain + * @LINE_MODE_OPEN_SOURCE: set line to be open source + */ +enum single_ended_mode { + LINE_MODE_PUSH_PULL, + LINE_MODE_OPEN_DRAIN, + LINE_MODE_OPEN_SOURCE, +}; + +/** * struct gpio_chip - abstract a GPIO controller * @label: a functional name for the GPIO device, such as a part * number or the name of the SoC IP-block implementing it. @@ -38,7 +50,15 @@ struct gpio_device; * @set: assigns output value for signal "offset" * @set_multiple: assigns output values for multiple signals defined by "mask" * @set_debounce: optional hook for setting debounce time for specified gpio in - * interrupt triggered gpio chips + * interrupt triggered gpio chips + * @set_single_ended: optional hook for setting a line as open drain, open + * source, or non-single ended (restore from open drain/source to normal + * push-pull mode) this should be implemented if the hardware supports + * open drain or open source settings. The GPIOlib will otherwise try + * to emulate open drain/source by not actively driving lines high/low + * if a consumer request this. The driver may return -ENOTSUPP if e.g. + * it supports just open drain but not open source and is called + * with LINE_MODE_OPEN_SOURCE as mode argument. * @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * implementation may not sleep * @dbg_show: optional routine to show contents in debugfs; default code @@ -130,6 +150,9 @@ struct gpio_chip { int (*set_debounce)(struct gpio_chip *chip, unsigned offset, unsigned debounce); + int (*set_single_ended)(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode); int (*to_irq)(struct gpio_chip *chip, unsigned offset); -- cgit v0.10.2 From cee1b40d96f1b49e9a1b38e2d57d37a2c20ced31 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 15:09:09 +0200 Subject: gpio: tc3589x: use BIT() macro This switch to use BIT(n) instead of (1 << n) which is less to the point. Most GPIO drivers do this to avoid mistakes. Also switch from using to the apropriate include. Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 4f566e6..2845653 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -10,10 +10,11 @@ #include #include #include -#include +#include #include #include #include +#include /* * These registers are modified under the irq bus lock and cached to avoid @@ -39,7 +40,7 @@ static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; - u8 mask = 1 << (offset % 8); + u8 mask = BIT(offset % 8); int ret; ret = tc3589x_reg_read(tc3589x, reg); @@ -55,7 +56,7 @@ static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; unsigned pos = offset % 8; - u8 data[] = {!!val << pos, 1 << pos}; + u8 data[] = {val ? BIT(pos) : 0, BIT(pos)}; tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); } @@ -70,7 +71,7 @@ static int tc3589x_gpio_direction_output(struct gpio_chip *chip, tc3589x_gpio_set(chip, offset, val); - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); + return tc3589x_set_bits(tc3589x, reg, BIT(pos), BIT(pos)); } static int tc3589x_gpio_direction_input(struct gpio_chip *chip, @@ -81,7 +82,7 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, u8 reg = TC3589x_GPIODIR0 + offset / 8; unsigned pos = offset % 8; - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); + return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0); } static struct gpio_chip template_chip = { @@ -100,7 +101,7 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); if (type == IRQ_TYPE_EDGE_BOTH) { tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; @@ -165,7 +166,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; } @@ -176,7 +177,7 @@ static void tc3589x_gpio_irq_unmask(struct irq_data *d) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] |= mask; } -- cgit v0.10.2 From 8b866b0682c5de249afed3f7cb23c8421bc735b0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 15:11:11 +0200 Subject: gpio: tc3589x: implement open drain/source callback This makes use of the new .set_single_ended() callback to set the GPIO line as open drain/open source using hardware. The TC3589x can do this by either disabling the N-MOS transistor (open drain) or the P-MOS transistor (open source) of the output driver stage, in the first case making the signal drive actively low and high impedance as "high" and in the second case actively high and high impedance, which is as close to native open drain support as we come. Cc: Michael Hennerich Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 2845653..15552fd 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -85,6 +85,46 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0); } +static int tc3589x_gpio_single_ended(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode) +{ + struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + /* + * These registers are alterated at each second address + * ODM bit 0 = drive to GND or Hi-Z (open drain) + * ODM bit 1 = drive to VDD or Hi-Z (open source) + */ + u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2; + u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2; + unsigned pos = offset % 8; + int ret; + + switch(mode) { + case LINE_MODE_OPEN_DRAIN: + /* Set open drain mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_OPEN_SOURCE: + /* Set open source mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos)); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_PUSH_PULL: + /* Disable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0); + default: + break; + } + return -ENOTSUPP; +} + static struct gpio_chip template_chip = { .label = "tc3589x", .owner = THIS_MODULE, @@ -92,6 +132,7 @@ static struct gpio_chip template_chip = { .get = tc3589x_gpio_get, .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, + .set_single_ended = tc3589x_gpio_single_ended, .can_sleep = true, }; -- cgit v0.10.2 From fe7b778802593ccb1cae859553be912a2a1ef412 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:33 -0400 Subject: gpio: rc5t583: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_RC5T583 drivers/gpio/Kconfig: bool "RICOH RC5T583 GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index 1d6100f..3b4dc1a 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -152,14 +151,3 @@ static int __init rc5t583_gpio_init(void) return platform_driver_register(&rc5t583_gpio_driver); } subsys_initcall(rc5t583_gpio_init); - -static void __exit rc5t583_gpio_exit(void) -{ - platform_driver_unregister(&rc5t583_gpio_driver); -} -module_exit(rc5t583_gpio_exit); - -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_DESCRIPTION("GPIO interface for RC5T583"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:rc5t583-gpio"); -- cgit v0.10.2 From 8513334115c818ef2bddbca5d2e6dd52c994ce19 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:34 -0400 Subject: gpio: tc3589x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TC3589X drivers/gpio/Kconfig: bool "TC3589X GPIOs" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Rabin Vincent Cc: Hanumath Prasad Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 15552fd..2e35ed3 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -6,7 +6,6 @@ * Author: Rabin Vincent for ST-Ericsson */ -#include #include #include #include @@ -353,13 +352,3 @@ static int __init tc3589x_gpio_init(void) return platform_driver_register(&tc3589x_gpio_driver); } subsys_initcall(tc3589x_gpio_init); - -static void __exit tc3589x_gpio_exit(void) -{ - platform_driver_unregister(&tc3589x_gpio_driver); -} -module_exit(tc3589x_gpio_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TC3589x GPIO driver"); -MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); -- cgit v0.10.2 From 24a876cef408eae8bad4f7d74f38dc1a2d919bcc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:35 -0400 Subject: gpio: sx150x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_SX150X drivers/gpio/Kconfig: bool "Semtech SX150x I2C GPIO expander" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Gregory Bean Cc: Linus Walleij Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d387eb5..d57e8ad 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -1,5 +1,9 @@ /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. * + * Driver for Semtech SX150X I2C GPIO Expanders + * + * Author: Gregory Bean + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -19,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -718,13 +721,3 @@ static int __init sx150x_init(void) return i2c_add_driver(&sx150x_driver); } subsys_initcall(sx150x_init); - -static void __exit sx150x_exit(void) -{ - return i2c_del_driver(&sx150x_driver); -} -module_exit(sx150x_exit); - -MODULE_AUTHOR("Gregory Bean "); -MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders"); -MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From f9f2b5cba71e51998e60b7cebba0413e5bf4d1f0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:36 -0400 Subject: gpio: palmas: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_PALMAS drivers/gpio/Kconfig: bool "TI PALMAS series PMICs GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 6f27b3d..e248707 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include @@ -218,14 +218,3 @@ static int __init palmas_gpio_init(void) return platform_driver_register(&palmas_gpio_driver); } subsys_initcall(palmas_gpio_init); - -static void __exit palmas_gpio_exit(void) -{ - platform_driver_unregister(&palmas_gpio_driver); -} -module_exit(palmas_gpio_exit); - -MODULE_ALIAS("platform:palmas-gpio"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs"); -MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 02c7a13eabd85103167a822d470743b640120e7d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:37 -0400 Subject: gpio: tps65910: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TPS65910 drivers/gpio/Kconfig: bool "TPS65910 GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Graeme Gregory Cc: Jorge Eduardo Candelaria Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index cdbd7c7..0ae6a5a 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -4,7 +4,7 @@ * Copyright 2010 Texas Instruments Inc. * * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> + * Author: Jorge Eduardo Candelaria * * 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 @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -193,15 +193,3 @@ static int __init tps65910_gpio_init(void) return platform_driver_register(&tps65910_gpio_driver); } subsys_initcall(tps65910_gpio_init); - -static void __exit tps65910_gpio_exit(void) -{ - platform_driver_unregister(&tps65910_gpio_driver); -} -module_exit(tps65910_gpio_exit); - -MODULE_AUTHOR("Graeme Gregory "); -MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>"); -MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65910-gpio"); -- cgit v0.10.2 From a0e637387a9858f9c2e8228bc15e299387dadcd1 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:38 -0400 Subject: gpio: tps6586x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TPS6586X drivers/gpio/Kconfig: bool "TPS6586X GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index c88bdc8..6b15e68 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -140,14 +140,3 @@ static int __init tps6586x_gpio_init(void) return platform_driver_register(&tps6586x_gpio_driver); } subsys_initcall(tps6586x_gpio_init); - -static void __exit tps6586x_gpio_exit(void) -{ - platform_driver_unregister(&tps6586x_gpio_driver); -} -module_exit(tps6586x_gpio_exit); - -MODULE_ALIAS("platform:tps6586x-gpio"); -MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 6b5029d3ec86ee9558a1ab0b4b41a98e970e2204 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 16:49:57 +0200 Subject: gpio: document open drain/source behaviour This has been a totally undocumented feature for years so add some generic concepts and documentation about open drain/source, include some facts on how we now support for hardware. Cc: Michael Hennerich Cc: Nicolas Saenz Julienne Cc: H. Nikolaus Schaller Signed-off-by: Linus Walleij diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index bbeec41..ae6e029 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -68,6 +68,95 @@ control callbacks) if it is expected to call GPIO APIs from atomic context on -RT (inside hard IRQ handlers and similar contexts). Normally this should not be required. + +GPIOs with open drain/source support +------------------------------------ + +Open drain (CMOS) or open collector (TTL) means the line is not actively driven +high: instead you provide the drain/collector as output, so when the transistor +is not open, it will present a high-impedance (tristate) to the external rail. + + + CMOS CONFIGURATION TTL CONFIGURATION + + ||--- out +--- out + in ----|| |/ + ||--+ in ----| + | |\ + GND GND + +This configuration is normally used as a way to achieve one of two things: + +- Level-shifting: to reach a logical level higher than that of the silicon + where the output resides. + +- inverse wire-OR on an I/O line, for example a GPIO line, making it possible + for any driving stage on the line to drive it low even if any other output + to the same line is simultaneously driving it high. A special case of this + is driving the SCL and SCA lines of an I2C bus, which is by definition a + wire-OR bus. + +Both usecases require that the line be equipped with a pull-up resistor. This +resistor will make the line tend to high level unless one of the transistors on +the rail actively pulls it down. + +Integrated electronics often have an output driver stage in the form of a CMOS +"totem-pole" with one N-MOS and one P-MOS transistor where one of them drives +the line high and one of them drives the line low. This is called a push-pull +output. The "totem-pole" looks like so: + + VDD + | + OD ||--+ + +--/ ---o|| P-MOS-FET + | ||--+ +in --+ +----- out + | ||--+ + +--/ ----|| N-MOS-FET + OS ||--+ + | + GND + +You see the little "switches" named "OD" and "OS" that enable/disable the +P-MOS or N-MOS transistor right after the split of the input. As you can see, +either transistor will go totally numb if this switch is open. The totem-pole +is then halved and give high impedance instead of actively driving the line +high or low respectively. That is usually how software-controlled open +drain/source works. + +Some GPIO hardware come in open drain / open source configuration. Some are +hard-wired lines that will only support open drain or open source no matter +what: there is only one transistor there. Some are software-configurable: +by flipping a bit in a register the output can be configured as open drain +or open source, by flicking open the switches labeled "OD" and "OS" in the +drawing above. + +By disabling the P-MOS transistor, the output can be driven between GND and +high impedance (open drain), and by disabling the N-MOS transistor, the output +can be driven between VDD and high impedance (open source). In the first case, +a pull-up resistor is needed on the outgoing rail to complete the circuit, and +in the second case, a pull-down resistor is needed on the rail. + +Hardware that supports open drain or open source or both, can implement a +special callback in the gpio_chip: .set_single_ended() that takes an enum flag +telling whether to configure the line as open drain, open source or push-pull. +This will happen in response to the GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag +set in the machine file, or coming from other hardware descriptions. + +If this state can not be configured in hardware, i.e. if the GPIO hardware does +not support open drain/open source in hardware, the GPIO library will instead +use a trick: when a line is set as output, if the line is flagged as open +drain, and the output value is negative, it will be driven low as usual. But +if the output value is set to positive, it will instead *NOT* be driven high, +instead it will be switched to input, as input mode is high impedance, thus +achieveing an "open drain emulation" of sorts: electrically the behaviour will +be identical, with the exception of possible hardware glitches when switching +the mode of the line. + +For open source configuration the same principle is used, just that instead +of actively driving the line low, it is set to input. + + GPIO drivers providing IRQs --------------------------- It is custom that GPIO drivers (GPIO chips) are also providing interrupts, -- cgit v0.10.2 From bd37c999c7ca76afd4f28987314e98e022875dbc Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 6 Apr 2016 20:34:53 +0800 Subject: gpio: Loongson1: add Loongson1 GPIO driver This patch adds GPIO driver for Loongson1B. Signed-off-by: Kelvin Cheung Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 08a93e0..37f0378 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -511,6 +511,13 @@ config GPIO_ZX help Say yes here to support the GPIO device on ZTE ZX SoCs. +config GPIO_LOONGSON1 + tristate "Loongson1 GPIO support" + depends on MACH_LOONGSON32 + select GPIO_GENERIC + help + Say Y or M here to support GPIO on Loongson1 SoCs. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1e0b74f..40ab913 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -127,3 +127,4 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o +obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c new file mode 100644 index 0000000..10c09bd --- /dev/null +++ b/drivers/gpio/gpio-loongson1.c @@ -0,0 +1,102 @@ +/* + * GPIO Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include + +/* Loongson 1 GPIO Register Definitions */ +#define GPIO_CFG 0x0 +#define GPIO_DIR 0x10 +#define GPIO_DATA 0x20 +#define GPIO_OUTPUT 0x30 + +static void __iomem *gpio_reg_base; + +static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask, + gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask, + gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int ls1x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_chip *gc; + struct resource *res; + int ret; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + return -EINVAL; + } + + gpio_reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(gpio_reg_base)) + return PTR_ERR(gpio_reg_base); + + ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, + gpio_reg_base + GPIO_OUTPUT, NULL, + NULL, gpio_reg_base + GPIO_DIR, 0); + if (ret) + goto err; + + gc->owner = THIS_MODULE; + gc->request = ls1x_gpio_request; + gc->free = ls1x_gpio_free; + gc->base = pdev->id * 32; + + ret = devm_gpiochip_add_data(dev, gc, NULL); + if (ret) + goto err; + + platform_set_drvdata(pdev, gc); + dev_info(dev, "Loongson1 GPIO driver registered\n"); + + return 0; +err: + dev_err(dev, "failed to register GPIO device\n"); + return ret; +} + +static struct platform_driver ls1x_gpio_driver = { + .probe = ls1x_gpio_probe, + .driver = { + .name = "ls1x-gpio", + }, +}; + +module_platform_driver(ls1x_gpio_driver); + +MODULE_AUTHOR("Kelvin Cheung "); +MODULE_DESCRIPTION("Loongson1 GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 615d23f80efc60f8c5146223f305d19207c742e4 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 4 Apr 2016 23:44:06 +0530 Subject: gpio: zynq: Fix the error path pm_runtime_disable is called only in remove it is missed out in the error path. Fix the same. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 66d3d24..75c6355 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -713,7 +713,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) - return ret; + goto err_pm_dis; /* report a bug if gpio chip registration fails */ ret = gpiochip_add_data(chip, gpio); @@ -745,6 +745,8 @@ err_rm_gpiochip: gpiochip_remove(chip); err_pm_put: pm_runtime_put(&pdev->dev); +err_pm_dis: + pm_runtime_disable(&pdev->dev); return ret; } -- cgit v0.10.2 From 44896beae605b93f2232301befccb7ef42953198 Mon Sep 17 00:00:00 2001 From: Yong Li Date: Thu, 7 Apr 2016 12:56:32 +0800 Subject: gpio: pca953x: add PCAL9535 interrupt support for Galileo Gen2 Galileo Gen2 board uses the PCAL9535 as the GPIO expansion, it is different from PCA9535 and includes interrupt mask/status registers, The current driver does not support the interrupt registers configuration, it causes some gpio pins cannot trigger interrupt events, this patch fix this issue. The original patch was submitted by Josef Ahmad http://git.yoctoproject.org/cgit/cgit.cgi/meta-intel-quark/tree/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch Signed-off-by: Yong Li Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d0d3065..8d8f06d 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -37,8 +37,13 @@ #define PCA957X_MSK 6 #define PCA957X_INTS 7 +#define PCAL953X_IN_LATCH 34 +#define PCAL953X_INT_MASK 37 +#define PCAL953X_INT_STAT 38 + #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 +#define PCA_PCAL 0x0200 #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 #define PCA_TYPE_MASK 0xF000 @@ -76,7 +81,7 @@ static const struct i2c_device_id pca953x_id[] = { MODULE_DEVICE_TABLE(i2c, pca953x_id); static const struct acpi_device_id pca953x_acpi_ids[] = { - { "INT3491", 16 | PCA953X_TYPE | PCA_INT, }, + { "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, { } }; MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); @@ -436,6 +441,18 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) struct pca953x_chip *chip = gpiochip_get_data(gc); u8 new_irqs; int level, i; + u8 invert_irq_mask[MAX_BANK]; + + if (chip->driver_data & PCA_PCAL) { + /* Enable latch on interrupt-enabled inputs */ + pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); + + for (i = 0; i < NBANK(chip); i++) + invert_irq_mask[i] = ~chip->irq_mask[i]; + + /* Unmask enabled interrupts */ + pca953x_write_regs(chip, PCAL953X_INT_MASK, invert_irq_mask); + } /* Look for any newly setup interrupt */ for (i = 0; i < NBANK(chip); i++) { @@ -497,6 +514,29 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) u8 trigger[MAX_BANK]; int ret, i, offset = 0; + if (chip->driver_data & PCA_PCAL) { + /* Read the current interrupt status from the device */ + ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger); + if (ret) + return false; + + /* Check latched inputs and clear interrupt status */ + ret = pca953x_read_regs(chip, PCA953X_INPUT, cur_stat); + if (ret) + return false; + + for (i = 0; i < NBANK(chip); i++) { + /* Apply filter for rising/falling edge selection */ + pending[i] = (~cur_stat[i] & chip->irq_trig_fall[i]) | + (cur_stat[i] & chip->irq_trig_raise[i]); + pending[i] &= trigger[i]; + if (pending[i]) + pending_seen = true; + } + + return pending_seen; + } + switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_INPUT; -- cgit v0.10.2 From cd97a449a7cedf7d9a61882a672d317429b5d599 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Apr 2016 17:57:53 +0200 Subject: MAINTAINERS: gpio: add DT bindings directory Helps get_maintainer.pl to find the right people. Signed-off-by: Wolfram Sang Signed-off-by: Linus Walleij diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7..a023775 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4884,6 +4884,7 @@ M: Alexandre Courbot L: linux-gpio@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained +F: Documentation/devicetree/bindings/gpio/ F: Documentation/gpio/ F: Documentation/ABI/testing/gpio-cdev F: Documentation/ABI/obsolete/sysfs-gpio -- cgit v0.10.2 From dfbd379ba9b7431eec46f1dbc2603491be98619a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:22 +0530 Subject: gpio: of: Return error if gpio hog configuration failed If GPIO hog configuration failed while adding OF based gpiochip() then return the error instead of ignoring it. This helps of properly handling the gpio driver dependency. When adding the gpio hog nodes for NVIDIA's Tegra210 platforms, the gpio_hogd() fails with EPROBE_DEFER because pinctrl is not ready at this time and gpio_request() for Tegra GPIO driver returns error. The error was not causing the Tegra GPIO driver to fail as the error was getting ignored. Signed-off-by: Laxman Dewangan Cc: Benoit Parrot Cc: Alexandre Courbot Reviewed-by: Thierry Reding Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 42a4bb7..a248509 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -201,14 +201,16 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, * * This is only used by of_gpiochip_add to request/set GPIO initial * configuration. + * It retures error if it fails otherwise 0 on success. */ -static void of_gpiochip_scan_gpios(struct gpio_chip *chip) +static int of_gpiochip_scan_gpios(struct gpio_chip *chip) { struct gpio_desc *desc = NULL; struct device_node *np; const char *name; enum gpio_lookup_flags lflags; enum gpiod_flags dflags; + int ret; for_each_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) @@ -218,9 +220,12 @@ static void of_gpiochip_scan_gpios(struct gpio_chip *chip) if (IS_ERR(desc)) continue; - if (gpiod_hog(desc, name, lflags, dflags)) - continue; + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret < 0) + return ret; } + + return 0; } /** @@ -442,9 +447,7 @@ int of_gpiochip_add(struct gpio_chip *chip) of_node_get(chip->of_node); - of_gpiochip_scan_gpios(chip); - - return 0; + return of_gpiochip_scan_gpios(chip); } void of_gpiochip_remove(struct gpio_chip *chip) -- cgit v0.10.2 From f30e49f1291bc309865f88126005d526421d7e3a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 8 Apr 2016 14:13:53 +0200 Subject: gpio: tps65218: use the new open drain callback The TPS65218 supports open drain mode on its three pins, with one of them configurable also as push-pull. Use the new .set_single_ended() callback to set this up properly from the core, so the core actually see it can drive the pin(s) as open drain, and does not attempt to emulate open drain by switching the pin to an input. Acked-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 313c0e4..0eaeac8 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -101,16 +101,6 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset) break; case 1: - /* GP02 is push-pull by default, can be set as open drain. */ - if (gpiochip_line_is_open_drain(gc, offset)) { - ret = tps65218_clear_bits(tps65218, - TPS65218_REG_CONFIG1, - TPS65218_CONFIG1_GPO2_BUF, - TPS65218_PROTECT_L1); - if (ret) - return ret; - } - /* Setup GPO2 */ ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1, TPS65218_CONFIG1_IO1_SEL, @@ -148,6 +138,40 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset) return 0; } +static int tps65218_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) +{ + struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); + struct tps65218 *tps65218 = tps65218_gpio->tps65218; + + switch (offset) { + case 0: + case 2: + /* GPO1 is hardwired to be open drain */ + if (mode == LINE_MODE_OPEN_DRAIN) + return 0; + return -ENOTSUPP; + case 1: + /* GPO2 is push-pull by default, can be set as open drain. */ + if (mode == LINE_MODE_OPEN_DRAIN) + return tps65218_clear_bits(tps65218, + TPS65218_REG_CONFIG1, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_PROTECT_L1); + if (mode == LINE_MODE_PUSH_PULL) + return tps65218_set_bits(tps65218, + TPS65218_REG_CONFIG1, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_PROTECT_L1); + return -ENOTSUPP; + default: + break; + } + return -ENOTSUPP; +} + static struct gpio_chip template_chip = { .label = "gpio-tps65218", .owner = THIS_MODULE, @@ -156,6 +180,7 @@ static struct gpio_chip template_chip = { .direction_input = tps65218_gpio_input, .get = tps65218_gpio_get, .set = tps65218_gpio_set, + .set_single_ended = tps65218_gpio_set_single_ended, .can_sleep = true, .ngpio = 3, .base = -1, -- cgit v0.10.2 From d17322feecf80152303426dd724577025d1fbd7e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 10:52:26 +0200 Subject: gpio: sx150x: move platform data into driver The sx150x has some platform data definition in but this file is only included from the driver in the whole kernel so move its contents into the driver. Cc: Wei Chen Cc: Peter Rosin Acked-by: Wolfram Sang Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d57e8ad..d4501d5 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -85,6 +84,65 @@ struct sx150x_device_data { } pri; }; +/** + * struct sx150x_platform_data - config data for SX150x driver + * @gpio_base: The index number of the first GPIO assigned to this + * GPIO expander. The expander will create a block of + * consecutively numbered gpios beginning at the given base, + * with the size of the block depending on the model of the + * expander chip. + * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO + * instead of as an oscillator, increasing the size of the + * GP(I)O pool created by this expander by one. The + * output-only GPO pin will be added at the end of the block. + * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor + * for each IO line in the expander. Setting the bit at + * position n will enable the pull-up for the IO at + * the corresponding offset. For chips with fewer than + * 16 IO pins, high-end bits are ignored. + * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down + * resistor for each IO line in the expander. Setting the + * bit at position n will enable the pull-down for the IO at + * the corresponding offset. For chips with fewer than + * 16 IO pins, high-end bits are ignored. + * @io_open_drain_ena: A bit-mask which enables-or disables open-drain + * operation for each IO line in the expander. Setting the + * bit at position n enables open-drain operation for + * the IO at the corresponding offset. Clearing the bit + * enables regular push-pull operation for that IO. + * For chips with fewer than 16 IO pins, high-end bits + * are ignored. + * @io_polarity: A bit-mask which enables polarity inversion for each IO line + * in the expander. Setting the bit at position n inverts + * the polarity of that IO line, while clearing it results + * in normal polarity. For chips with fewer than 16 IO pins, + * high-end bits are ignored. + * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line + * is connected, via which it reports interrupt events + * across all GPIO lines. This must be a real, + * pre-existing IRQ line. + * Setting this value < 0 disables the irq_chip functionality + * of the driver. + * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based + * IRQ lines will appear. Similarly to gpio_base, the expander + * will create a block of irqs beginning at this number. + * This value is ignored if irq_summary is < 0. + * @reset_during_probe: If set to true, the driver will trigger a full + * reset of the chip at the beginning of the probe + * in order to place it in a known state. + */ +struct sx150x_platform_data { + unsigned gpio_base; + bool oscio_is_gpo; + u16 io_pullup_ena; + u16 io_pulldn_ena; + u16 io_open_drain_ena; + u16 io_polarity; + int irq_summary; + unsigned irq_base; + bool reset_during_probe; +}; + struct sx150x_chip { struct gpio_chip gpio_chip; struct i2c_client *client; diff --git a/include/linux/i2c/sx150x.h b/include/linux/i2c/sx150x.h deleted file mode 100644 index 52baa79..0000000 --- a/include/linux/i2c/sx150x.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Driver for the Semtech SX150x I2C GPIO Expanders - * - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#ifndef __LINUX_I2C_SX150X_H -#define __LINUX_I2C_SX150X_H - -/** - * struct sx150x_platform_data - config data for SX150x driver - * @gpio_base: The index number of the first GPIO assigned to this - * GPIO expander. The expander will create a block of - * consecutively numbered gpios beginning at the given base, - * with the size of the block depending on the model of the - * expander chip. - * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO - * instead of as an oscillator, increasing the size of the - * GP(I)O pool created by this expander by one. The - * output-only GPO pin will be added at the end of the block. - * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor - * for each IO line in the expander. Setting the bit at - * position n will enable the pull-up for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down - * resistor for each IO line in the expander. Setting the - * bit at position n will enable the pull-down for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_open_drain_ena: A bit-mask which enables-or disables open-drain - * operation for each IO line in the expander. Setting the - * bit at position n enables open-drain operation for - * the IO at the corresponding offset. Clearing the bit - * enables regular push-pull operation for that IO. - * For chips with fewer than 16 IO pins, high-end bits - * are ignored. - * @io_polarity: A bit-mask which enables polarity inversion for each IO line - * in the expander. Setting the bit at position n inverts - * the polarity of that IO line, while clearing it results - * in normal polarity. For chips with fewer than 16 IO pins, - * high-end bits are ignored. - * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line - * is connected, via which it reports interrupt events - * across all GPIO lines. This must be a real, - * pre-existing IRQ line. - * Setting this value < 0 disables the irq_chip functionality - * of the driver. - * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based - * IRQ lines will appear. Similarly to gpio_base, the expander - * will create a block of irqs beginning at this number. - * This value is ignored if irq_summary is < 0. - * @reset_during_probe: If set to true, the driver will trigger a full - * reset of the chip at the beginning of the probe - * in order to place it in a known state. - */ -struct sx150x_platform_data { - unsigned gpio_base; - bool oscio_is_gpo; - u16 io_pullup_ena; - u16 io_pulldn_ena; - u16 io_open_drain_ena; - u16 io_polarity; - int irq_summary; - unsigned irq_base; - bool reset_during_probe; -}; - -#endif /* __LINUX_I2C_SX150X_H */ -- cgit v0.10.2 From 04b8695617fe6efeba5ca20e8be3a5c1879fd74a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 13:13:36 +0200 Subject: gpio: sx150x: use the new open drain callback One variant of the SX150X GPIO chip supports setting the pins in open drain mode. This is currently available to set from platform data, but completely unused in the kernel. Activate the new .set_single_ended() callback so users can set this up from e.g. device tree or board files using the new GPIO descriptors. As part of this, delete the platform data open drain setting method. Cc: Wei Chen Cc: Peter Rosin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d4501d5..a177ebd 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -105,13 +105,6 @@ struct sx150x_device_data { * bit at position n will enable the pull-down for the IO at * the corresponding offset. For chips with fewer than * 16 IO pins, high-end bits are ignored. - * @io_open_drain_ena: A bit-mask which enables-or disables open-drain - * operation for each IO line in the expander. Setting the - * bit at position n enables open-drain operation for - * the IO at the corresponding offset. Clearing the bit - * enables regular push-pull operation for that IO. - * For chips with fewer than 16 IO pins, high-end bits - * are ignored. * @io_polarity: A bit-mask which enables polarity inversion for each IO line * in the expander. Setting the bit at position n inverts * the polarity of that IO line, while clearing it results @@ -136,7 +129,6 @@ struct sx150x_platform_data { bool oscio_is_gpo; u16 io_pullup_ena; u16 io_pulldn_ena; - u16 io_open_drain_ena; u16 io_polarity; int irq_summary; unsigned irq_base; @@ -415,6 +407,32 @@ static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) mutex_unlock(&chip->lock); } +static int sx150x_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) +{ + struct sx150x_chip *chip = gpiochip_get_data(gc); + + /* On the SX160X 789 we can set open drain */ + if (chip->dev_cfg->model != SX150X_789) + return -ENOTSUPP; + + if (mode == LINE_MODE_PUSH_PULL) + return sx150x_write_cfg(chip, + offset, + 1, + chip->dev_cfg->pri.x789.reg_drain, + 0); + + if (mode == LINE_MODE_OPEN_DRAIN) + return sx150x_write_cfg(chip, + offset, + 1, + chip->dev_cfg->pri.x789.reg_drain, + 1); + return -ENOTSUPP; +} + static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { struct sx150x_chip *chip = gpiochip_get_data(gc); @@ -569,6 +587,7 @@ static void sx150x_init_chip(struct sx150x_chip *chip, chip->gpio_chip.direction_output = sx150x_gpio_direction_output; chip->gpio_chip.get = sx150x_gpio_get; chip->gpio_chip.set = sx150x_gpio_set; + chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended; chip->gpio_chip.base = pdata->gpio_base; chip->gpio_chip.can_sleep = true; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; @@ -658,12 +677,6 @@ static int sx150x_init_hw(struct sx150x_chip *chip, if (chip->dev_cfg->model == SX150X_789) { err = sx150x_init_io(chip, - chip->dev_cfg->pri.x789.reg_drain, - pdata->io_open_drain_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->pri.x789.reg_polarity, pdata->io_polarity); if (err < 0) -- cgit v0.10.2 From 148c864260dad94dd037d342679cd62f664a9b21 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 15:59:41 +0200 Subject: gpio: f7188x: use BIT() macro Align to how we handle bitmasks in most drivers in the subsystem: using the BIT(n) macro over (1 << n). Cc: Peter Hung Cc: Andreas Bofjall Cc: Simon Guinot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index daac2d4..8b10fbf 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #define DRVNAME "gpio-f7188x" @@ -217,7 +218,7 @@ static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) superio_select(sio->addr, SIO_LD_GPIO); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir &= ~(1 << offset); + dir &= ~BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -238,7 +239,7 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset) superio_select(sio->addr, SIO_LD_GPIO); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir = !!(dir & (1 << offset)); + dir = !!(dir & BIT(offset)); if (dir) data = superio_inb(sio->addr, gpio_data_out(bank->regbase)); else @@ -246,7 +247,7 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset) superio_exit(sio->addr); - return !!(data & 1 << offset); + return !!(data & BIT(offset)); } static int f7188x_gpio_direction_out(struct gpio_chip *chip, @@ -264,13 +265,13 @@ static int f7188x_gpio_direction_out(struct gpio_chip *chip, data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) - data_out |= (1 << offset); + data_out |= BIT(offset); else - data_out &= ~(1 << offset); + data_out &= ~BIT(offset); superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir |= (1 << offset); + dir |= BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -292,9 +293,9 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) - data_out |= (1 << offset); + data_out |= BIT(offset); else - data_out &= ~(1 << offset); + data_out &= ~BIT(offset); superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out); superio_exit(sio->addr); -- cgit v0.10.2 From f90c6bdb690bb12f3dbe8eaa5650a9ce952d0290 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 16:11:37 +0200 Subject: gpio: f7188x: use the new open drain callback The F7188x chips supports setting the pins in open drain mode. Activate the new .set_single_ended() callback. Cc: Peter Hung Cc: Andreas Bofjall Cc: Simon Guinot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 8b10fbf..58674ff 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -130,6 +130,9 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset); static int f7188x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value); static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); +static int f7188x_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode); #define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \ { \ @@ -140,6 +143,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); .get = f7188x_gpio_get, \ .direction_output = f7188x_gpio_direction_out, \ .set = f7188x_gpio_set, \ + .set_single_ended = f7188x_gpio_set_single_ended, \ .base = _base, \ .ngpio = _ngpio, \ .can_sleep = true, \ @@ -301,6 +305,35 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) superio_exit(sio->addr); } +static int f7188x_gpio_set_single_ended(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode) +{ + int err; + struct f7188x_gpio_bank *bank = gpiochip_get_data(chip); + struct f7188x_sio *sio = bank->data->sio; + u8 data; + + if (mode != LINE_MODE_OPEN_DRAIN && + mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; + + err = superio_enter(sio->addr); + if (err) + return err; + superio_select(sio->addr, SIO_LD_GPIO); + + data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); + if (mode == LINE_MODE_OPEN_DRAIN) + data &= ~BIT(offset); + else + data |= BIT(offset); + superio_outb(sio->addr, gpio_data_mode(bank->regbase), data); + + superio_exit(sio->addr); + return 0; +} + /* * Platform device and driver. */ -- cgit v0.10.2 From 811a1882b12bbbcbd447ad8c4d16d170e196c58f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 21:53:39 +0200 Subject: gpio: menz127: use the new open drain callback The menz127 driver tries to support open drain by detecting it at request time. However: without the new callbacks from the gpiolib it is not really working: the core will still just emulate the open drain mode by switching the line to an input. By adding a hook into the new .set_single_ended() call rather than trying to autodetect at request() time, proper open drain can be supported. Cc: Andreas Werner Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index 8c1ab8e..334fe27 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -88,21 +88,25 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, return 0; } -static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) +static int men_z127_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) { struct men_z127_gpio *priv = gpiochip_get_data(gc); u32 od_en; - if (gpio_pin >= gc->ngpio) - return -EINVAL; + if (mode != LINE_MODE_OPEN_DRAIN && + mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; spin_lock(&priv->lock); od_en = readl(priv->reg_base + MEN_Z127_ODER); - if (gpiochip_line_is_open_drain(gc, gpio_pin)) - od_en |= BIT(gpio_pin); + if (mode == LINE_MODE_OPEN_DRAIN) + od_en |= BIT(offset); else - od_en &= ~BIT(gpio_pin); + /* Implicitly LINE_MODE_PUSH_PULL */ + od_en &= ~BIT(offset); writel(od_en, priv->reg_base + MEN_Z127_ODER); spin_unlock(&priv->lock); @@ -147,7 +151,7 @@ static int men_z127_probe(struct mcb_device *mdev, goto err_unmap; men_z127_gpio->gc.set_debounce = men_z127_debounce; - men_z127_gpio->gc.request = men_z127_request; + men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended; ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio); if (ret) { -- cgit v0.10.2 From 640b9135c888f02afd058c213303ffbd10d3908d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 12:26:08 +0200 Subject: gpio: vx855: use the new open drain callback The vx855 driver clearly states it has three groups of lines: GPI, GPO and GPIO. The GPO are assumedly push-pull. The GPIO are implicit open drain, but if the GPIO subsystem ask for them to be explicitly open drain (i.e. set the flag on a machine table that we want open drain) it will currently misbehave: it will switch the GPIOs to input mode (emulate open drain). Instead: indicate in the .set_single_ended() callback that we support open drain and open drain only. Cc: Daniel Drake Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index 8cdb9f7..4e45012 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -186,6 +186,28 @@ static int vx855gpio_direction_output(struct gpio_chip *gpio, return 0; } +static int vx855gpio_set_single_ended(struct gpio_chip *gpio, + unsigned int nr, + enum single_ended_mode mode) +{ + /* The GPI cannot be single-ended */ + if (nr < NR_VX855_GPI) + return -EINVAL; + + /* The GPO's are push-pull */ + if (nr < NR_VX855_GPInO) { + if (mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; + return 0; + } + + /* The GPIO's are open drain */ + if (mode != LINE_MODE_OPEN_DRAIN) + return -ENOTSUPP; + + return 0; +} + static const char *vx855gpio_names[NR_VX855_GP] = { "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4", "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9", @@ -209,6 +231,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg) c->direction_output = vx855gpio_direction_output; c->get = vx855gpio_get; c->set = vx855gpio_set; + c->set_single_ended = vx855gpio_set_single_ended; c->dbg_show = NULL; c->base = 0; c->ngpio = NR_VX855_GP; -- cgit v0.10.2 From 51c27da19d3dbf3219afb225e1626e193c5e1c72 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 14:52:33 +0200 Subject: gpio: wm831x: use the new open drain callback The WM831x GPIOs clearly have a dedicated open drain control register. Implement support for controlling this from GPIO descriptor tables or other hardware descriptions such as device tree by implementing the .set_single_ended() callback. Before this patch, lines requesting open drain will just be switched to input mode by the framework, thus emulating open drain. But the hardware can do the real thing, so let's support that. As part of this, rename the debugfs string for output mode from "CMOS" to "push-pull" because it is the term used in the framework to signify a tomem-pole CMOS output. Cc: patches@opensource.wolfsonmicro.com Cc: Mark Brown Acked-by: Charles Keepax Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 18cb0f5..41ec783 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -132,6 +132,28 @@ static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); } +static int wm831x_set_single_ended(struct gpio_chip *chip, + unsigned int offset, + enum single_ended_mode mode) +{ + struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip); + struct wm831x *wm831x = wm831x_gpio->wm831x; + int reg = WM831X_GPIO1_CONTROL + offset; + + switch (mode) { + case LINE_MODE_OPEN_DRAIN: + return wm831x_set_bits(wm831x, reg, + WM831X_GPN_OD_MASK, WM831X_GPN_OD); + case LINE_MODE_PUSH_PULL: + return wm831x_set_bits(wm831x, reg, + WM831X_GPN_OD_MASK, 0); + default: + break; + } + + return -ENOTSUPP; +} + #ifdef CONFIG_DEBUG_FS static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { @@ -216,7 +238,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) pull, powerdomain, reg & WM831X_GPN_POL ? "" : " inverted", - reg & WM831X_GPN_OD ? "open-drain" : "CMOS", + reg & WM831X_GPN_OD ? "open-drain" : "push-pull", tristated ? " tristated" : "", reg); } @@ -234,6 +256,7 @@ static struct gpio_chip template_chip = { .set = wm831x_gpio_set, .to_irq = wm831x_gpio_to_irq, .set_debounce = wm831x_gpio_set_debounce, + .set_single_ended = wm831x_set_single_ended, .dbg_show = wm831x_gpio_dbg_show, .can_sleep = true, }; -- cgit v0.10.2 From 190ea4344bc3fb97c40befd1653a92e9a59fe0f7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 15:07:23 +0200 Subject: gpio: wm8994: use the new open drain callback The WM8994 GPIOs clearly have a dedicated open drain control register. Implement support for controlling this from GPIO descriptor tables or other hardware descriptions such as device tree by implementing the .set_single_ended() callback. Before this patch, lines requesting open drain will just be switched to input mode by the framework, thus emulating open drain. But the hardware can do the real thing, so let's support that. As part of this, rename the debugfs string for output mode from "CMOS" to "push-pull" because it is the term used in the framework to signify a tomem-pole CMOS output. Cc: patches@opensource.wolfsonmicro.com Cc: Mark Brown Acked-by: Charles Keepax Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index b089df9..744af38 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -103,6 +103,28 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); } +static int wm8994_gpio_set_single_ended(struct gpio_chip *chip, + unsigned int offset, + enum single_ended_mode mode) +{ + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); + struct wm8994 *wm8994 = wm8994_gpio->wm8994; + + switch (mode) { + case LINE_MODE_OPEN_DRAIN: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, + WM8994_GPN_OP_CFG); + case LINE_MODE_PUSH_PULL: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, 0); + default: + break; + } + + return -ENOTSUPP; +} + static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); @@ -217,7 +239,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (reg & WM8994_GPN_OP_CFG) seq_printf(s, "open drain "); else - seq_printf(s, "CMOS "); + seq_printf(s, "push-pull "); seq_printf(s, "%s (%x)\n", wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg); @@ -235,6 +257,7 @@ static struct gpio_chip template_chip = { .get = wm8994_gpio_get, .direction_output = wm8994_gpio_direction_out, .set = wm8994_gpio_set, + .set_single_ended = wm8994_gpio_set_single_ended, .to_irq = wm8994_gpio_to_irq, .dbg_show = wm8994_gpio_dbg_show, .can_sleep = true, -- cgit v0.10.2 From 1e4a80640338924b9f9fd7a121ac31d08134410a Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 24 Feb 2016 22:05:19 +0100 Subject: gpio: gpiolib-of: Allow compile testing Lower dependencies for compile testing. Signed-off-by: Alexander Stein diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 37f0378..9776ea5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -49,7 +49,7 @@ config GPIO_DEVRES config OF_GPIO def_bool y - depends on OF + depends on OF || COMPILE_TEST config GPIO_ACPI def_bool y -- cgit v0.10.2 From 4dd4dd1d21206cd05f5da031d709e9de8567957f Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 24 Feb 2016 20:54:32 +0100 Subject: gpio: tegra: Allow compile test Allow compile testing this driver by adding a new config option which is enabled by default and depends on the old symbol or COMPILE_TEST. Signed-off-by: Alexander Stein diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9776ea5..f73f26b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -400,6 +400,11 @@ config GPIO_TB10X select GENERIC_IRQ_CHIP select OF_GPIO +config GPIO_TEGRA + bool + default y + depends on ARCH_TEGRA || COMPILE_TEST + config GPIO_TS4800 tristate "TS-4800 DIO blocks and compatibles" depends on OF_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 40ab913..74eb1a7 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -95,7 +95,7 @@ obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o -obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o +obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o -- cgit v0.10.2 From d1279d94b4e47c3684f936ed6b6c89d3dd2cd5b9 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:20 +0530 Subject: gpio: of: Scan available child node for gpio-hog Look for child node which are available when iterating for gpio hog node for request/set GPIO initial configuration during OF gpio chip registration. All it really does is make it possible to set status = "disabled"; in the hog nodes, and then they will not be applied. Signed-off-by: Laxman Dewangan Reviewed-by: Thierry Reding Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a248509..d81dbd8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -212,7 +212,7 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) enum gpiod_flags dflags; int ret; - for_each_child_of_node(chip->of_node, np) { + for_each_available_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; -- cgit v0.10.2 From c31a571d4360a7765613615709627e83059ce946 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:21 +0530 Subject: gpio: gpiolib: Print error number if gpio hog failed Print the error number of GPIO hog failed during its configurations. This helps in identifying the failure without instrumenting the code. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1edc830..59a0d8e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2702,15 +2702,16 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, local_desc = gpiochip_request_own_desc(chip, hwnum, name); if (IS_ERR(local_desc)) { - pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n", - name, chip->label, hwnum); - return PTR_ERR(local_desc); + status = PTR_ERR(local_desc); + pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n", + name, chip->label, hwnum, status); + return status; } status = gpiod_configure_flags(desc, name, dflags); if (status < 0) { - pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n", - name, chip->label, hwnum); + pr_err("setup of hog GPIO %s (chip %s, offset %d) failed, %d\n", + name, chip->label, hwnum, status); gpiochip_free_own_desc(desc); return status; } -- cgit v0.10.2 From 35b3fc8876ef927885f68e481efc049285d07e53 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 10 Apr 2016 18:15:15 +0800 Subject: gpio: brcmstb: Return proper error if bank width is invalid Return proper error in brcmstb_gpio_probe if bank width is invalid. Signed-off-by: Axel Lin Acked-by: Gregory Fong Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 42d51c5..e648914 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -461,6 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) bank->id = num_banks; if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) { dev_err(dev, "Invalid bank width %d\n", bank_width); + err = -EINVAL; goto fail; } else { bank->width = bank_width; -- cgit v0.10.2 From c686090f14e0673f9b1a3aec316098742f8e003c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Apr 2016 18:00:53 +0200 Subject: gpio/reset: move gpio-{poweroff|restart} DT doc to proper place I did only find them after a fuzzy search, so let them be where one would expect them. Signed-off-by: Wolfram Sang Acked-By: Sebastian Reichel Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt deleted file mode 100644 index d4eab92..0000000 --- a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt +++ /dev/null @@ -1,36 +0,0 @@ -Driver a GPIO line that can be used to turn the power off. - -The driver supports both level triggered and edge triggered power off. -At driver load time, the driver will request the given gpio line and -install a pm_power_off handler. If the optional properties 'input' is -not found, the GPIO line will be driven in the inactive -state. Otherwise its configured as an input. - -When the pm_power_off is called, the gpio is configured as an output, -and drive active, so triggering a level triggered power off -condition. This will also cause an inactive->active edge condition, so -triggering positive edge triggered power off. After a delay of 100ms, -the GPIO is set to inactive, thus causing an active->inactive edge, -triggering negative edge triggered power off. After another 100ms -delay the GPIO is driver active again. If the power is still on and -the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted. - -Required properties: -- compatible : should be "gpio-poweroff". -- gpios : The GPIO to set high/low, see "gpios property" in - Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be - low to power down the board set it to "Active Low", otherwise set - gpio to "Active High". - -Optional properties: -- input : Initially configure the GPIO line as an input. Only reconfigure - it to an output when the pm_power_off function is called. If this optional - property is not specified, the GPIO is initialized as an output in its - inactive state. - -Examples: - -gpio-poweroff { - compatible = "gpio-poweroff"; - gpios = <&gpio 4 0>; -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-restart.txt b/Documentation/devicetree/bindings/gpio/gpio-restart.txt deleted file mode 100644 index af3701b..0000000 --- a/Documentation/devicetree/bindings/gpio/gpio-restart.txt +++ /dev/null @@ -1,54 +0,0 @@ -Drive a GPIO line that can be used to restart the system from a restart -handler. - -This binding supports level and edge triggered reset. At driver load -time, the driver will request the given gpio line and install a restart -handler. If the optional properties 'open-source' is not found, the GPIO line -will be driven in the inactive state. Otherwise its not driven until -the restart is initiated. - -When the system is restarted, the restart handler will be invoked in -priority order. The gpio is configured as an output, and driven active, -triggering a level triggered reset condition. This will also cause an -inactive->active edge condition, triggering positive edge triggered -reset. After a delay specified by active-delay, the GPIO is set to -inactive, thus causing an active->inactive edge, triggering negative edge -triggered reset. After a delay specified by inactive-delay, the GPIO -is driven active again. After a delay specified by wait-delay, the -restart handler completes allowing other restart handlers to be attempted. - -Required properties: -- compatible : should be "gpio-restart". -- gpios : The GPIO to set high/low, see "gpios property" in - Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be - low to reset the board set it to "Active Low", otherwise set - gpio to "Active High". - -Optional properties: -- open-source : Treat the GPIO as being open source and defer driving - it to when the restart is initiated. If this optional property is not - specified, the GPIO is initialized as an output in its inactive state. -- priority : A priority ranging from 0 to 255 (default 128) according to - the following guidelines: - 0: Restart handler of last resort, with limited restart - capabilities - 128: Default restart handler; use if no other restart handler is - expected to be available, and/or if restart functionality is - sufficient to restart the entire system - 255: Highest priority restart handler, will preempt all other - restart handlers -- active-delay: Delay (default 100) to wait after driving gpio active [ms] -- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms] -- wait-delay: Delay (default 3000) to wait after completing restart - sequence [ms] - -Examples: - -gpio-restart { - compatible = "gpio-restart"; - gpios = <&gpio 4 0>; - priority = <128>; - active-delay = <100>; - inactive-delay = <100>; - wait-delay = <3000>; -}; diff --git a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt new file mode 100644 index 0000000..d4eab92 --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt @@ -0,0 +1,36 @@ +Driver a GPIO line that can be used to turn the power off. + +The driver supports both level triggered and edge triggered power off. +At driver load time, the driver will request the given gpio line and +install a pm_power_off handler. If the optional properties 'input' is +not found, the GPIO line will be driven in the inactive +state. Otherwise its configured as an input. + +When the pm_power_off is called, the gpio is configured as an output, +and drive active, so triggering a level triggered power off +condition. This will also cause an inactive->active edge condition, so +triggering positive edge triggered power off. After a delay of 100ms, +the GPIO is set to inactive, thus causing an active->inactive edge, +triggering negative edge triggered power off. After another 100ms +delay the GPIO is driver active again. If the power is still on and +the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted. + +Required properties: +- compatible : should be "gpio-poweroff". +- gpios : The GPIO to set high/low, see "gpios property" in + Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be + low to power down the board set it to "Active Low", otherwise set + gpio to "Active High". + +Optional properties: +- input : Initially configure the GPIO line as an input. Only reconfigure + it to an output when the pm_power_off function is called. If this optional + property is not specified, the GPIO is initialized as an output in its + inactive state. + +Examples: + +gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio 4 0>; +}; diff --git a/Documentation/devicetree/bindings/power/reset/gpio-restart.txt b/Documentation/devicetree/bindings/power/reset/gpio-restart.txt new file mode 100644 index 0000000..af3701b --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/gpio-restart.txt @@ -0,0 +1,54 @@ +Drive a GPIO line that can be used to restart the system from a restart +handler. + +This binding supports level and edge triggered reset. At driver load +time, the driver will request the given gpio line and install a restart +handler. If the optional properties 'open-source' is not found, the GPIO line +will be driven in the inactive state. Otherwise its not driven until +the restart is initiated. + +When the system is restarted, the restart handler will be invoked in +priority order. The gpio is configured as an output, and driven active, +triggering a level triggered reset condition. This will also cause an +inactive->active edge condition, triggering positive edge triggered +reset. After a delay specified by active-delay, the GPIO is set to +inactive, thus causing an active->inactive edge, triggering negative edge +triggered reset. After a delay specified by inactive-delay, the GPIO +is driven active again. After a delay specified by wait-delay, the +restart handler completes allowing other restart handlers to be attempted. + +Required properties: +- compatible : should be "gpio-restart". +- gpios : The GPIO to set high/low, see "gpios property" in + Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be + low to reset the board set it to "Active Low", otherwise set + gpio to "Active High". + +Optional properties: +- open-source : Treat the GPIO as being open source and defer driving + it to when the restart is initiated. If this optional property is not + specified, the GPIO is initialized as an output in its inactive state. +- priority : A priority ranging from 0 to 255 (default 128) according to + the following guidelines: + 0: Restart handler of last resort, with limited restart + capabilities + 128: Default restart handler; use if no other restart handler is + expected to be available, and/or if restart functionality is + sufficient to restart the entire system + 255: Highest priority restart handler, will preempt all other + restart handlers +- active-delay: Delay (default 100) to wait after driving gpio active [ms] +- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms] +- wait-delay: Delay (default 3000) to wait after completing restart + sequence [ms] + +Examples: + +gpio-restart { + compatible = "gpio-restart"; + gpios = <&gpio 4 0>; + priority = <128>; + active-delay = <100>; + inactive-delay = <100>; + wait-delay = <3000>; +}; -- cgit v0.10.2 From 327819d1e52434de869aab2ee5183682357d8e6d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 18 Apr 2016 13:30:29 +0200 Subject: gpio: f7188x: fix edit mistake Fix a typo causing a build regression. Fixes: f90c6bdb690b ("gpio: f7188x: use the new open drain callback") Reported-by: Stephen Rothwell Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 58674ff..05aa538 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -328,7 +328,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *chip, data &= ~BIT(offset); else data |= BIT(offset); - superio_outb(sio->addr, gpio_data_mode(bank->regbase), data); + superio_outb(sio->addr, gpio_out_mode(bank->regbase), data); superio_exit(sio->addr); return 0; -- cgit v0.10.2 From 44c7288f791fa804a88f97496291ecf698fb3887 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Apr 2016 11:36:59 +0200 Subject: gpio: move gpiod_set_array_value_priv() This renames gpiod_set_array_value_priv() to gpiod_set_array_value_complex() and moves it to the gpiolib.h private header file so we can reuse it in the subsystem. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59a0d8e..bb3195d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1825,10 +1825,10 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip, } } -static void gpiod_set_array_value_priv(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, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) { int i = 0; @@ -1934,8 +1934,8 @@ void gpiod_set_raw_array_value(unsigned int array_size, { if (!desc_array) return; - gpiod_set_array_value_priv(true, false, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(true, false, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value); @@ -1956,8 +1956,8 @@ void gpiod_set_array_value(unsigned int array_size, { if (!desc_array) return; - gpiod_set_array_value_priv(false, false, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(false, false, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_array_value); @@ -2160,8 +2160,8 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size, might_sleep_if(extra_checks); if (!desc_array) return; - gpiod_set_array_value_priv(true, true, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(true, true, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep); @@ -2183,8 +2183,8 @@ void gpiod_set_array_value_cansleep(unsigned int array_size, might_sleep_if(extra_checks); if (!desc_array) return; - gpiod_set_array_value_priv(false, true, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(false, true, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index e30e5fd..2d9ea5e 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -141,6 +141,10 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags); struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum); +void gpiod_set_array_value_complex(bool raw, bool can_sleep, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); extern struct spinlock gpio_lock; extern struct list_head gpio_devices; -- cgit v0.10.2 From a89d6cb3b3c3226dfd8118eea7ec2b19635738f6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 14:47:50 +0200 Subject: gpio: revert bank bindings Keep the words talking about what a GPIO bank is, but remove the binding. We have not agreed that this is something we want to have. Acked-by: Rob Herring Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index f509ecf..c88d2cc 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -138,12 +138,6 @@ exposed in the device tree as an individual gpio-controller node, reflecting the fact that the hardware was synthesized by reusing the same IP block a few times over. -A GPIO controller may specify a bank ID. This is a hardware index that -indicate the logical order of the GPIO controller in the hardware architecture, -usually in the sequence 0, 1, 2 .. n. The hardware index may be different -from the order of register ranges and related to the backplane of how this -one bank is connected to the outside through a pin controller for example. - Optionally, a GPIO controller may have a "ngpios" property. This property indicates the number of in-use slots of available slots for GPIOs. The typical example is something like this: the hardware register is 32 bits @@ -165,7 +159,6 @@ gpio-controller@00000000 { reg = <0x00000000 0x1000>; gpio-controller; #gpio-cells = <2>; - gpio-bank = <0>; ngpios = <18>; } -- cgit v0.10.2 From 296ad4acb8efeffa456e344c73dc9459f4e9e1a0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 10:39:21 +0200 Subject: gpio: remove deps on ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIOLIB symbol currently require that ARCH_WANT_OPTIONAL_GPIOLIB or ARCH_REQUIRE_GPIOLIB is selected to be selectable. The ARCH_REQUIRE_GPIOLIB does only one thing: select GPIOLIB. This is just confusing: architectures that want GPIOLIB should be able to configure it in no matter what, and those who require it should just select GPIOLIB. It also creates problems for drivers that need to state "select GPIOLIB" to get dependencies: those depend on the selected architecture to select ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB first, and will cause compile errors for the few archs that state neither. These intermediary symbols need to go. As a first step, remove the dependencies so that: - ARCH_WANT_OPTIONAL_GPIOLIB becomes a noop (GPIOLIB will be available for everyone) and - "select ARCH_REQUIRE_GPIOLIB" can be replaced by just "select GPIOLIB" After this patch we can follow up with patches cleaning up the architectures one-by one and eventually remove the ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB symbols altogether. Reported-by: Michael Hennerich Cc: Michael Büsch Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f73f26b..a68d838 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -33,7 +33,6 @@ config ARCH_REQUIRE_GPIOLIB menuconfig GPIOLIB bool "GPIO Support" - depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB help This enables GPIO support through the generic GPIO library. You only need to enable this, if you also want to enable -- cgit v0.10.2 From 5a161394aeb0b36c1be7ef6f54103cd13c95b8a1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:10:42 +0200 Subject: avr32: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Haavard Skinnemoen Acked-by: Acked-by: Hans-Christian Noren Egtvedt Signed-off-by: Linus Walleij diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index b6878eb..18b8877 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -74,7 +74,7 @@ config PLATFORM_AT32AP select SUBARCH_AVR32B select MMU select PERFORMANCE_COUNTERS - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select GENERIC_ALLOCATOR select HAVE_FB_ATMEL -- cgit v0.10.2 From 769e4b8a3d84712db667a0fe55f6bdd4e1cfce8d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:32:21 +0200 Subject: metag: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: linux-metag@vger.kernel.org Acked-by: James Hogan Signed-off-by: Linus Walleij diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc index 973640f..50f979c 100644 --- a/arch/metag/Kconfig.soc +++ b/arch/metag/Kconfig.soc @@ -16,7 +16,6 @@ config META21_FPGA config SOC_TZ1090 bool "Toumaz Xenif TZ1090 SoC (Comet)" - select ARCH_WANT_OPTIONAL_GPIOLIB select IMGPDC_IRQ select METAG_LNKGET_AROUND_CACHE select METAG_META21 -- cgit v0.10.2 From 92cd663e4cd02c10f321ec2cf3c417b29fe8b387 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:30:21 +0200 Subject: alpha: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: linux-alpha@vger.kernel.org Acked-by: Matt Turner Signed-off-by: Linus Walleij diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9d8a858..fe99f89 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -13,7 +13,6 @@ config ALPHA select GENERIC_IRQ_PROBE select AUTO_IRQ_AFFINITY if SMP select GENERIC_IRQ_SHOW - select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_IPC_PARSE_VERSION select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE -- cgit v0.10.2 From e944b10ab03568e821145e38198197da2913af54 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:35:14 +0200 Subject: xtensa: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: Chris Zankel Cc: linux-xtensa@linux-xtensa.org Acked-by: Max Filippov Signed-off-by: Linus Walleij diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index e832d3e..85257af 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -5,7 +5,6 @@ config XTENSA def_bool y select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_IPC_PARSE_VERSION - select ARCH_WANT_OPTIONAL_GPIOLIB select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK -- cgit v0.10.2 From e05f2e187814b7b102c0f54c9a72c01e6bdb5360 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:17:49 +0200 Subject: m68k: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Geert Uytterhoeven Cc: linux-m68k@lists.linux-m68k.org Acked-by: Greg Ungerer Signed-off-by: Linus Walleij diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 0dfcf12..c1beb5a 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -22,11 +22,11 @@ config M68KCLASSIC config COLDFIRE bool "Coldfire CPU family support" - select ARCH_REQUIRE_GPIOLIB select ARCH_HAVE_CUSTOM_GPIO_H select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM + select GPIOLIB select HAVE_CLK endchoice -- cgit v0.10.2 From 2735e4c305be13b38680c5e2ddce131da2755ad5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:33:48 +0200 Subject: nios2: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: nios2-dev@lists.rocketboards.org Acked-by: Ley Foon Tan Signed-off-by: Linus Walleij diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 4375554..87ca653 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -1,6 +1,5 @@ config NIOS2 def_bool y - select ARCH_WANT_OPTIONAL_GPIOLIB select CLKSRC_OF select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS -- cgit v0.10.2 From f518abf00d503dc2cc330d189229fed926c424d8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:13:38 +0200 Subject: cris: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Mikael Starvik Cc: linux-cris-kernel@axis.com Acked-by: Jesper Nilsson Signed-off-by: Linus Walleij diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index e086f9e..99bda1b 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -61,7 +61,7 @@ config CRIS select CLONE_BACKWARDS2 select OLD_SIGSUSPEND select OLD_SIGACTION - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select IRQ_DOMAIN if ETRAX_ARCH_V32 select OF if ETRAX_ARCH_V32 select OF_EARLY_FLATTREE if ETRAX_ARCH_V32 -- cgit v0.10.2 From 30d473d4db623a84b3e8d708d332934ed2537fd8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:34:34 +0200 Subject: sparc: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: sparclinux@vger.kernel.org Acked-by: David S. Miller Signed-off-by: Linus Walleij diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 57ffaf2..6bd1b1c 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -21,7 +21,6 @@ config SPARC select HAVE_ARCH_KGDB if !SMP || SPARC64 select HAVE_ARCH_TRACEHOOK select SYSCTL_EXCEPTION_TRACE - select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select RTC_CLASS select RTC_DRV_M48T59 -- cgit v0.10.2 From 59851aa87c2ca92a1fd6b73e78a254242306b116 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 10:45:14 +0200 Subject: arc: select GPIOLIB directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of indirectly selecting GPIOLIB via the ARCH_REQUIRE_GPIOLIB symbol, just select GPIOLIB. Cc: Michael Büsch Cc: linux-snps-arc@lists.infradead.org Acked-by: Vineet Gupta Signed-off-by: Linus Walleij diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig index 426ac4b..c54d1ae 100644 --- a/arch/arc/plat-axs10x/Kconfig +++ b/arch/arc/plat-axs10x/Kconfig @@ -13,7 +13,7 @@ menuconfig ARC_PLAT_AXS10X select OF_GPIO select MIGHT_HAVE_PCI select GENERIC_IRQ_CHIP - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB help Support for the ARC AXS10x Software Development Platforms. diff --git a/arch/arc/plat-tb10x/Kconfig b/arch/arc/plat-tb10x/Kconfig index d14b3d3..149e091 100644 --- a/arch/arc/plat-tb10x/Kconfig +++ b/arch/arc/plat-tb10x/Kconfig @@ -21,7 +21,7 @@ menuconfig ARC_PLAT_TB10X select PINCTRL select PINCTRL_TB10X select PINMUX - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select GPIO_TB10X select TB10X_IRQC help -- cgit v0.10.2 From d3baee37f1488b0dea726597bb12a0086b233f8b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:29:50 +0100 Subject: input: adp5588-keys: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Michael Hennerich Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 21a62d0..53fe9a3 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -73,7 +73,7 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val) #ifdef CONFIG_GPIOLIB static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int val; @@ -93,7 +93,7 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) static void adp5588_gpio_set_value(struct gpio_chip *chip, unsigned off, int val) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); @@ -112,7 +112,7 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int ret; @@ -130,7 +130,7 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) static int adp5588_gpio_direction_output(struct gpio_chip *chip, unsigned off, int val) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int ret; @@ -210,7 +210,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad) mutex_init(&kpad->gpio_lock); - error = gpiochip_add(&kpad->gc); + error = gpiochip_add_data(&kpad->gc, kpad); if (error) { dev_err(dev, "gpiochip_add failed, err: %d\n", error); return error; -- cgit v0.10.2 From 3769a895b4a61b66085f97f8124df4833ee6e577 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 22:54:20 +0100 Subject: platform: x86: intel-pmic: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Feng Tang Signed-off-by: Linus Walleij diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 0e73fd1..63b371d 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -174,7 +174,7 @@ static int pmic_irq_type(struct irq_data *data, unsigned type) static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); + struct pmic_gpio *pg = gpiochip_get_data(chip); return pg->irq_base + offset; } @@ -279,7 +279,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) mutex_init(&pg->buslock); pg->chip.parent = dev; - retval = gpiochip_add(&pg->chip); + retval = gpiochip_add_data(&pg->chip, pg); if (retval) { pr_err("Can not add pmic gpio chip\n"); goto err; -- cgit v0.10.2 From 2d4443be10a70100cfdc1abcf1475a86bc62534b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:00:46 +0100 Subject: ssb: gpio_driver: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Hauke Mehrtens Cc: Michael Buesch Signed-off-by: Linus Walleij diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index f92e266..180e027 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c @@ -8,7 +8,7 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include +#include #include #include #include @@ -22,15 +22,10 @@ * Shared **************************************************/ -static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) -{ - return container_of(chip, struct ssb_bus, gpio); -} - #if IS_ENABLED(CONFIG_SSB_EMBEDDED) static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); if (bus->bustype == SSB_BUSTYPE_SSB) return irq_find_mapping(bus->irq_domain, gpio); @@ -45,7 +40,7 @@ static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); } @@ -53,7 +48,7 @@ static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); } @@ -61,7 +56,7 @@ static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); return 0; @@ -70,7 +65,7 @@ static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); @@ -79,7 +74,7 @@ static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); /* clear pulldown */ @@ -92,7 +87,7 @@ static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); /* clear pullup */ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); @@ -246,7 +241,7 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) if (err) return err; - err = gpiochip_add(chip); + err = gpiochip_add_data(chip, bus); if (err) { ssb_gpio_irq_chipco_domain_exit(bus); return err; @@ -263,7 +258,7 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); } @@ -271,7 +266,7 @@ static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); } @@ -279,7 +274,7 @@ static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); return 0; @@ -288,7 +283,7 @@ static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); @@ -439,7 +434,7 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) if (err) return err; - err = gpiochip_add(chip); + err = gpiochip_add_data(chip, bus); if (err) { ssb_gpio_irq_extif_domain_exit(bus); return err; -- cgit v0.10.2 From cbc3f10f9ead9c9f664a9dc6697c31312e36d50e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:06:50 +0100 Subject: staging: vme: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Manohar Vanga Cc: devel@driverdev.osuosl.org Acked-by: Martyn Welch Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index df992c3..6d361201 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -25,16 +25,11 @@ static const char driver_name[] = "pio2_gpio"; -static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip) -{ - return container_of(chip, struct pio2_card, gc); -} - static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset) { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -71,7 +66,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -100,7 +95,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -119,7 +114,7 @@ static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -205,7 +200,7 @@ int pio2_gpio_init(struct pio2_card *card) card->gc.set = pio2_gpio_set; /* This function adds a memory mapped GPIO chip */ - retval = gpiochip_add(&card->gc); + retval = gpiochip_add_data(&card->gc, card); if (retval) { dev_err(&card->vdev->dev, "Unable to register GPIO\n"); kfree(card->gc.label); -- cgit v0.10.2 From a00d60a0a2896bced073810fc86ea0764ac54939 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:11:05 +0100 Subject: serial: max310x: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Jiri Slaby Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 3f98165..3f6e0ab 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1036,7 +1036,7 @@ static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) { unsigned int val; - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; val = max310x_port_read(port, MAX310X_GPIODATA_REG); @@ -1046,7 +1046,7 @@ static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), @@ -1055,7 +1055,7 @@ static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4), 0); @@ -1066,7 +1066,7 @@ static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int max310x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), @@ -1183,7 +1183,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, s->gpio.base = -1; s->gpio.ngpio = devtype->nr * 4; s->gpio.can_sleep = 1; - ret = gpiochip_add(&s->gpio); + ret = gpiochip_add_data(&s->gpio, s); if (ret) goto out_uart; #endif -- cgit v0.10.2 From dee07cea5452a5d50c6273f7a0d3c1aaa7ce9508 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:15:53 +0100 Subject: serial: sc16is7xx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Jiri Slaby Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 025a426..e639361 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1104,8 +1104,7 @@ static const struct uart_ops sc16is7xx_ops = { static int sc16is7xx_gpio_get(struct gpio_chip *chip, unsigned offset) { unsigned int val; - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; val = sc16is7xx_port_read(port, SC16IS7XX_IOSTATE_REG); @@ -1115,8 +1114,7 @@ static int sc16is7xx_gpio_get(struct gpio_chip *chip, unsigned offset) static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), @@ -1126,8 +1124,7 @@ static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset), 0); @@ -1138,8 +1135,7 @@ static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip, static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int val) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), @@ -1210,7 +1206,7 @@ static int sc16is7xx_probe(struct device *dev, s->gpio.base = -1; s->gpio.ngpio = devtype->nr_gpio; s->gpio.can_sleep = 1; - ret = gpiochip_add(&s->gpio); + ret = gpiochip_add_data(&s->gpio, s); if (ret) goto out_thread; } -- cgit v0.10.2 From 14900363454b8244b41f77f42013a22db20bb2e2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:27:09 +0100 Subject: ASoC: rt5677: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Bard Liao Cc: Oder Chiou Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 33e290b..6021226 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4520,14 +4520,9 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, } #ifdef CONFIG_GPIOLIB -static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip) -{ - return container_of(chip, struct rt5677_priv, gpio_chip); -} - static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4548,7 +4543,7 @@ static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int rt5677_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4572,7 +4567,7 @@ static int rt5677_gpio_direction_out(struct gpio_chip *chip, static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); int value, ret; ret = regmap_read(rt5677->regmap, RT5677_GPIO_ST, &value); @@ -4584,7 +4579,7 @@ static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset) static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4638,7 +4633,7 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); struct regmap_irq_chip_data *data = rt5677->irq_data; int irq; @@ -4697,7 +4692,7 @@ static void rt5677_init_gpio(struct i2c_client *i2c) rt5677->gpio_chip.parent = &i2c->dev; rt5677->gpio_chip.base = -1; - ret = gpiochip_add(&rt5677->gpio_chip); + ret = gpiochip_add_data(&rt5677->gpio_chip, rt5677); if (ret != 0) dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); } -- cgit v0.10.2 From db1d127053c4c525086673e39691d274668a458d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:31:28 +0100 Subject: ASoC: wm5100: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 171a23d..512a9d2 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2236,14 +2237,9 @@ static irqreturn_t wm5100_edge_irq(int irq, void *data) } #ifdef CONFIG_GPIOLIB -static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip) -{ - return container_of(chip, struct wm5100_priv, gpio_chip); -} - static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT); @@ -2252,7 +2248,7 @@ static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm5100_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); int val, ret; val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT); @@ -2268,7 +2264,7 @@ static int wm5100_gpio_direction_out(struct gpio_chip *chip, static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); unsigned int reg; int ret; @@ -2281,7 +2277,7 @@ static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, WM5100_GP1_FN_MASK | WM5100_GP1_DIR, @@ -2313,7 +2309,7 @@ static void wm5100_init_gpio(struct i2c_client *i2c) else wm5100->gpio_chip.base = -1; - ret = gpiochip_add(&wm5100->gpio_chip); + ret = gpiochip_add_data(&wm5100->gpio_chip, wm5100); if (ret != 0) dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); } -- cgit v0.10.2 From 8f4160661fd251e651f24f61b7ba4c36898e2621 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:38:20 +0100 Subject: ASoC: wm8903: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a82b8bc..a26ca49 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -1766,11 +1766,6 @@ static int wm8903_resume(struct snd_soc_codec *codec) } #ifdef CONFIG_GPIOLIB -static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8903_priv, gpio_chip); -} - static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) { if (offset >= WM8903_NUM_GPIO) @@ -1781,7 +1776,7 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1799,7 +1794,7 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int reg; regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); @@ -1810,7 +1805,7 @@ static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1828,7 +1823,7 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, WM8903_GP1_LVL_MASK, @@ -1860,7 +1855,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) else wm8903->gpio_chip.base = -1; - ret = gpiochip_add(&wm8903->gpio_chip); + ret = gpiochip_add_data(&wm8903->gpio_chip, wm8903); if (ret != 0) dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); } -- cgit v0.10.2 From f42b6f5800b6d06442c193d4beb423b0186e7b6a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:41:55 +0100 Subject: ASoC: wm8962: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 8822360..7976df0 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -3307,14 +3307,9 @@ static void wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio) } #ifdef CONFIG_GPIOLIB -static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8962_priv, gpio_chip); -} - static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); /* The WM8962 GPIOs aren't linearly numbered. For simplicity * we export linear numbers and error out if the unsupported @@ -3337,7 +3332,7 @@ static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset) static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); struct snd_soc_codec *codec = wm8962->codec; snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, @@ -3347,7 +3342,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm8962_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); struct snd_soc_codec *codec = wm8962->codec; int ret, val; @@ -3386,7 +3381,7 @@ static void wm8962_init_gpio(struct snd_soc_codec *codec) else wm8962->gpio_chip.base = -1; - ret = gpiochip_add(&wm8962->gpio_chip); + ret = gpiochip_add_data(&wm8962->gpio_chip, wm8962); if (ret != 0) dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); } -- cgit v0.10.2 From c2aea142af6179d757424a21110da3fc90127e02 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:44:39 +0100 Subject: ASoC: wm8996: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index f99b34f..a730442 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2139,14 +2140,9 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } #ifdef CONFIG_GPIOLIB -static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8996_priv, gpio_chip); -} - static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT); @@ -2155,7 +2151,7 @@ static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm8996_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); int val; val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT); @@ -2167,7 +2163,7 @@ static int wm8996_gpio_direction_out(struct gpio_chip *chip, static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); unsigned int reg; int ret; @@ -2180,7 +2176,7 @@ static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, WM8996_GP1_FN_MASK | WM8996_GP1_DIR, @@ -2211,7 +2207,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996) else wm8996->gpio_chip.base = -1; - ret = gpiochip_add(&wm8996->gpio_chip); + ret = gpiochip_add_data(&wm8996->gpio_chip, wm8996); if (ret != 0) dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret); } -- cgit v0.10.2 From f7cb5120c4e0de10c3e069f5318417da0326fb45 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:48:29 +0100 Subject: ASoC: ac97: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Mark Brown Signed-off-by: Linus Walleij diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 7e0acd8..bc4a55b 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -59,8 +59,7 @@ static void soc_ac97_device_release(struct device *dev) #ifdef CONFIG_GPIOLIB static inline struct snd_soc_codec *gpio_to_codec(struct gpio_chip *chip) { - struct snd_ac97_gpio_priv *gpio_priv = - container_of(chip, struct snd_ac97_gpio_priv, gpio_chip); + struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip); return gpio_priv->codec; } @@ -98,8 +97,7 @@ static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset) static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct snd_ac97_gpio_priv *gpio_priv = - container_of(chip, struct snd_ac97_gpio_priv, gpio_chip); + struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip); struct snd_soc_codec *codec = gpio_to_codec(chip); gpio_priv->gpios_set &= ~(1 << offset); @@ -145,7 +143,7 @@ static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97, gpio_priv->gpio_chip.parent = codec->dev; gpio_priv->gpio_chip.base = -1; - ret = gpiochip_add(&gpio_priv->gpio_chip); + ret = gpiochip_add_data(&gpio_priv->gpio_chip, gpio_priv); if (ret != 0) dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); return ret; -- cgit v0.10.2 From 0c0451e7634564052a045d4398a91ea4ef1f755b Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 12 Apr 2016 13:52:31 +0300 Subject: gpio: omap: fix irq triggering in smart-idle wakeup mode Now GPIO IRQ loss is observed on dra7-evm after suspend/resume cycle in the following case: extcon_usb1(id_irq) -> pcf8575.gpio1 -> omapgpio6.gpio11 -> gic the extcon_usb1 is wake up source and it enables IRQ wake up for id_irq by calling enable/disable_irq_wake() during suspend/resume which, in turn, causes execution of omap_gpio_wake_enable(). And omap_gpio_wake_enable() will set/clear corresponding bit in GPIO_IRQWAKEN_x register. omapgpio6 configuration after boot - wakeup is enabled for GPIO IRQs by default from omap_gpio_irq_type: GPIO_IRQSTATUS_SET_0 | 0x00000400 GPIO_IRQSTATUS_CLR_0 | 0x00000400 GPIO_IRQWAKEN_0 | 0x00000400 GPIO_RISINGDETECT | 0x00000000 GPIO_FALLINGDETECT | 0x00000400 omapgpio6 configuration after after suspend/resume cycle: GPIO_IRQSTATUS_SET_0 | 0x00000400 GPIO_IRQSTATUS_CLR_0 | 0x00000400 GPIO_IRQWAKEN_0 | 0x00000000 <--- GPIO_RISINGDETECT | 0x00000000 GPIO_FALLINGDETECT | 0x00000400 As result, system will start to lose interrupts from pcf8575 GPIO expander, because when OMAP GPIO IP is in smart-idle wakeup mode, there is no guarantee that transition(s) on input non wake up GPIO pin will trigger asynchronous wake-up request to PRCM and then IRQ generation. IRQ will be generated when GPIO is in active mode - for example, some time after accessing GPIO bank registers IRQs will be generated normally, but issue will happen again once PRCM will put GPIO in low power smart-idle wakeup mode. Note 1. Issue is not reproduced if debounce clk is enabled for GPIO bank. Note 2. Issue hardly reproducible if GPIO pins group contains both wakeup/non-wakeup gpios - for example, it will be hard to reproduce issue with pin2 if GPIO_IRQWAKEN_0=0x1 GPIO_IRQSTATUS_SET_0=0x3 GPIO_FALLINGDETECT = 0x3 (TRM "Power Saving by Grouping the Edge/Level Detection"). Note 3. There nothing common bitween System wake up and OMAP GPIO bank IP wake up logic - the last one defines how the GPIO bank ON-IDLE-ON transition will happen inside SoC under control of PRCM. Hence, fix the problem by removing omap_set_gpio_wakeup() function completely and so keeping always in sync GPIO IRQ mask/unmask (IRQSTATUS_SET) and wake up enable (GPIO_IRQWAKEN) bits; and adding IRQCHIP_MASK_ON_SUSPEND flag in OMAP GPIO irqchip. That way non wakeup GPIO IRQs will be properly masked/unmask by IRQ PM core during suspend/resume cycle. Cc: Roger Quadros Signed-off-by: Grygorii Strashko Acked-by: Tony Lindgren Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 551dfa9..b98ede7 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -611,51 +611,12 @@ static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, omap_disable_gpio_irqbank(bank, BIT(offset)); } -/* - * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register. - * 1510 does not seem to have a wake-up register. If JTAG is connected - * to the target, system will wake up always on GPIO events. While - * system is running all registered GPIO interrupts need to have wake-up - * enabled. When system is suspended, only selected GPIO interrupts need - * to have wake-up enabled. - */ -static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, - int enable) -{ - u32 gpio_bit = BIT(offset); - unsigned long flags; - - if (bank->non_wakeup_gpios & gpio_bit) { - dev_err(bank->chip.parent, - "Unable to modify wakeup on non-wakeup GPIO%d\n", - offset); - return -EINVAL; - } - - raw_spin_lock_irqsave(&bank->lock, flags); - if (enable) - bank->context.wake_en |= gpio_bit; - else - bank->context.wake_en &= ~gpio_bit; - - writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); - raw_spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) { struct gpio_bank *bank = omap_irq_data_get_bank(d); - unsigned offset = d->hwirq; - int ret; - ret = omap_set_gpio_wakeup(bank, offset, enable); - if (!ret) - ret = irq_set_irq_wake(bank->irq, enable); - - return ret; + return irq_set_irq_wake(bank->irq, enable); } static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -1187,6 +1148,7 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_bus_lock = omap_gpio_irq_bus_lock, irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); + irqc->flags = IRQCHIP_MASK_ON_SUSPEND; bank->irq = platform_get_irq(pdev, 0); if (bank->irq <= 0) { -- cgit v0.10.2 From 451938d52fe838c766687484fd9a69e35d8a68bc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Apr 2016 10:23:44 +0200 Subject: gpio: clarify open drain/source docs Make the text clearer, remove reference to confusing "positive" and "negative" and elaborate a bit. Signed-off-by: Linus Walleij diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index ae6e029..6cb35a7 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -100,6 +100,10 @@ Both usecases require that the line be equipped with a pull-up resistor. This resistor will make the line tend to high level unless one of the transistors on the rail actively pulls it down. +The level on the line will go as high as the VDD on the pull-up resistor, which +may be higher than the level supported by the transistor, achieveing a +level-shift to the higher VDD. + Integrated electronics often have an output driver stage in the form of a CMOS "totem-pole" with one N-MOS and one P-MOS transistor where one of them drives the line high and one of them drives the line low. This is called a push-pull @@ -110,14 +114,18 @@ output. The "totem-pole" looks like so: OD ||--+ +--/ ---o|| P-MOS-FET | ||--+ -in --+ +----- out +IN --+ +----- out | ||--+ +--/ ----|| N-MOS-FET OS ||--+ | GND -You see the little "switches" named "OD" and "OS" that enable/disable the +The desired output signal (e.g. coming directly from some GPIO output register) +arrives at IN. The switches named "OD" and "OS" are normally closed, creating +a push-pull circuit. + +Consider the little "switches" named "OD" and "OS" that enable/disable the P-MOS or N-MOS transistor right after the split of the input. As you can see, either transistor will go totally numb if this switch is open. The totem-pole is then halved and give high impedance instead of actively driving the line @@ -128,8 +136,8 @@ Some GPIO hardware come in open drain / open source configuration. Some are hard-wired lines that will only support open drain or open source no matter what: there is only one transistor there. Some are software-configurable: by flipping a bit in a register the output can be configured as open drain -or open source, by flicking open the switches labeled "OD" and "OS" in the -drawing above. +or open source, in practice by flicking open the switches labeled "OD" and "OS" +in the drawing above. By disabling the P-MOS transistor, the output can be driven between GND and high impedance (open drain), and by disabling the N-MOS transistor, the output @@ -146,8 +154,8 @@ set in the machine file, or coming from other hardware descriptions. If this state can not be configured in hardware, i.e. if the GPIO hardware does not support open drain/open source in hardware, the GPIO library will instead use a trick: when a line is set as output, if the line is flagged as open -drain, and the output value is negative, it will be driven low as usual. But -if the output value is set to positive, it will instead *NOT* be driven high, +drain, and the IN output value is low, it will be driven low as usual. But +if the IN output value is set to high, it will instead *NOT* be driven high, instead it will be switched to input, as input mode is high impedance, thus achieveing an "open drain emulation" of sorts: electrically the behaviour will be identical, with the exception of possible hardware glitches when switching -- cgit v0.10.2 From 682366d5c93340b751bc547779209f502a80762e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Apr 2016 13:18:11 +0200 Subject: gpio: pl061: remove range check The gpiochip calls are already checking that the GPIO line offsets are in range. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 9afb415..70eb9ad 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -67,9 +67,6 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) unsigned long flags; unsigned char gpiodir; - if (offset >= gc->ngpio) - return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); gpiodir = readb(chip->base + GPIODIR); gpiodir &= ~(BIT(offset)); @@ -86,9 +83,6 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset, unsigned long flags; unsigned char gpiodir; - if (offset >= gc->ngpio) - return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); writeb(!!value << offset, chip->base + (BIT(offset + 2))); gpiodir = readb(chip->base + GPIODIR); -- cgit v0.10.2 From 3484f1be2dbf520ad150a0be11f04464b930a4e6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Apr 2016 13:18:59 +0200 Subject: gpio: pl061: implement .get_direction() Implement this callback so that the driver reports correctly the direction setting of each line. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 70eb9ad..6e3c143 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -61,6 +61,13 @@ struct pl061_gpio { #endif }; +static int pl061_get_direction(struct gpio_chip *gc, unsigned offset) +{ + struct pl061_gpio *chip = gpiochip_get_data(gc); + + return !(readb(chip->base + GPIODIR) & BIT(offset)); +} + static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) { struct pl061_gpio *chip = gpiochip_get_data(gc); @@ -315,6 +322,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) chip->gc.free = gpiochip_generic_free; } + chip->gc.get_direction = pl061_get_direction; chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value; -- cgit v0.10.2 From 171b92c830f48bd546e2d68d6f511b3d87e0544e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 25 Apr 2016 16:08:31 +0530 Subject: gpio: tegra: Don't open code of_device_get_match_data() Use of_device_get_match_data() for getting matched data instead of implementing this locally. Signed-off-by: Laxman Dewangan Reviewed-by: Stephen Warren Reviewed-by: Alexandre Courbot Acked-by: Thierry Reding Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 790bb11..1b0c497 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -75,6 +75,11 @@ struct tegra_gpio_bank { #endif }; +struct tegra_gpio_soc_config { + u32 bank_stride; + u32 upper_offset; +}; + static struct device *dev; static struct irq_domain *irq_domain; static void __iomem *regs; @@ -445,27 +450,6 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) }; -struct tegra_gpio_soc_config { - u32 bank_stride; - u32 upper_offset; -}; - -static struct tegra_gpio_soc_config tegra20_gpio_config = { - .bank_stride = 0x80, - .upper_offset = 0x800, -}; - -static struct tegra_gpio_soc_config tegra30_gpio_config = { - .bank_stride = 0x100, - .upper_offset = 0x80, -}; - -static const struct of_device_id tegra_gpio_of_match[] = { - { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, - { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, - { }, -}; - /* This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. */ @@ -473,8 +457,7 @@ static struct lock_class_key gpio_lock_class; static int tegra_gpio_probe(struct platform_device *pdev) { - const struct of_device_id *match; - struct tegra_gpio_soc_config *config; + const struct tegra_gpio_soc_config *config; struct resource *res; struct tegra_gpio_bank *bank; int ret; @@ -484,12 +467,11 @@ static int tegra_gpio_probe(struct platform_device *pdev) dev = &pdev->dev; - match = of_match_device(tegra_gpio_of_match, &pdev->dev); - if (!match) { + config = of_device_get_match_data(&pdev->dev); + if (!config) { dev_err(&pdev->dev, "Error: No device match found\n"); return -ENODEV; } - config = (struct tegra_gpio_soc_config *)match->data; tegra_gpio_bank_stride = config->bank_stride; tegra_gpio_upper_offset = config->upper_offset; @@ -578,6 +560,22 @@ static int tegra_gpio_probe(struct platform_device *pdev) return 0; } +static struct tegra_gpio_soc_config tegra20_gpio_config = { + .bank_stride = 0x80, + .upper_offset = 0x800, +}; + +static struct tegra_gpio_soc_config tegra30_gpio_config = { + .bank_stride = 0x100, + .upper_offset = 0x80, +}; + +static const struct of_device_id tegra_gpio_of_match[] = { + { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, + { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, + { }, +}; + static struct platform_driver tegra_gpio_driver = { .driver = { .name = "tegra-gpio", -- cgit v0.10.2 From 804f56804d480edc3463a91bbcb39e3b4abd2ac6 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 25 Apr 2016 16:08:32 +0530 Subject: gpio: tegra: Make of_device_id compatible data to constant The data member of the of_device_id is the constant type and hence all static structure which is used for this initialisation as static. Signed-off-by: Laxman Dewangan Suggested-by: Thierry Reding Reviewed-by: Stephen Warren Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 1b0c497..cd69422 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -560,12 +560,12 @@ static int tegra_gpio_probe(struct platform_device *pdev) return 0; } -static struct tegra_gpio_soc_config tegra20_gpio_config = { +static const struct tegra_gpio_soc_config tegra20_gpio_config = { .bank_stride = 0x80, .upper_offset = 0x800, }; -static struct tegra_gpio_soc_config tegra30_gpio_config = { +static const struct tegra_gpio_soc_config tegra30_gpio_config = { .bank_stride = 0x100, .upper_offset = 0x80, }; -- cgit v0.10.2 From b546be0db955840e2c14aae5d8e5f93a456f9982 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 25 Apr 2016 16:08:33 +0530 Subject: gpio: tegra: Get rid of all file scoped global variables Move the file scoped multiple global variable from Tegra GPIO driver to the structure and make this as gpiochip data which can be referred from GPIO chip callbacks. Signed-off-by: Laxman Dewangan Reviewed-by: Stephen Warren Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index cd69422..653825d 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -35,24 +35,24 @@ #define GPIO_PORT(x) (((x) >> 3) & 0x3) #define GPIO_BIT(x) ((x) & 0x7) -#define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \ +#define GPIO_REG(tgi, x) (GPIO_BANK(x) * tgi->soc->bank_stride + \ GPIO_PORT(x) * 4) -#define GPIO_CNF(x) (GPIO_REG(x) + 0x00) -#define GPIO_OE(x) (GPIO_REG(x) + 0x10) -#define GPIO_OUT(x) (GPIO_REG(x) + 0X20) -#define GPIO_IN(x) (GPIO_REG(x) + 0x30) -#define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40) -#define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50) -#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) -#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) - -#define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00) -#define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10) -#define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20) -#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40) -#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50) -#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60) +#define GPIO_CNF(t, x) (GPIO_REG(t, x) + 0x00) +#define GPIO_OE(t, x) (GPIO_REG(t, x) + 0x10) +#define GPIO_OUT(t, x) (GPIO_REG(t, x) + 0X20) +#define GPIO_IN(t, x) (GPIO_REG(t, x) + 0x30) +#define GPIO_INT_STA(t, x) (GPIO_REG(t, x) + 0x40) +#define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50) +#define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60) +#define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70) + +#define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00) +#define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10) +#define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20) +#define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40) +#define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50) +#define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60) #define GPIO_INT_LVL_MASK 0x010101 #define GPIO_INT_LVL_EDGE_RISING 0x000101 @@ -61,6 +61,8 @@ #define GPIO_INT_LVL_LEVEL_HIGH 0x000001 #define GPIO_INT_LVL_LEVEL_LOW 0x000000 +struct tegra_gpio_info; + struct tegra_gpio_bank { int bank; int irq; @@ -73,6 +75,7 @@ struct tegra_gpio_bank { u32 int_lvl[4]; u32 wake_enb[4]; #endif + struct tegra_gpio_info *tgi; }; struct tegra_gpio_soc_config { @@ -80,22 +83,27 @@ struct tegra_gpio_soc_config { u32 upper_offset; }; -static struct device *dev; -static struct irq_domain *irq_domain; -static void __iomem *regs; -static u32 tegra_gpio_bank_count; -static u32 tegra_gpio_bank_stride; -static u32 tegra_gpio_upper_offset; -static struct tegra_gpio_bank *tegra_gpio_banks; +struct tegra_gpio_info { + struct device *dev; + void __iomem *regs; + struct irq_domain *irq_domain; + struct tegra_gpio_bank *bank_info; + const struct tegra_gpio_soc_config *soc; + struct gpio_chip gc; + struct irq_chip ic; + struct lock_class_key lock_class; + u32 bank_count; +}; -static inline void tegra_gpio_writel(u32 val, u32 reg) +static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi, + u32 val, u32 reg) { - __raw_writel(val, regs + reg); + __raw_writel(val, tgi->regs + reg); } -static inline u32 tegra_gpio_readl(u32 reg) +static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 reg) { - return __raw_readl(regs + reg); + return __raw_readl(tgi->regs + reg); } static int tegra_gpio_compose(int bank, int port, int bit) @@ -103,24 +111,25 @@ static int tegra_gpio_compose(int bank, int port, int bit) return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7); } -static void tegra_gpio_mask_write(u32 reg, int gpio, int value) +static void tegra_gpio_mask_write(struct tegra_gpio_info *tgi, u32 reg, + int gpio, int value) { u32 val; val = 0x100 << GPIO_BIT(gpio); if (value) val |= 1 << GPIO_BIT(gpio); - tegra_gpio_writel(val, reg); + tegra_gpio_writel(tgi, val, reg); } -static void tegra_gpio_enable(int gpio) +static void tegra_gpio_enable(struct tegra_gpio_info *tgi, int gpio) { - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); + tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 1); } -static void tegra_gpio_disable(int gpio) +static void tegra_gpio_disable(struct tegra_gpio_info *tgi, int gpio) { - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); + tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0); } static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -130,83 +139,90 @@ static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) { + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + pinctrl_free_gpio(offset); - tegra_gpio_disable(offset); + tegra_gpio_disable(tgi, offset); } static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value); + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + + tegra_gpio_mask_write(tgi, GPIO_MSK_OUT(tgi, offset), offset, value); } static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) { + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + int bval = BIT(GPIO_BIT(offset)); + /* If gpio is in output mode then read from the out value */ - if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1) - return (tegra_gpio_readl(GPIO_OUT(offset)) >> - GPIO_BIT(offset)) & 0x1; + if (tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)) & bval) + return !!(tegra_gpio_readl(tgi, GPIO_OUT(tgi, offset)) & bval); - return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; + return !!(tegra_gpio_readl(tgi, GPIO_IN(tgi, offset)) & bval); } static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0); - tegra_gpio_enable(offset); + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + + tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0); + tegra_gpio_enable(tgi, offset); return 0; } static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + tegra_gpio_set(chip, offset, value); - tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1); - tegra_gpio_enable(offset); + tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1); + tegra_gpio_enable(tgi, offset); return 0; } static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - return irq_find_mapping(irq_domain, offset); -} + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); -static struct gpio_chip tegra_gpio_chip = { - .label = "tegra-gpio", - .request = tegra_gpio_request, - .free = tegra_gpio_free, - .direction_input = tegra_gpio_direction_input, - .get = tegra_gpio_get, - .direction_output = tegra_gpio_direction_output, - .set = tegra_gpio_set, - .to_irq = tegra_gpio_to_irq, - .base = 0, -}; + return irq_find_mapping(tgi->irq_domain, offset); +} static void tegra_gpio_irq_ack(struct irq_data *d) { + struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); + struct tegra_gpio_info *tgi = bank->tgi; int gpio = d->hwirq; - tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); + tegra_gpio_writel(tgi, 1 << GPIO_BIT(gpio), GPIO_INT_CLR(tgi, gpio)); } static void tegra_gpio_irq_mask(struct irq_data *d) { + struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); + struct tegra_gpio_info *tgi = bank->tgi; int gpio = d->hwirq; - tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0); + tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0); } static void tegra_gpio_irq_unmask(struct irq_data *d) { + struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); + struct tegra_gpio_info *tgi = bank->tgi; int gpio = d->hwirq; - tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1); + tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1); } static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) { int gpio = d->hwirq; struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); + struct tegra_gpio_info *tgi = bank->tgi; int port = GPIO_PORT(gpio); int lvl_type; int val; @@ -238,23 +254,24 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - ret = gpiochip_lock_as_irq(&tegra_gpio_chip, gpio); + ret = gpiochip_lock_as_irq(&tgi->gc, gpio); if (ret) { - dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio); + dev_err(tgi->dev, + "unable to lock Tegra GPIO %d as IRQ\n", gpio); return ret; } spin_lock_irqsave(&bank->lvl_lock[port], flags); - val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); + val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); val |= lvl_type << GPIO_BIT(gpio); - tegra_gpio_writel(val, GPIO_INT_LVL(gpio)); + tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio)); spin_unlock_irqrestore(&bank->lvl_lock[port], flags); - tegra_gpio_mask_write(GPIO_MSK_OE(gpio), gpio, 0); - tegra_gpio_enable(gpio); + tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0); + tegra_gpio_enable(tgi, gpio); if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) irq_set_handler_locked(d, handle_level_irq); @@ -266,9 +283,11 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) static void tegra_gpio_irq_shutdown(struct irq_data *d) { + struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); + struct tegra_gpio_info *tgi = bank->tgi; int gpio = d->hwirq; - gpiochip_unlock_as_irq(&tegra_gpio_chip, gpio); + gpiochip_unlock_as_irq(&tgi->gc, gpio); } static void tegra_gpio_irq_handler(struct irq_desc *desc) @@ -276,19 +295,24 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) int port; int pin; int unmasked = 0; + int gpio; + u32 lvl; + unsigned long sta; struct irq_chip *chip = irq_desc_get_chip(desc); struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc); + struct tegra_gpio_info *tgi = bank->tgi; chained_irq_enter(chip, desc); for (port = 0; port < 4; port++) { - int gpio = tegra_gpio_compose(bank->bank, port, 0); - unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & - tegra_gpio_readl(GPIO_INT_ENB(gpio)); - u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio)); + gpio = tegra_gpio_compose(bank->bank, port, 0); + sta = tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)) & + tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio)); + lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); for_each_set_bit(pin, &sta, 8) { - tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio)); + tegra_gpio_writel(tgi, 1 << pin, + GPIO_INT_CLR(tgi, gpio)); /* if gpio is edge triggered, clear condition * before executing the handler so that we don't @@ -311,22 +335,29 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) #ifdef CONFIG_PM_SLEEP static int tegra_gpio_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); unsigned long flags; int b; int p; local_irq_save(flags); - for (b = 0; b < tegra_gpio_bank_count; b++) { - struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; + for (b = 0; b < tgi->bank_count; b++) { + struct tegra_gpio_bank *bank = &tgi->bank_info[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); - tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio)); - tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio)); - tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio)); - tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); - tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); + tegra_gpio_writel(tgi, bank->cnf[p], + GPIO_CNF(tgi, gpio)); + tegra_gpio_writel(tgi, bank->out[p], + GPIO_OUT(tgi, gpio)); + tegra_gpio_writel(tgi, bank->oe[p], + GPIO_OE(tgi, gpio)); + tegra_gpio_writel(tgi, bank->int_lvl[p], + GPIO_INT_LVL(tgi, gpio)); + tegra_gpio_writel(tgi, bank->int_enb[p], + GPIO_INT_ENB(tgi, gpio)); } } @@ -336,25 +367,32 @@ static int tegra_gpio_resume(struct device *dev) static int tegra_gpio_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); unsigned long flags; int b; int p; local_irq_save(flags); - for (b = 0; b < tegra_gpio_bank_count; b++) { - struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; + for (b = 0; b < tgi->bank_count; b++) { + struct tegra_gpio_bank *bank = &tgi->bank_info[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); - bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio)); - bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio)); - bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); - bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); - bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); + bank->cnf[p] = tegra_gpio_readl(tgi, + GPIO_CNF(tgi, gpio)); + bank->out[p] = tegra_gpio_readl(tgi, + GPIO_OUT(tgi, gpio)); + bank->oe[p] = tegra_gpio_readl(tgi, + GPIO_OE(tgi, gpio)); + bank->int_enb[p] = tegra_gpio_readl(tgi, + GPIO_INT_ENB(tgi, gpio)); + bank->int_lvl[p] = tegra_gpio_readl(tgi, + GPIO_INT_LVL(tgi, gpio)); /* Enable gpio irq for wake up source */ - tegra_gpio_writel(bank->wake_enb[p], - GPIO_INT_ENB(gpio)); + tegra_gpio_writel(tgi, bank->wake_enb[p], + GPIO_INT_ENB(tgi, gpio)); } } local_irq_restore(flags); @@ -387,22 +425,23 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) static int dbg_gpio_show(struct seq_file *s, void *unused) { + struct tegra_gpio_info *tgi = s->private; int i; int j; - for (i = 0; i < tegra_gpio_bank_count; i++) { + for (i = 0; i < tgi->bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", i, j, - tegra_gpio_readl(GPIO_CNF(gpio)), - tegra_gpio_readl(GPIO_OE(gpio)), - tegra_gpio_readl(GPIO_OUT(gpio)), - tegra_gpio_readl(GPIO_IN(gpio)), - tegra_gpio_readl(GPIO_INT_STA(gpio)), - tegra_gpio_readl(GPIO_INT_ENB(gpio)), - tegra_gpio_readl(GPIO_INT_LVL(gpio))); + tegra_gpio_readl(tgi, GPIO_CNF(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_OE(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_OUT(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_IN(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio)), + tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio))); } } return 0; @@ -410,7 +449,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) static int dbg_gpio_open(struct inode *inode, struct file *file) { - return single_open(file, dbg_gpio_show, &inode->i_private); + return single_open(file, dbg_gpio_show, inode->i_private); } static const struct file_operations debug_fops = { @@ -420,44 +459,28 @@ static const struct file_operations debug_fops = { .release = single_release, }; -static void tegra_gpio_debuginit(void) +static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) { (void) debugfs_create_file("tegra_gpio", S_IRUGO, - NULL, NULL, &debug_fops); + NULL, tgi, &debug_fops); } #else -static inline void tegra_gpio_debuginit(void) +static inline void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) { } #endif -static struct irq_chip tegra_gpio_irq_chip = { - .name = "GPIO", - .irq_ack = tegra_gpio_irq_ack, - .irq_mask = tegra_gpio_irq_mask, - .irq_unmask = tegra_gpio_irq_unmask, - .irq_set_type = tegra_gpio_irq_set_type, - .irq_shutdown = tegra_gpio_irq_shutdown, -#ifdef CONFIG_PM_SLEEP - .irq_set_wake = tegra_gpio_irq_set_wake, -#endif -}; - static const struct dev_pm_ops tegra_gpio_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) }; -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - static int tegra_gpio_probe(struct platform_device *pdev) { const struct tegra_gpio_soc_config *config; + struct tegra_gpio_info *tgi; struct resource *res; struct tegra_gpio_bank *bank; int ret; @@ -465,88 +488,111 @@ static int tegra_gpio_probe(struct platform_device *pdev) int i; int j; - dev = &pdev->dev; - config = of_device_get_match_data(&pdev->dev); if (!config) { dev_err(&pdev->dev, "Error: No device match found\n"); return -ENODEV; } - tegra_gpio_bank_stride = config->bank_stride; - tegra_gpio_upper_offset = config->upper_offset; + tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL); + if (!tgi) + return -ENODEV; + + tgi->soc = config; + tgi->dev = &pdev->dev; for (;;) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count); + res = platform_get_resource(pdev, IORESOURCE_IRQ, + tgi->bank_count); if (!res) break; - tegra_gpio_bank_count++; + tgi->bank_count++; } - if (!tegra_gpio_bank_count) { + if (!tgi->bank_count) { dev_err(&pdev->dev, "Missing IRQ resource\n"); return -ENODEV; } - tegra_gpio_chip.ngpio = tegra_gpio_bank_count * 32; + tgi->gc.label = "tegra-gpio"; + tgi->gc.request = tegra_gpio_request; + tgi->gc.free = tegra_gpio_free; + tgi->gc.direction_input = tegra_gpio_direction_input; + tgi->gc.get = tegra_gpio_get; + tgi->gc.direction_output = tegra_gpio_direction_output; + tgi->gc.set = tegra_gpio_set; + tgi->gc.to_irq = tegra_gpio_to_irq; + tgi->gc.base = 0; + tgi->gc.ngpio = tgi->bank_count * 32; + tgi->gc.parent = &pdev->dev; + tgi->gc.of_node = pdev->dev.of_node; + + tgi->ic.name = "GPIO"; + tgi->ic.irq_ack = tegra_gpio_irq_ack; + tgi->ic.irq_mask = tegra_gpio_irq_mask; + tgi->ic.irq_unmask = tegra_gpio_irq_unmask; + tgi->ic.irq_set_type = tegra_gpio_irq_set_type; + tgi->ic.irq_shutdown = tegra_gpio_irq_shutdown; +#ifdef CONFIG_PM_SLEEP + tgi->ic.irq_set_wake = tegra_gpio_irq_set_wake; +#endif + + platform_set_drvdata(pdev, tgi); - tegra_gpio_banks = devm_kzalloc(&pdev->dev, - tegra_gpio_bank_count * sizeof(*tegra_gpio_banks), - GFP_KERNEL); - if (!tegra_gpio_banks) + tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * + sizeof(*tgi->bank_info), GFP_KERNEL); + if (!tgi->bank_info) return -ENODEV; - irq_domain = irq_domain_add_linear(pdev->dev.of_node, - tegra_gpio_chip.ngpio, - &irq_domain_simple_ops, NULL); - if (!irq_domain) + tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node, + tgi->gc.ngpio, + &irq_domain_simple_ops, NULL); + if (!tgi->irq_domain) return -ENODEV; - for (i = 0; i < tegra_gpio_bank_count; i++) { + for (i = 0; i < tgi->bank_count; i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, i); if (!res) { dev_err(&pdev->dev, "Missing IRQ resource\n"); return -ENODEV; } - bank = &tegra_gpio_banks[i]; + bank = &tgi->bank_info[i]; bank->bank = i; bank->irq = res->start; + bank->tgi = tgi; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) - return PTR_ERR(regs); + tgi->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(tgi->regs)) + return PTR_ERR(tgi->regs); - for (i = 0; i < tegra_gpio_bank_count; i++) { + for (i = 0; i < tgi->bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); - tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); + tegra_gpio_writel(tgi, 0x00, GPIO_INT_ENB(tgi, gpio)); } } - tegra_gpio_chip.of_node = pdev->dev.of_node; - - ret = devm_gpiochip_add_data(&pdev->dev, &tegra_gpio_chip, NULL); + ret = devm_gpiochip_add_data(&pdev->dev, &tgi->gc, tgi); if (ret < 0) { - irq_domain_remove(irq_domain); + irq_domain_remove(tgi->irq_domain); return ret; } - for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { - int irq = irq_create_mapping(irq_domain, gpio); + for (gpio = 0; gpio < tgi->gc.ngpio; gpio++) { + int irq = irq_create_mapping(tgi->irq_domain, gpio); /* No validity check; all Tegra GPIOs are valid IRQs */ - bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; + bank = &tgi->bank_info[GPIO_BANK(gpio)]; - irq_set_lockdep_class(irq, &gpio_lock_class); + irq_set_lockdep_class(irq, &tgi->lock_class); irq_set_chip_data(irq, bank); - irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, - handle_simple_irq); + irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq); } - for (i = 0; i < tegra_gpio_bank_count; i++) { - bank = &tegra_gpio_banks[i]; + for (i = 0; i < tgi->bank_count; i++) { + bank = &tgi->bank_info[i]; irq_set_chained_handler_and_data(bank->irq, tegra_gpio_irq_handler, bank); @@ -555,7 +601,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) spin_lock_init(&bank->lvl_lock[j]); } - tegra_gpio_debuginit(); + tegra_gpio_debuginit(tgi); return 0; } -- cgit v0.10.2 From 3737de42afb8d76f405689a4699e8e5dd5e2ef96 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 25 Apr 2016 16:08:34 +0530 Subject: gpio: tegra: Add support for gpio debounce NVIDIA's Tegra210 support the HW debounce in the GPIO controller for all its GPIO pins. Add support for setting debounce timing by implementing the set_debounce callback of gpiochip. Signed-off-by: Laxman Dewangan Reviewed-by: Stephen Warren Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 653825d..b3ddd92 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -46,10 +46,13 @@ #define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50) #define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60) #define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70) +#define GPIO_DBC_CNT(t, x) (GPIO_REG(t, x) + 0xF0) + #define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00) #define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10) #define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20) +#define GPIO_MSK_DBC_EN(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x30) #define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40) #define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50) #define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60) @@ -67,6 +70,7 @@ struct tegra_gpio_bank { int bank; int irq; spinlock_t lvl_lock[4]; + spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */ #ifdef CONFIG_PM_SLEEP u32 cnf[4]; u32 out[4]; @@ -74,11 +78,14 @@ struct tegra_gpio_bank { u32 int_enb[4]; u32 int_lvl[4]; u32 wake_enb[4]; + u32 dbc_enb[4]; #endif + u32 dbc_cnt[4]; struct tegra_gpio_info *tgi; }; struct tegra_gpio_soc_config { + bool debounce_supported; u32 bank_stride; u32 upper_offset; }; @@ -184,6 +191,39 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, return 0; } +static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned int debounce) +{ + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)]; + unsigned int debounce_ms = DIV_ROUND_UP(debounce, 1000); + unsigned long flags; + int port; + + if (!debounce_ms) { + tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), + offset, 0); + return 0; + } + + debounce_ms = min(debounce_ms, 255U); + port = GPIO_PORT(offset); + + /* There is only one debounce count register per port and hence + * set the maximum of current and requested debounce time. + */ + spin_lock_irqsave(&bank->dbc_lock[port], flags); + if (bank->dbc_cnt[port] < debounce_ms) { + tegra_gpio_writel(tgi, debounce_ms, GPIO_DBC_CNT(tgi, offset)); + bank->dbc_cnt[port] = debounce_ms; + } + spin_unlock_irqrestore(&bank->dbc_lock[port], flags); + + tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), offset, 1); + + return 0; +} + static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); @@ -350,6 +390,14 @@ static int tegra_gpio_resume(struct device *dev) unsigned int gpio = (b<<5) | (p<<3); tegra_gpio_writel(tgi, bank->cnf[p], GPIO_CNF(tgi, gpio)); + + if (tgi->soc->debounce_supported) { + tegra_gpio_writel(tgi, bank->dbc_cnt[p], + GPIO_DBC_CNT(tgi, gpio)); + tegra_gpio_writel(tgi, bank->dbc_enb[p], + GPIO_MSK_DBC_EN(tgi, gpio)); + } + tegra_gpio_writel(tgi, bank->out[p], GPIO_OUT(tgi, gpio)); tegra_gpio_writel(tgi, bank->oe[p], @@ -385,6 +433,13 @@ static int tegra_gpio_suspend(struct device *dev) GPIO_OUT(tgi, gpio)); bank->oe[p] = tegra_gpio_readl(tgi, GPIO_OE(tgi, gpio)); + if (tgi->soc->debounce_supported) { + bank->dbc_enb[p] = tegra_gpio_readl(tgi, + GPIO_MSK_DBC_EN(tgi, gpio)); + bank->dbc_enb[p] = (bank->dbc_enb[p] << 8) | + bank->dbc_enb[p]; + } + bank->int_enb[p] = tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio)); bank->int_lvl[p] = tegra_gpio_readl(tgi, @@ -538,6 +593,9 @@ static int tegra_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tgi); + if (config->debounce_supported) + tgi->gc.set_debounce = tegra_gpio_set_debounce; + tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * sizeof(*tgi->bank_info), GFP_KERNEL); if (!tgi->bank_info) @@ -597,8 +655,10 @@ static int tegra_gpio_probe(struct platform_device *pdev) irq_set_chained_handler_and_data(bank->irq, tegra_gpio_irq_handler, bank); - for (j = 0; j < 4; j++) + for (j = 0; j < 4; j++) { spin_lock_init(&bank->lvl_lock[j]); + spin_lock_init(&bank->dbc_lock[j]); + } } tegra_gpio_debuginit(tgi); @@ -616,7 +676,14 @@ static const struct tegra_gpio_soc_config tegra30_gpio_config = { .upper_offset = 0x80, }; +static const struct tegra_gpio_soc_config tegra210_gpio_config = { + .debounce_supported = true, + .bank_stride = 0x100, + .upper_offset = 0x80, +}; + static const struct of_device_id tegra_gpio_of_match[] = { + { .compatible = "nvidia,tegra210-gpio", .data = &tegra210_gpio_config }, { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, { }, -- cgit v0.10.2 From a8fa91a74fc385da5d52fd1008c8fd322154cad8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Apr 2016 14:10:08 +0200 Subject: gpio/qoriq: select IRQ_DOMAIN The gpio-mpc8xxx driver requires IRQ domains but can be built without them, resulting on a failure to build certain randconfigs on ARM: drivers/gpio/gpio-mpc8xxx.c: In function 'mpc8xxx_gpio_to_irq': drivers/gpio/gpio-mpc8xxx.c:92:10: error: implicit declaration of function 'irq_create_mapping' [-Werror=implicit-function-declaration] return irq_create_mapping(mpc8xxx_gc->irq, offset); This selects IRQ_DOMAIN from the driver to ensure we can build it. Signed-off-by: Arnd Bergmann Fixes: 5df7fd46b70b ("gpio/qoriq: Add qoriq platforms support") Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a68d838..d00e7b6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -303,6 +303,7 @@ config GPIO_MPC8XXX FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \ COMPILE_TEST select GPIO_GENERIC + select IRQ_DOMAIN help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. -- cgit v0.10.2 From e81591815de05572ed28cbdca631d4d97f0bd059 Mon Sep 17 00:00:00 2001 From: Jiang Qiu Date: Thu, 28 Apr 2016 17:32:01 +0800 Subject: gpio: dwapb: remove name from dwapb_port_property This patch removed the name property from dwapb_port_property. The name property is redundant, since we can get this info from dwapb_gpio dev node. Reviewed-by: Andy Shevchenko Signed-off-by: Jiang Qiu Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 597de1e..772d743 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -409,8 +409,8 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout, NULL, false); if (err) { - dev_err(gpio->dev, "failed to init gpio chip for %s\n", - pp->name); + dev_err(gpio->dev, "failed to init gpio chip for port%d\n", + port->idx); return err; } @@ -429,8 +429,8 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, err = gpiochip_add_data(&port->gc, port); if (err) - dev_err(gpio->dev, "failed to register gpiochip for %s\n", - pp->name); + dev_err(gpio->dev, "failed to register gpiochip for port%d\n", + port->idx); else port->is_registered = true; @@ -480,15 +480,16 @@ dwapb_gpio_get_pdata_of(struct device *dev) if (of_property_read_u32(port_np, "reg", &pp->idx) || pp->idx >= DWAPB_MAX_PORTS) { - dev_err(dev, "missing/invalid port index for %s\n", - port_np->full_name); + dev_err(dev, + "missing/invalid port index for port%d\n", i); return ERR_PTR(-EINVAL); } if (of_property_read_u32(port_np, "snps,nr-gpios", &pp->ngpio)) { - dev_info(dev, "failed to get number of gpios for %s\n", - port_np->full_name); + dev_info(dev, + "failed to get number of gpios for port%d\n", + i); pp->ngpio = 32; } @@ -499,15 +500,12 @@ dwapb_gpio_get_pdata_of(struct device *dev) if (pp->idx == 0 && of_property_read_bool(port_np, "interrupt-controller")) { pp->irq = irq_of_parse_and_map(port_np, 0); - if (!pp->irq) { - dev_warn(dev, "no irq for bank %s\n", - port_np->full_name); - } + if (!pp->irq) + dev_warn(dev, "no irq for port%d\n", pp->idx); } pp->irq_shared = false; pp->gpio_base = -1; - pp->name = port_np->full_name; } return pdata; diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index bdc5e27..a4ef99b 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -220,7 +220,6 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) /* Set the properties for portA */ pdata->properties->node = NULL; - pdata->properties->name = "intel-quark-x1000-gpio-portA"; pdata->properties->idx = 0; pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO; pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE; diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h index 28702c8..955b579 100644 --- a/include/linux/platform_data/gpio-dwapb.h +++ b/include/linux/platform_data/gpio-dwapb.h @@ -16,7 +16,6 @@ struct dwapb_port_property { struct device_node *node; - const char *name; unsigned int idx; unsigned int ngpio; unsigned int gpio_base; -- cgit v0.10.2 From 4ba8cfa79f44a9489b1d562430cb70fb53200adb Mon Sep 17 00:00:00 2001 From: Jiang Qiu Date: Thu, 28 Apr 2016 17:32:02 +0800 Subject: gpio: dwapb: convert device node to fwnode This patch converts device node to fwnode for dwapb driver, so as to provide a unified fwnode for DT and ACPI bindings. Tested-by: Alan Tull Acked-by: Andy Shevchenko Signed-off-by: Jiang Qiu Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 772d743..7517c2f 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -290,14 +291,14 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, struct dwapb_port_property *pp) { struct gpio_chip *gc = &port->gc; - struct device_node *node = pp->node; + struct fwnode_handle *fwnode = pp->fwnode; struct irq_chip_generic *irq_gc = NULL; unsigned int hwirq, ngpio = gc->ngpio; struct irq_chip_type *ct; int err, i; - gpio->domain = irq_domain_add_linear(node, ngpio, - &irq_generic_chip_ops, gpio); + gpio->domain = irq_domain_create_linear(fwnode, ngpio, + &irq_generic_chip_ops, gpio); if (!gpio->domain) return; @@ -415,7 +416,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, } #ifdef CONFIG_OF_GPIO - port->gc.of_node = pp->node; + port->gc.of_node = to_of_node(pp->fwnode); #endif port->gc.ngpio = pp->ngpio; port->gc.base = pp->gpio_base; @@ -447,19 +448,15 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) } static struct dwapb_platform_data * -dwapb_gpio_get_pdata_of(struct device *dev) +dwapb_gpio_get_pdata(struct device *dev) { - struct device_node *node, *port_np; + struct fwnode_handle *fwnode; struct dwapb_platform_data *pdata; struct dwapb_port_property *pp; int nports; int i; - node = dev->of_node; - if (!IS_ENABLED(CONFIG_OF_GPIO) || !node) - return ERR_PTR(-ENODEV); - - nports = of_get_child_count(node); + nports = device_get_child_node_count(dev); if (nports == 0) return ERR_PTR(-ENODEV); @@ -474,18 +471,18 @@ dwapb_gpio_get_pdata_of(struct device *dev) pdata->nports = nports; i = 0; - for_each_child_of_node(node, port_np) { + device_for_each_child_node(dev, fwnode) { pp = &pdata->properties[i++]; - pp->node = port_np; + pp->fwnode = fwnode; - if (of_property_read_u32(port_np, "reg", &pp->idx) || + if (fwnode_property_read_u32(fwnode, "reg", &pp->idx) || pp->idx >= DWAPB_MAX_PORTS) { dev_err(dev, "missing/invalid port index for port%d\n", i); return ERR_PTR(-EINVAL); } - if (of_property_read_u32(port_np, "snps,nr-gpios", + if (fwnode_property_read_u32(fwnode, "snps,nr-gpios", &pp->ngpio)) { dev_info(dev, "failed to get number of gpios for port%d\n", @@ -497,9 +494,10 @@ dwapb_gpio_get_pdata_of(struct device *dev) * Only port A can provide interrupts in all configurations of * the IP. */ - if (pp->idx == 0 && - of_property_read_bool(port_np, "interrupt-controller")) { - pp->irq = irq_of_parse_and_map(port_np, 0); + 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) dev_warn(dev, "no irq for port%d\n", pp->idx); } @@ -521,7 +519,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev) struct dwapb_platform_data *pdata = dev_get_platdata(dev); if (!pdata) { - pdata = dwapb_gpio_get_pdata_of(dev); + pdata = dwapb_gpio_get_pdata(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); } diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index a4ef99b..a24b35f 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -219,7 +219,7 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) return -ENOMEM; /* Set the properties for portA */ - pdata->properties->node = NULL; + pdata->properties->fwnode = NULL; pdata->properties->idx = 0; pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO; pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE; diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h index 955b579..2dc7f4a 100644 --- a/include/linux/platform_data/gpio-dwapb.h +++ b/include/linux/platform_data/gpio-dwapb.h @@ -15,7 +15,7 @@ #define GPIO_DW_APB_H struct dwapb_port_property { - struct device_node *node; + struct fwnode_handle *fwnode; unsigned int idx; unsigned int ngpio; unsigned int gpio_base; -- cgit v0.10.2 From e6cb3486f5a1bd55240e8326691dbfb86564f8c6 Mon Sep 17 00:00:00 2001 From: Jiang Qiu Date: Thu, 28 Apr 2016 17:32:03 +0800 Subject: gpio: dwapb: add gpio-signaled acpi event support This patch adds gpio-signaled acpi event support. It is used for power button on hisilicon D02 board, an arm64 platform. The corresponding DSDT file is defined as follows: Device(GPI0) { Name(_HID, "HISI0181") Name(_ADR, 0) Name(_UID, 0) Name (_CRS, ResourceTemplate () { Memory32Fixed (ReadWrite, 0x802e0000, 0x10000) Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive,,,) {344} }) Device(PRTa) { Name (_DSD, Package () { Package () { Package () {"reg",0}, Package () {"snps,nr-gpios",32}, } }) } Name (_AEI, ResourceTemplate () { GpioInt(Edge, ActiveLow, ExclusiveAndWake, PullUp, , " \\_SB.GPI0") {8} }) Method (_E08, 0x0, NotSerialized) { Notify (\_SB.PWRB, 0x80) } } Acked-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Jiang Qiu Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 7517c2f..b235d70 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -7,6 +7,7 @@ * * All enquiries to support@picochip.com */ +#include #include /* FIXME: for gpio_get_value(), replace this with direct register read */ #include @@ -27,6 +28,8 @@ #include #include +#include "gpiolib.h" + #define GPIO_SWPORTA_DR 0x00 #define GPIO_SWPORTA_DDR 0x04 #define GPIO_SWPORTB_DR 0x0c @@ -435,6 +438,10 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, else port->is_registered = true; + /* Add GPIO-signaled ACPI event support */ + if (pp->irq) + acpi_gpiochip_request_interrupts(&port->gc); + return err; } @@ -502,6 +509,9 @@ dwapb_gpio_get_pdata(struct device *dev) 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); + pp->irq_shared = false; pp->gpio_base = -1; } @@ -576,6 +586,12 @@ static const struct of_device_id dwapb_of_match[] = { }; MODULE_DEVICE_TABLE(of, dwapb_of_match); +static const struct acpi_device_id dwapb_acpi_match[] = { + {"HISI0181", 0}, + { } +}; +MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match); + #ifdef CONFIG_PM_SLEEP static int dwapb_gpio_suspend(struct device *dev) { @@ -670,6 +686,7 @@ static struct platform_driver dwapb_gpio_driver = { .name = "gpio-dwapb", .pm = &dwapb_gpio_pm_ops, .of_match_table = of_match_ptr(dwapb_of_match), + .acpi_match_table = ACPI_PTR(dwapb_acpi_match), }, .probe = dwapb_gpio_probe, .remove = dwapb_gpio_remove, -- cgit v0.10.2 From 8f01c9d05733db0071884b4af0003f8ac10513ae Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 29 Apr 2016 02:53:14 +0200 Subject: gpio: generic: fix GPIO_GENERIC_PLATFORM is set to module case GPIO_GENERIC_PLATFORM is a tristate. If the module option is selected the resulting gpio-generic.ko will lack most of the module initialzation and probe code. Signed-off-by: Christian Lamparter Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 54cddfa..6c1cb3b 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -549,7 +549,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, } EXPORT_SYMBOL_GPL(bgpio_init); -#ifdef CONFIG_GPIO_GENERIC_PLATFORM +#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) static void __iomem *bgpio_map(struct platform_device *pdev, const char *name, -- cgit v0.10.2 From e9f4d569fb897e77200cd431f3aab138c3c733e6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 28 Apr 2016 11:05:12 +0200 Subject: gpio: rename gpio-generic.c into gpio-mmio.c This patch renames the gpio-generic.c into gpio-mmio.c. This is because currently the file only contains code for a memory-mapped GPIO driver. There isn't any support for ioports or other resource type. Signed-off-by: Christian Lamparter Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 74eb1a7..991598e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,9 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o +# directly supported by gpio-generic +gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o + obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c deleted file mode 100644 index 6c1cb3b..0000000 --- a/drivers/gpio/gpio-generic.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Generic driver for memory-mapped GPIO controllers. - * - * Copyright 2008 MontaVista Software, Inc. - * Copyright 2008,2010 Anton Vorontsov - * - * 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. - * - * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... - * ...`` ```````.. - * ..The simplest form of a GPIO controller that the driver supports is`` - * `.just a single "data" register, where GPIO state can be read and/or ` - * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` - * ````````` - ___ -_/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... -__________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . -o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` - `....trivial..'~`.```.``` - * ``````` - * .```````~~~~`..`.``.``. - * . The driver supports `... ,..```.`~~~```````````````....````.``,, - * . big-endian notation, just`. .. A bit more sophisticated controllers , - * . register the device with -be`. .with a pair of set/clear-bit registers , - * `.. suffix. ```~~`````....`.` . affecting the data register and the .` - * ``.`.``...``` ```.. output pins are also supported.` - * ^^ `````.`````````.,``~``~``~~`````` - * . ^^ - * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. - * .. The expectation is that in at least some cases . ,-~~~-, - * .this will be used with roll-your-own ASIC/FPGA .` \ / - * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / - * ..````````......``````````` \o_ - * | - * ^^ / \ - * - * ...`````~~`.....``.`..........``````.`.``.```........``. - * ` 8, 16, 32 and 64 bits registers are supported, and``. - * . the number of GPIOs is determined by the width of ~ - * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ - * `.......````.``` - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void bgpio_write8(void __iomem *reg, unsigned long data) -{ - writeb(data, reg); -} - -static unsigned long bgpio_read8(void __iomem *reg) -{ - return readb(reg); -} - -static void bgpio_write16(void __iomem *reg, unsigned long data) -{ - writew(data, reg); -} - -static unsigned long bgpio_read16(void __iomem *reg) -{ - return readw(reg); -} - -static void bgpio_write32(void __iomem *reg, unsigned long data) -{ - writel(data, reg); -} - -static unsigned long bgpio_read32(void __iomem *reg) -{ - return readl(reg); -} - -#if BITS_PER_LONG >= 64 -static void bgpio_write64(void __iomem *reg, unsigned long data) -{ - writeq(data, reg); -} - -static unsigned long bgpio_read64(void __iomem *reg) -{ - return readq(reg); -} -#endif /* BITS_PER_LONG >= 64 */ - -static void bgpio_write16be(void __iomem *reg, unsigned long data) -{ - iowrite16be(data, reg); -} - -static unsigned long bgpio_read16be(void __iomem *reg) -{ - return ioread16be(reg); -} - -static void bgpio_write32be(void __iomem *reg, unsigned long data) -{ - iowrite32be(data, reg); -} - -static unsigned long bgpio_read32be(void __iomem *reg) -{ - return ioread32be(reg); -} - -static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin) -{ - return BIT(pin); -} - -static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc, - unsigned int pin) -{ - return BIT(gc->bgpio_bits - 1 - pin); -} - -static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) -{ - unsigned long pinmask = gc->pin2mask(gc, gpio); - - if (gc->bgpio_dir & pinmask) - return !!(gc->read_reg(gc->reg_set) & pinmask); - else - return !!(gc->read_reg(gc->reg_dat) & pinmask); -} - -static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio)); -} - -static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) -{ -} - -static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long mask = gc->pin2mask(gc, gpio); - unsigned long flags; - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - if (val) - gc->bgpio_data |= mask; - else - gc->bgpio_data &= ~mask; - - gc->write_reg(gc->reg_dat, gc->bgpio_data); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); -} - -static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - unsigned long mask = gc->pin2mask(gc, gpio); - - if (val) - gc->write_reg(gc->reg_set, mask); - else - gc->write_reg(gc->reg_clr, mask); -} - -static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long mask = gc->pin2mask(gc, gpio); - unsigned long flags; - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - if (val) - gc->bgpio_data |= mask; - else - gc->bgpio_data &= ~mask; - - gc->write_reg(gc->reg_set, gc->bgpio_data); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); -} - -static void bgpio_multiple_get_masks(struct gpio_chip *gc, - unsigned long *mask, unsigned long *bits, - unsigned long *set_mask, - unsigned long *clear_mask) -{ - int i; - - *set_mask = 0; - *clear_mask = 0; - - for (i = 0; i < gc->bgpio_bits; i++) { - if (*mask == 0) - break; - if (__test_and_clear_bit(i, mask)) { - if (test_bit(i, bits)) - *set_mask |= gc->pin2mask(gc, i); - else - *clear_mask |= gc->pin2mask(gc, i); - } - } -} - -static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, - unsigned long *mask, - unsigned long *bits, - void __iomem *reg) -{ - unsigned long flags; - unsigned long set_mask, clear_mask; - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); - - gc->bgpio_data |= set_mask; - gc->bgpio_data &= ~clear_mask; - - gc->write_reg(reg, gc->bgpio_data); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); -} - -static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, - unsigned long *bits) -{ - bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat); -} - -static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, - unsigned long *bits) -{ - bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set); -} - -static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, - unsigned long *mask, - unsigned long *bits) -{ - unsigned long set_mask, clear_mask; - - bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); - - if (set_mask) - gc->write_reg(gc->reg_set, set_mask); - if (clear_mask) - gc->write_reg(gc->reg_clr, clear_mask); -} - -static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - return 0; -} - -static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - return -EINVAL; -} - -static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, - int val) -{ - gc->set(gc, gpio, val); - - return 0; -} - -static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - unsigned long flags; - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); - - return 0; -} - -static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) -{ - /* Return 0 if output, 1 of input */ - return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); -} - -static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - gc->bgpio_dir |= gc->pin2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); - - return 0; -} - -static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) -{ - unsigned long flags; - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - gc->bgpio_dir |= gc->pin2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); - - return 0; -} - -static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) -{ - unsigned long flags; - - gc->set(gc, gpio, val); - - spin_lock_irqsave(&gc->bgpio_lock, flags); - - gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); - - spin_unlock_irqrestore(&gc->bgpio_lock, flags); - - return 0; -} - -static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) -{ - /* Return 0 if output, 1 if input */ - return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); -} - -static int bgpio_setup_accessors(struct device *dev, - struct gpio_chip *gc, - bool bit_be, - bool byte_be) -{ - - switch (gc->bgpio_bits) { - case 8: - gc->read_reg = bgpio_read8; - gc->write_reg = bgpio_write8; - break; - case 16: - if (byte_be) { - gc->read_reg = bgpio_read16be; - gc->write_reg = bgpio_write16be; - } else { - gc->read_reg = bgpio_read16; - gc->write_reg = bgpio_write16; - } - break; - case 32: - if (byte_be) { - gc->read_reg = bgpio_read32be; - gc->write_reg = bgpio_write32be; - } else { - gc->read_reg = bgpio_read32; - gc->write_reg = bgpio_write32; - } - break; -#if BITS_PER_LONG >= 64 - case 64: - if (byte_be) { - dev_err(dev, - "64 bit big endian byte order unsupported\n"); - return -EINVAL; - } else { - gc->read_reg = bgpio_read64; - gc->write_reg = bgpio_write64; - } - break; -#endif /* BITS_PER_LONG >= 64 */ - default: - dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits); - return -EINVAL; - } - - gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask; - - return 0; -} - -/* - * Create the device and allocate the resources. For setting GPIO's there are - * three supported configurations: - * - * - single input/output register resource (named "dat"). - * - set/clear pair (named "set" and "clr"). - * - single output register resource and single input resource ("set" and - * dat"). - * - * For the single output register, this drives a 1 by setting a bit and a zero - * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit - * in the set register and clears it by setting a bit in the clear register. - * The configuration is detected by which resources are present. - * - * For setting the GPIO direction, there are three supported configurations: - * - * - simple bidirection GPIO that requires no configuration. - * - an output direction register (named "dirout") where a 1 bit - * indicates the GPIO is an output. - * - an input direction register (named "dirin") where a 1 bit indicates - * the GPIO is an input. - */ -static int bgpio_setup_io(struct gpio_chip *gc, - void __iomem *dat, - void __iomem *set, - void __iomem *clr, - unsigned long flags) -{ - - gc->reg_dat = dat; - if (!gc->reg_dat) - return -EINVAL; - - if (set && clr) { - gc->reg_set = set; - gc->reg_clr = clr; - gc->set = bgpio_set_with_clear; - gc->set_multiple = bgpio_set_multiple_with_clear; - } else if (set && !clr) { - gc->reg_set = set; - gc->set = bgpio_set_set; - gc->set_multiple = bgpio_set_multiple_set; - } else if (flags & BGPIOF_NO_OUTPUT) { - gc->set = bgpio_set_none; - gc->set_multiple = NULL; - } else { - gc->set = bgpio_set; - gc->set_multiple = bgpio_set_multiple; - } - - if (!(flags & BGPIOF_UNREADABLE_REG_SET) && - (flags & BGPIOF_READ_OUTPUT_REG_SET)) - gc->get = bgpio_get_set; - else - gc->get = bgpio_get; - - return 0; -} - -static int bgpio_setup_direction(struct gpio_chip *gc, - void __iomem *dirout, - void __iomem *dirin, - unsigned long flags) -{ - if (dirout && dirin) { - return -EINVAL; - } else if (dirout) { - gc->reg_dir = dirout; - gc->direction_output = bgpio_dir_out; - gc->direction_input = bgpio_dir_in; - gc->get_direction = bgpio_get_dir; - } else if (dirin) { - gc->reg_dir = dirin; - gc->direction_output = bgpio_dir_out_inv; - gc->direction_input = bgpio_dir_in_inv; - gc->get_direction = bgpio_get_dir_inv; - } else { - if (flags & BGPIOF_NO_OUTPUT) - gc->direction_output = bgpio_dir_out_err; - else - gc->direction_output = bgpio_simple_dir_out; - gc->direction_input = bgpio_simple_dir_in; - } - - return 0; -} - -static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) -{ - if (gpio_pin < chip->ngpio) - return 0; - - return -EINVAL; -} - -int bgpio_init(struct gpio_chip *gc, struct device *dev, - unsigned long sz, void __iomem *dat, void __iomem *set, - void __iomem *clr, void __iomem *dirout, void __iomem *dirin, - unsigned long flags) -{ - int ret; - - if (!is_power_of_2(sz)) - return -EINVAL; - - gc->bgpio_bits = sz * 8; - if (gc->bgpio_bits > BITS_PER_LONG) - return -EINVAL; - - spin_lock_init(&gc->bgpio_lock); - gc->parent = dev; - gc->label = dev_name(dev); - gc->base = -1; - gc->ngpio = gc->bgpio_bits; - gc->request = bgpio_request; - - ret = bgpio_setup_io(gc, dat, set, clr, flags); - if (ret) - return ret; - - ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN, - flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); - if (ret) - return ret; - - ret = bgpio_setup_direction(gc, dirout, dirin, flags); - if (ret) - return ret; - - gc->bgpio_data = gc->read_reg(gc->reg_dat); - if (gc->set == bgpio_set_set && - !(flags & BGPIOF_UNREADABLE_REG_SET)) - gc->bgpio_data = gc->read_reg(gc->reg_set); - if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) - gc->bgpio_dir = gc->read_reg(gc->reg_dir); - - return ret; -} -EXPORT_SYMBOL_GPL(bgpio_init); - -#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) - -static void __iomem *bgpio_map(struct platform_device *pdev, - const char *name, - resource_size_t sane_sz) -{ - struct resource *r; - resource_size_t sz; - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!r) - return NULL; - - sz = resource_size(r); - if (sz != sane_sz) - return IOMEM_ERR_PTR(-EINVAL); - - return devm_ioremap_resource(&pdev->dev, r); -} - -static int bgpio_pdev_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *r; - void __iomem *dat; - void __iomem *set; - void __iomem *clr; - void __iomem *dirout; - void __iomem *dirin; - unsigned long sz; - unsigned long flags = pdev->id_entry->driver_data; - int err; - struct gpio_chip *gc; - struct bgpio_pdata *pdata = dev_get_platdata(dev); - - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); - if (!r) - return -EINVAL; - - sz = resource_size(r); - - dat = bgpio_map(pdev, "dat", sz); - if (IS_ERR(dat)) - return PTR_ERR(dat); - - set = bgpio_map(pdev, "set", sz); - if (IS_ERR(set)) - return PTR_ERR(set); - - clr = bgpio_map(pdev, "clr", sz); - if (IS_ERR(clr)) - return PTR_ERR(clr); - - dirout = bgpio_map(pdev, "dirout", sz); - if (IS_ERR(dirout)) - return PTR_ERR(dirout); - - dirin = bgpio_map(pdev, "dirin", sz); - if (IS_ERR(dirin)) - return PTR_ERR(dirin); - - gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); - if (!gc) - return -ENOMEM; - - err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags); - if (err) - return err; - - if (pdata) { - if (pdata->label) - gc->label = pdata->label; - gc->base = pdata->base; - if (pdata->ngpio > 0) - gc->ngpio = pdata->ngpio; - } - - platform_set_drvdata(pdev, gc); - - return devm_gpiochip_add_data(&pdev->dev, gc, NULL); -} - -static const struct platform_device_id bgpio_id_table[] = { - { - .name = "basic-mmio-gpio", - .driver_data = 0, - }, { - .name = "basic-mmio-gpio-be", - .driver_data = BGPIOF_BIG_ENDIAN, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, bgpio_id_table); - -static struct platform_driver bgpio_driver = { - .driver = { - .name = "basic-mmio-gpio", - }, - .id_table = bgpio_id_table, - .probe = bgpio_pdev_probe, -}; - -module_platform_driver(bgpio_driver); - -#endif /* CONFIG_GPIO_GENERIC_PLATFORM */ - -MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); -MODULE_AUTHOR("Anton Vorontsov "); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c new file mode 100644 index 0000000..6c1cb3b --- /dev/null +++ b/drivers/gpio/gpio-mmio.c @@ -0,0 +1,660 @@ +/* + * Generic driver for memory-mapped GPIO controllers. + * + * Copyright 2008 MontaVista Software, Inc. + * Copyright 2008,2010 Anton Vorontsov + * + * 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. + * + * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... + * ...`` ```````.. + * ..The simplest form of a GPIO controller that the driver supports is`` + * `.just a single "data" register, where GPIO state can be read and/or ` + * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` + * ````````` + ___ +_/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... +__________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . +o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` + `....trivial..'~`.```.``` + * ``````` + * .```````~~~~`..`.``.``. + * . The driver supports `... ,..```.`~~~```````````````....````.``,, + * . big-endian notation, just`. .. A bit more sophisticated controllers , + * . register the device with -be`. .with a pair of set/clear-bit registers , + * `.. suffix. ```~~`````....`.` . affecting the data register and the .` + * ``.`.``...``` ```.. output pins are also supported.` + * ^^ `````.`````````.,``~``~``~~`````` + * . ^^ + * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. + * .. The expectation is that in at least some cases . ,-~~~-, + * .this will be used with roll-your-own ASIC/FPGA .` \ / + * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / + * ..````````......``````````` \o_ + * | + * ^^ / \ + * + * ...`````~~`.....``.`..........``````.`.``.```........``. + * ` 8, 16, 32 and 64 bits registers are supported, and``. + * . the number of GPIOs is determined by the width of ~ + * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ + * `.......````.``` + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void bgpio_write8(void __iomem *reg, unsigned long data) +{ + writeb(data, reg); +} + +static unsigned long bgpio_read8(void __iomem *reg) +{ + return readb(reg); +} + +static void bgpio_write16(void __iomem *reg, unsigned long data) +{ + writew(data, reg); +} + +static unsigned long bgpio_read16(void __iomem *reg) +{ + return readw(reg); +} + +static void bgpio_write32(void __iomem *reg, unsigned long data) +{ + writel(data, reg); +} + +static unsigned long bgpio_read32(void __iomem *reg) +{ + return readl(reg); +} + +#if BITS_PER_LONG >= 64 +static void bgpio_write64(void __iomem *reg, unsigned long data) +{ + writeq(data, reg); +} + +static unsigned long bgpio_read64(void __iomem *reg) +{ + return readq(reg); +} +#endif /* BITS_PER_LONG >= 64 */ + +static void bgpio_write16be(void __iomem *reg, unsigned long data) +{ + iowrite16be(data, reg); +} + +static unsigned long bgpio_read16be(void __iomem *reg) +{ + return ioread16be(reg); +} + +static void bgpio_write32be(void __iomem *reg, unsigned long data) +{ + iowrite32be(data, reg); +} + +static unsigned long bgpio_read32be(void __iomem *reg) +{ + return ioread32be(reg); +} + +static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin) +{ + return BIT(pin); +} + +static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc, + unsigned int pin) +{ + return BIT(gc->bgpio_bits - 1 - pin); +} + +static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) +{ + unsigned long pinmask = gc->pin2mask(gc, gpio); + + if (gc->bgpio_dir & pinmask) + return !!(gc->read_reg(gc->reg_set) & pinmask); + else + return !!(gc->read_reg(gc->reg_dat) & pinmask); +} + +static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio)); +} + +static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) +{ +} + +static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long mask = gc->pin2mask(gc, gpio); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + if (val) + gc->bgpio_data |= mask; + else + gc->bgpio_data &= ~mask; + + gc->write_reg(gc->reg_dat, gc->bgpio_data); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + unsigned long mask = gc->pin2mask(gc, gpio); + + if (val) + gc->write_reg(gc->reg_set, mask); + else + gc->write_reg(gc->reg_clr, mask); +} + +static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long mask = gc->pin2mask(gc, gpio); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + if (val) + gc->bgpio_data |= mask; + else + gc->bgpio_data &= ~mask; + + gc->write_reg(gc->reg_set, gc->bgpio_data); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void bgpio_multiple_get_masks(struct gpio_chip *gc, + unsigned long *mask, unsigned long *bits, + unsigned long *set_mask, + unsigned long *clear_mask) +{ + int i; + + *set_mask = 0; + *clear_mask = 0; + + for (i = 0; i < gc->bgpio_bits; i++) { + if (*mask == 0) + break; + if (__test_and_clear_bit(i, mask)) { + if (test_bit(i, bits)) + *set_mask |= gc->pin2mask(gc, i); + else + *clear_mask |= gc->pin2mask(gc, i); + } + } +} + +static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, + unsigned long *mask, + unsigned long *bits, + void __iomem *reg) +{ + unsigned long flags; + unsigned long set_mask, clear_mask; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); + + gc->bgpio_data |= set_mask; + gc->bgpio_data &= ~clear_mask; + + gc->write_reg(reg, gc->bgpio_data); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat); +} + +static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set); +} + +static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, + unsigned long *mask, + unsigned long *bits) +{ + unsigned long set_mask, clear_mask; + + bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); + + if (set_mask) + gc->write_reg(gc->reg_set, set_mask); + if (clear_mask) + gc->write_reg(gc->reg_clr, clear_mask); +} + +static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + return 0; +} + +static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + return -EINVAL; +} + +static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + gc->set(gc, gpio, val); + + return 0; +} + +static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); + gc->write_reg(gc->reg_dir, gc->bgpio_dir); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) +{ + /* Return 0 if output, 1 of input */ + return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); +} + +static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + + gc->set(gc, gpio, val); + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->bgpio_dir |= gc->pin2mask(gc, gpio); + gc->write_reg(gc->reg_dir, gc->bgpio_dir); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) +{ + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->bgpio_dir |= gc->pin2mask(gc, gpio); + gc->write_reg(gc->reg_dir, gc->bgpio_dir); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + + gc->set(gc, gpio, val); + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); + gc->write_reg(gc->reg_dir, gc->bgpio_dir); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) +{ + /* Return 0 if output, 1 if input */ + return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); +} + +static int bgpio_setup_accessors(struct device *dev, + struct gpio_chip *gc, + bool bit_be, + bool byte_be) +{ + + switch (gc->bgpio_bits) { + case 8: + gc->read_reg = bgpio_read8; + gc->write_reg = bgpio_write8; + break; + case 16: + if (byte_be) { + gc->read_reg = bgpio_read16be; + gc->write_reg = bgpio_write16be; + } else { + gc->read_reg = bgpio_read16; + gc->write_reg = bgpio_write16; + } + break; + case 32: + if (byte_be) { + gc->read_reg = bgpio_read32be; + gc->write_reg = bgpio_write32be; + } else { + gc->read_reg = bgpio_read32; + gc->write_reg = bgpio_write32; + } + break; +#if BITS_PER_LONG >= 64 + case 64: + if (byte_be) { + dev_err(dev, + "64 bit big endian byte order unsupported\n"); + return -EINVAL; + } else { + gc->read_reg = bgpio_read64; + gc->write_reg = bgpio_write64; + } + break; +#endif /* BITS_PER_LONG >= 64 */ + default: + dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits); + return -EINVAL; + } + + gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask; + + return 0; +} + +/* + * Create the device and allocate the resources. For setting GPIO's there are + * three supported configurations: + * + * - single input/output register resource (named "dat"). + * - set/clear pair (named "set" and "clr"). + * - single output register resource and single input resource ("set" and + * dat"). + * + * For the single output register, this drives a 1 by setting a bit and a zero + * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit + * in the set register and clears it by setting a bit in the clear register. + * The configuration is detected by which resources are present. + * + * For setting the GPIO direction, there are three supported configurations: + * + * - simple bidirection GPIO that requires no configuration. + * - an output direction register (named "dirout") where a 1 bit + * indicates the GPIO is an output. + * - an input direction register (named "dirin") where a 1 bit indicates + * the GPIO is an input. + */ +static int bgpio_setup_io(struct gpio_chip *gc, + void __iomem *dat, + void __iomem *set, + void __iomem *clr, + unsigned long flags) +{ + + gc->reg_dat = dat; + if (!gc->reg_dat) + return -EINVAL; + + if (set && clr) { + gc->reg_set = set; + gc->reg_clr = clr; + gc->set = bgpio_set_with_clear; + gc->set_multiple = bgpio_set_multiple_with_clear; + } else if (set && !clr) { + gc->reg_set = set; + gc->set = bgpio_set_set; + gc->set_multiple = bgpio_set_multiple_set; + } else if (flags & BGPIOF_NO_OUTPUT) { + gc->set = bgpio_set_none; + gc->set_multiple = NULL; + } else { + gc->set = bgpio_set; + gc->set_multiple = bgpio_set_multiple; + } + + if (!(flags & BGPIOF_UNREADABLE_REG_SET) && + (flags & BGPIOF_READ_OUTPUT_REG_SET)) + gc->get = bgpio_get_set; + else + gc->get = bgpio_get; + + return 0; +} + +static int bgpio_setup_direction(struct gpio_chip *gc, + void __iomem *dirout, + void __iomem *dirin, + unsigned long flags) +{ + if (dirout && dirin) { + return -EINVAL; + } else if (dirout) { + gc->reg_dir = dirout; + gc->direction_output = bgpio_dir_out; + gc->direction_input = bgpio_dir_in; + gc->get_direction = bgpio_get_dir; + } else if (dirin) { + gc->reg_dir = dirin; + gc->direction_output = bgpio_dir_out_inv; + gc->direction_input = bgpio_dir_in_inv; + gc->get_direction = bgpio_get_dir_inv; + } else { + if (flags & BGPIOF_NO_OUTPUT) + gc->direction_output = bgpio_dir_out_err; + else + gc->direction_output = bgpio_simple_dir_out; + gc->direction_input = bgpio_simple_dir_in; + } + + return 0; +} + +static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) +{ + if (gpio_pin < chip->ngpio) + return 0; + + return -EINVAL; +} + +int bgpio_init(struct gpio_chip *gc, struct device *dev, + unsigned long sz, void __iomem *dat, void __iomem *set, + void __iomem *clr, void __iomem *dirout, void __iomem *dirin, + unsigned long flags) +{ + int ret; + + if (!is_power_of_2(sz)) + return -EINVAL; + + gc->bgpio_bits = sz * 8; + if (gc->bgpio_bits > BITS_PER_LONG) + return -EINVAL; + + spin_lock_init(&gc->bgpio_lock); + gc->parent = dev; + gc->label = dev_name(dev); + gc->base = -1; + gc->ngpio = gc->bgpio_bits; + gc->request = bgpio_request; + + ret = bgpio_setup_io(gc, dat, set, clr, flags); + if (ret) + return ret; + + ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN, + flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); + if (ret) + return ret; + + ret = bgpio_setup_direction(gc, dirout, dirin, flags); + if (ret) + return ret; + + gc->bgpio_data = gc->read_reg(gc->reg_dat); + if (gc->set == bgpio_set_set && + !(flags & BGPIOF_UNREADABLE_REG_SET)) + gc->bgpio_data = gc->read_reg(gc->reg_set); + if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) + gc->bgpio_dir = gc->read_reg(gc->reg_dir); + + return ret; +} +EXPORT_SYMBOL_GPL(bgpio_init); + +#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) + +static void __iomem *bgpio_map(struct platform_device *pdev, + const char *name, + resource_size_t sane_sz) +{ + struct resource *r; + resource_size_t sz; + + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + if (!r) + return NULL; + + sz = resource_size(r); + if (sz != sane_sz) + return IOMEM_ERR_PTR(-EINVAL); + + return devm_ioremap_resource(&pdev->dev, r); +} + +static int bgpio_pdev_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *r; + void __iomem *dat; + void __iomem *set; + void __iomem *clr; + void __iomem *dirout; + void __iomem *dirin; + unsigned long sz; + unsigned long flags = pdev->id_entry->driver_data; + int err; + struct gpio_chip *gc; + struct bgpio_pdata *pdata = dev_get_platdata(dev); + + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); + if (!r) + return -EINVAL; + + sz = resource_size(r); + + dat = bgpio_map(pdev, "dat", sz); + if (IS_ERR(dat)) + return PTR_ERR(dat); + + set = bgpio_map(pdev, "set", sz); + if (IS_ERR(set)) + return PTR_ERR(set); + + clr = bgpio_map(pdev, "clr", sz); + if (IS_ERR(clr)) + return PTR_ERR(clr); + + dirout = bgpio_map(pdev, "dirout", sz); + if (IS_ERR(dirout)) + return PTR_ERR(dirout); + + dirin = bgpio_map(pdev, "dirin", sz); + if (IS_ERR(dirin)) + return PTR_ERR(dirin); + + gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags); + if (err) + return err; + + if (pdata) { + if (pdata->label) + gc->label = pdata->label; + gc->base = pdata->base; + if (pdata->ngpio > 0) + gc->ngpio = pdata->ngpio; + } + + platform_set_drvdata(pdev, gc); + + return devm_gpiochip_add_data(&pdev->dev, gc, NULL); +} + +static const struct platform_device_id bgpio_id_table[] = { + { + .name = "basic-mmio-gpio", + .driver_data = 0, + }, { + .name = "basic-mmio-gpio-be", + .driver_data = BGPIOF_BIG_ENDIAN, + }, + { } +}; +MODULE_DEVICE_TABLE(platform, bgpio_id_table); + +static struct platform_driver bgpio_driver = { + .driver = { + .name = "basic-mmio-gpio", + }, + .id_table = bgpio_id_table, + .probe = bgpio_pdev_probe, +}; + +module_platform_driver(bgpio_driver); + +#endif /* CONFIG_GPIO_GENERIC_PLATFORM */ + +MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); +MODULE_AUTHOR("Anton Vorontsov "); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 72d3200061776264941be1b5a9bb8e926b3b30a5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Apr 2016 13:33:59 +0200 Subject: gpio: set up initial state from .get_direction() If the gpiochip supports the .get_direction() callback, then the initial state of the descriptor flags should be set up as output accordingly. Also put in comments explaining what is going on. Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bb3195d..340b021 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -565,14 +565,31 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) struct gpio_desc *desc = &gdev->descs[i]; desc->gdev = gdev; - - /* REVISIT: most hardware initializes GPIOs as inputs (often - * with pullups enabled) so power usage is minimized. Linux - * code should set the gpio direction first thing; but until - * it does, and in case chip->get_direction is not set, we may - * expose the wrong direction in sysfs. + /* + * REVISIT: most hardware initializes GPIOs as inputs + * (often with pullups enabled) so power usage is + * minimized. Linux code should set the gpio direction + * first thing; but until it does, and in case + * chip->get_direction is not set, we may expose the + * wrong direction in sysfs. */ - desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0; + + if (chip->get_direction) { + /* + * If we have .get_direction, set up the initial + * direction flag from the hardware. + */ + int dir = chip->get_direction(chip, i); + + if (!dir) + set_bit(FLAG_IS_OUT, &desc->flags); + } else if (!chip->direction_input) { + /* + * If the chip lacks the .direction_input callback + * we logically assume all lines are outputs. + */ + set_bit(FLAG_IS_OUT, &desc->flags); + } } spin_unlock_irqrestore(&gpio_lock, flags); -- cgit v0.10.2 From f002d07c56c7b7007328e8fff2adf04db1c81e90 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 29 Apr 2016 21:55:23 +0530 Subject: gpio: tegra: Implement gpio_get_direction callback Implement gpio_get_direction() callback for Tegra GPIO. The direction is only valid if the pin is configured as GPIO. If pin is not configured in GPIO mode then this function return error. Signed-off-by: Laxman Dewangan Reviewed-by: Stephen Warren Acked-by: Jon Hunter Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index b3ddd92..ec891a27 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -191,6 +191,21 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, return 0; } +static int tegra_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + u32 pin_mask = BIT(GPIO_BIT(offset)); + u32 cnf, oe; + + cnf = tegra_gpio_readl(tgi, GPIO_CNF(tgi, offset)); + if (!(cnf & pin_mask)) + return -EINVAL; + + oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)); + + return (oe & pin_mask) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; +} + static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, unsigned int debounce) { @@ -575,6 +590,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) tgi->gc.get = tegra_gpio_get; tgi->gc.direction_output = tegra_gpio_direction_output; tgi->gc.set = tegra_gpio_set; + tgi->gc.get_direction = tegra_gpio_get_direction; tgi->gc.to_irq = tegra_gpio_to_irq; tgi->gc.base = 0; tgi->gc.ngpio = tgi->bank_count * 32; -- cgit v0.10.2 From 0c60de3f73cddde6a83979c64f63cb1101f5326c Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Sat, 30 Apr 2016 13:49:27 -0700 Subject: gpio: xgene: Enable ACPI support for X-Gene GFC GPIO driver This patch enables ACPI support for X-Gene GFC GPIO driver. Signed-off-by: Duc Dang Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 4193502..46faecd1 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -211,10 +212,18 @@ static const struct of_device_id xgene_gpio_of_match[] = { {}, }; +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgene_gpio_acpi_match[] = { + { "APMC0D14", 0 }, + { }, +}; +#endif + static struct platform_driver xgene_gpio_driver = { .driver = { .name = "xgene-gpio", .of_match_table = xgene_gpio_of_match, + .acpi_match_table = ACPI_PTR(xgene_gpio_acpi_match), .pm = XGENE_GPIO_PM_OPS, }, .probe = xgene_gpio_probe, -- cgit v0.10.2 From 3b711e0781f34400326f911c15784e84deca84b6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 1 May 2016 10:29:10 +0200 Subject: gpio: xgene: implement .get_direction() This implements the .get_direction() callback for the xgene GPIO controller. Cc: Duc Dang Cc: Feng Kan Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 46faecd1..dc85dcd 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -85,6 +85,17 @@ static void xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) spin_unlock_irqrestore(&chip->lock, flags); } +static int xgene_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct xgene_gpio *chip = gpiochip_get_data(gc); + unsigned long bank_offset, bit_offset; + + bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); + bit_offset = GPIO_BIT_OFFSET(offset); + + return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset)); +} + static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) { struct xgene_gpio *chip = gpiochip_get_data(gc); @@ -184,6 +195,7 @@ static int xgene_gpio_probe(struct platform_device *pdev) spin_lock_init(&gpio->lock); gpio->chip.parent = &pdev->dev; + gpio->chip.get_direction = xgene_gpio_get_direction; gpio->chip.direction_input = xgene_gpio_dir_in; gpio->chip.direction_output = xgene_gpio_dir_out; gpio->chip.get = xgene_gpio_get; -- cgit v0.10.2 From 4c37ce8608a8c6521726d4cd1d4f54424e8d095f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 May 2016 13:13:10 +0200 Subject: gpio: make gpiod_to_irq() return negative for NO_IRQ If a translation returns zero, that means NO_IRQ, so we should return an error since the function is documented to return a negative code on error. Reported-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 340b021..a68c6d7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1999,13 +1999,22 @@ EXPORT_SYMBOL_GPL(gpiod_cansleep); */ int gpiod_to_irq(const struct gpio_desc *desc) { - struct gpio_chip *chip; - int offset; + struct gpio_chip *chip; + int offset; VALIDATE_DESC(desc); chip = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); - return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; + if (chip->to_irq) { + int retirq = chip->to_irq(chip, offset); + + /* Zero means NO_IRQ */ + if (!retirq) + return -ENXIO; + + return retirq; + } + return -ENXIO; } EXPORT_SYMBOL_GPL(gpiod_to_irq); -- cgit v0.10.2 From fd9c55315db9bc89c54bb644a0f8b1f9306010d4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 15:26:26 +0200 Subject: gpio: of: make it possible to name GPIO lines Make it possible to name the producer side of a GPIO line using a "gpio-line-names" property array, modeled on the "clock-output-names" property from the clock bindings. This naming is especially useful for: - Debugging: lines are named after function, not just opaque offset numbers. - Exploration: systems where some or all GPIO lines are available to end users, such as prototyping, one-off's "makerspace usecases" users are helped by the names of the GPIO lines when tinkering. This usecase has been surfacing recently. The gpio-line-names attribute is completely optional. Example output from lsgpio on a patched Snowball tree: GPIO chip: gpiochip6, "8000e180.gpio", 32 GPIO lines line 0: unnamed unused line 1: "AP_GPIO161" "extkb3" [kernel] line 2: "AP_GPIO162" "extkb4" [kernel] line 3: "ACCELEROMETER_INT1_RDY" unused [kernel] line 4: "ACCELEROMETER_INT2" unused line 5: "MAG_DRDY" unused [kernel] line 6: "GYRO_DRDY" unused [kernel] line 7: "RSTn_MLC" unused line 8: "RSTn_SLC" unused line 9: "GYRO_INT" unused line 10: "UART_WAKE" unused line 11: "GBF_RESET" unused line 12: unnamed unused Cc: Grant Likely Cc: Amit Kucheria Cc: David Mandala Cc: Lee Campbell Cc: devicetree@vger.kernel.org Acked-by: Rob Herring Reviewed-by: Michael Welling Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index c88d2cc..68d28f6 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -152,6 +152,21 @@ additional bitmask is needed to specify which GPIOs are actually in use, and which are dummies. The bindings for this case has not yet been specified, but should be specified if/when such hardware appears. +Optionally, a GPIO controller may have a "gpio-line-names" property. This is +an array of strings defining the names of the GPIO lines going out of the +GPIO controller. This name should be the most meaningful producer name +for the system, such as a rail name indicating the usage. Package names +such as pin name are discouraged: such lines have opaque names (since they +are by definition generic purpose) and such names are usually not very +helpful. For example "MMC-CD", "Red LED Vdd" and "ethernet reset" are +reasonable line names as they describe what the line is used for. "GPIO0" +is not a good name to give to a GPIO line. Placeholders are discouraged: +rather use the "" (blank string) if the use of the GPIO line is undefined +in your design. The names are assigned starting from line offset 0 from +left to right from the passed array. An incomplete array (where the number +of passed named are less than ngpios) will still be used up until the last +provided valid line index. + Example: gpio-controller@00000000 { @@ -160,6 +175,10 @@ gpio-controller@00000000 { gpio-controller; #gpio-cells = <2>; ngpios = <18>; + gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R", + "LED G", "LED B", "Col A", "Col B", "Col C", "Col D", + "Row A", "Row B", "Row C", "Row D", "NMI button", + "poweroff", "reset"; } The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d81dbd8..d22dcc3 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -196,6 +196,51 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, } /** + * of_gpiochip_set_names() - set up the names of the lines + * @chip: GPIO chip whose lines should be named, if possible + */ +static void of_gpiochip_set_names(struct gpio_chip *gc) +{ + struct gpio_device *gdev = gc->gpiodev; + struct device_node *np = gc->of_node; + int i; + int nstrings; + + nstrings = of_property_count_strings(np, "gpio-line-names"); + if (nstrings <= 0) + /* Lines names not present */ + return; + + /* This is normally not what you want */ + if (gdev->ngpio != nstrings) + dev_info(&gdev->dev, "gpio-line-names specifies %d line " + "names but there are %d lines on the chip\n", + nstrings, gdev->ngpio); + + /* + * Make sure to not index beyond the end of the number of descriptors + * of the GPIO device. + */ + for (i = 0; i < gdev->ngpio; i++) { + const char *name; + int ret; + + ret = of_property_read_string_index(np, + "gpio-line-names", + i, + &name); + if (ret) { + if (ret != -ENODATA) + dev_err(&gdev->dev, + "unable to name line %d: %d\n", + i, ret); + break; + } + gdev->descs[i].name = name; + } +} + +/** * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on * @@ -445,6 +490,10 @@ int of_gpiochip_add(struct gpio_chip *chip) if (status) return status; + /* If the chip defines names itself, these take precedence */ + if (!chip->names) + of_gpiochip_set_names(chip); + of_node_get(chip->of_node); return of_gpiochip_scan_gpios(chip); -- cgit v0.10.2 From 5b64250b614a9d3dff380035be17811cd479d8e8 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 8 May 2016 15:08:22 +0200 Subject: gpio: dt-bindings: add wd,mbl-gpio bindings This patch adds the device tree bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers. The gpios will be supported by gpio-mmio code of the GPIO generic library. Signed-off-by: Christian Lamparter Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt new file mode 100644 index 0000000..038c3a6 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt @@ -0,0 +1,38 @@ +Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers. + +The Western Digital MyBook Live has two memory-mapped GPIO controllers. +Both GPIO controller only have a single 8-bit data register, where GPIO +state can be read and/or written. + +Required properties: + - compatible: should be "wd,mbl-gpio" + - reg-names: must contain + "dat" - data register + - reg: address + size pairs describing the GPIO register sets; + order must correspond with the order of entries in reg-names + - #gpio-cells: must be set to 2. The first cell is the pin number and + the second cell is used to specify the gpio polarity: + 0 = active high + 1 = active low + - gpio-controller: Marks the device node as a gpio controller. + +Optional properties: + - no-output: GPIOs are read-only. + +Examples: + gpio0: gpio0@e0000000 { + compatible = "wd,mbl-gpio"; + reg-names = "dat"; + reg = <0xe0000000 0x1>; + #gpio-cells = <2>; + gpio-controller; + }; + + gpio1: gpio1@e0100000 { + compatible = "wd,mbl-gpio"; + reg-names = "dat"; + reg = <0xe0100000 0x1>; + #gpio-cells = <2>; + gpio-controller; + no-output; + }; -- cgit v0.10.2 From 1b0d5287dafc7651af1d55cf47209209f79a964b Mon Sep 17 00:00:00 2001 From: Duc Dang Date: Tue, 3 May 2016 00:53:41 -0700 Subject: gpio: dwapb: Add ACPI device ID for DWAPB GPIO controller on X-Gene platforms This patch enables DWAPB GPIO controller support on X-Gene platforms in ACPI boot mode. Signed-off-by: Duc Dang Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index b235d70..34779bb 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -588,6 +588,7 @@ MODULE_DEVICE_TABLE(of, dwapb_of_match); static const struct acpi_device_id dwapb_acpi_match[] = { {"HISI0181", 0}, + {"APMC0D07", 0}, { } }; MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match); -- cgit v0.10.2 From 9697643ff3edca036e8843235cd6e4d598a50e63 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 4 May 2016 10:21:53 +0200 Subject: pinctrl: sh-pfc: Let gpio_chip.to_irq() return zero on error Currrently the gpio_chip.to_irq() callback returns -ENOSYS on error, which causes bad interactions with the serial_mctrl_gpio helpers. mctrl_gpio_init() returns -ENOSYS if GPIOLIB is not enabled, which is intended to be ignored by its callers. However, ignoring -ENOSYS when it was caused by a gpiod_to_irq() failure will lead to a crash later: Unable to handle kernel paging request at virtual address ffffffde ... PC is at mctrl_gpio_set+0x14/0x78 Fix this by returning zero instead, like gpiochip_to_irq() does. Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index a6681b8..97dff6a 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -212,7 +212,7 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) } } - return -ENOSYS; + return 0; found: return pfc->irqs[i]; -- cgit v0.10.2 From 6a5ead91d45d091f6d60b20d47e595a1b9e25d67 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 9 May 2016 19:59:55 -0400 Subject: gpio: sodaville: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_SODAVILLE drivers/gpio/Kconfig: bool "Intel Sodaville GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_pci_driver() uses the same init level as the builtin_pci_driver() does, there is no init ordering change caused by this commit. We don't replace module.h with init.h since the file already has that. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Hans J. Koch Cc: Linus Walleij Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index e3cb677..7da9e6c 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -3,6 +3,8 @@ * * Copyright (c) 2010, 2011 Intel Corporation * + * Author: Hans J. Koch + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License 2 as published * by the Free Software Foundation. @@ -15,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -257,34 +258,17 @@ done: return ret; } -static void sdv_gpio_remove(struct pci_dev *pdev) -{ - struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev); - - free_irq(pdev->irq, sd); - irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); - - gpiochip_remove(&sd->chip); - pci_release_region(pdev, GPIO_BAR); - iounmap(sd->gpio_pub_base); - pci_disable_device(pdev); - kfree(sd); -} - static const struct pci_device_id sdv_gpio_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, { 0, }, }; static struct pci_driver sdv_gpio_driver = { + .driver = { + .suppress_bind_attrs = true, + }, .name = DRV_NAME, .id_table = sdv_gpio_pci_ids, .probe = sdv_gpio_probe, - .remove = sdv_gpio_remove, }; - -module_pci_driver(sdv_gpio_driver); - -MODULE_AUTHOR("Hans J. Koch "); -MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs"); -MODULE_LICENSE("GPL v2"); +builtin_pci_driver(sdv_gpio_driver); -- cgit v0.10.2 From 3b52bb960ec66f3788697e42e72ec3fa0e7f8178 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 9 May 2016 19:59:56 -0400 Subject: gpio: stmpe: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_STMPE drivers/gpio/Kconfig: bool "STMPE GPIOs" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Curiously, this driver was using subsys_initcall since day one, so we don't have the "normal" module_init replacement in this change like we've done in other similar driver updates. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Rabin Vincent Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 5197edf..6f7af28 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -5,7 +5,6 @@ * Author: Rabin Vincent for ST-Ericsson */ -#include #include #include #include @@ -413,23 +412,13 @@ out_free: return ret; } -static int stmpe_gpio_remove(struct platform_device *pdev) -{ - struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); - struct stmpe *stmpe = stmpe_gpio->stmpe; - - gpiochip_remove(&stmpe_gpio->chip); - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - kfree(stmpe_gpio); - - return 0; -} - static struct platform_driver stmpe_gpio_driver = { - .driver.name = "stmpe-gpio", - .driver.owner = THIS_MODULE, + .driver = { + .suppress_bind_attrs = true, + .name = "stmpe-gpio", + .owner = THIS_MODULE, + }, .probe = stmpe_gpio_probe, - .remove = stmpe_gpio_remove, }; static int __init stmpe_gpio_init(void) @@ -437,13 +426,3 @@ static int __init stmpe_gpio_init(void) return platform_driver_register(&stmpe_gpio_driver); } subsys_initcall(stmpe_gpio_init); - -static void __exit stmpe_gpio_exit(void) -{ - platform_driver_unregister(&stmpe_gpio_driver); -} -module_exit(stmpe_gpio_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("STMPExxxx GPIO driver"); -MODULE_AUTHOR("Rabin Vincent "); -- cgit v0.10.2 From 52ad90531aaebf101699974cd7fb7d7def729078 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 9 May 2016 19:59:57 -0400 Subject: gpio: timberdale: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TIMBERDALE drivers/gpio/Kconfig: bool "Support for timberdale GPIO IP" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 85ed608..181f86c 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -1,5 +1,6 @@ /* * Timberdale FPGA GPIO driver + * Author: Mocean Laboratories * Copyright (c) 2009 Intel Corporation * * This program is free software; you can redistribute it and/or modify @@ -20,7 +21,7 @@ * Timberdale FPGA GPIO */ -#include +#include #include #include #include @@ -290,40 +291,14 @@ static int timbgpio_probe(struct platform_device *pdev) return 0; } -static int timbgpio_remove(struct platform_device *pdev) -{ - struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct timbgpio *tgpio = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (irq >= 0 && tgpio->irq_base > 0) { - int i; - for (i = 0; i < pdata->nr_pins; i++) { - irq_set_chip(tgpio->irq_base + i, NULL); - irq_set_chip_data(tgpio->irq_base + i, NULL); - } - - irq_set_handler(irq, NULL); - irq_set_handler_data(irq, NULL); - } - - return 0; -} - static struct platform_driver timbgpio_platform_driver = { .driver = { - .name = DRIVER_NAME, + .name = DRIVER_NAME, + .suppress_bind_attrs = true, }, .probe = timbgpio_probe, - .remove = timbgpio_remove, }; /*--------------------------------------------------------------------------*/ -module_platform_driver(timbgpio_platform_driver); - -MODULE_DESCRIPTION("Timberdale GPIO driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Mocean Laboratories"); -MODULE_ALIAS("platform:"DRIVER_NAME); - +builtin_platform_driver(timbgpio_platform_driver); -- cgit v0.10.2 From a90295b4884f7467f4d5a4ffccc6facdf3ba9fe2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 9 May 2016 19:59:58 -0400 Subject: gpio: zevio: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_ZEVIO drivers/gpio/Kconfig: bool "LSI ZEVIO SoC memory mapped GPIOs" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Fabian Vogt Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c index cda6d92..e23ef7b 100644 --- a/drivers/gpio/gpio-zevio.c +++ b/drivers/gpio/gpio-zevio.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -203,32 +203,17 @@ static int zevio_gpio_probe(struct platform_device *pdev) return 0; } -static int zevio_gpio_remove(struct platform_device *pdev) -{ - struct zevio_gpio *controller = platform_get_drvdata(pdev); - - of_mm_gpiochip_remove(&controller->chip); - - return 0; -} - static const struct of_device_id zevio_gpio_of_match[] = { { .compatible = "lsi,zevio-gpio", }, { }, }; -MODULE_DEVICE_TABLE(of, zevio_gpio_of_match); - static struct platform_driver zevio_gpio_driver = { .driver = { .name = "gpio-zevio", .of_match_table = zevio_gpio_of_match, + .suppress_bind_attrs = true, }, .probe = zevio_gpio_probe, - .remove = zevio_gpio_remove, }; -module_platform_driver(zevio_gpio_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Fabian Vogt "); -MODULE_DESCRIPTION("LSI ZEVIO SoC GPIO driver"); +builtin_platform_driver(zevio_gpio_driver); -- cgit v0.10.2 From d30a2b47d4c2b75573d93f60655d48ba8e3ed2b3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:23:22 +0200 Subject: MIPS: do away with ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replaces: - "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. - "select ARCH_WANT_OPTIONAL_GPIOLIB" with no dependency: GPIOLIB is now selectable by everyone, so we need not declare our intent to select it. When ordering the symbols the following rationale was used: if the selects were in alphabetical order, I moved select GPIOLIB to be in alphabetical order, but if the selects were not maintained in alphabetical order, I just replaced "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB". Cc: Michael Büsch Cc: linux-mips@linux-mips.org Acked-by: Ralf Baechle Signed-off-by: Linus Walleij diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2018c2b..512b5de 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -79,7 +79,7 @@ config MIPS_ALCHEMY select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_APM_EMULATION - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select SYS_SUPPORTS_ZBOOT select COMMON_CLK @@ -98,7 +98,7 @@ config AR7 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_ZBOOT_UART16550 - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select VLYNQ select HAVE_CLK help @@ -122,11 +122,11 @@ config ATH25 config ATH79 bool "Atheros AR71XX/AR724X/AR913X based boards" select ARCH_HAS_RESET_CONTROLLER - select ARCH_REQUIRE_GPIOLIB select BOOT_RAW select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT + select GPIOLIB select HAVE_CLK select COMMON_CLK select CLKDEV_LOOKUP @@ -170,7 +170,6 @@ config BMIPS_GENERIC select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN - select ARCH_WANT_OPTIONAL_GPIOLIB help Build a generic DT-based kernel image that boots on select BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top @@ -179,7 +178,6 @@ config BMIPS_GENERIC config BCM47XX bool "Broadcom BCM47XX based boards" - select ARCH_WANT_OPTIONAL_GPIOLIB select BOOT_RAW select CEVT_R4K select CSRC_R4K @@ -211,7 +209,7 @@ config BCM63XX select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK select SWAP_IO_SPACE - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select HAVE_CLK select MIPS_L1_CACHE_SHIFT_4 help @@ -305,7 +303,7 @@ config MACH_INGENIC select SYS_SUPPORTS_ZBOOT_UART16550 select DMA_NONCOHERENT select IRQ_MIPS_CPU - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select COMMON_CLK select GENERIC_IRQ_CHIP select BUILTIN_DTB @@ -325,7 +323,7 @@ config LANTIQ select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_MULTITHREADING select SYS_HAS_EARLY_PRINTK - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select SWAP_IO_SPACE select BOOT_RAW select CLKDEV_LOOKUP @@ -377,7 +375,6 @@ config MACH_LOONGSON64 config MACH_PISTACHIO bool "IMG Pistachio SoC based boards" - select ARCH_REQUIRE_GPIOLIB select BOOT_ELF32 select BOOT_RAW select CEVT_R4K @@ -385,6 +382,7 @@ config MACH_PISTACHIO select COMMON_CLK select CSRC_R4K select DMA_MAYBE_COHERENT + select GPIOLIB select IRQ_MIPS_CPU select LIBFDT select MFD_SYSCON @@ -406,13 +404,13 @@ config MACH_PISTACHIO config MACH_XILFPGA bool "MIPSfpga Xilinx based boards" - select ARCH_REQUIRE_GPIOLIB select BOOT_ELF32 select BOOT_RAW select BUILTIN_DTB select CEVT_R4K select COMMON_CLK select CSRC_R4K + select GPIOLIB select IRQ_MIPS_CPU select LIBFDT select MIPS_CPU_SCACHE @@ -536,7 +534,7 @@ config MACH_VR41XX select CSRC_R4K select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_MIPS16 - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB config NXP_STB220 bool "NXP STB220 board" @@ -856,7 +854,7 @@ config MIKROTIK_RB532 select SYS_SUPPORTS_LITTLE_ENDIAN select SWAP_IO_SPACE select BOOT_RAW - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select MIPS_L1_CACHE_SHIFT_4 help Support the Mikrotik(tm) RouterBoard 532 series, @@ -879,7 +877,7 @@ config CAVIUM_OCTEON_SOC select HW_HAS_PCI select ZONE_DMA32 select HOLES_IN_ZONE - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select LIBFDT select USE_OF select ARCH_SPARSEMEM_ENABLE @@ -937,7 +935,7 @@ config NLM_XLP_BOARD select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select ARCH_PHYS_ADDR_T_64BIT - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_HIGHMEM @@ -1077,7 +1075,7 @@ config MIPS_CLOCK_VSYSCALL def_bool CSRC_R4K || CLKSRC_MIPS_GIC config GPIO_TXX9 - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB bool config FW_CFE @@ -1342,7 +1340,7 @@ config CPU_LOONGSON3 select CPU_SUPPORTS_HUGEPAGES select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB help The Loongson 3 processor implements the MIPS64R2 instruction set with many extensions. @@ -1362,7 +1360,7 @@ config CPU_LOONGSON2F bool "Loongson 2F" depends on SYS_HAS_CPU_LOONGSON2F select CPU_LOONGSON2 - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB help The Loongson 2F processor implements the MIPS III instruction set with many extensions. diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index 7fa2488..88b4d6a 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -20,7 +20,7 @@ config MIPS_MTX1 config MIPS_DB1XXX bool "Alchemy DB1XXX / PB1XXX boards" - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select HW_HAS_PCI select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK diff --git a/arch/mips/pic32/Kconfig b/arch/mips/pic32/Kconfig index 1985971..527d37d 100644 --- a/arch/mips/pic32/Kconfig +++ b/arch/mips/pic32/Kconfig @@ -14,7 +14,7 @@ config PIC32MZDA select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select COMMON_CLK select CLKDEV_LOOKUP select LIBFDT -- cgit v0.10.2