linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers
@ 2018-03-15 15:46 William Breathitt Gray
  2018-03-15 15:46 ` [PATCH v2 1/8] iio: stx104: Implement get_multiple callback William Breathitt Gray
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:46 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

Changes in v2:
  - Utilize bitmap_zero macro to clear bits array
  - Refactor bitwise operations and loop structure for clarity
  - Implement set_multiple callback for PCIe-IDIO-16 driver

This patchset implements get_multiple callbacks for the PC104 GPIO
drivers as well as the PCI-IDIO-16 and PCIe-IDIO-24 GPIO drivers. These
devices all acquire the multiple input lines with a single read, so
utilizing the get_multiple callback can provide improvement for those
users who regularly access multiple input lines.

While developing this patchset I noticed many of these devices make use
of Intel 8255 compatible interfaces for their I/O. I may write a generic
8255 GPIO driver in the future to reduce some of the redundant code I
see pop among the drivers for these devices.

William Breathitt Gray (8):
  iio: stx104: Implement get_multiple callback
  gpio: 104-idio-16: Implement get_multiple callback
  gpio: pci-idio-16: Implement get_multiple callback
  gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks
  gpio: 104-dio-48e: Implement get_multiple callback
  gpio: 104-idi-48: Implement get_multiple callback
  gpio: gpio-mm: Implement get_multiple callback
  gpio: ws16c48: Implement get_multiple callback

 drivers/gpio/gpio-104-dio-48e.c  |  46 +++++++++++++++
 drivers/gpio/gpio-104-idi-48.c   |  46 +++++++++++++++
 drivers/gpio/gpio-104-idio-16.c  |  15 +++++
 drivers/gpio/gpio-gpio-mm.c      |  46 +++++++++++++++
 drivers/gpio/gpio-pci-idio-16.c  |  50 +++++++++++++++++
 drivers/gpio/gpio-pcie-idio-24.c | 118 +++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-ws16c48.c      |  46 +++++++++++++++
 drivers/iio/adc/stx104.c         |  11 ++++
 8 files changed, 378 insertions(+)

-- 
2.16.2

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/8] iio: stx104: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
@ 2018-03-15 15:46 ` William Breathitt Gray
  2018-03-15 15:46 ` [PATCH v2 2/8] gpio: 104-idio-16: " William Breathitt Gray
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:46 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler

The Apex Embedded Systems STX104 series of devices provides 4 TTL
compatible lines of inputs accessed via a single 4-bit port. Since four
input lines are acquired on a single port input read, the STX104 GPIO
driver may improve multiple input reads by utilizing a get_multiple
callback. This patch implements the stx104_gpio_get_multiple function
which serves as the respective get_multiple callback.

Cc: Jonathan Cameron <jic23@kernel.org>
Cc: Hartmut Knaack <knaack.h@gmx.de>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/iio/adc/stx104.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c
index 17b021f33180..0662ca199eb0 100644
--- a/drivers/iio/adc/stx104.c
+++ b/drivers/iio/adc/stx104.c
@@ -233,6 +233,16 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	return !!(inb(stx104gpio->base) & BIT(offset));
 }
 
+static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+
+	*bits = inb(stx104gpio->base);
+
+	return 0;
+}
+
 static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	int value)
 {
@@ -342,6 +352,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
 	stx104gpio->chip.direction_input = stx104_gpio_direction_input;
 	stx104gpio->chip.direction_output = stx104_gpio_direction_output;
 	stx104gpio->chip.get = stx104_gpio_get;
+	stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
 	stx104gpio->chip.set = stx104_gpio_set;
 	stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
 	stx104gpio->base = base[id] + 3;
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/8] gpio: 104-idio-16: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
  2018-03-15 15:46 ` [PATCH v2 1/8] iio: stx104: Implement get_multiple callback William Breathitt Gray
@ 2018-03-15 15:46 ` William Breathitt Gray
  2018-03-15 15:47 ` [PATCH v2 3/8] gpio: pci-idio-16: " William Breathitt Gray
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:46 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The ACCES I/O 104-IDIO-16 series of devices provides 16
optically-isolated digital inputs accessed via two 8-bit ports. Since
eight input lines are acquired on a single port input read, the
104-IDIO-16 GPIO driver may improve multiple input reads by utilizing a
get_multiple callback. This patch implements the
idio_16_gpio_get_multiple function which serves as the respective
get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-104-idio-16.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
index 2f16638a0589..5de5819e5156 100644
--- a/drivers/gpio/gpio-104-idio-16.c
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -90,6 +90,20 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return !!(inb(idio16gpio->base + 5) & (mask>>8));
 }
 
+static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
+
+	*bits = 0;
+	if (*mask & 0xFF0000)
+		*bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
+	if (*mask & 0xFF000000)
+		*bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
+
+	return 0;
+}
+
 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
@@ -244,6 +258,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 	idio16gpio->chip.get = idio_16_gpio_get;
+	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 	idio16gpio->chip.set = idio_16_gpio_set;
 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 	idio16gpio->base = base[id];
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/8] gpio: pci-idio-16: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
  2018-03-15 15:46 ` [PATCH v2 1/8] iio: stx104: Implement get_multiple callback William Breathitt Gray
  2018-03-15 15:46 ` [PATCH v2 2/8] gpio: 104-idio-16: " William Breathitt Gray
