summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-merrifield.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-13 18:54:57 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-13 18:54:57 +0300
commit061ad5038ca5ac75419204b216bddc2806008ead (patch)
treeedd48af16a121d6a457f5e29119cac91b3a9c61c /drivers/gpio/gpio-merrifield.c
parente7aa8c2eb11ba69b1b69099c3c7bd6be3087b0ba (diff)
parentacf1fcf77247efa01d7213f53082451f6c9c8f3b (diff)
downloadlinux-061ad5038ca5ac75419204b216bddc2806008ead.tar.xz
Merge tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Luinus Walleij: "Bulk GPIO changes for the v4.10 kernel cycle: Core changes: - Simplify threaded interrupt handling: instead of passing numbed parameters to gpiochip_irqchip_add_chained() we create a new call: gpiochip_irqchip_add_nested() so the two types are clearly semantically different. Also make sure that all nested chips call gpiochip_set_nested_irqchip() which is necessary for IRQ resend to work properly if it happens. - Return error on seek operations for the chardev. - Clamp values set as part of gpio[d]_direction_output() so that anything != 0 will be send down to the driver as "1" not the value passed in. - ACPI can now support naming of GPIO lines, hogs and holes in the GPIO lists. New drivers: - The SX150x driver was deemed unfit for the GPIO subsystem and was moved over to a combined GPIO+pinctrl driver in the pinctrl subsystem. New features: - Various cleanups to various drivers" * tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (49 commits) gpio: merrifield: Implement gpio_get_direction callback gpio: merrifield: Add support for hardware debouncer gpio: chardev: Return error for seek operations gpio: arizona: Tidy up probe error path gpio: arizona: Remove pointless set of platform drvdata gpio: pl061: delete platform data handling gpio: pl061: move platform data into driver gpio: pl061: rename variable from chip to pl061 gpio: pl061: rename state container struct gpio: pl061: use local state for parent IRQ storage gpio: set explicit nesting on drivers gpio: simplify adding threaded interrupts gpio: vf610: use builtin_platform_driver gpio: axp209: use correct register for GPIO input status gpio: stmpe: fix interrupt handling bug gpio: em: depnd on ARCH_SHMOBILE gpio: zx: depend on ARCH_ZX gpio: x86: update config dependencies for x86 specific hardware gpio: mb86s7x: use builtin_platform_driver gpio: etraxfs: use builtin_platform_driver ...
Diffstat (limited to 'drivers/gpio/gpio-merrifield.c')
-rw-r--r--drivers/gpio/gpio-merrifield.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index 45b51278b8ee..69e0f4ace465 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -161,6 +162,34 @@ static int mrfld_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
+static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+
+ return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
+static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+ unsigned int debounce)
+{
+ struct mrfld_gpio *priv = gpiochip_get_data(chip);
+ void __iomem *gfbr = gpio_reg(chip, offset, GFBR);
+ unsigned long flags;
+ u32 value;
+
+ raw_spin_lock_irqsave(&priv->lock, flags);
+
+ if (debounce)
+ value = readl(gfbr) & ~BIT(offset % 32);
+ else
+ value = readl(gfbr) | BIT(offset % 32);
+ writel(value, gfbr);
+
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
static void mrfld_irq_ack(struct irq_data *d)
{
struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
@@ -384,6 +413,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
priv->chip.direction_output = mrfld_gpio_direction_output;
priv->chip.get = mrfld_gpio_get;
priv->chip.set = mrfld_gpio_set;
+ priv->chip.get_direction = mrfld_gpio_get_direction;
+ priv->chip.set_debounce = mrfld_gpio_set_debounce;
priv->chip.base = gpio_base;
priv->chip.ngpio = MRFLD_NGPIO;
priv->chip.can_sleep = false;
@@ -411,7 +442,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
}
retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
- handle_simple_irq, IRQ_TYPE_NONE);
+ handle_bad_irq, IRQ_TYPE_NONE);
if (retval) {
dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
return retval;