summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-generic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-11 11:17:34 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-11 11:17:34 -0800
commita1df7efedab047a8ea4d5850737f03d3679726a7 (patch)
tree0b8d73947b9eff3dc4a49915cccd31f4d928a2ba /drivers/gpio/gpio-generic.c
parentaa7ed01f93ff7e149cad46f13f66b269d59c9bc0 (diff)
parent0a4a3529df40c4be163b3909942b16c6c46b9d03 (diff)
Merge tag 'gpio-v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO changes from Linus Walleij: "This is the GPIO bulk changes for the v3.20 series: GPIOLIB core changes: - Create and use of_mm_gpiochip_remove() for removing memory-mapped OF GPIO chips - GPIO MMIO library suppports bgpio_set_multiple for switching several lines at once, a feature merged in the last cycle. New drivers: - New driver for the APM X-gene standby GPIO controller - New driver for the Fujitsu MB86S7x GPIO controller Cleanups: - Moved rcar driver to use gpiolib irqchip - Moxart converted to the GPIO MMIO library - GE driver converted to GPIO MMIO library - Move sx150x to irqdomain - Move max732x to irqdomain - Move vx855 to use managed resources - Move dwapb to use managed resources - Clean tc3589x from platform data - Clean stmpe driver to use device tree only probe New subtypes: - sx1506 support in the sx150x driver - Quark 1000 SoC support in the SCH driver - Support X86 in the Xilinx driver - Support PXA1928 in the PXA driver Extended drivers: - max732x supports device tree probe - sx150x supports device tree probe Various minor cleanups and bug fixes" * tag 'gpio-v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (61 commits) gpio: kconfig: replace PPC_OF with PPC gpio: pxa: add PXA1928 gpio type support dt/bindings: gpio: add compatible string for marvell,pxa1928-gpio gpio: pxa: remove mach IRQ includes gpio: max732x: use an inline function for container cast gpio: use sizeof() instead of hardcoded values gpio: max732x: add set_multiple function gpio: sch: Consolidate similar algorithms gpio: tz1090-pdc: Use resource_size to fix off-by-one resource size calculation gpio: ge: Convert to use devm_kstrdup gpio: correctly use const char * const gpio: sx150x: fixup OF support gpio: mpc8xxx: Use of_mm_gpiochip_remove gpio: Add Fujitsu MB86S7x GPIO driver gpio: mpc8xxx: Convert to platform device interface. gpio: zevio: Use of_mm_gpiochip_remove gpio: gpio-mm-lantiq: Use of_mm_gpiochip_remove gpio: gpio-mm-lantiq: Use of_property_read_u32 gpio: gpio-mm-lantiq: Do not replicate code gpio :gpio-mm-lantiq: Use devm_kzalloc ...
Diffstat (limited to 'drivers/gpio/gpio-generic.c')
-rw-r--r--drivers/gpio/gpio-generic.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 16f6115e5bd..b92a690f576 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&bgc->lock, flags);
}
+static void bgpio_multiple_get_masks(struct bgpio_chip *bgc,
+ 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 < bgc->bits; i++) {
+ if (*mask == 0)
+ break;
+ if (__test_and_clear_bit(i, mask)) {
+ if (test_bit(i, bits))
+ *set_mask |= bgc->pin2mask(bgc, i);
+ else
+ *clear_mask |= bgc->pin2mask(bgc, i);
+ }
+ }
+}
+
+static void bgpio_set_multiple_single_reg(struct bgpio_chip *bgc,
+ unsigned long *mask,
+ unsigned long *bits,
+ void __iomem *reg)
+{
+ unsigned long flags;
+ unsigned long set_mask, clear_mask;
+
+ spin_lock_irqsave(&bgc->lock, flags);
+
+ bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask);
+
+ bgc->data |= set_mask;
+ bgc->data &= ~clear_mask;
+
+ bgc->write_reg(reg, bgc->data);
+
+ spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+ unsigned long *bits)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+ bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_dat);
+}
+
+static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
+ unsigned long *bits)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+ bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_set);
+}
+
+static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
+ unsigned long *mask,
+ unsigned long *bits)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ unsigned long set_mask, clear_mask;
+
+ bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask);
+
+ if (set_mask)
+ bgc->write_reg(bgc->reg_set, set_mask);
+ if (clear_mask)
+ bgc->write_reg(bgc->reg_clr, clear_mask);
+}
+
static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
return 0;
@@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
bgc->reg_set = set;
bgc->reg_clr = clr;
bgc->gc.set = bgpio_set_with_clear;
+ bgc->gc.set_multiple = bgpio_set_multiple_with_clear;
} else if (set && !clr) {
bgc->reg_set = set;
bgc->gc.set = bgpio_set_set;
+ bgc->gc.set_multiple = bgpio_set_multiple_set;
} else {
bgc->gc.set = bgpio_set;
+ bgc->gc.set_multiple = bgpio_set_multiple;
}
bgc->gc.get = bgpio_get;