@ 2018-03-15 15:47 ` William Breathitt Gray
  2018-03-17 19:16   ` kbuild test robot
  2018-03-15 15:52 ` [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks William Breathitt Gray
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:47 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The ACCES I/O PCI-IDIO-16 series of devices provides 16
optically-isolated digital inputs accessed via two 8-bit ports. Since
eight input lines are acquired on a single port input read, the
PCI-IDIO-16 GPIO driver may improve multiple input reads by utilizing a
get_multiple callback. This patch implements the
idio_16_gpio_get_multiple function which serves as the respective
get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-pci-idio-16.c | 50 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 57d1b7fbf07b..ef43a37ccaff 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -11,6 +11,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  */
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/errno.h>
@@ -103,6 +104,54 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
 }
 
+static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
+	size_t i;
+	const unsigned int gpio_reg_size = 8;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+	const u8 __iomem ports[] = {
+		idio16gpio->reg->out0_7, idio16gpio->reg->out8_15,
+		idio16gpio->reg->in0_7, idio16gpio->reg->in8_15
+	};
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port */
+		port_state = ioread8(ports + i);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	int value)
 {
@@ -299,6 +348,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 	idio16gpio->chip.get = idio_16_gpio_get;
+	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
 	idio16gpio->chip.set = idio_16_gpio_set;
 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
                   ` (2 preceding siblings ...)
  2018-03-15 15:47 ` [PATCH v2 3/8] gpio: pci-idio-16: " William Breathitt Gray
@ 2018-03-15 15:52 ` William Breathitt Gray
  2018-03-17 21:01   ` kbuild test robot
  2018-03-15 15:53 ` [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback William Breathitt Gray
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:52 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The ACCES I/O PCIe-IDIO-24 series of devices provides 24
optically-isolated digital I/O accessed via six 8-bit ports. Since eight
input lines are acquired on a single port input read -- and similarly
eight output lines are set on a single port output write -- the
PCIe-IDIO-24 GPIO driver may improve multiple I/O reads/writes by
utilizing a get_multiple/set_multiple callbacks. This patch implements
the idio_24_gpio_get_multiple function which serves as the respective
get_multiple callback, and implements the idio_24_gpio_set_multiple
function which serves as the respective set_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-pcie-idio-24.c | 118 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c
index f666e2e69074..8d2f4745a13c 100644
--- a/drivers/gpio/gpio-pcie-idio-24.c
+++ b/drivers/gpio/gpio-pcie-idio-24.c
@@ -15,6 +15,7 @@
  * This driver supports the following ACCES devices: PCIe-IDIO-24,
  * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
  */
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/errno.h>
@@ -193,6 +194,61 @@ static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
 }
 
+static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
+	size_t i;
+	const unsigned int gpio_reg_size = 8;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+	const u8 __iomem ports[] = {
+		idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
+		idio24gpio->reg->out16_23, idio24gpio->reg->in0_7,
+		idio24gpio->reg->in8_15, idio24gpio->reg->in16_23
+	};
+	const unsigned long out_mode_mask = BIT(1);
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port (port 6 is TTL GPIO) */
+		if (i < 6)
+			port_state = ioread8(ports + i);
+		else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
+			port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
+		else
+			port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	int value)
 {
@@ -234,6 +290,66 @@ static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
 }
 
+static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
+	size_t i;
+	unsigned long bits_offset;
+	unsigned long gpio_mask;
+	const unsigned int gpio_reg_size = 8;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long gpio_mask;
+	unsigned long flags;
+	unsigned int out_state;
+	const u8 __iomem ports[] = {
+		idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
+		idio24gpio->reg->out16_23
+	};
+	const unsigned long out_mode_mask = BIT(1);
+	const unsigned int ttl_offset = 48;
+	const size_t ttl_i = BIT_WORD(ttl_offset);
+	const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
+	const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
+	const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
+
+	/* set bits are processed a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* check if any set bits for current port */
+		gpio_mask = (*mask >> bits_offset) & port_mask;
+		if (!gpio_mask) {
+			/* no set bits for this port so move on to next port */
+			continue;
+		}
+
+		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
+
+		/* process output lines */
+		out_state = ioread8(ports + i) & ~gpio_mask;
+		out_state |= (*bits >> bits_offset) & gpio_mask;
+		iowrite8(out_state, ports + i);
+
+		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
+	}
+
+	/* check if setting TTL lines and if they are in output mode */
+	if (!ttl_mask || !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
+		return;
+
+	/* handle TTL output */
+	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
+
+	/* process output lines */
+	out_state = ioread8(&idio24gpio->reg->ttl_out0_7) & ~ttl_mask;
+	out_state |= ttl_bits;
+	iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
+
+	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
+}
+
 static void idio_24_irq_ack(struct irq_data *data)
 {
 }
@@ -397,7 +513,9 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
 	idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
 	idio24gpio->chip.get = idio_24_gpio_get;
+	idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
 	idio24gpio->chip.set = idio_24_gpio_set;
