Skip to contentSkip to conversation

GPIO driver for Maxim MAX3191x

PATCH In review Lukas Wunner 9 participants 21 messages Oct 12, 2017 – Oct 19, 2017 3 messages not in the archive

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v2 cover GPIO driver for Maxim MAX3191x

GPIO driver for Maxim MAX31910, MAX31911, MAX31912, MAX31913, MAX31953 and MAX31963 industrial serializer, a daisy-chainable chip to make 8 digital 24V inputs available via SPI. Supports CRC checksums to guard against electromagnetic interference, as well as undervoltage and overtemperature detection.

The chip is used by the "Revolution Pi" family of open source PLCs based on the Raspberry Pi (https://revolution.kunbus.com/).

In a typical SCADA system, all input signals are read periodically, say, every 5 or 10 ms, and stored in a so-called "process image". To make this perform well with serializers, add a ->get_multiple callback to struct gpio_chip, add corresponding consumer functions and wire it up with linehandle_ioctl().

Changes v1 -> v2:

- Patch [1/5]: Change the argument order of assign_bit() to reflect traditional "dst = src" in C. (Peter Zijlstra)

- Patch [2/5]: Update documentation. (Linus Walleij) Drop const qualifier from struct gpio_desc ** in all function signatures to avoid a cast when passing a non-const array created with gpiod_get_array(), which is likely the most common use case.

- Patch [3/5]: Newly inserted patch to introduce common property for number of daisy-chained devices.

- Patch [4/5]: Add vendor prefix to GPIO identifiers, use boolean instead of integer to select mode, rename boolean to ignore undervoltage alarms, separate compatible strings with newlines. (Rob Herring)

- Patch [5/5]: Optimize algorithm in max3191x_get_multiple() to iterate over the bits in the mask, instead of iterating over every chip, thus implicitly skipping chips which are not selected at all by the mask.
Support configurations where all chips in a daisy-chain share the same modesel, fault or debounce pin.
Verify that the number of db0 and db1 GPIOs specified in the DT is identical.

Link to v1:

https://www.spinics.net/lists/linux-gpio/msg25067.html

Thanks,

Lukas

Lukas Wunner (5):
bitops: Introduce assign_bit()
gpio: Introduce ->get_multiple callback
dt-bindings: Document common property for daisy-chained devices
dt-bindings: gpio: max3191x: Document new driver
gpio: Add driver for Maxim MAX3191x industrial serializer

 .../devicetree/bindings/common-properties.txt      |  26 ++
 .../devicetree/bindings/gpio/gpio-max3191x.txt     |  59 +++
 Documentation/gpio/consumer.txt                    |  41 +-
 drivers/gpio/Kconfig                               |  10 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-max3191x.c                       | 492 +++++++++++++++++++++
 drivers/gpio/gpiolib.c                             | 179 +++++++-
 drivers/gpio/gpiolib.h                             |   4 +
 drivers/md/dm-mpath.c                              |  22 +-
 include/linux/bitops.h                             |  24 +
 include/linux/gpio/consumer.h                      |  43 ++
 include/linux/gpio/driver.h                        |   5 +
 12 files changed, 869 insertions(+), 37 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-max3191x.txt
 create mode 100644 drivers/gpio/gpio-max3191x.c
Signature · 1 line
2.11.0
#1 lore raw

PATCH v2 1/5 bitops: Introduce assign_bit()

A common idiom is to assign a value to a bit with:

    if (value)
        set_bit(nr, addr);
    else
        clear_bit(nr, addr);

Likewise common is the one-line expression variant:

    value ? set_bit(nr, addr) : clear_bit(nr, addr);

Commit 9a8ac3ae682e ("dm mpath: cleanup QUEUE_IF_NO_PATH bit manipulation by introducing assign_bit()") introduced assign_bit() to the md subsystem for brevity.

Make it available to others, specifically gpiolib and the upcoming driver for Maxim MAX3191x industrial serializer chips.

As requested by Peter Zijlstra, change the argument order to reflect traditional "dst = src" in C, hence "assign_bit(nr, addr, value)".

Cc Bart Van Assche <[email protected]>
Cc Alasdair Kergon <[email protected]>
Cc Mike Snitzer <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Neil Brown <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Theodore Ts'o <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Denys Vlasenko <[email protected]>

---
Changes v1 -> v2:

- Change the argument order of assign_bit() to reflect traditional "dst = src" in C. (Peter Zijlstra)

 drivers/md/dm-mpath.c  | 22 +++++++---------------
 include/linux/bitops.h | 24 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 15 deletions(-)
drivers/md/dm-mpath.c +7 -15
index 11f273d2f018..0e211de9bc54 100644
@@ -641,14 +641,6 @@ static void process_queued_bios(struct work_struct *work)
 	blk_finish_plug(&plug);
 }
 
-static void assign_bit(bool value, long nr, unsigned long *addr)
-{
-	if (value)
-		set_bit(nr, addr);
-	else
-		clear_bit(nr, addr);
-}
-
 /*
  * If we run out of usable paths, should we queue I/O or error it?
  */
@@ -658,11 +650,11 @@ static int queue_if_no_path(struct multipath *m, bool queue_if_no_path,
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-	assign_bit((save_old_value && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) ||
-		   (!save_old_value && queue_if_no_path),
-		   MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
-	assign_bit(queue_if_no_path || dm_noflush_suspending(m->ti),
-		   MPATHF_QUEUE_IF_NO_PATH, &m->flags);
+	assign_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags,
+		   (save_old_value && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) ||
+		   (!save_old_value && queue_if_no_path));
+	assign_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags,
+		   queue_if_no_path || dm_noflush_suspending(m->ti));
 	spin_unlock_irqrestore(&m->lock, flags);
 
 	if (!queue_if_no_path) {
@@ -1588,8 +1580,8 @@ static void multipath_resume(struct dm_target *ti)
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-	assign_bit(test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags),
-		   MPATHF_QUEUE_IF_NO_PATH, &m->flags);
+	assign_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags,
+		   test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags));
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
include/linux/bitops.h +24 -0
index 8fbe259b197c..9a874deee6e2 100644
@@ -227,6 +227,30 @@ static inline unsigned long __ffs64(u64 word)
 	return __ffs((unsigned long)word);
 }
 
+/**
+ * assign_bit - Assign value to a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ * @value: the value to assign
+ */
+static __always_inline void assign_bit(long nr, volatile unsigned long *addr,
+				       bool value)
+{
+	if (value)
+		set_bit(nr, addr);
+	else
+		clear_bit(nr, addr);
+}
+
+static __always_inline void __assign_bit(long nr, volatile unsigned long *addr,
+					 bool value)
+{
+	if (value)
+		__set_bit(nr, addr);
+	else
+		__clear_bit(nr, addr);
+}
+
 #ifdef __KERNEL__
 
 #ifndef set_mask_bits
Signature · 1 line
2.11.0
#5 lore raw

PATCH v2 4/5 dt-bindings: gpio: max3191x: Document new driver

In reply to a message not in the archive

Add device tree bindings for Maxim MAX3191x industrial serializer.

Cc Mathias Duckeck <m.duckeck-XB/[email protected]>

---
Changes v1 -> v2:

- Add vendor prefix to GPIO identifiers, use boolean instead of integer to select mode, rename boolean to ignore undervoltage alarms, separate compatible strings with newlines. (Rob Herring)

 .../devicetree/bindings/gpio/gpio-max3191x.txt     | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-max3191x.txt
Documentation/devicetree/bindings/gpio/gpio-max3191x.txt new file +59 -0
new file mode 100644
index 000000000000..b3a6444b8f45
@@ -0,0 +1,59 @@
+GPIO driver for Maxim MAX3191x industrial serializer
+
+Required properties:
+ - compatible:		Must be one of:
+			"maxim,max31910"
+			"maxim,max31911"
+			"maxim,max31912"
+			"maxim,max31913"
+			"maxim,max31953"
+			"maxim,max31963"
+ - reg: 		Chip select number.
+ - gpio-controller:	Marks the device node as a GPIO controller.
+ - #gpio-cells: 	Should be two. For consumer use see gpio.txt.
+
+Optional properties:
+ - #daisy-chained-devices:
+			Number of chips in the daisy-chain (default is 1).
+ - maxim,modesel-gpios: GPIO pins to configure modesel of each chip.
+			The number of GPIOs must equal "#daisy-chained-devices"
+			(if each chip is driven by a separate pin) or 1
+			(if all chips are wired to the same pin).
+ - maxim,fault-gpios: 	GPIO pins to read fault of each chip.
+			The number of GPIOs must equal "#daisy-chained-devices"
+			or 1.
+ - maxim,db0-gpios:	GPIO pins to configure debounce of each chip.
+			The number of GPIOs must equal "#daisy-chained-devices"
+			or 1.
+ - maxim,db1-gpios:	GPIO pins to configure debounce of each chip.
+			The number of GPIOs must equal "maxim,db0-gpios".
+ - maxim,modesel-8bit:	Boolean whether the modesel pin of the chips is
+			pulled high (8-bit mode).  Use this if the modesel pin
+			is hardwired and consequently "maxim,modesel-gpios"
+			cannot be specified.  By default if neither this nor
+			"maxim,modesel-gpios" is given, the driver assumes
+			that modesel is pulled low (16-bit mode).
+ - maxim,ignore-undervoltage:
+			Boolean whether to ignore undervoltage alarms signaled
+			by the "maxim,fault-gpios" or by the status byte
+			(in 16-bit mode).  Use this if the chips are powered
+			through 5VOUT instead of VCC24V, in which case they
+			will constantly signal undervoltage.
+
+For other required and optional properties of SPI slave nodes please refer to
+../spi/spi-bus.txt.
+
+Example:
+	gpio@0 {
+		compatible = "maxim,max31913";
+		reg = <0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		maxim,modesel-gpios = <&gpio2 23>;
+		maxim,fault-gpios   = <&gpio2 24 GPIO_ACTIVE_LOW>;
+		maxim,db0-gpios     = <&gpio2 25>;
+		maxim,db1-gpios     = <&gpio2 26>;
+
+		spi-max-frequency = <25000000>;
+	};
Signature · 6 lines
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#9 lore raw

PATCH v2 5/5 gpio: Add driver for Maxim MAX3191x industrial serializer

In reply to a message not in the archive

The driver was developed for and tested with the MAX31913 built into the Revolution Pi by KUNBUS, but should work with all members of the MAX3191x family:

MAX31910: low power
MAX31911: LED drivers
MAX31912: LED drivers + 2nd voltage monitor + low power
MAX31913: LED drivers + 2nd voltage monitor
MAX31953: LED drivers + 2nd voltage monitor + isolation
MAX31963: LED drivers + 2nd voltage monitor + isolation + buck regulator

Cc Mathias Duckeck <m.duckeck-XB/[email protected]>

---
Changes v1 -> v2:

- Optimize algorithm in max3191x_get_multiple() to iterate over the bits in the mask, instead of iterating over every chip, thus implicitly skipping chips which are not selected at all by the mask. Support configurations where all chips in a daisy-chain share the same modesel, fault or debounce pin.
Verify that the number of db0 and db1 GPIOs specified in the DT is identical.

 drivers/gpio/Kconfig         |  10 +
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-max3191x.c | 492 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 503 insertions(+)
 create mode 100644 drivers/gpio/gpio-max3191x.c