+	idio24gpio->chip.set = idio_24_gpio_set_multiple;
 
 	raw_spin_lock_init(&idio24gpio->lock);
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
                   ` (3 preceding siblings ...)
  2018-03-15 15:52 ` [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks William Breathitt Gray
@ 2018-03-15 15:53 ` William Breathitt Gray
  2018-03-17 15:47   ` kbuild test robot
  2018-03-15 15:53 ` [PATCH v2 6/8] gpio: 104-idi-48: " William Breathitt Gray
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:53 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The ACCES I/O 104-DIO-48E series of devices contain two Programmable
Peripheral Interface (PPI) chips of type 82C55, which each feature three
8-bit ports of I/O. Since eight input lines are acquired on a single
port input read, the 104-DIO-48E GPIO driver may improve multiple input
reads by utilizing a get_multiple callback. This patch implements the
dio48e_gpio_get_multiple function which serves as the respective
get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-104-dio-48e.c | 46 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index bab3b94c5cbc..537b436c6e7f 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -182,6 +182,51 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return !!(port_state & mask);
 }
 
+static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
+	size_t i;
+	const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+	const unsigned int gpio_reg_size = 8;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port */
+		port_state = inb(dio48egpio->base + ports[i]);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
@@ -384,6 +429,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
 	dio48egpio->chip.direction_input = dio48e_gpio_direction_input;
 	dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
 	dio48egpio->chip.get = dio48e_gpio_get;
+	dio48egpio->chip.get_multiple = dio48e_gpio_get_multiple;
 	dio48egpio->chip.set = dio48e_gpio_set;
 	dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
 	dio48egpio->base = base[id];
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 6/8] gpio: 104-idi-48: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
                   ` (4 preceding siblings ...)
  2018-03-15 15:53 ` [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback William Breathitt Gray
@ 2018-03-15 15:53 ` William Breathitt Gray
  2018-03-17 15:13   ` kbuild test robot
  2018-03-15 15:53 ` [PATCH v2 7/8] gpio: gpio-mm: " William Breathitt Gray
  2018-03-15 15:53 ` [PATCH v2 8/8] gpio: ws16c48: " William Breathitt Gray
  7 siblings, 1 reply; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:53 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The ACCES I/O 104-IDI-48 series of devices provides 48
optically-isolated inputs accessed via six 8-bit ports. Since eight
input lines are acquired on a single port input read, the 104-IDI-48
GPIO driver may improve multiple input reads by utilizing a get_multiple
callback. This patch implements the idi_48_gpio_get_multiple function
which serves as the respective get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-104-idi-48.c | 46 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index add859d59766..1beb6b0591ee 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -88,6 +88,51 @@ static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return 0;
 }
 
+static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
+	size_t i;
+	const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+	const unsigned int gpio_reg_size = 8;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port */
+		port_state = inb(idi48egpio->base + ports[i]);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void idi_48_irq_ack(struct irq_data *data)
 {
 }
@@ -256,6 +301,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
 	idi48gpio->chip.get = idi_48_gpio_get;
+	idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
 	idi48gpio->base = base[id];
 
 	raw_spin_lock_init(&idi48gpio->lock);
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 7/8] gpio: gpio-mm: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
                   ` (5 preceding siblings ...)
  2018-03-15 15:53 ` [PATCH v2 6/8] gpio: 104-idi-48: " William Breathitt Gray
@ 2018-03-15 15:53 ` William Breathitt Gray
  2018-03-15 15:53 ` [PATCH v2 8/8] gpio: ws16c48: " William Breathitt Gray
  7 siblings, 0 replies; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:53 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The Diamond Systems GPIO-MM series of devices contain two 82C55A
devices, which each feature three 8-bit ports of I/O. Since eight input
lines are acquired on a single port input read, the GPIO-MM GPIO driver
may improve multiple input reads by utilizing a get_multiple callback.
This patch implements the gpiomm_gpio_get_multiple function which serves
as the respective get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-gpio-mm.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c
index 11ade5b288f8..d9be9ebe41cf 100644
--- a/drivers/gpio/gpio-gpio-mm.c
+++ b/drivers/gpio/gpio-gpio-mm.c
@@ -171,6 +171,51 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	return !!(port_state & mask);
 }
 
+static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
+	size_t i;
+	const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+	const unsigned int gpio_reg_size = 8;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port */
+		port_state = inb(gpiommgpio->base + ports[i]);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	int value)
 {
@@ -268,6 +313,7 @@ static int gpiomm_probe(struct device *dev, unsigned int id)
 	gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input;
 	gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output;
 	gpiommgpio->chip.get = gpiomm_gpio_get;
+	gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple;
 	gpiommgpio->chip.set = gpiomm_gpio_set;
 	gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple;
 	gpiommgpio->base = base[id];
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 8/8] gpio: ws16c48: Implement get_multiple callback
  2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
                   ` (6 preceding siblings ...)
  2018-03-15 15:53 ` [PATCH v2 7/8] gpio: gpio-mm: " William Breathitt Gray
@ 2018-03-15 15:53 ` William Breathitt Gray
  7 siblings, 0 replies; 13+ messages in thread
From: William Breathitt Gray @ 2018-03-15 15:53 UTC (permalink / raw)
  To: linus.walleij
  Cc: andy.shevchenko, linux-gpio, linux-kernel, linux-iio,
	William Breathitt Gray

The WinSystems WS16C48 device provides 48 lines of digital I/O accessed
via six 8-bit ports. Since eight input lines are acquired on a single
port input read, the WS16C48 GPIO driver may improve multiple input
reads by utilizing a get_multiple callback. This patch implements the
ws16c48_gpio_get_multiple function which serves as the respective
get_multiple callback.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
---
 drivers/gpio/gpio-ws16c48.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index 746648244bf3..9f2e7d0b48f9 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -129,6 +129,51 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return !!(port_state & mask);
 }
 
+static int ws16c48_gpio_get_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
+	const unsigned int gpio_reg_size = 8;
+	size_t i;
+	const size_t num_ports = chip->ngpio / gpio_reg_size;
+	unsigned int bits_offset;
+	size_t word_index;
+	unsigned int word_offset;
+	unsigned long mask_word;
+	const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
+	unsigned long port_state;
+
+	/* clear bits array to a clean slate */
+	bitmap_zero(bits, chip->ngpio);
+
+	/* get bits are evaluated a gpio port register at a time */
+	for (i = 0; i < num_ports; i++) {
+		/* gpio offset in bits array */
+		bits_offset = i * gpio_reg_size;
+
+		/* word index for bits array */
+		word_index = BIT_WORD(bits_offset);
+
+		/* gpio offset within current word of bits array */
+		word_offset = bits_offset % BITS_PER_LONG;
+
+		/* mask of get bits for current gpio within current word */
+		word_mask = mask[word_index] & (port_mask << word_offset);
+		if (!word_mask) {
+			/* no get bits in this port so skip to next one */
+			continue;
+		}
+
+		/* read bits from current gpio port */
+		port_state = inb(ws16c48gpio->base + i);
+
+		/* store acquired bits at respective bits array offset */
+		bits[word_index] |= port_state << word_offset;
+	}
+
+	return 0;
+}
+
 static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
@@ -383,6 +428,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
 	ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input;
 	ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output;
 	ws16c48gpio->chip.get = ws16c48_gpio_get;
+	ws16c48gpio->chip.get_multiple = ws16c48_gpio_get_multiple;
 	ws16c48gpio->chip.set = ws16c48_gpio_set;
 	ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
 	ws16c48gpio->base = base[id];
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 6/8] gpio: 104-idi-48: Implement get_multiple callback
  2018-03-15 15:53 ` [PATCH v2 6/8] gpio: 104-idi-48: " William Breathitt Gray
@ 2018-03-17 15:13   ` kbuild test robot
  0 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2018-03-17 15:13 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: kbuild-all, linus.walleij, andy.shevchenko, linux-gpio,
	linux-kernel, linux-iio, William Breathitt Gray