drivers/gpio/Kconfig +10 -0
index 3388d54ba114..d5282cac6ea6 100644
@@ -1255,6 +1255,16 @@ config GPIO_74X164
 	  shift registers. This driver can be used to provide access
 	  to more gpio outputs.
 
+config GPIO_MAX3191X
+	tristate "Maxim MAX3191x industrial serializer"
+	select CRC8
+	help
+	  GPIO driver for Maxim MAX31910, MAX31911, MAX31912, MAX31913,
+	  MAX31953 and MAX31963 industrial serializer, a daisy-chainable
+	  chip to make 8 digital 24V inputs available via SPI.  Supports
+	  CRC checksums to guard against electromagnetic interference,
+	  as well as undervoltage and overtemperature detection.
+
 config GPIO_MAX7301
 	tristate "Maxim MAX7301 GPIO expander"
 	select GPIO_MAX730X
drivers/gpio/Makefile +1 -0
index aeb70e9de6f2..cf9ecfb24ef4 100644
@@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_LP873X)	+= gpio-lp873x.o
 obj-$(CONFIG_GPIO_LP87565)	+= gpio-lp87565.o
 obj-$(CONFIG_GPIO_LYNXPOINT)	+= gpio-lynxpoint.o
+obj-$(CONFIG_GPIO_MAX3191X)	+= gpio-max3191x.o
 obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
drivers/gpio/gpio-max3191x.c new file +492 -0

492 lines not on this page · raw message

Signature · 6 lines
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#18 lore raw

PATCH v2 3/5 dt-bindings: Document common property for daisy-chained devices

In reply to Lukas Wunner

Many serially-attached GPIO and IIO devices are daisy-chainable.

    Examples for GPIO devices are Maxim MAX3191x and TI SN65HVS88x:
    https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf
    http://www.ti.com/lit/ds/symlink/sn65hvs880.pdf

    Examples for IIO devices are TI DAC128S085 and TI DAC161S055:
    http://www.ti.com/lit/ds/symlink/dac128s085.pdf
    http://www.ti.com/lit/ds/symlink/dac161s055.pdf

We already have drivers for daisy-chainable devices in the tree but their devicetree bindings are somewhat inconsistent and ill-named:

The gpio-74x164.c driver uses "registers-number" to convey the number of devices in the daisy-chain. (Sans vendor prefix, multiple vendors sell compatible versions of this chip.)

The gpio-pisosr.c driver takes a different approach and calculates the number of devices in the daisy-chain by dividing the common "ngpios" property (Documentation/devicetree/bindings/gpio/gpio.txt) by 8 (which assumes that each chip has 8 inputs).

Let's standardize on a common "#daisy-chained-devices" property. That name was chosen because it's the term most frequently used in datasheets. (A less frequently used synonym is "cascaded devices".)

---
Changes v1 -> v2:

- Newly inserted patch.

 .../devicetree/bindings/common-properties.txt      | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
Documentation/devicetree/bindings/common-properties.txt +26 -0
index 697714f8d75c..a3448bfa1c82 100644
@@ -1,4 +1,8 @@
 Common properties
+=================
+
+Endianness
+----------
 
 The Devicetree Specification does not define any properties related to hardware
 byteswapping, but endianness issues show up frequently in porting Linux to
@@ -58,3 +62,25 @@ dev: dev@40031000 {
 	      ...
 	      little-endian;
 };
+
+Daisy-chained devices
+---------------------
+
+Many serially-attached GPIO and IIO devices are daisy-chainable.  To the
+host controller, a daisy-chain appears as a single device, but the number
+of inputs and outputs it provides is the sum of inputs and outputs provided
+by all of its devices.  The driver needs to know how many devices the
+daisy-chain comprises to determine the amount of data exchanged, how many
+inputs and outputs to register and so on.
+
+Optional properties:
+ - #daisy-chained-devices: Number of devices in the daisy-chain (default is 1).
+
+Example:
+gpio@0 {
+	      compatible = "name";
+	      reg = <0>;
+	      gpio-controller;
+	      #gpio-cells = <2>;
+	      #daisy-chained-devices = <3>;
+};
Signature · 1 line
2.11.0
#16 lore raw

PATCH v2 2/5 gpio: Introduce ->get_multiple callback

In reply to Lukas Wunner

SPI-attached GPIO controllers typically read out all inputs in one go. If callers desire the values of multipe inputs, ideally a single readout should take place to return the desired values. However the current driver API only offers a ->get callback but no ->get_multiple (unlike ->set_multiple, which is present). Thus, to read multiple inputs, a full readout needs to be performed for every single value (barring driver-internal caching), which is inefficient.

In fact, the lack of a ->get_multiple callback has been bemoaned repeatedly by the gpio subsystem maintainer:
http://www.spinics.net/lists/linux-gpio/msg10571.html
http://www.spinics.net/lists/devicetree/msg121734.html

Introduce the missing callback. Add corresponding consumer functions such as gpiod_get_array_value(). Amend linehandle_ioctl() to take advantage of the newly added infrastructure. Update the documentation.

Cc Rojhalat Ibrahim <[email protected]>

---
Changes v1 -> v2:

- Update documentation. (Linus Walleij)
Drop const qualifier from struct gpio_desc ** in all function signatures to avoid a cast when passing a non-const array created with gpiod_get_array(), which is likely the most common use case.

 Documentation/gpio/consumer.txt |  41 ++++++---
 drivers/gpio/gpiolib.c          | 179 +++++++++++++++++++++++++++++++++++++---
 drivers/gpio/gpiolib.h          |   4 +
 include/linux/gpio/consumer.h   |  43 ++++++++++
 include/linux/gpio/driver.h     |   5 ++
 5 files changed, 250 insertions(+), 22 deletions(-)