[-- Attachment #1: Type: text/plain, Size: 3484 bytes --]

Hi William,

I love your patch! Yet something to improve:

[auto build test ERROR on v4.16-rc4]
[also build test ERROR on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/William-Breathitt-Gray/Implement-get_multiple-for-ACCES-and-PC-104-drivers/20180317-224135
config: x86_64-randconfig-x016-201810 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/gpio/gpio-104-idi-48.c: In function 'idi_48_gpio_get_multiple':
>> drivers/gpio/gpio-104-idi-48.c:120:3: error: 'word_mask' undeclared (first use in this function); did you mean 'port_mask'?
      word_mask = mask[word_index] & (port_mask << word_offset);
      ^~~~~~~~~
      port_mask
   drivers/gpio/gpio-104-idi-48.c:120:3: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/gpio/gpio-104-idi-48.c:127:20: error: 'idi48egpio' undeclared (first use in this function); did you mean 'idi48gpio'?
      port_state = inb(idi48egpio->base + ports[i]);
                       ^~~~~~~~~~
                       idi48gpio
   drivers/gpio/gpio-104-idi-48.c:101:16: warning: unused variable 'mask_word' [-Wunused-variable]
     unsigned long mask_word;
                   ^~~~~~~~~
   drivers/gpio/gpio-104-idi-48.c:94:28: warning: unused variable 'idi48gpio' [-Wunused-variable]
     struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
                               ^~~~~~~~~

vim +120 drivers/gpio/gpio-104-idi-48.c

    90	
    91	static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
    92		unsigned long *bits)
    93	{
    94		struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
    95		size_t i;
    96		const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
    97		const unsigned int gpio_reg_size = 8;
    98		unsigned int bits_offset;
    99		size_t word_index;
   100		unsigned int word_offset;
   101		unsigned long mask_word;
   102		const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
   103		unsigned long port_state;
   104	
   105		/* clear bits array to a clean slate */
   106		bitmap_zero(bits, chip->ngpio);
   107	
   108		/* get bits are evaluated a gpio port register at a time */
   109		for (i = 0; i < ARRAY_SIZE(ports); i++) {
   110			/* gpio offset in bits array */
   111			bits_offset = i * gpio_reg_size;
   112	
   113			/* word index for bits array */
   114			word_index = BIT_WORD(bits_offset);
   115	
   116			/* gpio offset within current word of bits array */
   117			word_offset = bits_offset % BITS_PER_LONG;
   118	
   119			/* mask of get bits for current gpio within current word */
 > 120			word_mask = mask[word_index] & (port_mask << word_offset);
   121			if (!word_mask) {
   122				/* no get bits in this port so skip to next one */
   123				continue;
   124			}
   125	
   126			/* read bits from current gpio port */
 > 127			port_state = inb(idi48egpio->base + ports[i]);
   128	
   129			/* store acquired bits at respective bits array offset */
   130			bits[word_index] |= port_state << word_offset;
   131		}
   132	
   133		return 0;
   134	}
   135	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26822 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback
  2018-03-15 15:53 ` [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback William Breathitt Gray
@ 2018-03-17 15:47   ` kbuild test robot
  0 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2018-03-17 15:47 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: kbuild-all, linus.walleij, andy.shevchenko, linux-gpio,
	linux-kernel, linux-iio, William Breathitt Gray

[-- Attachment #1: Type: text/plain, Size: 2983 bytes --]

Hi William,

I love your patch! Yet something to improve:

[auto build test ERROR on v4.16-rc4]
[also build test ERROR on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/William-Breathitt-Gray/Implement-get_multiple-for-ACCES-and-PC-104-drivers/20180317-224135
config: i386-randconfig-a0-201810 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/gpio/gpio-104-dio-48e.c: In function 'dio48e_gpio_get_multiple':
>> drivers/gpio/gpio-104-dio-48e.c:214:3: error: 'word_mask' undeclared (first use in this function)
      word_mask = mask[word_index] & (port_mask << word_offset);
      ^
   drivers/gpio/gpio-104-dio-48e.c:214:3: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpio/gpio-104-dio-48e.c:195:16: warning: unused variable 'mask_word' [-Wunused-variable]
     unsigned long mask_word;
                   ^

vim +/word_mask +214 drivers/gpio/gpio-104-dio-48e.c

   184	
   185	static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
   186		unsigned long *bits)
   187	{
   188		struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
   189		size_t i;
   190		const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
   191		const unsigned int gpio_reg_size = 8;
   192		unsigned int bits_offset;
   193		size_t word_index;
   194		unsigned int word_offset;
   195		unsigned long mask_word;
   196		const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
   197		unsigned long port_state;
   198	
   199		/* clear bits array to a clean slate */
   200		bitmap_zero(bits, chip->ngpio);
   201	
   202		/* get bits are evaluated a gpio port register at a time */
   203		for (i = 0; i < ARRAY_SIZE(ports); i++) {
   204			/* gpio offset in bits array */
   205			bits_offset = i * gpio_reg_size;
   206	
   207			/* word index for bits array */
   208			word_index = BIT_WORD(bits_offset);
   209	
   210			/* gpio offset within current word of bits array */
   211			word_offset = bits_offset % BITS_PER_LONG;
   212	
   213			/* mask of get bits for current gpio within current word */
 > 214			word_mask = mask[word_index] & (port_mask << word_offset);
   215			if (!word_mask) {
   216				/* no get bits in this port so skip to next one */
   217				continue;
   218			}
   219	
   220			/* read bits from current gpio port */
   221			port_state = inb(dio48egpio->base + ports[i]);
   222	
   223			/* store acquired bits at respective bits array offset */
   224			bits[word_index] |= port_state << word_offset;
   225		}
   226	
   227		return 0;
   228	}
   229	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26851 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/8] gpio: pci-idio-16: Implement get_multiple callback
  2018-03-15 15:47 ` [PATCH v2 3/8] gpio: pci-idio-16: " William Breathitt Gray
@ 2018-03-17 19:16   ` kbuild test robot
  0 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2018-03-17 19:16 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: kbuild-all, linus.walleij, andy.shevchenko, linux-gpio,
	linux-kernel, linux-iio, William Breathitt Gray

Hi William,

I love your patch! Perhaps something to improve:

[auto build test WARNING on v4.16-rc4]
[also build test WARNING on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/William-Breathitt-Gray/Implement-get_multiple-for-ACCES-and-PC-104-drivers/20180317-224135
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   drivers/gpio/gpio-pci-idio-16.c:139:17: sparse: undefined identifier 'word_mask'
   drivers/gpio/gpio-pci-idio-16.c:140:22: sparse: undefined identifier 'word_mask'
>> drivers/gpio/gpio-pci-idio-16.c:120:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pci-idio-16.c:120:52: sparse: dereference of noderef expression
   drivers/gpio/gpio-pci-idio-16.c:121:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pci-idio-16.c:121:51: sparse: dereference of noderef expression
>> drivers/gpio/gpio-pci-idio-16.c:139:17: sparse: generating address of non-lvalue (3)
   drivers/gpio/gpio-pci-idio-16.c: In function 'idio_16_gpio_get_multiple':
   drivers/gpio/gpio-pci-idio-16.c:139:3: error: 'word_mask' undeclared (first use in this function); did you mean 'port_mask'?
      word_mask = mask[word_index] & (port_mask << word_offset);
      ^~~~~~~~~
      port_mask
   drivers/gpio/gpio-pci-idio-16.c:139:3: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpio/gpio-pci-idio-16.c:146:24: warning: passing argument 1 of 'ioread8' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
      port_state = ioread8(ports + i);
                           ^~~~~
   In file included from arch/x86/include/asm/io.h:223:0,
                    from arch/x86/include/asm/realmode.h:15,
                    from arch/x86/include/asm/acpi.h:33,
                    from arch/x86/include/asm/fixmap.h:19,
                    from arch/x86/include/asm/apic.h:10,
                    from arch/x86/include/asm/smp.h:13,
                    from arch/x86/include/asm/mmzone_64.h:11,
                    from arch/x86/include/asm/mmzone.h:5,
                    from include/linux/mmzone.h:912,
                    from include/linux/gfp.h:6,
                    from include/linux/idr.h:16,
                    from include/linux/kernfs.h:14,
                    from include/linux/sysfs.h:16,
                    from include/linux/kobject.h:20,
                    from include/linux/device.h:16,
                    from drivers/gpio/gpio-pci-idio-16.c:16:
   include/asm-generic/iomap.h:29:21: note: expected 'void *' but argument is of type 'const u8 * {aka const unsigned char *}'
    extern unsigned int ioread8(void __iomem *);
                        ^~~~~~~
   drivers/gpio/gpio-pci-idio-16.c:116:16: warning: unused variable 'mask_word' [-Wunused-variable]
     unsigned long mask_word;
                   ^~~~~~~~~

vim +120 drivers/gpio/gpio-pci-idio-16.c

   106	
   107	static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
   108		unsigned long *mask, unsigned long *bits)
   109	{
   110		struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
   111		size_t i;
   112		const unsigned int gpio_reg_size = 8;
   113		unsigned int bits_offset;
   114		size_t word_index;
   115		unsigned int word_offset;
   116		unsigned long mask_word;
   117		const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
   118		unsigned long port_state;
   119		const u8 __iomem ports[] = {
 > 120			idio16gpio->reg->out0_7, idio16gpio->reg->out8_15,
   121			idio16gpio->reg->in0_7, idio16gpio->reg->in8_15
   122		};
   123	
   124		/* clear bits array to a clean slate */
   125		bitmap_zero(bits, chip->ngpio);
   126	
   127		/* get bits are evaluated a gpio port register at a time */
   128		for (i = 0; i < ARRAY_SIZE(ports); i++) {
   129			/* gpio offset in bits array */
   130			bits_offset = i * gpio_reg_size;
   131	
   132			/* word index for bits array */
   133			word_index = BIT_WORD(bits_offset);
   134	
   135			/* gpio offset within current word of bits array */
   136			word_offset = bits_offset % BITS_PER_LONG;
   137	
   138			/* mask of get bits for current gpio within current word */
 > 139			word_mask = mask[word_index] & (port_mask << word_offset);
   140			if (!word_mask) {
   141				/* no get bits in this port so skip to next one */
   142				continue;
   143			}
   144	
   145			/* read bits from current gpio port */
   146			port_state = ioread8(ports + i);
   147	
   148			/* store acquired bits at respective bits array offset */
   149			bits[word_index] |= port_state << word_offset;
   150		}
   151	
   152		return 0;
   153	}
   154	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks
  2018-03-15 15:52 ` [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks William Breathitt Gray
@ 2018-03-17 21:01   ` kbuild test robot
  0 siblings, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2018-03-17 21:01 UTC (permalink / raw)
  To: William Breathitt Gray
  Cc: kbuild-all, linus.walleij, andy.shevchenko, linux-gpio,
	linux-kernel, linux-iio, William Breathitt Gray

Hi William,

I love your patch! Perhaps something to improve:

[auto build test WARNING on v4.16-rc4]
[also build test WARNING on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/William-Breathitt-Gray/Implement-get_multiple-for-ACCES-and-PC-104-drivers/20180317-224135
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   drivers/gpio/gpio-pcie-idio-24.c:231:17: sparse: undefined identifier 'word_mask'
   drivers/gpio/gpio-pcie-idio-24.c:232:22: sparse: undefined identifier 'word_mask'
>> drivers/gpio/gpio-pcie-idio-24.c:331:43: sparse: incorrect type in argument 1 (different modifiers) @@    expected void [noderef] <asn:2>*<noident> @@    got unsigned char cvoid [noderef] <asn:2>*<noident> @@
   drivers/gpio/gpio-pcie-idio-24.c:333:43: sparse: incorrect type in argument 2 (different modifiers) @@    expected void [noderef] <asn:2>*<noident> @@    got unsigned char cvoid [noderef] <asn:2>*<noident> @@
>> drivers/gpio/gpio-pcie-idio-24.c:518:30: sparse: incorrect type in assignment (incompatible argument 2 (different base types)) @@    expected void ( *set )( ... ) @@    got void ( *set )( ... ) @@
>> drivers/gpio/gpio-pcie-idio-24.c:210:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:210:52: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:211:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:211:54: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:212:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:212:52: sparse: dereference of noderef expression
>> drivers/gpio/gpio-pcie-idio-24.c:231:17: sparse: generating address of non-lvalue (3)
   drivers/gpio/gpio-pcie-idio-24.c:306:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:306:52: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c:307:27: sparse: dereference of noderef expression
   drivers/gpio/gpio-pcie-idio-24.c: In function 'idio_24_gpio_get_multiple':
   drivers/gpio/gpio-pcie-idio-24.c:231:3: error: 'word_mask' undeclared (first use in this function); did you mean 'port_mask'?
      word_mask = mask[word_index] & (port_mask << word_offset);
      ^~~~~~~~~
      port_mask
   drivers/gpio/gpio-pcie-idio-24.c:231:3: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpio/gpio-pcie-idio-24.c:239:25: warning: passing argument 1 of 'ioread8' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
       port_state = ioread8(ports + i);
                            ^~~~~
   In file included from arch/x86/include/asm/io.h:223:0,
                    from arch/x86/include/asm/realmode.h:15,
                    from arch/x86/include/asm/acpi.h:33,
                    from arch/x86/include/asm/fixmap.h:19,
                    from arch/x86/include/asm/apic.h:10,
                    from arch/x86/include/asm/smp.h:13,
                    from arch/x86/include/asm/mmzone_64.h:11,
                    from arch/x86/include/asm/mmzone.h:5,
                    from include/linux/mmzone.h:912,
                    from include/linux/gfp.h:6,
                    from include/linux/idr.h:16,
                    from include/linux/kernfs.h:14,
                    from include/linux/sysfs.h:16,
                    from include/linux/kobject.h:20,
                    from include/linux/device.h:16,
                    from drivers/gpio/gpio-pcie-idio-24.c:20:
   include/asm-generic/iomap.h:29:21: note: expected 'void *' but argument is of type 'const u8 * {aka const unsigned char *}'
    extern unsigned int ioread8(void __iomem *);
                        ^~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c:206:16: warning: unused variable 'mask_word' [-Wunused-variable]
     unsigned long mask_word;
                   ^~~~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c: In function 'idio_24_gpio_set_multiple':
   drivers/gpio/gpio-pcie-idio-24.c:302:16: error: redeclaration of 'gpio_mask' with no linkage
     unsigned long gpio_mask;
                   ^~~~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c:299:16: note: previous declaration of 'gpio_mask' was here
     unsigned long gpio_mask;
                   ^~~~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c:331:23: warning: passing argument 1 of 'ioread8' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
      out_state = ioread8(ports + i) & ~gpio_mask;
                          ^~~~~
   In file included from arch/x86/include/asm/io.h:223:0,
                    from arch/x86/include/asm/realmode.h:15,
                    from arch/x86/include/asm/acpi.h:33,
                    from arch/x86/include/asm/fixmap.h:19,
                    from arch/x86/include/asm/apic.h:10,
                    from arch/x86/include/asm/smp.h:13,
                    from arch/x86/include/asm/mmzone_64.h:11,
                    from arch/x86/include/asm/mmzone.h:5,
                    from include/linux/mmzone.h:912,
                    from include/linux/gfp.h:6,
                    from include/linux/idr.h:16,
                    from include/linux/kernfs.h:14,
                    from include/linux/sysfs.h:16,
                    from include/linux/kobject.h:20,
                    from include/linux/device.h:16,
                    from drivers/gpio/gpio-pcie-idio-24.c:20:
   include/asm-generic/iomap.h:29:21: note: expected 'void *' but argument is of type 'const u8 * {aka const unsigned char *}'
    extern unsigned int ioread8(void __iomem *);
                        ^~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c:333:23: warning: passing argument 2 of 'iowrite8' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
      iowrite8(out_state, ports + i);
                          ^~~~~
   In file included from arch/x86/include/asm/io.h:223:0,
                    from arch/x86/include/asm/realmode.h:15,
                    from arch/x86/include/asm/acpi.h:33,
                    from arch/x86/include/asm/fixmap.h:19,
                    from arch/x86/include/asm/apic.h:10,
                    from arch/x86/include/asm/smp.h:13,
                    from arch/x86/include/asm/mmzone_64.h:11,
                    from arch/x86/include/asm/mmzone.h:5,
                    from include/linux/mmzone.h:912,
                    from include/linux/gfp.h:6,
                    from include/linux/idr.h:16,
                    from include/linux/kernfs.h:14,
                    from include/linux/sysfs.h:16,
                    from include/linux/kobject.h:20,
                    from include/linux/device.h:16,
                    from drivers/gpio/gpio-pcie-idio-24.c:20:
   include/asm-generic/iomap.h:39:13: note: expected 'void *' but argument is of type 'const u8 * {aka const unsigned char *}'
    extern void iowrite8(u8, void __iomem *);
                ^~~~~~~~
   drivers/gpio/gpio-pcie-idio-24.c: In function 'idio_24_probe':
   drivers/gpio/gpio-pcie-idio-24.c:518:23: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     idio24gpio->chip.set = idio_24_gpio_set_multiple;
                          ^
   cc1: some warnings being treated as errors

vim +331 drivers/gpio/gpio-pcie-idio-24.c

   196	
   197	static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
   198		unsigned long *mask, unsigned long *bits)
   199	{
   200		struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
   201		size_t i;
   202		const unsigned int gpio_reg_size = 8;
   203		unsigned int bits_offset;
   204		size_t word_index;
   205		unsigned int word_offset;
   206		unsigned long mask_word;
   207		const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
   208		unsigned long port_state;
   209		const u8 __iomem ports[] = {
 > 210			idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
   211			idio24gpio->reg->out16_23, idio24gpio->reg->in0_7,
   212			idio24gpio->reg->in8_15, idio24gpio->reg->in16_23
   213		};
   214		const unsigned long out_mode_mask = BIT(1);
   215	
   216		/* clear bits array to a clean slate */
   217		bitmap_zero(bits, chip->ngpio);
   218	
   219		/* get bits are evaluated a gpio port register at a time */
   220		for (i = 0; i < ARRAY_SIZE(ports); i++) {
   221			/* gpio offset in bits array */
   222			bits_offset = i * gpio_reg_size;
   223	
   224			/* word index for bits array */
   225			word_index = BIT_WORD(bits_offset);
   226	
   227			/* gpio offset within current word of bits array */
   228			word_offset = bits_offset % BITS_PER_LONG;
   229	
   230			/* mask of get bits for current gpio within current word */
 > 231			word_mask = mask[word_index] & (port_mask << word_offset);
   232			if (!word_mask) {
   233				/* no get bits in this port so skip to next one */
   234				continue;
   235			}
   236	
   237			/* read bits from current gpio port (port 6 is TTL GPIO) */
   238			if (i < 6)
   239				port_state = ioread8(ports + i);
   240			else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
   241				port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
   242			else
   243				port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
   244	
   245			/* store acquired bits at respective bits array offset */
   246			bits[word_index] |= port_state << word_offset;
   247		}
   248	
   249		return 0;
   250	}
   251	
   252	static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
   253		int value)
   254	{
   255		struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
   256		const unsigned long out_mode_mask = BIT(1);
   257		void __iomem *base;
   258		const unsigned int mask = BIT(offset % 8);
   259		unsigned long flags;
   260		unsigned int out_state;
   261	
   262		/* Isolated Inputs */
   263		if (offset > 23 && offset < 48)
   264			return;
   265	
   266		/* TTL/CMOS Inputs */
   267		if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
   268			return;
   269	
   270		/* TTL/CMOS Outputs */
   271		if (offset > 47)
   272			base = &idio24gpio->reg->ttl_out0_7;
   273		/* FET Outputs */
   274		else if (offset > 15)
   275			base = &idio24gpio->reg->out16_23;
   276		else if (offset > 7)
   277			base = &idio24gpio->reg->out8_15;
   278		else
   279			base = &idio24gpio->reg->out0_7;
   280	
   281		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
   282	
   283		if (value)
   284			out_state = ioread8(base) | mask;
   285		else
   286			out_state = ioread8(base) & ~mask;
   287	
   288		iowrite8(out_state, base);
   289	
   290		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
   291	}
   292	
   293	static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
   294		unsigned long *mask, unsigned long *bits)
   295	{
   296		struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
   297		size_t i;
   298		unsigned long bits_offset;
   299		unsigned long gpio_mask;
   300		const unsigned int gpio_reg_size = 8;
   301		const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
   302		unsigned long gpio_mask;
   303		unsigned long flags;
   304		unsigned int out_state;
   305		const u8 __iomem ports[] = {
   306			idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
   307			idio24gpio->reg->out16_23
   308		};
   309		const unsigned long out_mode_mask = BIT(1);
   310		const unsigned int ttl_offset = 48;
   311		const size_t ttl_i = BIT_WORD(ttl_offset);
   312		const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
   313		const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
   314		const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
   315	
   316		/* set bits are processed a gpio port register at a time */
   317		for (i = 0; i < ARRAY_SIZE(ports); i++) {
   318			/* gpio offset in bits array */
   319			bits_offset = i * gpio_reg_size;
   320	
   321			/* check if any set bits for current port */
   322			gpio_mask = (*mask >> bits_offset) & port_mask;
   323			if (!gpio_mask) {
   324				/* no set bits for this port so move on to next port */
   325				continue;
   326			}
   327	
   328			raw_spin_lock_irqsave(&idio24gpio->lock, flags);
   329	
   330			/* process output lines */
 > 331			out_state = ioread8(ports + i) & ~gpio_mask;
   332			out_state |= (*bits >> bits_offset) & gpio_mask;
   333			iowrite8(out_state, ports + i);
   334	
   335			raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
   336		}
   337	
   338		/* check if setting TTL lines and if they are in output mode */
   339		if (!ttl_mask || !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
   340			return;
   341	
   342		/* handle TTL output */
   343		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
   344	
   345		/* process output lines */
   346		out_state = ioread8(&idio24gpio->reg->ttl_out0_7) & ~ttl_mask;
   347		out_state |= ttl_bits;
   348		iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
   349	
   350		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
   351	}
   352	
   353	static void idio_24_irq_ack(struct irq_data *data)
   354	{
   355	}
   356	
   357	static void idio_24_irq_mask(struct irq_data *data)
   358	{
   359		struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
   360		struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
   361		unsigned long flags;
   362		const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
   363		unsigned char new_irq_mask;
   364		const unsigned long bank_offset = bit_offset/8 * 8;
   365		unsigned char cos_enable_state;
   366	
   367		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
   368	
   369		idio24gpio->irq_mask &= BIT(bit_offset);
   370		new_irq_mask = idio24gpio->irq_mask >> bank_offset;
   371	
   372		if (!new_irq_mask) {
   373			cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
   374	
   375			/* Disable Rising Edge detection */
   376			cos_enable_state &= ~BIT(bank_offset);
   377			/* Disable Falling Edge detection */
   378			cos_enable_state &= ~BIT(bank_offset + 4);
   379	
   380			iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
   381		}
   382	
   383		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
   384	}
   385	
   386	static void idio_24_irq_unmask(struct irq_data *data)
   387	{
   388		struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
   389		struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
   390		unsigned long flags;
   391		unsigned char prev_irq_mask;
   392		const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
   393		const unsigned long bank_offset = bit_offset/8 * 8;
   394		unsigned char cos_enable_state;
   395	
   396		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
   397	
   398		prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
   399		idio24gpio->irq_mask |= BIT(bit_offset);
   400	
   401		if (!prev_irq_mask) {
   402			cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
   403	
   404			/* Enable Rising Edge detection */
   405			cos_enable_state |= BIT(bank_offset);
   406			/* Enable Falling Edge detection */
   407			cos_enable_state |= BIT(bank_offset + 4);
   408	
   409			iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
   410		}
   411	
   412		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
   413	}
   414	
   415	static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
   416	{
   417		/* The only valid irq types are none and both-edges */
   418		if (flow_type != IRQ_TYPE_NONE &&
   419			(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
   420			return -EINVAL;
   421	
   422		return 0;
   423	}
   424	
   425	static struct irq_chip idio_24_irqchip = {
   426		.name = "pcie-idio-24",
   427		.irq_ack = idio_24_irq_ack,
   428		.irq_mask = idio_24_irq_mask,
   429		.irq_unmask = idio_24_irq_unmask,
   430		.irq_set_type = idio_24_irq_set_type
   431	};
   432	
   433	static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
   434	{
   435		struct idio_24_gpio *const idio24gpio = dev_id;
   436		unsigned long irq_status;
   437		struct gpio_chip *const chip = &idio24gpio->chip;
   438		unsigned long irq_mask;
   439		int gpio;
   440	
   441		raw_spin_lock(&idio24gpio->lock);
   442	
   443		/* Read Change-Of-State status */
   444		irq_status = ioread32(&idio24gpio->reg->cos0_7);
   445	
   446		raw_spin_unlock(&idio24gpio->lock);
   447	
   448		/* Make sure our device generated IRQ */
   449		if (!irq_status)
   450			return IRQ_NONE;
   451	
   452		/* Handle only unmasked IRQ */
   453		irq_mask = idio24gpio->irq_mask & irq_status;
   454	
   455		for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
   456			generic_handle_irq(irq_find_mapping(chip->irq.domain,
   457				gpio + 24));
   458	
   459		raw_spin_lock(&idio24gpio->lock);
   460	
   461		/* Clear Change-Of-State status */
   462		iowrite32(irq_status, &idio24gpio->reg->cos0_7);
   463	
   464		raw_spin_unlock(&idio24gpio->lock);
   465	
   466		return IRQ_HANDLED;
   467	}
   468	
   469	#define IDIO_24_NGPIO 56
   470	static const char *idio_24_names[IDIO_24_NGPIO] = {
   471		"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
   472		"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
   473		"OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
   474		"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
   475		"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
   476		"IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
   477		"TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
   478	};
   479	
   480	static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
   481	{
   482		struct device *const dev = &pdev->dev;
   483		struct idio_24_gpio *idio24gpio;
   484		int err;
   485		const size_t pci_bar_index = 2;
   486		const char *const name = pci_name(pdev);
   487	
   488		idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
   489		if (!idio24gpio)
   490			return -ENOMEM;
   491	
   492		err = pcim_enable_device(pdev);
   493		if (err) {
   494			dev_err(dev, "Failed to enable PCI device (%d)\n", err);
   495			return err;
   496		}
   497	
   498		err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
   499		if (err) {
   500			dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
   501			return err;
   502		}
   503	
   504		idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
   505	
   506		idio24gpio->chip.label = name;
   507		idio24gpio->chip.parent = dev;
   508		idio24gpio->chip.owner = THIS_MODULE;
   509		idio24gpio->chip.base = -1;
   510		idio24gpio->chip.ngpio = IDIO_24_NGPIO;
   511		idio24gpio->chip.names = idio_24_names;
   512		idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
   513		idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
   514		idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
   515		idio24gpio->chip.get = idio_24_gpio_get;
   516		idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
   517		idio24gpio->chip.set = idio_24_gpio_set;
 > 518		idio24gpio->chip.set = idio_24_gpio_set_multiple;
   519	
   520		raw_spin_lock_init(&idio24gpio->lock);
   521	
   522		/* Software board reset */
   523		iowrite8(0, &idio24gpio->reg->soft_reset);
   524	
   525		err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
   526		if (err) {
   527			dev_err(dev, "GPIO registering failed (%d)\n", err);
   528			return err;
   529		}
   530	
   531		err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
   532			handle_edge_irq, IRQ_TYPE_NONE);
   533		if (err) {
   534			dev_err(dev, "Could not add irqchip (%d)\n", err);
   535			return err;
   536		}
   537	
   538		err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
   539			name, idio24gpio);
   540		if (err) {
   541			dev_err(dev, "IRQ handler registering failed (%d)\n", err);
   542			return err;
   543		}
   544	
   545		return 0;
   546	}
   547	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2018-03-17 21:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-15 15:46 [PATCH v2 0/8] Implement get_multiple for ACCES and PC/104 drivers William Breathitt Gray
2018-03-15 15:46 ` [PATCH v2 1/8] iio: stx104: Implement get_multiple callback William Breathitt Gray
2018-03-15 15:46 ` [PATCH v2 2/8] gpio: 104-idio-16: " William Breathitt Gray
2018-03-15 15:47 ` [PATCH v2 3/8] gpio: pci-idio-16: " William Breathitt Gray
2018-03-17 19:16   ` kbuild test robot
2018-03-15 15:52 ` [PATCH v2 4/8] gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks William Breathitt Gray
2018-03-17 21:01   ` kbuild test robot
2018-03-15 15:53 ` [PATCH v2 5/8] gpio: 104-dio-48e: Implement get_multiple callback William Breathitt Gray
2018-03-17 15:47   ` kbuild test robot
2018-03-15 15:53 ` [PATCH v2 6/8] gpio: 104-idi-48: " William Breathitt Gray
2018-03-17 15:13   ` kbuild test robot
2018-03-15 15:53 ` [PATCH v2 7/8] gpio: gpio-mm: " William Breathitt Gray
2018-03-15 15:53 ` [PATCH v2 8/8] gpio: ws16c48: " William Breathitt Gray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).