Documentation/gpio/consumer.txt +30 -11
index ddbfa775a78a..63e1bd1d88e3 100644
@@ -295,9 +295,22 @@ as possible, especially by drivers which should not care about the actual
 physical line level and worry about the logical value instead.
 
 
-Set multiple GPIO outputs with a single function call
------------------------------------------------------
-The following functions set the output values of an array of GPIOs:
+Access multiple GPIOs with a single function call
+-------------------------------------------------
+The following functions get or set the values of an array of GPIOs:
+
+	int gpiod_get_array_value(unsigned int array_size,
+				  struct gpio_desc **desc_array,
+				  int *value_array);
+	int gpiod_get_raw_array_value(unsigned int array_size,
+				      struct gpio_desc **desc_array,
+				      int *value_array);
+	int gpiod_get_array_value_cansleep(unsigned int array_size,
+					   struct gpio_desc **desc_array,
+					   int *value_array);
+	int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
+					   struct gpio_desc **desc_array,
+					   int *value_array);
 
 	void gpiod_set_array_value(unsigned int array_size,
 				   struct gpio_desc **desc_array,
@@ -312,34 +325,40 @@ The following functions set the output values of an array of GPIOs:
 						struct gpio_desc **desc_array,
 						int *value_array)
 
-The array can be an arbitrary set of GPIOs. The functions will try to set
+The array can be an arbitrary set of GPIOs. The functions will try to access
 GPIOs belonging to the same bank or chip simultaneously if supported by the
 corresponding chip driver. In that case a significantly improved performance
-can be expected. If simultaneous setting is not possible the GPIOs will be set
-sequentially.
+can be expected. If simultaneous access is not possible the GPIOs will be
+accessed sequentially.
 
-The gpiod_set_array() functions take three arguments:
+The functions take three arguments:
 	* array_size	- the number of array elements
 	* desc_array	- an array of GPIO descriptors
-	* value_array	- an array of values to assign to the GPIOs
+	* value_array	- an array to store the GPIOs' values (get) or
+			  an array of values to assign to the GPIOs (set)
 
 The descriptor array can be obtained using the gpiod_get_array() function
 or one of its variants. If the group of descriptors returned by that function
-matches the desired group of GPIOs, those GPIOs can be set by simply using
+matches the desired group of GPIOs, those GPIOs can be accessed by simply using
 the struct gpio_descs returned by gpiod_get_array():
 
 	struct gpio_descs *my_gpio_descs = gpiod_get_array(...);
 	gpiod_set_array_value(my_gpio_descs->ndescs, my_gpio_descs->desc,
 			      my_gpio_values);
 
-It is also possible to set a completely arbitrary array of descriptors. The
+It is also possible to access a completely arbitrary array of descriptors. The
 descriptors may be obtained using any combination of gpiod_get() and
 gpiod_get_array(). Afterwards the array of descriptors has to be setup
-manually before it can be used with gpiod_set_array().
+manually before it can be passed to one of the above functions.
 
 Note that for optimal performance GPIOs belonging to the same chip should be
 contiguous within the array of descriptors.
 
+The return value of gpiod_get_array_value() and its variants is 0 on success
+or negative on error. Note the difference to gpiod_get_value(), which returns
+0 or 1 on success to convey the GPIO value. With the array functions, the GPIO
+values are stored in value_array rather than passed back as return value.
+
 
 GPIOs mapped to IRQs
 --------------------
drivers/gpio/gpiolib.c +168 -11

214 lines not on this page · raw message

drivers/gpio/gpiolib.h +4 -0
index d003ccb12781..10a48caf8477 100644
@@ -180,6 +180,10 @@ static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
 #endif
 
 struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
+int gpiod_get_array_value_complex(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,
include/linux/gpio/consumer.h +43 -0

88 lines not on this page · raw message

include/linux/gpio/driver.h +5 -0
index 1de5dd185118..5fe533408b3a 100644
@@ -35,6 +35,8 @@ struct module;
  * @direction_input: configures signal "offset" as input, or returns error
  * @direction_output: configures signal "offset" as output, or returns error
  * @get: returns value for signal "offset", 0=low, 1=high, or negative error
+ * @get_multiple: reads values for multiple signals defined by "mask" and
+ *	stores them in "bits", returns 0 on success or negative error
  * @set: assigns output value for signal "offset"
  * @set_multiple: assigns output values for multiple signals defined by "mask"
  * @set_config: optional hook for all kinds of settings. Uses the same
@@ -126,6 +128,9 @@ struct gpio_chip {
 						unsigned offset, int value);
 	int			(*get)(struct gpio_chip *chip,
 						unsigned offset);
+	int			(*get_multiple)(struct gpio_chip *chip,
+						unsigned long *mask,
+						unsigned long *bits);
 	void			(*set)(struct gpio_chip *chip,
 						unsigned offset, int value);
 	void			(*set_multiple)(struct gpio_chip *chip,
Signature · 1 line
2.11.0
Acked-by on v2 1/5
#2 lore raw

Re: [PATCH v2 1/5] bitops: Introduce assign_bit()

In reply to Lukas Wunner
Quoted 15 lines · On Thu, 12 Oct 2017 12:40:10 +0200 Lukas Wunner <[email protected]> wrote:

A common idiom is to assign a value to a bit with:

    if (value)
        set_bit(nr, addr);
    else
        clear_bit(nr, addr);

Likewise common is the one-line expression variant:

    value ? set_bit(nr, addr) : clear_bit(nr, addr);

Commit 9a8ac3ae682e ("dm mpath: cleanup QUEUE_IF_NO_PATH bit manipulation by introducing assign_bit()") introduced assign_bit() to the md subsystem for brevity.

Quoted 5 lines

Make it available to others, specifically gpiolib and the upcoming driver for Maxim MAX3191x industrial serializer chips.

As requested by Peter Zijlstra, change the argument order to reflect traditional "dst = src" in C, hence "assign_bit(nr, addr, value)".

#10 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

In reply to Lukas Wunner

[cc += William Breathitt Gray, Geert Uytterhoeven, Phil Reid,
David Daney, Iban Rodriguez]

The drivers

       gpio-104-dio-48e.c, gpio-74x164.c, gpio-gpio-mm.c,
       gpio-pca953x.c, gpio-thunderx.c, gpio-ws16c48.c,
       gpio-xilinx.c

currently use an inefficient algorithm for their ->set_multiple
callback: They iterate over every chip (or bank or gpio pin), check if any bits are set in the mask for this particular chip, and if so, update the affected GPIOs. If the mask is sparsely populated, you'll waste CPU time checking chips even though they're not affected by the operation at all.

Iterating over the chips is backwards, it is more efficient to iterate over the bits set in the mask, identify the corresponding chip and update its affected GPIOs. The gpio-max3191x.c driver I posted yesterday contains an example for such an algorithm and you may want to improve your ->set_mutiple implementation accordingly:

Quoted 23 lines
drivers/gpio/gpio-max3191x.c new file +23 -0
+static int max3191x_get_multiple(struct gpio_chip *gpio, unsigned long *mask,
+				 unsigned long *bits)
+{
+	struct max3191x_chip *max3191x = gpiochip_get_data(gpio);
+	int ret, bit = 0, wordlen = max3191x_wordlen(max3191x);
+
+	mutex_lock(&max3191x->lock);
+	ret = max3191x_readout_locked(max3191x);
+	if (ret)
+		goto out_unlock;
+
+	while ((bit = find_next_bit(mask, gpio->ngpio, bit)) != gpio->ngpio) {
+		unsigned int chipnum = bit / MAX3191X_NGPIO;
+		unsigned long in, shift, index;
+
+		if (max3191x_chip_is_faulting(max3191x, chipnum)) {
+			ret = -EIO;
+			goto out_unlock;
+		}
+
+		in = ((u8 *)max3191x->xfer.rx_buf)[chipnum * wordlen];
+		shift = round_down(bit % BITS_PER_LONG, MAX3191X_NGPIO);
+		index = bit / BITS_PER_LONG;

drivers/gpio/gpio-max3191x.c line 266

Quoted 10 lines
drivers/gpio/gpio-max3191x.c new file +10 -0
+		bits[index] &= ~(mask[index] & (0xff << shift));
+		bits[index] |= mask[index] & (in << shift); /* copy bits */
+
+		bit = (chipnum + 1) * MAX3191X_NGPIO; /* go to next chip */
+	}
+
+out_unlock:
+	mutex_unlock(&max3191x->lock);
+	return ret;
+}

I've used a while loop, obviously the same can be achieved with a for loop but I found that harder to read and it didn't save any LoC.

This particular chip has 8 inputs (= MAX3191X_NGPIO) that can be read concurrently.

The series containing this driver introduces a ->get_multiple callback. Since you've implemented a ->set_multiple callback, you may want to add a ->get_multiple callback to your driver as well. (If supported by the hardware, which is not the case for output-only chips such as gpio-74x164.c.)

You can find the full series here:
https://www.spinics.net/lists/linux-gpio/msg25997.html

If you want to fetch the series from a git repo, use this branch:
https://github.com/RevolutionPi/linux/commits/revpi-4.9

Thanks,

Lukas

#3 lore raw

Re: [PATCH v2 1/5] bitops: Introduce assign_bit()

In reply to Lukas Wunner
Quoted 21 lines · Lukas Wunner

A common idiom is to assign a value to a bit with:

    if (value)
        set_bit(nr, addr);
    else
        clear_bit(nr, addr);

Likewise common is the one-line expression variant:

    value ? set_bit(nr, addr) : clear_bit(nr, addr);

Commit 9a8ac3ae682e ("dm mpath: cleanup QUEUE_IF_NO_PATH bit manipulation by introducing assign_bit()") introduced assign_bit() to the md subsystem for brevity.

Make it available to others, specifically gpiolib and the upcoming driver for Maxim MAX3191x industrial serializer chips.

As requested by Peter Zijlstra, change the argument order to reflect traditional "dst = src" in C, hence "assign_bit(nr, addr, value)".

Quoted 13 lines
Cc Bart Van Assche <[email protected]>
Cc Alasdair Kergon <[email protected]>
Cc Mike Snitzer <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Neil Brown <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Theodore Ts'o <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Denys Vlasenko <[email protected]>

This v2 applied with Andrew's ACK.

Yours,
Linus Walleij

#17 lore raw

Re: [PATCH v2 2/5] gpio: Introduce ->get_multiple callback

In reply to Lukas Wunner
Quoted 13 lines · Lukas Wunner

SPI-attached GPIO controllers typically read out all inputs in one go. If callers desire the values of multipe inputs, ideally a single readout should take place to return the desired values. However the current driver API only offers a ->get callback but no ->get_multiple (unlike ->set_multiple, which is present). Thus, to read multiple inputs, a full readout needs to be performed for every single value (barring driver-internal caching), which is inefficient.

In fact, the lack of a ->get_multiple callback has been bemoaned repeatedly by the gpio subsystem maintainer:
http://www.spinics.net/lists/linux-gpio/msg10571.html
http://www.spinics.net/lists/devicetree/msg121734.html

Quoted 8 lines

Introduce the missing callback. Add corresponding consumer functions such as gpiod_get_array_value(). Amend linehandle_ioctl() to take advantage of the newly added infrastructure. Update the documentation.

Cc Rojhalat Ibrahim <[email protected]>

---
Changes v1 -> v2:

Applied this v2 version.

Good work! I'm happy :)

We should take a sweep over existing drivers and see which in-tree drivers that can exploit this and send some patches for testing.

Yours,
Linus Walleij

#23 lore raw
In reply to Lukas Wunner
Quoted 7 lines · Lukas Wunner

- Patch [1/5]: Change the argument order of assign_bit() to reflect traditional "dst = src" in C. (Peter Zijlstra)

- Patch [2/5]: Update documentation. (Linus Walleij) Drop const qualifier from struct gpio_desc ** in all function signatures to avoid a cast when passing a non-const array created with gpiod_get_array(), which is likely the most common use case.

Applied these two so we get the infrastructure in place so others can use it too.

Quoted 8 lines

- Patch [3/5]: Newly inserted patch to introduce common property for number of daisy-chained devices.

- Patch [4/5]: Add vendor prefix to GPIO identifiers, use boolean instead of integer to select mode, rename boolean to ignore undervoltage alarms, separate compatible strings with newlines. (Rob Herring)

Quoted 4 lines

- Patch [5/5]: Optimize algorithm in max3191x_get_multiple() to iterate over the bits in the mask, instead of iterating over every chip, thus implicitly skipping chips which are not selected at all by the mask.

These are pending device tree maintainer review.

Yours,
Linus Walleij

#11 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

In reply to Lukas Wunner
Quoted 16 lines · Lukas Wunner

[cc += William Breathitt Gray, Geert Uytterhoeven, Phil Reid,
David Daney, Iban Rodriguez]

The drivers

        gpio-104-dio-48e.c, gpio-74x164.c, gpio-gpio-mm.c,
        gpio-pca953x.c, gpio-thunderx.c, gpio-ws16c48.c,
        gpio-xilinx.c

currently use an inefficient algorithm for their ->set_multiple
callback: They iterate over every chip (or bank or gpio pin), check if any bits are set in the mask for this particular chip, and if so, update the affected GPIOs. If the mask is sparsely populated, you'll waste CPU time checking chips even though they're not affected by the operation at all.

Quoted 7 lines

Iterating over the chips is backwards, it is more efficient to iterate over the bits set in the mask, identify the corresponding chip and update its affected GPIOs. The gpio-max3191x.c driver I posted yesterday contains an example for such an algorithm and you may want to improve your ->set_mutiple implementation accordingly:

Do you have any profiling results that demonstrate significant system-wide performance improvements by making such a change?

For the gpio-thunderx.c driver, the words in the bits/mask exactly match the banks, so the number of iterations doesn't change with the approach you suggest.

In fact, an argument could be made in the other direction. The increased ICache pressure from code bloat and branch prediction misses resulting from extra testing of the mask bits could easily make the system slower using your suggestion.

Thanks,
David Daney

#12 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

Quoted 14 lines · David Daney
Quoted 13 lines · Lukas Wunner

The drivers

       gpio-104-dio-48e.c, gpio-74x164.c, gpio-gpio-mm.c,
       gpio-pca953x.c, gpio-thunderx.c, gpio-ws16c48.c,
       gpio-xilinx.c

currently use an inefficient algorithm for their ->set_multiple
callback: They iterate over every chip (or bank or gpio pin), check if any bits are set in the mask for this particular chip, and if so, update the affected GPIOs. If the mask is sparsely populated, you'll waste CPU time checking chips even though they're not affected by the operation at all.

Quoted 8 lines
Quoted 5 lines

Iterating over the chips is backwards, it is more efficient to iterate over the bits set in the mask, identify the corresponding chip and update its affected GPIOs. The gpio-max3191x.c driver I posted yesterday contains an example for such an algorithm and you may want to improve your ->set_mutiple implementation accordingly:

Do you have any profiling results that demonstrate significant system-wide performance improvements by making such a change?

Sorry, no.

Quoted 3 lines

For the gpio-thunderx.c driver, the words in the bits/mask exactly match the banks, so the number of iterations doesn't change with the approach you suggest.

No, I was specifically referring to a sparsely populated mask above. Let's say the mask consists of several 64-bit words and only the last word has set bits. With the existing algorithm you have as many iterations as you have banks:

	for (bank = 0; bank <= chip->ngpio / 64; bank++) {
		set_bits = bits[bank] & mask[bank];
		clear_bits = ~bits[bank] & mask[bank];
		writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
		writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
	}

Whereas with the algorithm I'm proposing you only have a single iteration:

	int bit = 0;
	while ((bit = find_next_bit(mask, chip->ngpio, bit)) != chip->ngpio) {
		unsigned int bank = bit / 64;
		set_bits = bits[bank] & mask[bank];
		clear_bits = ~bits[bank] & mask[bank];
		writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
		writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
		bit = (bank + 1) * 64; /* continue search from next bank */
	}

find_next_bit() uses the clz instruction on ARM, similar instructions exist on most arches, so the search is very fast.

Or did you mean that find_next_bit() iterates over the words to find the first one with set bits?

BTW, why isn't there a check in your code whether mask[bank] != 0, n which case the mmio writes can be skipped?

Quoted 4 lines

In fact, an argument could be made in the other direction. The increased ICache pressure from code bloat and branch prediction misses resulting from extra testing of the mask bits could easily make the system slower using your suggestion.

I don't quite follow, where should the branch prediction misses come from, the number of branch instructions is the same with both algorithms, and fewer with the proposed algorithm on sparsely populated masks.

Also, 2 additional LoC is hardly code bloat.

Are you referring to the call to find_next_bit() specifically?

Thanks,

Lukas

#13 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

Quoted 55 lines · Lukas Wunner
Quoted 14 lines · David Daney
Quoted 13 lines · Lukas Wunner

The drivers

        gpio-104-dio-48e.c, gpio-74x164.c, gpio-gpio-mm.c,
        gpio-pca953x.c, gpio-thunderx.c, gpio-ws16c48.c,
        gpio-xilinx.c

currently use an inefficient algorithm for their ->set_multiple
callback: They iterate over every chip (or bank or gpio pin), check if any bits are set in the mask for this particular chip, and if so, update the affected GPIOs. If the mask is sparsely populated, you'll waste CPU time checking chips even though they're not affected by the operation at all.

Quoted 8 lines
Quoted 5 lines

Iterating over the chips is backwards, it is more efficient to iterate over the bits set in the mask, identify the corresponding chip and update its affected GPIOs. The gpio-max3191x.c driver I posted yesterday contains an example for such an algorithm and you may want to improve your ->set_mutiple implementation accordingly:

Do you have any profiling results that demonstrate significant system-wide performance improvements by making such a change?

Sorry, no.

Quoted 3 lines

For the gpio-thunderx.c driver, the words in the bits/mask exactly match the banks, so the number of iterations doesn't change with the approach you suggest.

No, I was specifically referring to a sparsely populated mask above. Let's say the mask consists of several 64-bit words and only the last word has set bits. With the existing algorithm you have as many iterations as you have banks:

	for (bank = 0; bank <= chip->ngpio / 64; bank++) {
		set_bits = bits[bank] & mask[bank];
		clear_bits = ~bits[bank] & mask[bank];
		writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
		writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
	}

Whereas with the algorithm I'm proposing you only have a single iteration:

	int bit = 0;
	while ((bit = find_next_bit(mask, chip->ngpio, bit)) != chip->ngpio) {
		unsigned int bank = bit / 64;
		set_bits = bits[bank] & mask[bank];
		clear_bits = ~bits[bank] & mask[bank];
		writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
		writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
		bit = (bank + 1) * 64; /* continue search from next bank */
	}
Quoted 3 lines

find_next_bit() uses the clz instruction on ARM, similar instructions exist on most arches, so the search is very fast.

There are a maximum of two banks.

For some thunderx SoCs there is only a single bank, so my code has exactly one iteration. For the SoCs with two banks, my code has exactly two iterations. There are no function calls in the loop.

Your suggested code does a function call to the find_next_bit() function for each iteration. I assert that your method will be slower.

Unless you can show an instruction trace where your code results in fewer instructions being executed, I would NAK the patch.

I can't believe I have spent so much time on this issue, for which no matter what you do, will not impact system performance in any measurable way.

David.

#14 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

Quoted 5 lines · David Daney

There are a maximum of two banks.

For some thunderx SoCs there is only a single bank, so my code has exactly one iteration. For the SoCs with two banks, my code has exactly two iterations. There are no function calls in the loop.

Fair enough. So as you've pointed out, if the number of GPIOs per bank is identical to the number of bits in an unsigned long, the iteration count is the same with both algorithms and just iterating over the banks results in simpler and less code. Doubly so if there's just one or two banks. Those are good points.

The situation is different with e.g. gpio-max3191x.c and gpio-74x164.c where each bank has only 8 GPIOs.

Quoted 2 lines

I can't believe I have spent so much time on this issue, for which no matter what you do, will not impact system performance in any measurable way.

The use case that I'm referring to in the cover letter of this series are PLCs which poll all inputs and write all outputs in cycles of e.g. every 500 us to 10 ms, so optimizations pay off.

Thanks,

Lukas

#20 lore raw

Re: [PATCH v2 3/5] dt-bindings: Document common property for daisy-chained devices

In reply to a message not in the archive
Quoted 22 lines · On Thu, 12 Oct 2017 12:40:10 +0200 Lukas Wunner…

Many serially-attached GPIO and IIO devices are daisy-chainable.

    Examples for GPIO devices are Maxim MAX3191x and TI SN65HVS88x:
    https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf
    http://www.ti.com/lit/ds/symlink/sn65hvs880.pdf

    Examples for IIO devices are TI DAC128S085 and TI DAC161S055:
    http://www.ti.com/lit/ds/symlink/dac128s085.pdf
    http://www.ti.com/lit/ds/symlink/dac161s055.pdf

We already have drivers for daisy-chainable devices in the tree but their devicetree bindings are somewhat inconsistent and ill-named:

The gpio-74x164.c driver uses "registers-number" to convey the number of devices in the daisy-chain. (Sans vendor prefix, multiple vendors sell compatible versions of this chip.)

The gpio-pisosr.c driver takes a different approach and calculates the number of devices in the daisy-chain by dividing the common "ngpios" property (Documentation/devicetree/bindings/gpio/gpio.txt) by 8 (which assumes that each chip has 8 inputs).

Quoted 5 lines

Let's standardize on a common "#daisy-chained-devices" property. That name was chosen because it's the term most frequently used in datasheets. (A less frequently used synonym is "cascaded devices".)

Makes sense to me.

Quoted 37 lines

---
Changes v1 -> v2:

- Newly inserted patch.

 .../devicetree/bindings/common-properties.txt      | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
Documentation/devicetree/bindings/common-properties.txt +16 -0
index 697714f8d75c..a3448bfa1c82 100644
@@ -1,4 +1,8 @@
 Common properties
+=================
+
+Endianness
+----------
 
 The Devicetree Specification does not define any properties related to hardware
 byteswapping, but endianness issues show up frequently in porting Linux to
@@ -58,3 +62,25 @@ dev: dev@40031000 {
...
 	      little-endian;
 };
+
+Daisy-chained devices
+---------------------
+
+Many serially-attached GPIO and IIO devices are daisy-chainable.  To the
+host controller, a daisy-chain appears as a single device, but the number
+of inputs and outputs it provides is the sum of inputs and outputs provided
+by all of its devices.  The driver needs to know how many devices the
+daisy-chain comprises to determine the amount of data exchanged, how many
+inputs and outputs to register and so on.
+
+Optional properties:

Documentation/devicetree/bindings/common-properties.txt dev: dev@40031000 { · line 86

Quoted 10 lines
Documentation/devicetree/bindings/common-properties.txt +10 -0
+ - #daisy-chained-devices: Number of devices in the daisy-chain (default is 1).
+
+Example:
+gpio@0 {
+	      compatible = "name";
+	      reg = <0>;
+	      gpio-controller;
+	      #gpio-cells = <2>;
+	      #daisy-chained-devices = <3>;
+};

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer Acked-by on v2 4/5
#6 lore raw

Re: [PATCH v2 4/5] dt-bindings: gpio: max3191x: Document new driver

In reply to Lukas Wunner
Quoted 7 lines · Lukas Wunner

Add device tree bindings for Maxim MAX3191x industrial serializer.

Cc Mathias Duckeck <[email protected]>

---
Changes v1 -> v2:

Quoted 7 lines

- Add vendor prefix to GPIO identifiers, use boolean instead of integer to select mode, rename boolean to ignore undervoltage alarms, separate compatible strings with newlines. (Rob Herring)

 .../devicetree/bindings/gpio/gpio-max3191x.txt     | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-max3191x.txt
Acked-by
#21 lore raw

Re: [PATCH v2 3/5] dt-bindings: Document common property for daisy-chained devices

In reply to a message not in the archive
Quoted 26 lines · Lukas Wunner

Many serially-attached GPIO and IIO devices are daisy-chainable.

    Examples for GPIO devices are Maxim MAX3191x and TI SN65HVS88x:
    https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf
    http://www.ti.com/lit/ds/symlink/sn65hvs880.pdf

    Examples for IIO devices are TI DAC128S085 and TI DAC161S055:
    http://www.ti.com/lit/ds/symlink/dac128s085.pdf
    http://www.ti.com/lit/ds/symlink/dac161s055.pdf

We already have drivers for daisy-chainable devices in the tree but their devicetree bindings are somewhat inconsistent and ill-named:

The gpio-74x164.c driver uses "registers-number" to convey the number of devices in the daisy-chain. (Sans vendor prefix, multiple vendors sell compatible versions of this chip.)

The gpio-pisosr.c driver takes a different approach and calculates the number of devices in the daisy-chain by dividing the common "ngpios" property (Documentation/devicetree/bindings/gpio/gpio.txt) by 8 (which assumes that each chip has 8 inputs).

Let's standardize on a common "#daisy-chained-devices" property. That name was chosen because it's the term most frequently used in datasheets. (A less frequently used synonym is "cascaded devices".)

Quoted 8 lines

---
Changes v1 -> v2:

- Newly inserted patch.

 .../devicetree/bindings/common-properties.txt      | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#22 lore raw

Re: [PATCH v2 3/5] dt-bindings: Document common property for daisy-chained devices

In reply to a message not in the archive
Quoted 26 lines · Lukas Wunner

Many serially-attached GPIO and IIO devices are daisy-chainable.

    Examples for GPIO devices are Maxim MAX3191x and TI SN65HVS88x:
    https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf
    http://www.ti.com/lit/ds/symlink/sn65hvs880.pdf

    Examples for IIO devices are TI DAC128S085 and TI DAC161S055:
    http://www.ti.com/lit/ds/symlink/dac128s085.pdf
    http://www.ti.com/lit/ds/symlink/dac161s055.pdf

We already have drivers for daisy-chainable devices in the tree but their devicetree bindings are somewhat inconsistent and ill-named:

The gpio-74x164.c driver uses "registers-number" to convey the number of devices in the daisy-chain. (Sans vendor prefix, multiple vendors sell compatible versions of this chip.)

The gpio-pisosr.c driver takes a different approach and calculates the number of devices in the daisy-chain by dividing the common "ngpios" property (Documentation/devicetree/bindings/gpio/gpio.txt) by 8 (which assumes that each chip has 8 inputs).

Let's standardize on a common "#daisy-chained-devices" property. That name was chosen because it's the term most frequently used in datasheets. (A less frequently used synonym is "cascaded devices".)

Quoted 5 lines

---
Changes v1 -> v2:

- Newly inserted patch.

Patch applied with the ACKs.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw

Re: [PATCH v2 4/5] dt-bindings: gpio: max3191x: Document new driver

In reply to a message not in the archive
Quoted 6 lines · Lukas Wunner

Add device tree bindings for Maxim MAX3191x industrial serializer.

Cc Mathias Duckeck <m.duckeck-XB/[email protected]>

---
Changes v1 -> v2:

Patch applied with Rob's ACK.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#15 lore raw

Re: [PATCH v2 5/5] gpio: Add driver for Maxim MAX3191x industrial serializer

In reply to Lukas Wunner
Quoted 11 lines · Lukas Wunner

The driver was developed for and tested with the MAX31913 built into the Revolution Pi by KUNBUS, but should work with all members of the MAX3191x family:

MAX31910: low power
MAX31911: LED drivers
MAX31912: LED drivers + 2nd voltage monitor + low power
MAX31913: LED drivers + 2nd voltage monitor
MAX31953: LED drivers + 2nd voltage monitor + isolation
MAX31963: LED drivers + 2nd voltage monitor + isolation + buck regulator

Quoted 2 lines
Cc Mathias Duckeck <[email protected]>

Patch applied.

Yours,
Linus Walleij