Re: [PATCH v3 05/11] dt-bindings: i3c: Document core bindings

2018-03-23 Thread Peter Rosin
On 2018-03-23 12:00, Boris Brezillon wrote:
> From: Boris Brezillon 
> 
> A new I3C subsystem has been added and a generic description has been
> created to represent the I3C bus and the devices connected on it.
> 
> Document this generic representation.
> 
> Signed-off-by: Boris Brezillon 
> ---
> Changes in v3:
> - Rename {i2c,i3c}-scl-frequency DT prop into {i2c,i3c}-scl-hz
> - Rework the way we expose the provisional ID and LVR information
> - Rename dynamic-address into assigned-address
> - Enforce the I3C master node name
> 
> Changes in v2:
> - Define how to describe I3C devices in the DT and when it should be
>   used. Note that the parsing of I3C devices is not yet implemented in
>   the framework. Will be added when someone really needs it.
> ---
>  Documentation/devicetree/bindings/i3c/i3c.txt | 140 
> ++
>  1 file changed, 140 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i3c/i3c.txt
> 
> diff --git a/Documentation/devicetree/bindings/i3c/i3c.txt 
> b/Documentation/devicetree/bindings/i3c/i3c.txt
> new file mode 100644
> index ..ed858228d26b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i3c/i3c.txt
> @@ -0,0 +1,140 @@
> +Generic device tree bindings for I3C busses
> +===
> +
> +This document describes generic bindings that should be used to describe I3C
> +busses in a device tree.
> +
> +Required properties
> +---
> +
> +- #address-cells  - should be <3>. Read more about addresses below.
> +- #size-cells - should be <0>.
> +- compatible  - name of the I3C master controller driving the I3C bus
> +
> +For other required properties e.g. to describe register sets,
> +clocks, etc. check the binding documentation of the specific driver.
> +The node describing an I3C bus should be named i3c-master.
> +
> +Optional properties
> +---
> +
> +These properties may not be supported by all I3C master drivers. Each I3C
> +master bindings should specify which of them are supported.
> +
> +- i3c-scl-hz: frequency of the SCL signal used for I3C transfers.
> +   When undefined the core sets it to 12.5MHz.
> +
> +- i2c-scl-hz: frequency of the SCL signal used for I2C transfers.
> +   When undefined, the core looks at LVR (Legacy Virtual Register)
> +   values of I2C devices described in the device tree to determine
> +   the maximum I2C frequency.
> +
> +I2C devices
> +===
> +
> +Each I2C device connected to the bus should be described in a subnode. All
> +properties described in Documentation/devicetree/bindings/i2c/i2c.txt are
> +valid here, but several new properties have been added.
> +
> +New constraint on existing properties:
> +--
> +- reg: contains 3 cells
> +  + first cell : still encoding the I2C address
> +
> +  + second cell: should have bit 31 set to 1 signify that this is an I2C
> +  device. Bits 0 to 7 encode the I3C LVR (Legacy Virtual
> +  Register):
> +
> + bit[7:5]: I2C device index. Possible values
> + * 0: I2C device has a 50 ns spike filter
> + * 1: I2C device does not have a 50 ns spike filter but supports high
> +  frequency on SCL
> + * 2: I2C device does not have a 50 ns spike filter and is not tolerant
> +  to high frequencies
> + * 3-7: reserved
> +
> + bit[4]: tell whether the device operates in FM (Fast Mode) or FM+ mode
> + * 0: FM+ mode
> + * 1: FM mode
> +
> + bit[3:0]: device type
> + * 0-15: reserved
> +
> +  + third cell: should be 0
> +
> +I3C devices
> +===
> +
> +All I3C devices are supposed to support DAA (Dynamic Address Assignment), and
> +are thus discoverable. So, by default, I3C devices do not have to be 
> described
> +in the device tree.
> +This being said, one might want to attach extra resources to these devices,
> +and those resources may have to be described in the device tree, which in 
> turn
> +means we have to describe I3C devices.
> +
> +Another use case for describing an I3C device in the device tree is when this
> +I3C device has a static address and we want to assign it a specific dynamic
> +address before the DAA takes place (so that other devices on the bus can't
> +take this dynamic address).
> +
> +The I3C device should be names @,,
> +where device-type is describing the type of device connected on the bus
> +(gpio-controller, sensor, ...).
> +
> +Required properties
> +---
> +- reg: contains 3 cells
> +  + first cell : encodes the I2C address. Should be 0 if the device does not
> +  have one (0 is not a valid I3C address).
> +
> +  + second and third cells: should encode the ProvisionalID. The second cell
> + contains the manufacturer ID left-shifted by 1.
> + The third cell contains ORing of 

Re: [PATCH v2 0/2] mux: add overview and add to driver-api docs

2018-03-02 Thread Peter Rosin
On 2017-12-21 23:11, Peter Rosin wrote:
> On 2017-12-21 22:35, Jonathan Corbet wrote:
>> On Tue, 12 Dec 2017 09:46:31 +0100
>> Peter Rosin <p...@axentia.se> wrote:
>>
>>> Changes since v1:
>>> - added a short introductory paragraph to mux.rst
>>> - added an entry in MAINTAINERS.
>>>
>>> I forgot to mention that this applies on top of linux-next, I suspect
>>> there will be a trivial conflict with an SPDX conversion in mux/core.c
>>> on Linus upstream.
>>
>> Sorry, I've had this just sitting here for a bit.  Did you want me to take
>> both patches through the docs tree?
> 
> I think that's going to be easiest, thanks! Let me know if you want me
> to rebase them to something w/o the SPDX change.

Hi,

Gentle ping...

Cheers,
Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/2] mux: add overview and add to driver-api docs

2017-12-21 Thread Peter Rosin
On 2017-12-21 22:35, Jonathan Corbet wrote:
> On Tue, 12 Dec 2017 09:46:31 +0100
> Peter Rosin <p...@axentia.se> wrote:
> 
>> Changes since v1:
>> - added a short introductory paragraph to mux.rst
>> - added an entry in MAINTAINERS.
>>
>> I forgot to mention that this applies on top of linux-next, I suspect
>> there will be a trivial conflict with an SPDX conversion in mux/core.c
>> on Linus upstream.
> 
> Sorry, I've had this just sitting here for a bit.  Did you want me to take
> both patches through the docs tree?

I think that's going to be easiest, thanks! Let me know if you want me
to rebase them to something w/o the SPDX change.

Cheers,
Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 5/7] dt-bindings: i3c: Document core bindings

2017-12-14 Thread Peter Rosin
On 2017-12-14 16:16, Boris Brezillon wrote:
> +Optional properties
> +---
> +- reg: static address. Only valid is the device has a static address.
> +- i3c-dynamic-address: dynamic address to be assigned to this device. This
> +property depends on the reg property.
> +
> +Example:
> +
> + i3c-master@0d04 {

i3c-master@d04

(same in patch 7/7)

Cheers,
Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] docs: add mux docs to the driver-api docs

2017-12-12 Thread Peter Rosin
Include both the overview and the more detailed api docs.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-api/index.rst |  1 +
 Documentation/driver-api/mux.rst   | 25 +
 MAINTAINERS|  1 +
 3 files changed, 27 insertions(+)
 create mode 100644 Documentation/driver-api/mux.rst

diff --git a/Documentation/driver-api/index.rst 
b/Documentation/driver-api/index.rst
index d17a9876b473..d10b01b2b429 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -47,6 +47,7 @@ available subsections can be seen below.
gpio
misc_devices
dmaengine/index
+   mux
 
 .. only::  subproject and html
 
diff --git a/Documentation/driver-api/mux.rst b/Documentation/driver-api/mux.rst
new file mode 100644
index ..48fc5108ff0e
--- /dev/null
+++ b/Documentation/driver-api/mux.rst
@@ -0,0 +1,25 @@
+Multiplexer Subsystem
+=
+
+A multiplexer is a type of device that selects one of many signals and
+forwards this signal to a single output. A variant is a demultiplexer
+that instead forwards a single input to one of many outputs. There are
+also bidirectional variants. All these variants are handled the same
+by the multiplexer subsystem, and can be used to e.g. fan out an I2C
+bus to avoid client device address collisions or to allow converting
+more signals using a single analog to digital converter.
+
+Overview
+
+
+.. kernel-doc:: drivers/mux/core.c
+   :doc: overview
+
+Details
+---
+
+.. kernel-doc:: include/linux/mux/driver.h
+   :internal:
+
+.. kernel-doc:: drivers/mux/core.c
+   :export:
diff --git a/MAINTAINERS b/MAINTAINERS
index d4fdcb12616c..2c0bbabedca0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9298,6 +9298,7 @@ M:    Peter Rosin <p...@axentia.se>
 S: Maintained
 F: Documentation/ABI/testing/mux/sysfs-class-mux*
 F: Documentation/devicetree/bindings/mux/
+F: Documentation/driver-api/mux.rst
 F: include/linux/dt-bindings/mux/
 F: include/linux/mux/
 F: drivers/mux/
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/2] mux: add overview and add to driver-api docs

2017-12-12 Thread Peter Rosin
Hi!

Changes since v1:
- added a short introductory paragraph to mux.rst
- added an entry in MAINTAINERS.

I forgot to mention that this applies on top of linux-next, I suspect
there will be a trivial conflict with an SPDX conversion in mux/core.c
on Linus upstream.

Cheers,
Peter

Peter Rosin (2):
  mux: core: add a brief overview of the subsystem
  docs: add mux docs to the driver-api docs

 Documentation/driver-api/index.rst |  1 +
 Documentation/driver-api/mux.rst   | 25 +
 MAINTAINERS|  1 +
 drivers/mux/core.c | 37 +
 4 files changed, 64 insertions(+)
 create mode 100644 Documentation/driver-api/mux.rst

-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/2] mux: core: add a brief overview of the subsystem

2017-12-12 Thread Peter Rosin
Preparation for adding the mux subsystem to the driver-api documenation.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/core.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index d1271c1ee23c..ccb5479f8a39 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -7,6 +7,43 @@
  * Author: Peter Rosin <p...@axentia.se>
  */
 
+/**
+ * DOC: overview
+ *
+ * The multiplexer subsystem uses the following naming:
+ *
+ * - Multiplexer controller: the piece of hardware that changes the
+ *   state of a hardware multiplexer (or indeed, several parallel
+ *   multiplexers).
+ *
+ * - Multiplexer chip: a collection of multiplexer controllers, in a chip.
+ *
+ * - Multiplexer driver: the device driver that interacts with and handles the
+ *   above hardware. The driver has structures representing a mux chip and mux
+ *   controllers.
+ *
+ * - Multiplexer consumer: the driver that needs to manipulate the hardware
+ *   multiplexer.
+ *
+ * The mux subsystem provides a framework for multiplexer drivers that can
+ * be used by other consumer drivers. It has two primary purposes.
+ *
+ * First, when a consumer driver can be used with one of several multiplexers,
+ * depending on hardware configuration, the actual multiplexer is abstracted
+ * away in the mux drivers. The multiplexer consumer driver can be neater
+ * this way.
+ *
+ * Second, when two consumers -- possibly from different subsystems -- compete
+ * for the same mux controller, i.e. when one mux controller muxes more than
+ * one signal, the mux framework provides locking.
+ *
+ * If the mux driver is so special that it will only ever have a single
+ * consumer, and that consumer can really only work with that one mux driver,
+ * the mux framework is not really providing much benefit. It might be a better
+ * idea to simply manipulate the mux hardware directly from the consumer
+ * driver.
+ */
+
 #define pr_fmt(fmt) "mux-core: " fmt
 
 #include 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] mux: core: add a brief overview of the subsystem

2017-12-11 Thread Peter Rosin
Preparation for adding the mux subsystem to the driver-api documenation.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/core.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index d1271c1ee23c..ccb5479f8a39 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -7,6 +7,43 @@
  * Author: Peter Rosin <p...@axentia.se>
  */
 
+/**
+ * DOC: overview
+ *
+ * The multiplexer subsystem uses the following naming:
+ *
+ * - Multiplexer controller: the piece of hardware that changes the
+ *   state of a hardware multiplexer (or indeed, several parallel
+ *   multiplexers).
+ *
+ * - Multiplexer chip: a collection of multiplexer controllers, in a chip.
+ *
+ * - Multiplexer driver: the device driver that interacts with and handles the
+ *   above hardware. The driver has structures representing a mux chip and mux
+ *   controllers.
+ *
+ * - Multiplexer consumer: the driver that needs to manipulate the hardware
+ *   multiplexer.
+ *
+ * The mux subsystem provides a framework for multiplexer drivers that can
+ * be used by other consumer drivers. It has two primary purposes.
+ *
+ * First, when a consumer driver can be used with one of several multiplexers,
+ * depending on hardware configuration, the actual multiplexer is abstracted
+ * away in the mux drivers. The multiplexer consumer driver can be neater
+ * this way.
+ *
+ * Second, when two consumers -- possibly from different subsystems -- compete
+ * for the same mux controller, i.e. when one mux controller muxes more than
+ * one signal, the mux framework provides locking.
+ *
+ * If the mux driver is so special that it will only ever have a single
+ * consumer, and that consumer can really only work with that one mux driver,
+ * the mux framework is not really providing much benefit. It might be a better
+ * idea to simply manipulate the mux hardware directly from the consumer
+ * driver.
+ */
+
 #define pr_fmt(fmt) "mux-core: " fmt
 
 #include 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] mux: add overview and add to driver-api docs

2017-12-11 Thread Peter Rosin
Hi!

Don't know if this is worth adding, but it might answer at least a few
questions.

It looks ok when I view the htmldocs output, but I'm not all that certain
this is good to go?

Cheers,
Peter

Peter Rosin (2):
  mux: core: add a brief overview of the subsystem
  docs: add mux docs to the driver-api docs

 Documentation/driver-api/index.rst |  1 +
 Documentation/driver-api/mux.rst   | 17 +
 drivers/mux/core.c | 37 +
 3 files changed, 55 insertions(+)
 create mode 100644 Documentation/driver-api/mux.rst

-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 2/5] i3c: Add core I3C infrastructure

2017-07-31 Thread Peter Rosin
On 2017-07-31 23:15, Boris Brezillon wrote:
> [1]https://www.mipi.org/MIPI_I3C_device_characteristics_register

Stupid non-programmers...

This part

65 41 0101  Accelerometer
66 42 0110  Gyroscope
67 43 0111  Magnetometer
68 44 01000100  Accel/Gyro Combo
69 45 01000101  Accel/Mag Combo
70 46 01000110  Accel/Gyro/Mag Combo

should *obviously* have been something like

65 41 0101  Accelerometer
66 42 0110  Gyroscope
67 43 0111  Accel/Gyro Combo
68 44 01000100  Magnetometer
69 45 01000101  Accel/Mag Combo
71 47 01000111  Accel/Gyro/Mag Combo

Cheers,
peda
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v15 00/13] mux controller abstraction and iio/i2c muxes

2017-06-03 Thread Peter Rosin
On 2017-06-03 12:31, Greg Kroah-Hartman wrote:
> On Sat, Jun 03, 2017 at 07:26:27PM +0900, Greg Kroah-Hartman wrote:
>> On Sun, May 14, 2017 at 09:51:03PM +0200, Peter Rosin wrote:
>>> From: Peter Rosin <p...@axentia.se>
>>>
>>> Hi Greg,
>>>
>>> Philipp found problems in v14 with using a mutex for locking that was
>>> the outcome of the review for v13, so I'm now using a semaphore instead
>>> of the rwsem that was in v13. That at least got rid of the scary call
>>> to downgrade_write. However, I'm still unsure about what you actually
>>> meant with your comment about lack of sparse markings [1]. I did add
>>> __must_check to the funcs that selects the mux, but I've got this
>>> feeling that this is not what you meant?
>>
>> I thought there was a way to mark a function as requiring a lock be held
>> when it is being called.  Does sparse not support that anymore?
> 
> Anyway, not a big deal.  I still worry about the calls blocking when
> people are not expecting them to, but it is just the nature of th api I
> guess.

Yeah, first come first serve. I don't know what else I can do, except maybe
follow up with a timed version of mux_control_select()...

> All now queued up, nice work, thanks for sticking with this.

*big sigh of relief*

I was getting pretty fed up with the series to be honest :-), so thanks
a bunch for taking it!

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v15 00/13] mux controller abstraction and iio/i2c muxes

2017-06-03 Thread Peter Rosin
On 2017-06-03 22:26, Luc Van Oostenryck wrote:
> On Sat, Jun 3, 2017 at 9:34 PM, Greg Kroah-Hartman
> <gre...@linuxfoundation.org> wrote:
>> On Sat, Jun 03, 2017 at 08:37:21PM +0200, Luc Van Oostenryck wrote:
>>> On Sat, Jun 3, 2017 at 12:26 PM, Greg Kroah-Hartman
>>> <gre...@linuxfoundation.org> wrote:
>>>> On Sun, May 14, 2017 at 09:51:03PM +0200, Peter Rosin wrote:
>>>>> From: Peter Rosin <p...@axentia.se>
>>>>>
>>>>> Hi Greg,
>>>>>
>>>>> Philipp found problems in v14 with using a mutex for locking that was
>>>>> the outcome of the review for v13, so I'm now using a semaphore instead
>>>>> of the rwsem that was in v13. That at least got rid of the scary call
>>>>> to downgrade_write. However, I'm still unsure about what you actually
>>>>> meant with your comment about lack of sparse markings [1]. I did add
>>>>> __must_check to the funcs that selects the mux, but I've got this
>>>>> feeling that this is not what you meant?
>>>>
>>>> I thought there was a way to mark a function as requiring a lock be held
>>>> when it is being called.  Does sparse not support that anymore?
>>>
>>> sparse still support these annotations, of course.
>>> In this case, I suppose you're talking about '__must_hold()' which
>>> *must* be used instead of a pair of '__releases()' + '__acquires()'
>>> when the lock is help on function entry and exit.
>>
>> Ah, yes, that's what I was thinking of.  I don't know if sparse can
>> track things like this across an exported symbol, so I doubt it really
>> will help here.  Sorry for the noise.
> 
> No problem, I'm glad to help for sparse related things.
> 
> I didn't saw the code in question because the lkml.org link Peter
> gave didn't work for me and I don't know much about exported symbols
> (but I think the sole effect is to add some data in some symbol table).
> But these annotations just work based on the declarations, very much
> like type checking. So if you have something in scope like the following:
> 
> void do_stuff_locked(struct s *ptr) __must_hold(*ptr);
> 
> ...
> 
> void do_stuff_unlocked(struct s *ptr)
> {
> ...
> do_stuff_locked(ptr);// will warn
> ...
> }
> 
> You will have a warning from sparse unless the code preceding and following
> the call to do_stuff_locked() lock & then unlock 'ptr', generaly
> indirectly by a pair
> of functions, the one before with an '__acquires()' in its declaration
> the one after
> with a '__releases()' in its declaration:
> 
> void lock_stuff(struct s *ptr) __acquires(*ptr);
> void unlock_stuff(struct s *ptr) __releases(*ptr);
> 
> void do_stuff_unlocked(struct s *ptr)
> {
> lock_stuff(ptr);
> do_stuff_locked(ptr);// won't warn
> unlock_stuff(ptr);
> }

Ok, thanks for the explanation! The above was what I gathered when I
looked around, and since it didn't really fit the usage pattern of the
mux api I was stomped. When comparing the mux code with the above,
mux_control_select would be an __acquires (albeit a conditional one,
but let's not muddy the waters unnecessarily) and mux_control_deselect
would be a __releases.

But for long time mux consumers, like the video mux, it must be OK to
only acquire the mux, and not release it right away in the same context,
which I assume will be very hard for sparse to handle sanely? E.g. I
think sparse also complains if there are unbalanced __acquires and
__releases in some context, no?

Cheers,
peda

BTW, the core mux code is at the below link if the lkml link continues
to fail:
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git/commit/?h=char-misc-testing=a3b02a9c6591ce154cd44e2383406390a45b530c
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 09/13] i2c: i2c-mux-gpmux: new driver

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 1e160fc37ecc..2c64d0e0740f 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF || COMPILE_TEST
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_LTC4306
tristate "LTC LTC4306/5 I2C multiplexer"
select GPIOLIB
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index ff7618cd5312..4a67d3199877 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_LTC4306)  += i2c-mux-ltc4306.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..92cf5f48afe6
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+ 

[PATCH v15 06/13] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index a0cce325b08e..eea8432b2df1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6474,6 +6474,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 03/13] mux: minimal mux subsystem

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

Thanks go out to Lars-Peter Clausen, Jonathan Cameron, Rob Herring,
Wolfram Sang, Paul Gortmaker, Dan Carpenter, Colin Ian King, Greg
Kroah-Hartman and last but certainly not least to Philipp Zabel for
helpful comments, reviews, patches and general encouragement!

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/ABI/testing/sysfs-class-mux |  16 +
 Documentation/driver-model/devres.txt |   5 +
 MAINTAINERS   |   3 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  16 +
 drivers/mux/Makefile  |   5 +
 drivers/mux/mux-core.c| 547 ++
 include/linux/mux/consumer.h  |  32 ++
 include/linux/mux/driver.h| 108 ++
 10 files changed, 735 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-mux
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 include/linux/mux/consumer.h
 create mode 100644 include/linux/mux/driver.h

diff --git a/Documentation/ABI/testing/sysfs-class-mux 
b/Documentation/ABI/testing/sysfs-class-mux
new file mode 100644
index ..8715f9c7bd4f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-mux
@@ -0,0 +1,16 @@
+What:  /sys/class/mux/
+Date:  April 2017
+KernelVersion: 4.13
+Contact:   Peter Rosin <p...@axentia.se>
+Description:
+   The mux/ class sub-directory belongs to the Generic MUX
+   Framework and provides a sysfs interface for using MUX
+   controllers.
+
+What:  /sys/class/mux/muxchipN/
+Date:  April 2017
+KernelVersion: 4.13
+Contact:   Peter Rosin <p...@axentia.se>
+Description:
+   A /sys/class/mux/muxchipN directory is created for each
+   probed MUX chip where N is a simple enumeration.
diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index af08b4cd7968..40e4787c399c 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,11 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_register()
+  devm_mux_control_get()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index e17dd0bf2c9f..a0cce325b08e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8712,8 +8712,11 @@ F:   include/linux/spi/mmc_spi.h
 MULTIPLEXER SUBSYSTEM
 M: Peter Rosin <p...@axentia.se>
 S: Maintained
+F: Documentation/ABI/testing/mux/sysfs-class-mux*
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux/
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ba2901e76769..505c676fa9c7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -206,4 +206,6 @@ source "drivers/fsi/Kconfig"
 
 source "drivers/tee/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index cfabd141dba2..dfdcda00bfe3 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -181,3 +181,4 @@ obj-$(CONFIG_NVMEM) += nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
 obj-$(CONFIG_TEE)  += tee/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..23ab2cde83b1
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,16 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.
+
+ To compile the subsystem as a module, choose M her

[PATCH v15 04/13] mux: gpio: add mux controller driver for gpio based multiplexers

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

The driver builds a single multiplexer controller using a number
of gpio pins. For N pins, there will be 2^N possible multiplexer
states. The GPIO pins can be connected (by the hardware) to several
multiplexers, which in that case will be operated in parallel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig|  18 
 drivers/mux/Makefile   |   1 +
 drivers/mux/mux-gpio.c | 114 +
 3 files changed, 133 insertions(+)
 create mode 100644 drivers/mux/mux-gpio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 23ab2cde83b1..738670aaecb7 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -14,3 +14,21 @@ menuconfig MULTIPLEXER
 
  To compile the subsystem as a module, choose M here: the module will
  be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on GPIOLIB || COMPILE_TEST
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 09f0299e109d..bb16953f6290 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c
new file mode 100644
index ..468bf1709606
--- /dev/null
+++ b/drivers/mux/mux-gpio.c
@@ -0,0 +1,114 @@
+/*
+ * GPIO-controlled multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_gpio {
+   struct gpio_descs *gpios;
+   int *val;
+};
+
+static int mux_gpio_set(struct mux_control *mux, int state)
+{
+   struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
+   int i;
+
+   for (i = 0; i < mux_gpio->gpios->ndescs; i++)
+   mux_gpio->val[i] = (state >> i) & 1;
+
+   gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
+  mux_gpio->gpios->desc,
+  mux_gpio->val);
+
+   return 0;
+}
+
+static const struct mux_control_ops mux_gpio_ops = {
+   .set = mux_gpio_set,
+};
+
+static const struct of_device_id mux_gpio_dt_ids[] = {
+   { .compatible = "gpio-mux", },
+   { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
+
+static int mux_gpio_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   struct mux_gpio *mux_gpio;
+   int pins;
+   s32 idle_state;
+   int ret;
+
+   pins = gpiod_count(dev, "mux");
+   if (pins < 0)
+   return pins;
+
+   mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
+  pins * sizeof(*mux_gpio->val));
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   mux_gpio = mux_chip_priv(mux_chip);
+   mux_gpio->val = (int *)(mux_gpio + 1);
+   mux_chip->ops = _gpio_ops;
+
+   mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
+   if (IS_ERR(mux_gpio->gpios)) {
+   ret = PTR_ERR(mux_gpio->gpios);
+   if (ret != -EPROBE_DEFER)
+   dev_err(dev, "failed to get gpios\n");
+   return ret;
+   }
+   WARN_ON(pins != mux_gpio->gpios->ndescs);
+   mux_chip->mux->states = 1 << pins;
+
+   ret = device_property_read_u32(dev, "idle-state", (u32 *)_state);
+   if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) {
+   if (idle_state < 0 || idle_state >= mux_chip->mux->states) {
+   dev_err(dev, "invalid idle-state %u\n", idle_state);
+   return -EINVAL;
+   }
+
+   mux_chip->mux->idle_state = idle_state;
+   }
+
+   ret = devm_mux_chip_register(dev, mux_chip);
+   if (ret < 0)
+   return ret;
+
+   dev_info(dev, 

[PATCH v15 11/13] mux: adg792a: add mux controller driver for ADG792A/G

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 157 ++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 738670aaecb7..c4d050645605 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C || COMPILE_TEST
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..12aa221ab90d
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,157 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESETB BIT(1)
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_write_cmd(struct i2c_client *i2c, u8 cmd, int reset)
+{
+   u8 data = ADG792A_RESETB | ADG792A_LDSW;
+
+   /* ADG792A_RESETB is active low, the chip resets when it is zero. */
+   if (reset)
+   data &= ~ADG792A_RESETB;
+
+   return i2c_smbus_write_byte_data(i2c, cmd, data);
+}
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return adg792a_write_cmd(i2c, cmd, 0);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   s32 idle_state[3];
+   u32 cells;
+   int ret;
+   int i;
+
+   if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+   return -ENODEV;
+
+   ret = device_property_read_u32(dev, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   mux_chip->ops = _ops;
+
+   ret = adg792a_write_cmd(i2c, ADG792A_DISABLE_ALL, 1);
+   if (ret < 0)
+   return ret;
+
+   ret = device_property_read_u32_array(dev, "idle-state",
+(u32 *)idle_state,
+mux_chip->controllers);
+   if (ret < 0) {
+   idle_state[0] = MUX_IDLE_AS_IS;
+   idle_state[1] = MUX_IDLE_AS_IS;
+   idle_state[2] = MUX_IDLE_AS_IS;
+   }
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux

[PATCH v15 00/13] mux controller abstraction and iio/i2c muxes

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Hi Greg,

Philipp found problems in v14 with using a mutex for locking that was
the outcome of the review for v13, so I'm now using a semaphore instead
of the rwsem that was in v13. That at least got rid of the scary call
to downgrade_write. However, I'm still unsure about what you actually
meant with your comment about lack of sparse markings [1]. I did add
__must_check to the funcs that selects the mux, but I've got this
feeling that this is not what you meant?

Anyway, I have acted on all your comments from the v13 review, at
least I think I did. So, please apply.

[1] https://lkml.org/lkml/2017/4/21/794


v14 -> v15 changes
- Rebased onto v4.12-rc1
- Add the mmio-mux driver from Philipp Zabel to the end of the series.
- Using a mutex to lock the mux state did not work out for Philipp Zabel
  and his video-mux, which is locking the mux over long periods of time.
  So, switch to a semaphore (where different tasks can call down/up).
- Remove unused devm_mux_chip_free, devm_mux_chip_unregister and
  devm_mux_control_put. Those are currently unused and can be added when
  someone needs them.
- Add more words in the kernel-doc comments for mux_control_select,
  mux_control_try_select and mux_control_deselect on the calling rules.
- Add "|| COMPILE_TEST" to the Kconfig depends for all new drivers.

[older changes follow below]


This adds a new mux controller subsystem with an interface for accessing
mux controllers, along with three drivers providing the interface (gpio,
mmio and adg792) and two consumers (iio and i2c). This is done in a way
that several consumers can independently access the same mux controller
if one controller controls several multiplexers, thus allowing sharing.
But sharing is by no means required, of course. It is perfectly fine to
have a single consumer of a dedicated mux controller controlling only
one mux for said consumer.

The prediction is that the typical use case will be for gpio-based muxing
(which is also what drove the development), where the below schematics
show the flexibility with one gpio-based mux controller being shared by
the iio-mux and i2c-mux-gpmux drivers.

..
|GPO0|--.
|GPO1|. |
||| |
|| .---.
|| |dg4052a|
|| |   |
|ADC0|-|XX0| signal X0
|| | X1| signal X1
|| | X2| signal X2
|| | X3| signal X3
|| |   |
|SDA0|-|YY0| i2c segment Y0
|SCL0|--.  | Y1| i2c segment Y1
''  |  | Y2| i2c segment Y2
|  | Y3| i2c segment Y3
|  '---'
|0 1 2 3   (feed SCL0 to each of
|| | | |the 4 muxed segments)
'+-+-+-'

GPO0 and GPO1 may also be fed to further parallel muxers, which is perhaps
desired in a real application to minimize digital noise from the I2C Y
channel leaking into the analog X channel. I.e. it might be a good idea
to separate the analog and digital signals...

And the below hypothetical schematics indicate something similar but using
the I2C-based adg792a multiplexer instead.

..
|SDA0|--.
|SCL0|. |
||| |
|| .---.
|| |adg792a|
|| |   |
|ADC0|-|D1  S1A| signal S1A
|| |S1B| signal S1B
|| |S1C| signal S1C
|| |S1D| signal S1D
|| |   |
|SDA1|---+-|D2  S2A| i2c segment S2A
|SCL1|-. | |S2B| i2c segment S2B
'' | | |S2C| i2c segment S2C
   | | |S2D| i2c segment S2D
   | | |   |
   | '-|D3  S3A| i2c segment S3A
   |   |S3B| i2c segment S3B
   |   |S3C| i2c segment S3C
   |   |S3D| i2c segment S3D
   |   '---'
   | A B C D   A B C D  (feed SCL1 to each of
   | | | | |   | | | |   the 8 muxed segments)
   '-+-+-+-+---+-+-+-'


Background:

I have a piece of hardware that is using the same 3 GPIO pins
to control four 8-way muxes. Three of them control ADC lines
to an ADS1015 chip with an iio driver, and the last one
controls the SDA line of an i2c bus. We have some deployed
code to handle this, but you do not want to see it or ever
hear about it. I'm not sure why I even mention it. Anyway,
the situation has nagged me to no end for quite some time.

So, after first getting more intimate with the i2c muxing code
and later discovering the drivers/iio/inkern.c file and
writing a couple of drivers making use of it, I came up with
what I think is an acceptable solution; add a generic mux
controller driver (and subsystem) that is shared between all
instances, and combine that with an iio mux driver and a new

[PATCH v15 08/13] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 12/13] dt-bindings: add mmio-based syscon mux controller DT bindings

2017-05-14 Thread Peter Rosin
From: Philipp Zabel <p.za...@pengutronix.de>

This adds device tree binding documentation for mmio-based syscon
multiplexers controlled by a bitfields in a syscon register range.

Signed-off-by: Philipp Zabel <p.za...@pengutronix.de>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/mmio-mux.txt | 60 ++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/mmio-mux.txt

diff --git a/Documentation/devicetree/bindings/mux/mmio-mux.txt 
b/Documentation/devicetree/bindings/mux/mmio-mux.txt
new file mode 100644
index ..a9bfb4d8b6ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mmio-mux.txt
@@ -0,0 +1,60 @@
+MMIO register bitfield-based multiplexer controller bindings
+
+Define register bitfields to be used to control multiplexers. The parent
+device tree node must be a syscon node to provide register access.
+
+Required properties:
+- compatible : "mmio-mux"
+- #mux-control-cells : <1>
+- mux-reg-masks : an array of register offset and pre-shifted bitfield mask
+  pairs, each describing a single mux control.
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-states : if present, the state the muxes will have when idle. The
+   special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state of each multiplexer is defined as the value of the
+bitfield described by the corresponding register offset and bitfield mask pair
+in the mux-reg-masks array, accessed through the parent syscon.
+
+Example:
+
+   syscon {
+   compatible = "syscon";
+
+   mux: mux-controller {
+   compatible = "mmio-mux";
+   #mux-control-cells = <1>;
+
+   mux-reg-masks = <0x3 0x30>, /* 0: reg 0x3, bits 5:4 */
+   <0x3 0x40>, /* 1: reg 0x3, bit 6 */
+   idle-states = , <0>;
+   };
+   };
+
+   video-mux {
+   compatible = "video-mux";
+   mux-controls = < 0>;
+
+   ports {
+   /* inputs 0..3 */
+   port@0 {
+   reg = <0>;
+   };
+   port@1 {
+   reg = <1>;
+   };
+   port@2 {
+   reg = <2>;
+   };
+   port@3 {
+   reg = <3>;
+   };
+
+   /* output */
+   port@4 {
+   reg = <4>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 07/13] iio: multiplexer: new iio category and iio-mux driver

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 459 ++
 6 files changed, 486 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index eea8432b2df1..c89d70c29089 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6479,6 +6479,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..735a7b0e6fd8
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF || COMPILE_TEST
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..37ba007f8dca
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,459 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   ssize_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   

[PATCH v15 05/13] iio: inkern: api for manipulating ext_info of iio channels

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Extend the inkern api with functions for reading and writing ext_info
of iio channels.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/inkern.c | 60 
 include/linux/iio/consumer.h | 37 +++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..8292ad4435ea 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -869,3 +869,63 @@ int iio_write_channel_raw(struct iio_channel *chan, int 
val)
return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+   unsigned int i = 0;
+
+   if (!chan->channel->ext_info)
+   return i;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
+   ++i;
+
+   return i;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+
+static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
+   const struct iio_channel *chan,
+   const char *attr)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   if (!chan->channel->ext_info)
+   return NULL;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+   if (!strcmp(attr, ext_info->name))
+   return ext_info;
+   }
+
+   return NULL;
+}
+
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->read(chan->indio_dev, ext_info->private,
+ chan->channel, buf);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->write(chan->indio_dev, ext_info->private,
+  chan->channel, buf, len);
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 47eeec3218b5..5e347a9805fd 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -312,4 +312,41 @@ int iio_read_channel_scale(struct iio_channel *chan, int 
*val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);
 
+/**
+ * iio_get_channel_ext_info_count() - get number of ext_info attributes
+ *   connected to the channel.
+ * @chan:  The channel being queried
+ *
+ * Returns the number of ext_info attributes
+ */
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
+
+/**
+ * iio_read_channel_ext_info() - read ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   Where to store the attribute value. Assumed to hold
+ * at least PAGE_SIZE bytes.
+ *
+ * Returns the number of bytes written to buf (perhaps w/o zero termination;
+ * it need not even be a string), or an error code.
+ */
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf);
+
+/**
+ * iio_write_channel_ext_info() - write ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   The new attribute value. Strings needs to be zero-
+ * terminated, but the terminator should not be included
+ * in the below len.
+ * @len:   The size of the new attribute value.
+ *
+ * Returns the number of accepted bytes, which should be the same as len.
+ * An error code can also be returned.
+ */
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len);
+
 #endif
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 10/13] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v15 13/13] mux: mmio-based syscon mux controller

2017-05-14 Thread Peter Rosin
From: Philipp Zabel <p.za...@pengutronix.de>

This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.

Signed-off-by: Philipp Zabel <p.za...@pengutronix.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig|  13 +
 drivers/mux/Makefile   |   1 +
 drivers/mux/mux-mmio.c | 141 +
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/mux/mux-mmio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index c4d050645605..e8f1df74644c 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -43,4 +43,17 @@ config MUX_GPIO
  To compile the driver as a module, choose M here: the module will
  be called mux-gpio.
 
+config MUX_MMIO
+   tristate "MMIO register bitfield-controlled Multiplexer"
+   depends on (OF && MFD_SYSCON) || COMPILE_TEST
+   help
+ MMIO register bitfield-controlled Multiplexer controller.
+
+ The driver builds multiplexer controllers for bitfields in a syscon
+ register. For N bit wide bitfields, there will be 2^N possible
+ multiplexer states.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-mmio.
+
 endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index b00a7d37d2fb..6bac5b0fea13 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
 obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
+obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
diff --git a/drivers/mux/mux-mmio.c b/drivers/mux/mux-mmio.c
new file mode 100644
index ..37c1de359a70
--- /dev/null
+++ b/drivers/mux/mux-mmio.c
@@ -0,0 +1,141 @@
+/*
+ * MMIO register bitfield-controlled multiplexer driver
+ *
+ * Copyright (C) 2017 Pengutronix, Philipp Zabel <ker...@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int mux_mmio_set(struct mux_control *mux, int state)
+{
+   struct regmap_field **fields = mux_chip_priv(mux->chip);
+
+   return regmap_field_write(fields[mux_control_get_index(mux)], state);
+}
+
+static const struct mux_control_ops mux_mmio_ops = {
+   .set = mux_mmio_set,
+};
+
+static const struct of_device_id mux_mmio_dt_ids[] = {
+   { .compatible = "mmio-mux", },
+   { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_mmio_dt_ids);
+
+static int mux_mmio_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct regmap_field **fields;
+   struct mux_chip *mux_chip;
+   struct regmap *regmap;
+   int num_fields;
+   int ret;
+   int i;
+
+   regmap = syscon_node_to_regmap(np->parent);
+   if (IS_ERR(regmap)) {
+   ret = PTR_ERR(regmap);
+   dev_err(dev, "failed to get regmap: %d\n", ret);
+   return ret;
+   }
+
+   ret = of_property_count_u32_elems(np, "mux-reg-masks");
+   if (ret == 0 || ret % 2)
+   ret = -EINVAL;
+   if (ret < 0) {
+   dev_err(dev, "mux-reg-masks property missing or invalid: %d\n",
+   ret);
+   return ret;
+   }
+   num_fields = ret / 2;
+
+   mux_chip = devm_mux_chip_alloc(dev, num_fields, num_fields *
+  sizeof(*fields));
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   fields = mux_chip_priv(mux_chip);
+
+   for (i = 0; i < num_fields; i++) {
+   struct mux_control *mux = _chip->mux[i];
+   struct reg_field field;
+   s32 idle_state = MUX_IDLE_AS_IS;
+   u32 reg, mask;
+   int bits;
+
+   ret = of_property_read_u32_index(np, "mux-reg-masks",
+2 * i, );
+   if (!ret)
+   ret = of_property_read_u32_index(np, "mux-reg-masks",
+2 * i + 1, );
+   if (ret < 0) {
+   dev_err(dev, "bitfield %d: failed to read mux-reg-masks 
property: %d\n",
+   i, ret);
+   return ret;
+   }
+
+   field.reg = reg;
+   field.msb = fls(mask) - 1;
+   field.lsb = ffs(mask) - 1;
+
+   if (mask != GENMASK(field.msb, field.lsb)) {
+   dev_err(dev, "bitfield %d: inval

[PATCH v15 02/13] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Allow specifying that a single multiplexer controller can be used to
control several parallel multiplexers, thus enabling sharing of the
multiplexer controller by different consumers.

Add a binding for a first mux controller in the form of a GPIO based mux
controller.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +
 .../devicetree/bindings/mux/mux-controller.txt | 157 +
 MAINTAINERS|   6 +
 include/dt-bindings/mux/mux.h  |  16 +++
 4 files changed, 248 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 include/dt-bindings/mux/mux.h

diff --git a/Documentation/devicetree/bindings/mux/gpio-mux.txt 
b/Documentation/devicetree/bindings/mux/gpio-mux.txt
new file mode 100644
index ..b8f746344d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/gpio-mux.txt
@@ -0,0 +1,69 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "gpio-mux"
+- mux-gpios : list of gpios used to control the multiplexer, least
+ significant bit first.
+- #mux-control-cells : <0>
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-state : if present, the state the mux will have when idle. The
+  special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state is defined as the number represented by the
+multiplexer GPIO pins, where the first pin is the least significant
+bit. An active pin is a binary 1, an inactive pin is a binary 0.
+
+Example:
+
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "in", "out", "sync-2";
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   /* ... */
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   /* ... */
+   };
+   };
+   };
diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt 
b/Documentation/devicetree/bindings/mux/mux-controller.txt
new file mode 100644
index ..4f47e4bd2fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
@@ -0,0 +1,157 @@
+Common multiplexer controller bindings
+==
+
+A multiplexer (or mux) controller will have one, or several, consumer devices
+that uses the mux controller. Thus, a mux controller can possibly control
+several parallel multiplexers. Presumably there will be at least one
+multiplexer needed by each consumer, but a single mux controller can of course
+control several multiplexers for a single consumer.
+
+A mux controller provides a number of states to its consumers, and the state
+space is a simple zero-based enumeration. I.e. 0-1 for a 2-way multiplexer,
+0-7 for an 8-way multiplexer, etc.
+
+
+Consumers
+-
+
+Mux controller consumers should specify a list of mux controllers that they
+want to use with a property containing a 'mux-ctrl-list':
+
+   mux-ctrl-list ::=  [mux-ctrl-list]
+   single-mux-ctrl ::=  [mux-ctrl-specifier]
+   mux-ctrl-phandle : phandle to mux controller node
+   mux-ctrl-specifier : array of #mux-control-cells specifying the
+given mux controller (controller specific)
+
+Mux controller properties should be named "mux-controls". The exact meaning of
+each mux controller property must 

[PATCH v15 01/13] devres: trivial whitespace fix

2017-05-14 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index e72587fe477d..af08b4cd7968 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-05-05 Thread Peter Rosin
On 2017-04-18 12:59, Peter Rosin wrote:
> On 2017-04-18 10:51, Greg Kroah-Hartman wrote:
>> On Thu, Apr 13, 2017 at 06:43:07PM +0200, Peter Rosin wrote:
>>> +/**
>>> + * devm_mux_chip_unregister() - Resource-managed version 
>>> mux_chip_unregister().
>>> + * @dev: The device that originally registered the mux-chip.
>>> + * @mux_chip: The mux-chip to unregister.
>>> + *
>>> + * See mux_chip_unregister() for more details.
>>> + *
>>> + * Note that you do not normally need to call this function.
>>
>> Odd, then why is it exported???
> 
> You normally don't call the devm_foo_{free,release,unregister,etc} functions.
> The intention is of course that the resourse cleans up automatically. But 
> there
> are no cases where the manual clean up is not available, at least not that I 
> can
> find?

I had a second look and there are of course plenty of examples of missing clean 
up
versions for devm function. I simply hadn't looked very hard at all.

So, for v15 I intend to remove all of devm_mux_chip_unregister, 
devm_mux_chip_free
and devm_mux_control_put. They are all just sitting there with no callers. And 
the
mux-mmio/video-mux drivers by Philipp Zabel that build on top of this series 
don't
need them either. Besides, easy to resurrect if needed...

I will do v15 with the above, the change from mutex to semaphore for locking the
mux controller state [1] and a few small documentation improvements. That will 
be
rebased onto v4.12-rc1 and sent in 10 days or so, or whenever v4.12-rc1 is out.

Meanwhile, what I currently intend for v15 but based on v4.11 is available from
https://gitlab.com/peda-linux/mux.git in the "mux" branch.

Cheers,
peda

[1] https://lkml.org/lkml/2017/4/25/411
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes

2017-04-25 Thread Peter Rosin
On 2017-04-25 16:16, Peter Rosin wrote:
> On 2017-04-24 16:59, Philipp Zabel wrote:
>> On Mon, 2017-04-24 at 16:36 +0200, Peter Rosin wrote:
>> [...]
>>>> How about an atomic use_count on the mux_control, a bool shared that is
>>>> only set by the first consumer, and controls whether selecting locks?
>>>
>>> That has the drawback that it is hard to restore the mux-control in a safe
>>> way so that exclusive consumers are allowed after the last shared consumer
>>> puts the mux away.
>>
>> True.
>>
>>> Agreed, it's a corner case, but I had this very similar
>>> patch going through the compiler when I got this mail. Does it work as well
>>> as what you suggested?
>>
>> Yes, this patch works just as well.
> 
> Right, as expected :-) However, I don't like it much. It divides the mux
> consumers into two camps in a way that makes it difficult to select which
> camp a consumer should be in.
> 
> E.g. consider the iio-mux. The current implementation only supports quick
> accesses that fit the mux_control_get_shared case. But if that mux in the
> future needs to grow continuous buffered accesses, I think there will be
> pressure to switch it over to the exclusive mode. Because that is a lot
> closer to what you are doing with the video-mux. And then what? It will be
> impossible to predict if the end user is going to use buffered accesses or
> not...
> 
> So, I think the best approach is to skip the distinction between shared
> and exclusive consumers and instead implement the locking with an ordinary
> semaphore (instead of the old rwsem or the current mutex). Semaphores don't
> have the property that the same task should down/up them (mutexes require
> that for lock/unlock, and is also the reason for the lockdep complaint) and
> thus fits better for long-time use such as yours or the above iio-mux with
> buffered accesses. It should also hopefully be cheaper that an rwsem, and
> not have any downgrade_write calls thus possibly keeping Greg sufficiently
> happy...
> 
> Sure, consumers can still dig themselves into a hole by not calling deselect
> as they should, but at least I think it can be made to work w/o dividing the
> consumers...

Like this (only compile-tested). Philipp, it should work the same as with
the rwsem in v13 and earlier. At least for your case...

Cheers,
peda

diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
index c02fa4dd2d09..f99b70d4e319 100644
--- a/drivers/mux/mux-core.c
+++ b/drivers/mux/mux-core.c
@@ -116,7 +116,7 @@ struct mux_chip *mux_chip_alloc(struct device *dev,
struct mux_control *mux = _chip->mux[i];

mux->chip = mux_chip;
-   mutex_init(>lock);
+   sema_init(>lock, 1);
mux->cached_state = MUX_CACHE_UNKNOWN;
mux->idle_state = MUX_IDLE_AS_IS;
}
@@ -372,12 +372,14 @@ int mux_control_select(struct mux_control *mux, unsigned 
int state)
 {
int ret;

-   mutex_lock(>lock);
+   ret = down_killable(>lock);
+   if (ret < 0)
+   return ret;

ret = __mux_control_select(mux, state);

if (ret < 0)
-   mutex_unlock(>lock);
+   up(>lock);

return ret;
 }
@@ -399,13 +401,13 @@ int mux_control_try_select(struct mux_control *mux, 
unsigned int state)
 {
int ret;

-   if (!mutex_trylock(>lock))
+   if (down_trylock(>lock))
return -EBUSY;

ret = __mux_control_select(mux, state);

if (ret < 0)
-   mutex_unlock(>lock);
+   up(>lock);

return ret;
 }
@@ -427,7 +429,7 @@ int mux_control_deselect(struct mux_control *mux)
mux->idle_state != mux->cached_state)
ret = mux_control_set(mux, mux->idle_state);

-   mutex_unlock(>lock);
+   up(>lock);

return ret;
 }
diff --git a/include/linux/mux/driver.h b/include/linux/mux/driver.h
index 95269f40670a..43f65f80c275 100644
--- a/include/linux/mux/driver.h
+++ b/include/linux/mux/driver.h
@@ -15,7 +15,6 @@

 #include 
 #include 
-#include 
 #include 

 struct mux_chip;
@@ -44,7 +43,7 @@ struct mux_control_ops {
  * mux drivers.
  */
 struct mux_control {
-   struct mutex lock; /* protects the state of the mux */
+   struct semaphore lock; /* protects the state of the mux */

struct mux_chip *chip;
int cached_state;


--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes

2017-04-25 Thread Peter Rosin
On 2017-04-24 16:59, Philipp Zabel wrote:
> On Mon, 2017-04-24 at 16:36 +0200, Peter Rosin wrote:
> [...]
>>> How about an atomic use_count on the mux_control, a bool shared that is
>>> only set by the first consumer, and controls whether selecting locks?
>>
>> That has the drawback that it is hard to restore the mux-control in a safe
>> way so that exclusive consumers are allowed after the last shared consumer
>> puts the mux away.
> 
> True.
> 
>> Agreed, it's a corner case, but I had this very similar
>> patch going through the compiler when I got this mail. Does it work as well
>> as what you suggested?
> 
> Yes, this patch works just as well.

Right, as expected :-) However, I don't like it much. It divides the mux
consumers into two camps in a way that makes it difficult to select which
camp a consumer should be in.

E.g. consider the iio-mux. The current implementation only supports quick
accesses that fit the mux_control_get_shared case. But if that mux in the
future needs to grow continuous buffered accesses, I think there will be
pressure to switch it over to the exclusive mode. Because that is a lot
closer to what you are doing with the video-mux. And then what? It will be
impossible to predict if the end user is going to use buffered accesses or
not...

So, I think the best approach is to skip the distinction between shared
and exclusive consumers and instead implement the locking with an ordinary
semaphore (instead of the old rwsem or the current mutex). Semaphores don't
have the property that the same task should down/up them (mutexes require
that for lock/unlock, and is also the reason for the lockdep complaint) and
thus fits better for long-time use such as yours or the above iio-mux with
buffered accesses. It should also hopefully be cheaper that an rwsem, and
not have any downgrade_write calls thus possibly keeping Greg sufficiently
happy...

Sure, consumers can still dig themselves into a hole by not calling deselect
as they should, but at least I think it can be made to work w/o dividing the
consumers...

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes

2017-04-24 Thread Peter Rosin
On 2017-04-24 16:10, Philipp Zabel wrote:
> On Mon, 2017-04-24 at 13:37 +0200, Peter Rosin wrote:
>> On 2017-04-24 12:52, Philipp Zabel wrote:
>>> On Mon, 2017-04-24 at 10:36 +0200, Peter Rosin wrote:
>>>> Hi!
>>>>
>>>> The big change since v13 is that the mux state is now locked with a mutex
>>>> instead of an rwsem. Other that that, it is mostly restructuring and doc
>>>> changes. There are a few other "real" changes as well, but those changes
>>>> feel kind of minor. I guess what I'm trying to say is that although the
>>>> list of changes for v14 is longish, it's still basically the same as last
>>>> time.
>>>
>>> I have hooked this up to the video-multiplexer and now I trigger
>>> the lockdep debug_check_no_locks_held error message when selecting the
>>> mux input from userspace:
>>>
>>> $ media-ctl --links "'imx6-mipi-csi2':1->'ipu1_csi0_mux':0[1]"
>>> [   66.258368] 
>>> [   66.259919] =
>>> [   66.265369] [ BUG: media-ctl/258 still has locks held! ]
>>> [   66.270810] 4.11.0-rc8-20170424-1+ #1305 Not tainted
>>> [   66.275863] -
>>> [   66.282158] 1 lock held by media-ctl/258:
>>> [   66.286464]  #0:  (>lock){+.+.+.}, at: [<8074a6c0>] 
>>> mux_control_select+0x24/0x50
>>> [   66.294424] 
>>> [   66.294424] stack backtrace:
>>> [   66.298980] CPU: 0 PID: 258 Comm: media-ctl Not tainted 4.11.0-rc8+ #1305
>>> [   66.306771] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
>>> [   66.313334] Backtrace: 
>>> [   66.315858] [<8010e5a4>] (dump_backtrace) from [<8010e8ac>] 
>>> (show_stack+0x20/0x24)
>>> [   66.323473]  r7:80e518d0 r6:80e518d0 r5:600d0013 r4:
>>> [   66.329190] [<8010e88c>] (show_stack) from [<80496cf4>] 
>>> (dump_stack+0xb0/0xdc)
>>> [   66.336470] [<80496c44>] (dump_stack) from [<8017e404>] 
>>> (debug_check_no_locks_held+0xb8/0xbc)
>>> [   66.345043]  r9:ae8566b8 r8:ad88dc84 r7:ad88df58 r6:ad88dc84 r5:ad88df58 
>>> r4:ae856400
>>> [   66.352837] [<8017e34c>] (debug_check_no_locks_held) from [<8012b258>] 
>>> (do_exit+0x79c/0xcc8)
>>> [   66.361321] [<8012aabc>] (do_exit) from [<8012d25c>] 
>>> (do_group_exit+0x4c/0xcc)
>>> [   66.368581]  r7:00f8
>>> [   66.371161] [<8012d210>] (do_group_exit) from [<8012d2fc>] 
>>> (__wake_up_parent+0x0/0x30)
>>> [   66.379120]  r7:00f8 r6:76f71798 r5: r4:0001
>>> [   66.384837] [<8012d2dc>] (SyS_exit_group) from [<80109380>] 
>>> (ret_fast_syscall+0x0/0x1c)
>>>
>>> That correctly warns that the media-ctl process caused the mux->lock to
>>> be locked and still held when the process exited. Do we need a usage
>>> counter based mechanism for muxes that are (indirectly) controlled from
>>> userspace?
> [...]
>> The question then becomes how to best tell the mux core that you want
>> an exclusive mux. I see two options. Either you declare a mux controller
>> as exclusive up front somehow (in the device tree presumably), or you
>> add a mux_control_get_exclusive call that makes further calls to
>> mux_control_get{,_exclusive} fail with -EBUSY. I think I like the
>> latter better, if that can be made to work...
> 
> How about an atomic use_count on the mux_control, a bool shared that is
> only set by the first consumer, and controls whether selecting locks?

That has the drawback that it is hard to restore the mux-control in a safe
way so that exclusive consumers are allowed after the last shared consumer
puts the mux away. Agreed, it's a corner case, but I had this very similar
patch going through the compiler when I got this mail. Does it work as well
as what you suggested?

Cheers,
peda

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index e2343d9cbec7..5a7352a83124 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -342,7 +342,8 @@ MUX
   devm_mux_chip_free()
   devm_mux_chip_register()
   devm_mux_chip_unregister()
-  devm_mux_control_get()
+  devm_mux_control_get_shared()
+  devm_mux_control_get_exclusive()
   devm_mux_control_put()
 
 PER-CPU MEM
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
index 92cf5f48afe6..135d6baaebe5 100644
--- a/drivers/i2c/muxes/i2c-mux-gpmux.c
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -87,7 +87,7

Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes

2017-04-24 Thread Peter Rosin
On 2017-04-24 12:52, Philipp Zabel wrote:
> On Mon, 2017-04-24 at 10:36 +0200, Peter Rosin wrote:
>> Hi!
>>
>> The big change since v13 is that the mux state is now locked with a mutex
>> instead of an rwsem. Other that that, it is mostly restructuring and doc
>> changes. There are a few other "real" changes as well, but those changes
>> feel kind of minor. I guess what I'm trying to say is that although the
>> list of changes for v14 is longish, it's still basically the same as last
>> time.
> 
> I have hooked this up to the video-multiplexer and now I trigger
> the lockdep debug_check_no_locks_held error message when selecting the
> mux input from userspace:
> 
> $ media-ctl --links "'imx6-mipi-csi2':1->'ipu1_csi0_mux':0[1]"
> [   66.258368] 
> [   66.259919] =
> [   66.265369] [ BUG: media-ctl/258 still has locks held! ]
> [   66.270810] 4.11.0-rc8-20170424-1+ #1305 Not tainted
> [   66.275863] -
> [   66.282158] 1 lock held by media-ctl/258:
> [   66.286464]  #0:  (>lock){+.+.+.}, at: [<8074a6c0>] 
> mux_control_select+0x24/0x50
> [   66.294424] 
> [   66.294424] stack backtrace:
> [   66.298980] CPU: 0 PID: 258 Comm: media-ctl Not tainted 4.11.0-rc8+ #1305
> [   66.306771] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> [   66.313334] Backtrace: 
> [   66.315858] [<8010e5a4>] (dump_backtrace) from [<8010e8ac>] 
> (show_stack+0x20/0x24)
> [   66.323473]  r7:80e518d0 r6:80e518d0 r5:600d0013 r4:
> [   66.329190] [<8010e88c>] (show_stack) from [<80496cf4>] 
> (dump_stack+0xb0/0xdc)
> [   66.336470] [<80496c44>] (dump_stack) from [<8017e404>] 
> (debug_check_no_locks_held+0xb8/0xbc)
> [   66.345043]  r9:ae8566b8 r8:ad88dc84 r7:ad88df58 r6:ad88dc84 r5:ad88df58 
> r4:ae856400
> [   66.352837] [<8017e34c>] (debug_check_no_locks_held) from [<8012b258>] 
> (do_exit+0x79c/0xcc8)
> [   66.361321] [<8012aabc>] (do_exit) from [<8012d25c>] 
> (do_group_exit+0x4c/0xcc)
> [   66.368581]  r7:00f8
> [   66.371161] [<8012d210>] (do_group_exit) from [<8012d2fc>] 
> (__wake_up_parent+0x0/0x30)
> [   66.379120]  r7:00f8 r6:76f71798 r5: r4:0001
> [   66.384837] [<8012d2dc>] (SyS_exit_group) from [<80109380>] 
> (ret_fast_syscall+0x0/0x1c)
> 
> That correctly warns that the media-ctl process caused the mux->lock to
> be locked and still held when the process exited. Do we need a usage
> counter based mechanism for muxes that are (indirectly) controlled from
> userspace?

Ok, so the difference is probably that the rwsem locking primitive
don't have any lockdep checking hooked up. Because the rwsem was
definitely held in the same way in v13 as the mutex is now held in
v14, so there's no fundamental difference.

So, yes, we can use some kind of refcount scheme to not hold an actual
mutex for the duration of the mux select/deselect, but that doesn't
really change anything. Userspace is still locking something, and that
seems dangerous. How do you make sure that mux_control_deselect is
called as it should?

What I don't like about abandoning the lock is that there is still a
need to support the multi-consumer case and then you need some way
of keeping track of waiters. A lock does this, and any attempt to open
code that will get messy.

What might be better is to support some kind of exclusive mux, i.e. a
mux that only allows one consumer per mux controller. Then the mux core
could trust that exclusive consumer to not fuck things up for itself and
thus have no lock at all for select/deselect for the exclusive case. Or
perhaps keep a refcount (as you suggested) for the exclusive case so
that mux_control_try_select still makes sense, because you still want
that, right? 

The question then becomes how to best tell the mux core that you want
an exclusive mux. I see two options. Either you declare a mux controller
as exclusive up front somehow (in the device tree presumably), or you
add a mux_control_get_exclusive call that makes further calls to
mux_control_get{,_exclusive} fail with -EBUSY. I think I like the
latter better, if that can be made to work...

Cheers,
peda
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 06/11] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-04-24 Thread Peter Rosin
Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 4cfa080878e2..1cde195bba25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6360,6 +6360,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 08/11] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-04-24 Thread Peter Rosin
Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 10/11] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-04-24 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 09/11] i2c: i2c-mux-gpmux: new driver

2017-04-24 Thread Peter Rosin
This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 10b3d17ae3ea..5fb34f24 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 9948fa45037f..af43c6c3e861 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..92cf5f48afe6
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+   return PTR_ERR(mux->control);
+   }
+
+   

[PATCH v14 11/11] mux: adg792a: add mux controller driver for ADG792A/G

2017-04-24 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 157 ++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index e580c2d028d2..34b8284d6d29 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on GPIOLIB
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..12aa221ab90d
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,157 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESETB BIT(1)
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_write_cmd(struct i2c_client *i2c, u8 cmd, int reset)
+{
+   u8 data = ADG792A_RESETB | ADG792A_LDSW;
+
+   /* ADG792A_RESETB is active low, the chip resets when it is zero. */
+   if (reset)
+   data &= ~ADG792A_RESETB;
+
+   return i2c_smbus_write_byte_data(i2c, cmd, data);
+}
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return adg792a_write_cmd(i2c, cmd, 0);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   s32 idle_state[3];
+   u32 cells;
+   int ret;
+   int i;
+
+   if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+   return -ENODEV;
+
+   ret = device_property_read_u32(dev, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   mux_chip->ops = _ops;
+
+   ret = adg792a_write_cmd(i2c, ADG792A_DISABLE_ALL, 1);
+   if (ret < 0)
+   return ret;
+
+   ret = device_property_read_u32_array(dev, "idle-state",
+(u32 *)idle_state,
+mux_chip->controllers);
+   if (ret < 0) {
+   idle_state[0] = MUX_IDLE_AS_IS;
+   idle_state[1] = MUX_IDLE_AS_IS;
+   idle_state[2] = MUX_IDLE_AS_IS;
+   }
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux = _chip->mux[i];
+
+   mux->states = 4;
+
+ 

[PATCH v14 07/11] iio: multiplexer: new iio category and iio-mux driver

2017-04-24 Thread Peter Rosin
When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 459 ++
 6 files changed, 486 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1cde195bba25..519719069211 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6365,6 +6365,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..70a044510686
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..37ba007f8dca
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,459 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   ssize_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   const char *attr = chan->ext_info[i].name;
+   

[PATCH v14 05/11] iio: inkern: api for manipulating ext_info of iio channels

2017-04-24 Thread Peter Rosin
Extend the inkern api with functions for reading and writing ext_info
of iio channels.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/inkern.c | 60 
 include/linux/iio/consumer.h | 37 +++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..8292ad4435ea 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -869,3 +869,63 @@ int iio_write_channel_raw(struct iio_channel *chan, int 
val)
return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+   unsigned int i = 0;
+
+   if (!chan->channel->ext_info)
+   return i;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
+   ++i;
+
+   return i;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+
+static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
+   const struct iio_channel *chan,
+   const char *attr)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   if (!chan->channel->ext_info)
+   return NULL;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+   if (!strcmp(attr, ext_info->name))
+   return ext_info;
+   }
+
+   return NULL;
+}
+
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->read(chan->indio_dev, ext_info->private,
+ chan->channel, buf);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->write(chan->indio_dev, ext_info->private,
+  chan->channel, buf, len);
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 47eeec3218b5..5e347a9805fd 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -312,4 +312,41 @@ int iio_read_channel_scale(struct iio_channel *chan, int 
*val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);
 
+/**
+ * iio_get_channel_ext_info_count() - get number of ext_info attributes
+ *   connected to the channel.
+ * @chan:  The channel being queried
+ *
+ * Returns the number of ext_info attributes
+ */
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
+
+/**
+ * iio_read_channel_ext_info() - read ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   Where to store the attribute value. Assumed to hold
+ * at least PAGE_SIZE bytes.
+ *
+ * Returns the number of bytes written to buf (perhaps w/o zero termination;
+ * it need not even be a string), or an error code.
+ */
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf);
+
+/**
+ * iio_write_channel_ext_info() - write ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   The new attribute value. Strings needs to be zero-
+ * terminated, but the terminator should not be included
+ * in the below len.
+ * @len:   The size of the new attribute value.
+ *
+ * Returns the number of accepted bytes, which should be the same as len.
+ * An error code can also be returned.
+ */
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len);
+
 #endif
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 04/11] mux: gpio: add mux controller driver for gpio based multiplexers

2017-04-24 Thread Peter Rosin
The driver builds a single multiplexer controller using a number
of gpio pins. For N pins, there will be 2^N possible multiplexer
states. The GPIO pins can be connected (by the hardware) to several
multiplexers, which in that case will be operated in parallel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig|  18 
 drivers/mux/Makefile   |   1 +
 drivers/mux/mux-gpio.c | 114 +
 3 files changed, 133 insertions(+)
 create mode 100644 drivers/mux/mux-gpio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 23ab2cde83b1..e580c2d028d2 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -14,3 +14,21 @@ menuconfig MULTIPLEXER
 
  To compile the subsystem as a module, choose M here: the module will
  be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on GPIOLIB
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 09f0299e109d..bb16953f6290 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c
new file mode 100644
index ..468bf1709606
--- /dev/null
+++ b/drivers/mux/mux-gpio.c
@@ -0,0 +1,114 @@
+/*
+ * GPIO-controlled multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_gpio {
+   struct gpio_descs *gpios;
+   int *val;
+};
+
+static int mux_gpio_set(struct mux_control *mux, int state)
+{
+   struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
+   int i;
+
+   for (i = 0; i < mux_gpio->gpios->ndescs; i++)
+   mux_gpio->val[i] = (state >> i) & 1;
+
+   gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
+  mux_gpio->gpios->desc,
+  mux_gpio->val);
+
+   return 0;
+}
+
+static const struct mux_control_ops mux_gpio_ops = {
+   .set = mux_gpio_set,
+};
+
+static const struct of_device_id mux_gpio_dt_ids[] = {
+   { .compatible = "gpio-mux", },
+   { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
+
+static int mux_gpio_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   struct mux_gpio *mux_gpio;
+   int pins;
+   s32 idle_state;
+   int ret;
+
+   pins = gpiod_count(dev, "mux");
+   if (pins < 0)
+   return pins;
+
+   mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
+  pins * sizeof(*mux_gpio->val));
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   mux_gpio = mux_chip_priv(mux_chip);
+   mux_gpio->val = (int *)(mux_gpio + 1);
+   mux_chip->ops = _gpio_ops;
+
+   mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
+   if (IS_ERR(mux_gpio->gpios)) {
+   ret = PTR_ERR(mux_gpio->gpios);
+   if (ret != -EPROBE_DEFER)
+   dev_err(dev, "failed to get gpios\n");
+   return ret;
+   }
+   WARN_ON(pins != mux_gpio->gpios->ndescs);
+   mux_chip->mux->states = 1 << pins;
+
+   ret = device_property_read_u32(dev, "idle-state", (u32 *)_state);
+   if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) {
+   if (idle_state < 0 || idle_state >= mux_chip->mux->states) {
+   dev_err(dev, "invalid idle-state %u\n", idle_state);
+   return -EINVAL;
+   }
+
+   mux_chip->mux->idle_state = idle_state;
+   }
+
+   ret = devm_mux_chip_register(dev, mux_chip);
+   if (ret < 0)
+   return ret;
+
+   dev_info(dev, "%u-way mux-controller registered\n",
+  

[PATCH v14 03/11] mux: minimal mux subsystem

2017-04-24 Thread Peter Rosin
Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

Thanks go out to Lars-Peter Clausen, Jonathan Cameron, Rob Herring,
Wolfram Sang, Paul Gortmaker, Dan Carpenter, Colin Ian King, Greg
Kroah-Hartman and last but certainly not least to Philipp Zabel for
helpful comments, reviews, patches and general encouragement!

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/ABI/testing/sysfs-class-mux |  16 +
 Documentation/driver-model/devres.txt |   8 +
 MAINTAINERS   |   3 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  16 +
 drivers/mux/Makefile  |   5 +
 drivers/mux/mux-core.c| 593 ++
 include/linux/mux/consumer.h  |  33 ++
 include/linux/mux/driver.h| 111 ++
 10 files changed, 788 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-mux
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 include/linux/mux/consumer.h
 create mode 100644 include/linux/mux/driver.h

diff --git a/Documentation/ABI/testing/sysfs-class-mux 
b/Documentation/ABI/testing/sysfs-class-mux
new file mode 100644
index ..8715f9c7bd4f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-mux
@@ -0,0 +1,16 @@
+What:  /sys/class/mux/
+Date:  April 2017
+KernelVersion: 4.13
+Contact:   Peter Rosin <p...@axentia.se>
+Description:
+   The mux/ class sub-directory belongs to the Generic MUX
+   Framework and provides a sysfs interface for using MUX
+   controllers.
+
+What:  /sys/class/mux/muxchipN/
+Date:  April 2017
+KernelVersion: 4.13
+Contact:   Peter Rosin <p...@axentia.se>
+Description:
+   A /sys/class/mux/muxchipN directory is created for each
+   probed MUX chip where N is a simple enumeration.
diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index efb8200819d6..e2343d9cbec7 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,14 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_free()
+  devm_mux_chip_register()
+  devm_mux_chip_unregister()
+  devm_mux_control_get()
+  devm_mux_control_put()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fc06739c8ad..4cfa080878e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8561,8 +8561,11 @@ F:   include/linux/spi/mmc_spi.h
 MULTIPLEXER SUBSYSTEM
 M: Peter Rosin <p...@axentia.se>
 S: Maintained
+F: Documentation/ABI/testing/mux/sysfs-class-mux*
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux/
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 117ca14ccf85..a7ea13e1b869 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2eced9afba53..c0436f6dd5a9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -177,3 +177,4 @@ obj-$(CONFIG_ANDROID)   += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..23ab2cde83b1
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,16 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.

[PATCH v14 01/11] devres: trivial whitespace fix

2017-04-24 Thread Peter Rosin
Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index bf34d5b3a733..efb8200819d6 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v14 00/11] mux controller abstraction and iio/i2c muxes

2017-04-24 Thread Peter Rosin
ux state, it was possible
  to drop the state member from the mux_child struct.
- cleanup dt bindings for i2c-mux-simple, it had some of copy-paste
  problems from ots origin (i2c-mux-gpio).
- select the mux control subsystem in config for the i2c-mux-simple driver.
- add entries to MAINTAINERS and my sign-off, I'm now satisfied and know
  nothing in this to be ashamed of.

v1 -> v2 changes:  https://lkml.org/lkml/2016/11/17/918
- fixup export of mux_control_put reported by kbuild
- drop devicetree iio-ext-info property as noted by Lars-Peter,
  and replace the functionality by exposing all ext_info
  attributes of the parent channel for each of the muxed
  channels. A cache on top of that and each muxed channel
  gets its own view of the ext_info of the parent channel.
- implement idle-state for muxes
- clear out the cache on failure in order to force a mux
  update on the following use
- cleanup the probe of i2c-mux-simple driver
- fix a bug in the i2c-mux-simple driver, where failure in
  the selection of the mux caused a deadlock when the mux
  was later unconditionally deselected.

v1:  https://lkml.org/lkml/2016/11/16/812

Cheers,
peda

Peter Rosin (11):
  devres: trivial whitespace fix
  dt-bindings: document devicetree bindings for mux-controllers and
gpio-mux
  mux: minimal mux subsystem
  mux: gpio: add mux controller driver for gpio based multiplexers
  iio: inkern: api for manipulating ext_info of iio channels
  dt-bindings: iio: io-channel-mux: document io-channel-mux bindings
  iio: multiplexer: new iio category and iio-mux driver
  dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings
  i2c: i2c-mux-gpmux: new driver
  dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G
mux
  mux: adg792a: add mux controller driver for ADG792A/G

 Documentation/ABI/testing/sysfs-class-mux  |  16 +
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  |  99 
 .../bindings/iio/multiplexer/io-channel-mux.txt|  39 ++
 .../devicetree/bindings/mux/adi,adg792a.txt|  75 +++
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +++
 .../devicetree/bindings/mux/mux-controller.txt | 157 ++
 Documentation/driver-model/devres.txt  |  10 +-
 MAINTAINERS|  16 +
 drivers/Kconfig|   2 +
 drivers/Makefile   |   1 +
 drivers/i2c/muxes/Kconfig  |  13 +
 drivers/i2c/muxes/Makefile |   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c  | 173 ++
 drivers/iio/Kconfig|   1 +
 drivers/iio/Makefile   |   1 +
 drivers/iio/inkern.c   |  60 +++
 drivers/iio/multiplexer/Kconfig|  18 +
 drivers/iio/multiplexer/Makefile   |   6 +
 drivers/iio/multiplexer/iio-mux.c  | 459 
 drivers/mux/Kconfig|  46 ++
 drivers/mux/Makefile   |   7 +
 drivers/mux/mux-adg792a.c  | 157 ++
 drivers/mux/mux-core.c | 593 +
 drivers/mux/mux-gpio.c | 114 
 include/dt-bindings/mux/mux.h  |  16 +
 include/linux/iio/consumer.h   |  37 ++
 include/linux/mux/consumer.h   |  33 ++
 include/linux/mux/driver.h | 111 
 28 files changed, 2329 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-mux
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-adg792a.c
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/linux/mux/consumer.h
 create mode 100644 include/linux/mux/driver.h

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-21 Thread Peter Rosin
On 2017-04-20 23:53, Peter Rosin wrote:
> On 2017-04-18 23:53, Peter Rosin wrote:
>> On 2017-04-18 13:44, Greg Kroah-Hartman wrote:
>>> On Tue, Apr 18, 2017 at 12:59:50PM +0200, Peter Rosin wrote:
>>>> On 2017-04-18 10:51, Greg Kroah-Hartman wrote:
>>>>> On Thu, Apr 13, 2017 at 06:43:07PM +0200, Peter Rosin wrote:
> 
> *snip*
> 
>>>>>> +if (mux->idle_state != MUX_IDLE_AS_IS &&
>>>>>> +mux->idle_state != mux->cached_state)
>>>>>> +ret = mux_control_set(mux, mux->idle_state);
>>>>>> +
>>>>>> +up_read(>lock);
>>>>>
>>>>> You require a lock to be held for a "global" function?  Without
>>>>> documentation?  Or even a sparse marking?  That's asking for trouble...
>>>>
>>>> Documentation I can handle, but where should I look to understand how I
>>>> should add sparse markings?
>>>
>>> Run sparse on the code and see what it says :)
>>
>> Will do.
> 
> I just did, and even went through the trouble of getting the bleeding
> edge sparse from the git repo when sparse 0.5.0 came up empty, but it's
> all silence for me. So, how do I add sparse markings?

I looked some more into this, and the markings I find that seem related
are __acquire() and __release(). But neither mutex_lock() nor up_read()
has markings like that, so adding them when using those kinds of locks
in an imbalanced way seems like a sure way of *getting* sparse messages
about context imbalance...

So, either that, or you are talking about __must_check markings?

I feel like I'm missing something, please advise further.

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-21 Thread Peter Rosin
On 2017-04-21 16:41, Philipp Zabel wrote:
> On Fri, 2017-04-21 at 16:32 +0200, Peter Rosin wrote:
>> On 2017-04-21 16:23, Philipp Zabel wrote:
>>> On Thu, 2017-04-13 at 18:43 +0200, Peter Rosin wrote:
>>> [...]
>>>> +int mux_chip_register(struct mux_chip *mux_chip)
>>>> +{
>>>> +  int i;
>>>> +  int ret;
>>>> +
>>>> +  for (i = 0; i < mux_chip->controllers; ++i) {
>>>> +  struct mux_control *mux = _chip->mux[i];
>>>> +
>>>> +  if (mux->idle_state == mux->cached_state)
>>>> +  continue;
>>>
>>> I think this should be changed to
>>>  
>>> -   if (mux->idle_state == mux->cached_state)
>>> +   if (mux->idle_state == mux->cached_state ||
>>> +   mux->idle_state == MUX_IDLE_AS_IS)
>>> continue;
>>>
>>> or the following mux_control_set will be called with state ==
>>> MUX_IDLE_AS_IS. Alternatively, mux_control_set should return when passed
>>> this value.
>>
>> That cannot happen because ->cached_state is initialized to -1
>> in mux_chip_alloc, so should always be == MUX_IDLE_AS_IS when
>> registering. And drivers are not supposed to touch ->cached_state.
>> I.e., ->cached_state is "owned" by the core.
> 
> So this was caused by me filling cached_state from register reads in the
> mmio driver. Makes me wonder why I am not allowed to do this, though, if
> I am able to read back the initial state?

You gain fairly little by reading back the original state. If the mux
should idle-as-is, you can avoid a maximum of one mux update if the first
consumer happens to starts by requesting the previously active state.
Similarly, if the mux should idle in a specific state, you can avoid a
maximum of one mux update.

In both cases it costs one unconditional read of the mux state.

Sure, in some cases reads are cheaper than writes, but I didn't think
support for seeding the cache was worth it. Is it worth it?

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-21 Thread Peter Rosin
On 2017-04-21 16:18, Philipp Zabel wrote:
> Hi Peter,
> 
> On Thu, 2017-04-13 at 18:43 +0200, Peter Rosin wrote:
> [...]
>> +int mux_control_select(struct mux_control *mux, int state)
> 
> state could be unsigned int for the consumer facing API.
> 
>> +{
>> +int ret;
> 
> And mux_control_select should check that (0 <= state < mux->states).

Yes, that makes sense. I worried that we might end up with
signed/unsigned comparisons since the internal state still needs
to be signed, but that didn't happen when I tried...

I'll include this change in v14.

Cheers,
peda
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-20 Thread Peter Rosin
On 2017-04-18 23:53, Peter Rosin wrote:
> On 2017-04-18 13:44, Greg Kroah-Hartman wrote:
>> On Tue, Apr 18, 2017 at 12:59:50PM +0200, Peter Rosin wrote:
>>> On 2017-04-18 10:51, Greg Kroah-Hartman wrote:
>>>> On Thu, Apr 13, 2017 at 06:43:07PM +0200, Peter Rosin wrote:

*snip*

>>>>> + if (mux->idle_state != MUX_IDLE_AS_IS &&
>>>>> + mux->idle_state != mux->cached_state)
>>>>> + ret = mux_control_set(mux, mux->idle_state);
>>>>> +
>>>>> + up_read(>lock);
>>>>
>>>> You require a lock to be held for a "global" function?  Without
>>>> documentation?  Or even a sparse marking?  That's asking for trouble...
>>>
>>> Documentation I can handle, but where should I look to understand how I
>>> should add sparse markings?
>>
>> Run sparse on the code and see what it says :)
> 
> Will do.

I just did, and even went through the trouble of getting the bleeding
edge sparse from the git repo when sparse 0.5.0 came up empty, but it's
all silence for me. So, how do I add sparse markings?

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-19 Thread Peter Rosin
On 2017-04-19 15:49, Philipp Zabel wrote:
> On Wed, 2017-04-19 at 14:00 +0200, Peter Rosin wrote:
> [...]
>>>> +int mux_control_select(struct mux_control *mux, int state)
>>>
>>> If we let two of these race, ...
>>
>> The window for this "race" is positively huge. If there are several
>> mux consumers of a single mux controller, it is self-evident that
>> if one of them grabs the mux for a long time, the others will suffer.
>>
>> The design is that the rwsem is reader-locked for the full duration
>> of a select/deselect operation by the mux consumer.
> 
> I was not clear. I meant: I think this can also happen if we let them
> race with the same state target.

Right, but there is another glaring problem with the v13 implementation
of select/deselect. If there are three consumers and the first one
holds the mux while the other two tries to select it to some other
position, then even if the two "new" consumers agree on the mux state,
then both of them will end up in the "it's just contended" case and
then be serialized. So, yes, the select/deselect implementation is not
perfect. To quote the cover letter:

I'm using an rwsem to lock a mux, but that isn't really a
perfect fit. Is there a better locking primitive that I don't
know about that fits better? I had a mutex at one point, but
that didn't allow any concurrent accesses at all. At least
the rwsem allows concurrent access as long as all users
agree on the mux state, but I suspect that the rwsem will
degrade to the mutex situation pretty quickly if there is
any contention.

But with your discovery that there's a race when two consumers go
for the same state in a free mux, in addition to the above contention
problem, I'm about ready to go with Greg's suggestion and just use a
mutex. I.e. ignore the desire to allow concurrent use. Because it's
not like the sketchy thing I threw out in the other part of the thread
solves any of these problems. I can live without the concurrency, and
I guess I can also live with passing the buck to the poor sod that
eventually needs it.

>>>> +{
>>>> +  int ret;
>>>> +
>>>> +  if (down_read_trylock(>lock)) {
>>>> +  if (mux->cached_state == state)
>>>> +  return 0;
> 
> This check makes it clear that a second select call is not intended to
> block if the intended state is already selected. But if the instance we
> will lose the race against has not yet updated cached_state, ...
> 
>>>> +  /* Sigh, the mux needs updating... */
>>>> +  up_read(>lock);
>>>> +  }
>>>> +
>>>> +  /* ...or it's just contended. */
>>>> +  down_write(>lock);
> 
> ... we are blocking here until the other instance calls up_read. Even
> though in this case (same state target) we would only have to block
> until the other instance calls downgrade_write after the mux control is
> set to the correct state.
> 
> Basically there is a small window before down_write with no lock at all,
> where multiple instances can already have decided they must change the
> mux (to the same state). If this happens, they go on to block each other
> unnecessarily.
> 
>>> ... then the last to get to down_write will just wait here forever (or
>>> until the first consumer calls mux_control_deselect, which may never
>>> happen)?
>>
>> It is vital that the mux consumer call _deselect when it is done with
>> the mux. Not doing so will surely starve out any other mux consumers.
>> The whole thing is designed around the fact that mux consumers should
>> deselect the mux as soon as it's no longer needed.
> 
> I'd like to use this for video bus multiplexers. Those would not be
> selected for the duration of an i2c transfer, but for the duration of a
> running video capture stream, or for the duration of an enabled display
> path. While I currently have no use case for multiple consumers
> controlling the same mux, this scenario is what shapes my perspective.
> For such long running selections the consumer should have the option to
> return -EBUSY instead of blocking when the lock can't be taken.

I'll see if I can implement a try variant for the mutex based select I
will probably end up with in v14...

Cheers,
peda
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 02/10] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-04-19 Thread Peter Rosin
On 2017-04-19 13:05, Philipp Zabel wrote:
> On Wed, 2017-04-19 at 12:41 +0200, Peter Rosin wrote:
>> On 2017-04-19 11:17, Philipp Zabel wrote:
>>> On Tue, 2017-04-18 at 15:36 +0200, Peter Rosin wrote:
>>>> If I got things wrong when I skimmed whatever I came across, and if the
>>>> mmio register is the only mux control option in the stars, it becomes
>>>> less obvious... It's of course still possible to hook into the mux
>>>> subsystem, but the benefit is questionable. And you do get the extra
>>>> device tree node. You could of course also implement a mux driver
>>>> outside of drivers/mux and thus make use of the mux api, but it's tiny
>>>> and any benefit is truly small.
>>>
>>> What I wondered mostly is whether it would be a good idea to move the
>>> OF-graph ports into the mux controller node, and let the video capture
>>> device be the consumer of the mux.
>>> But this wouldn't fit well with the clear split between the mux
>>> controller and the actual mux hardware in the mux DT bindings.
>>
>> I have tried to do something similar. I think. The current
>> drivers/i2c/muxes/i2c-mux-gpio.c is a good candidate for the same thing
>> IIUC.
>>
>> That dedicated driver and the general purpose i2c mux driver does pretty
>> much the same thing with these two DT snippets:
>>
>> Dedicated i2c-mux-gpio DT snippet:
>>
>>  i2c-mux {
>>  compatible = "i2c-mux-gpio";
>>  i2c-parent = <>;
>>
>>  mux-gpios = < 22 0  23 0>;
>>
>>  #address-cells = <1>;
>>  #size-cells = <0>;
>>
>>  i2c@1 {
>>  ...
>>  };
>>
>>  i2c@3 {
>>  ...
>>  };
>>  };
>>
>> General purpose mux DT snippet:
>>
>>  mux: mux-controller {
>>  compatible = "gpio-mux";
>>  #mux-control-cells = <0>;
>>
>>  mux-gpios = < 22 0  23 0>;
>>  };
>>
>>  i2c-mux {
>>  compatible = "i2c-mux";
>>  i2c-parent = <>;
>>
>>  mux-controls = <>;
>>
>>  #address-cells = <1>;
>>  #size-cells = <0>;
>>
>>  i2c@1 {
>>  ...
>>  };
>>
>>  i2c@3 {
>>  ...
>>  };
>>  };
> 
> Yes, replace i2c-mux with video-mux and the i2c@x nodes with port@x
> nodes, and this is very close to what I am thinking about.
> 
>> I would love to find a way to cleanly get the mux framework to handle
>> the first DT as well, and thus being able to obsolete the dedicated
>> i2c-mux-gpio driver. I have not figured out how to accomplish that
>> without abusing the driver-model to a point that it's not working.
>> Help with that task is dearly appreciated.
>>
>> What I have stumbled on, I think, is that two drivers needs to be
>> instantiated from the same DT node. At the same time, I need the
>> mux framework to handle the current out-of-node thing with a
>> phandle as well, so that several mux consumers can share a common
>> mux controller. My understanding of these matters are apparently not
>> deep enough...
> 
> Not necessarily, if the framework could export a function to create a
> gpio/mmio mux_chip on a given device and the gpio-mux and *-mux-gpio
> drivers just reuse that.

I've been up that creek. Why should the gpio mux be special cased?
That's not clean, the implication is that all mux consumers need
to handle the gpio case and have a special compatible for that
case etc. Then someone thinks the DT should look equally "clean" for
some i2c based mux, and the weeds start piling up. This is exactly
what we don't want. We want the mux consumer drivers to be totally
agnostic about the fact that they happen to use a gpio mux.

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 02/10] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-04-19 Thread Peter Rosin
On 2017-04-19 11:17, Philipp Zabel wrote:
> On Tue, 2017-04-18 at 15:36 +0200, Peter Rosin wrote:
>> If I got things wrong when I skimmed whatever I came across, and if the
>> mmio register is the only mux control option in the stars, it becomes
>> less obvious... It's of course still possible to hook into the mux
>> subsystem, but the benefit is questionable. And you do get the extra
>> device tree node. You could of course also implement a mux driver
>> outside of drivers/mux and thus make use of the mux api, but it's tiny
>> and any benefit is truly small.
> 
> What I wondered mostly is whether it would be a good idea to move the
> OF-graph ports into the mux controller node, and let the video capture
> device be the consumer of the mux.
> But this wouldn't fit well with the clear split between the mux
> controller and the actual mux hardware in the mux DT bindings.

I have tried to do something similar. I think. The current
drivers/i2c/muxes/i2c-mux-gpio.c is a good candidate for the same thing
IIUC.

That dedicated driver and the general purpose i2c mux driver does pretty
much the same thing with these two DT snippets:

Dedicated i2c-mux-gpio DT snippet:

i2c-mux {
compatible = "i2c-mux-gpio";
i2c-parent = <>;

mux-gpios = < 22 0  23 0>;

#address-cells = <1>;
#size-cells = <0>;

i2c@1 {
...
};

i2c@3 {
...
};
};

General purpose mux DT snippet:

mux: mux-controller {
compatible = "gpio-mux";
#mux-control-cells = <0>;

mux-gpios = < 22 0  23 0>;
};

i2c-mux {
compatible = "i2c-mux";
i2c-parent = <>;

mux-controls = <>;

#address-cells = <1>;
#size-cells = <0>;

i2c@1 {
...
};

i2c@3 {
...
};
};

I would love to find a way to cleanly get the mux framework to handle
the first DT as well, and thus being able to obsolete the dedicated
i2c-mux-gpio driver. I have not figured out how to accomplish that
without abusing the driver-model to a point that it's not working.
Help with that task is dearly appreciated.

What I have stumbled on, I think, is that two drivers needs to be
instantiated from the same DT node. At the same time, I need the
mux framework to handle the current out-of-node thing with a
phandle as well, so that several mux consumers can share a common
mux controller. My understanding of these matters are apparently not
deep enough...

I think you would like a DT that looks more like the first DT
snippet but still enjoy the flexibility of the mux framework and w/o
implementing a (another) full muxing sub-sub-system like the i2c
sub-system has done. Correct?

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-18 Thread Peter Rosin
On 2017-04-18 13:44, Greg Kroah-Hartman wrote:
> On Tue, Apr 18, 2017 at 12:59:50PM +0200, Peter Rosin wrote:
>> On 2017-04-18 10:51, Greg Kroah-Hartman wrote:
>>> On Thu, Apr 13, 2017 at 06:43:07PM +0200, Peter Rosin wrote:
>>>> +config MUX_GPIO
>>>> +  tristate "GPIO-controlled Multiplexer"
>>>> +  depends on OF && GPIOLIB
>>>
>>> Why have the gpio and mux core in the same patch?
>>
>> One is not usable w/o the other. I can split them if you want to?
> 
> Then why are they two different config options?  Add the core code in
> one patch, and then add the gpio controled mutiplexer in a separate
> patch.

Ah, I meant when there are not yet any other mux drivers. I'll just
split the patch.

>>>> +static struct class mux_class = {
>>>> +  .name = "mux",
>>>> +  .owner = THIS_MODULE,
>>>> +};
>>>
>>> No Documentation/ABI/ update for your sysfs files?  Please do so.
>>
>> Ok I'll look into it. Wasn't even aware that I added any. But there's the
>> new class of course...
> 
> Hint, you have files, the devices that belong to the class :)

Right.

>>>> +static int __init mux_init(void)
>>>> +{
>>>> +  return class_register(_class);
>>>> +}
>>>> +
>>>> +static DEFINE_IDA(mux_ida);
>>>
>>> When your module is unloaded, you forgot to clean this structure up with
>>> what was done with it.
>>
>> I was under the impression that not providing an exit function for modules
>> made the module infrastructure prevent unloading (by bumping some reference
>> counter). Maybe that is a misconception?
> 
> Ah, messy, don't do that.  Make it so you can unload your module please,
> why wouldn't you want that to happen?

What made me do it was the worry that mux drivers might be left dangling
w/o the core. But that can probably only happen if someone is very
deliberately trying to break stuff by forcing unloads??

>>>> +  mux_chip = kzalloc(sizeof(*mux_chip) +
>>>> + controllers * sizeof(*mux_chip->mux) +
>>>> + sizeof_priv, GFP_KERNEL);
>>>> +  if (!mux_chip)
>>>> +  return NULL;
>>>
>>> You don't return PTR_ERR(-ENOMEM)?  Ok, why not?  (I'm not arguing for
>>> it, just curious...)
>>
>> There's no particular reason. Do you think I should change it?
> 
> What does the caller do with an error?  Pass it up to where?  Who gets
> it?  Don't you want the caller to know you are out of memory?

The current callers return -ENOMEM when NULL is returned here. Looks
like I'm going to be doing some fairly major changes anyway so I'll
just change this too while at it...

>>>> +
>>>> +  device_initialize(_chip->dev);
>>>
>>> Why are you not registering the device here as well?  Why have this be a
>>> two step process?
>>
>> Because of idle state handling. The drivers are expected to fill in
>> the desired idle state(s) after allocating the mux controller(s).
>> Then, when registering, the desired idle state is activated (if the
>> idle state is not idle-as-is, of course) and as a last step the mux
>> is "advertised".
> 
> Ok, is that documented in the functions somewhere?

I'll make sure to add it if it's missing.

>>>> +  ret = device_add(_chip->dev);
>>>> +  if (ret < 0)
>>>> +  dev_err(_chip->dev,
>>>> +  "device_add failed in mux_chip_register: %d\n", ret);
>>>
>>> Did you run checkpatch.pl in strict mode on this new file?  Please do so :)
>>
>> I did, and did it again just to be sure, and I do not get any complaints.
>> So, what's wrong?
> 
> You list the function name in the printk string, it should complain
> that __func__ should be used.  Oh well, it's just a perl script, it
> doesn't always catch everything.
> isn't always correct :)

Ah, ok.

>>>> +EXPORT_SYMBOL_GPL(devm_mux_chip_alloc);
>>>
>>>
>>> Having devm functions that create/destroy other struct devices worries
>>> me, do we have other examples of this happening today?  Are you sure you
>>> got the reference counting all correct?
>>
>> drivers/iio/industrialio_core.c:devm_iio_device_alloc
>>
>> Or is the iio case different in some subtle way that I'm missing?
> 
> I don't know, hopefully you got it all correct, I haven't audited that
> code path in a long time :)

Looks as ok to me as it did before. Moving on... :-)

>>>> +
>

Re: [PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-18 Thread Peter Rosin
On 2017-04-18 10:51, Greg Kroah-Hartman wrote:
> On Thu, Apr 13, 2017 at 06:43:07PM +0200, Peter Rosin wrote:
>> +config MUX_GPIO
>> +tristate "GPIO-controlled Multiplexer"
>> +depends on OF && GPIOLIB
> 
> Why have the gpio and mux core in the same patch?

One is not usable w/o the other. I can split them if you want to?

> And why does this depend on OF?

That's historical, I was originally using of_property_read_u32.
I'll remove the dep...

>> +help
>> +  GPIO-controlled Multiplexer controller.
>> +
>> +  The driver builds a single multiplexer controller using a number
>> +  of gpio pins. For N pins, there will be 2^N possible multiplexer
>> +  states. The GPIO pins can be connected (by the hardware) to several
>> +  multiplexers, which in that case will be operated in parallel.
>> +
>> +  To compile the driver as a module, choose M here: the module will
>> +  be called mux-gpio.
>> +
>> +endif
>> diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
>> new file mode 100644
>> index ..bb16953f6290
>> --- /dev/null
>> +++ b/drivers/mux/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Makefile for multiplexer devices.
>> +#
>> +
>> +obj-$(CONFIG_MULTIPLEXER)   += mux-core.o
>> +obj-$(CONFIG_MUX_GPIO)  += mux-gpio.o
>> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
>> new file mode 100644
>> index 0000..66a8bccfc3d7
>> --- /dev/null
>> +++ b/drivers/mux/mux-core.c
>> @@ -0,0 +1,422 @@
>> +/*
>> + * Multiplexer subsystem
>> + *
>> + * Copyright (C) 2017 Axentia Technologies AB
>> + *
>> + * Author: Peter Rosin <p...@axentia.se>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#define pr_fmt(fmt) "mux-core: " fmt
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +/*
>> + * The idle-as-is "state" is not an actual state that may be selected, it
>> + * only implies that the state should not be changed. So, use that state
>> + * as indication that the cached state of the multiplexer is unknown.
>> + */
>> +#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
>> +
>> +static struct class mux_class = {
>> +.name = "mux",
>> +.owner = THIS_MODULE,
>> +};
> 
> No Documentation/ABI/ update for your sysfs files?  Please do so.

Ok I'll look into it. Wasn't even aware that I added any. But there's the
new class of course...

>> +
>> +static int __init mux_init(void)
>> +{
>> +return class_register(_class);
>> +}
>> +
>> +static DEFINE_IDA(mux_ida);
> 
> When your module is unloaded, you forgot to clean this structure up with
> what was done with it.

I was under the impression that not providing an exit function for modules
made the module infrastructure prevent unloading (by bumping some reference
counter). Maybe that is a misconception?

>> +
>> +static void mux_chip_release(struct device *dev)
>> +{
>> +struct mux_chip *mux_chip = to_mux_chip(dev);
>> +
>> +ida_simple_remove(_ida, mux_chip->id);
>> +kfree(mux_chip);
>> +}
>> +
>> +static struct device_type mux_type = {
>> +.name = "mux-chip",
>> +.release = mux_chip_release,
>> +};
>> +
>> +struct mux_chip *mux_chip_alloc(struct device *dev,
>> +unsigned int controllers, size_t sizeof_priv)
>> +{
>> +struct mux_chip *mux_chip;
>> +int i;
>> +
>> +if (WARN_ON(!dev || !controllers))
>> +return NULL;
>> +
>> +mux_chip = kzalloc(sizeof(*mux_chip) +
>> +   controllers * sizeof(*mux_chip->mux) +
>> +   sizeof_priv, GFP_KERNEL);
>> +if (!mux_chip)
>> +return NULL;
> 
> You don't return PTR_ERR(-ENOMEM)?  Ok, why not?  (I'm not arguing for
> it, just curious...)

There's no particular reason. Do you think I should change it?

>> +
>> +mux_chip->mux = (struct mux_control *)(mux_chip + 1);
>> +mux_chip->dev.class = _class;
>> +mux_chip->dev.type = _type;
>> +mux_chip->dev.parent = dev;
>> +mux_chip

[PATCH v13 02/10] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-04-13 Thread Peter Rosin
Allow specifying that a single multiplexer controller can be used to
control several parallel multiplexers, thus enabling sharing of the
multiplexer controller by different consumers.

Add a binding for a first mux controller in the form of a GPIO based mux
controller.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +
 .../devicetree/bindings/mux/mux-controller.txt | 157 +
 MAINTAINERS|   6 +
 include/dt-bindings/mux/mux.h  |  16 +++
 4 files changed, 248 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 include/dt-bindings/mux/mux.h

diff --git a/Documentation/devicetree/bindings/mux/gpio-mux.txt 
b/Documentation/devicetree/bindings/mux/gpio-mux.txt
new file mode 100644
index ..b8f746344d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/gpio-mux.txt
@@ -0,0 +1,69 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "gpio-mux"
+- mux-gpios : list of gpios used to control the multiplexer, least
+ significant bit first.
+- #mux-control-cells : <0>
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-state : if present, the state the mux will have when idle. The
+  special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state is defined as the number represented by the
+multiplexer GPIO pins, where the first pin is the least significant
+bit. An active pin is a binary 1, an inactive pin is a binary 0.
+
+Example:
+
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "in", "out", "sync-2";
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   /* ... */
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   /* ... */
+   };
+   };
+   };
diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt 
b/Documentation/devicetree/bindings/mux/mux-controller.txt
new file mode 100644
index ..4f47e4bd2fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
@@ -0,0 +1,157 @@
+Common multiplexer controller bindings
+==
+
+A multiplexer (or mux) controller will have one, or several, consumer devices
+that uses the mux controller. Thus, a mux controller can possibly control
+several parallel multiplexers. Presumably there will be at least one
+multiplexer needed by each consumer, but a single mux controller can of course
+control several multiplexers for a single consumer.
+
+A mux controller provides a number of states to its consumers, and the state
+space is a simple zero-based enumeration. I.e. 0-1 for a 2-way multiplexer,
+0-7 for an 8-way multiplexer, etc.
+
+
+Consumers
+-
+
+Mux controller consumers should specify a list of mux controllers that they
+want to use with a property containing a 'mux-ctrl-list':
+
+   mux-ctrl-list ::=  [mux-ctrl-list]
+   single-mux-ctrl ::=  [mux-ctrl-specifier]
+   mux-ctrl-phandle : phandle to mux controller node
+   mux-ctrl-specifier : array of #mux-control-cells specifying the
+given mux controller (controller specific)
+
+Mux controller properties should be named "mux-controls". The exact meaning of
+each mux controller property must be documented in the device tree bind

[PATCH v13 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-04-13 Thread Peter Rosin
Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

This new mux controller subsystem initially comes with a single backend
driver that controls gpio based multiplexers. Even though not needed by
this initial driver, the mux controller subsystem is prepared to handle
chips with multiple (independent) mux controllers.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt |   8 +
 MAINTAINERS   |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  34 +++
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-core.c| 422 ++
 drivers/mux/mux-gpio.c| 114 +
 include/linux/mux.h   | 252 
 9 files changed, 841 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/linux/mux.h

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index efb8200819d6..e2343d9cbec7 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,14 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_free()
+  devm_mux_chip_register()
+  devm_mux_chip_unregister()
+  devm_mux_control_get()
+  devm_mux_control_put()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fc06739c8ad..591eba737678 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8563,6 +8563,8 @@ M:    Peter Rosin <p...@axentia.se>
 S: Maintained
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux.h
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 117ca14ccf85..a7ea13e1b869 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2eced9afba53..c0436f6dd5a9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -177,3 +177,4 @@ obj-$(CONFIG_ANDROID)   += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..41dfe08ead84
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,34 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.
+
+ To compile the subsystem as a module, choose M here: the module will
+ be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on OF && GPIOLIB
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index ..bb16953f6290
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for multiplexer devices.
+#
+
+obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
new fil

[PATCH v13 08/10] i2c: i2c-mux-gpmux: new driver

2017-04-13 Thread Peter Rosin
This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 10b3d17ae3ea..5fb34f24 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 9948fa45037f..af43c6c3e861 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..fb23b2278462
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+   return PTR_ERR(mux->control);
+   }
+
+   

[PATCH v13 06/10] iio: multiplexer: new iio category and iio-mux driver

2017-04-13 Thread Peter Rosin
When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 459 ++
 6 files changed, 486 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4af912305d2c..23cfd5bc2158 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6365,6 +6365,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..70a044510686
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..bab9e6902090
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,459 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   ssize_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   const char *attr = chan->ext_info[i].name;
+   

[PATCH v13 10/10] mux: adg792a: add mux controller driver for ADG792A/G

2017-04-13 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 141 ++
 3 files changed, 154 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 41dfe08ead84..86668b4d2fc5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on OF && GPIOLIB
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..58c0ecf49a4a
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,141 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESETB BIT(1) /* active low, reset when zero */
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return i2c_smbus_write_byte_data(i2c, cmd,
+ADG792A_RESETB | ADG792A_LDSW);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   u32 cells;
+   int ret;
+   int i;
+
+   ret = of_property_read_u32(dev->of_node, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (!mux_chip)
+   return -ENOMEM;
+
+   mux_chip->ops = _ops;
+
+   ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL,
+   ADG792A_LDSW);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux = _chip->mux[i];
+   s32 idle_state;
+
+   mux->states = 4;
+
+   ret = of_property_read_u32_index(dev->of_node, "idle-state", i,
+(s32 *)_state);
+   if (ret < 0)
+   continue;
+
+   switch (idle_state) {
+   case 0 ... 4:
+   case MUX_IDLE_DISCONNECT:
+   mux_chip->mux[i].idle_state = idle_state;
+   break;
+   case MUX_IDLE_AS_IS:
+   break;
+   default:
+   dev_err(dev, "invalid idle-state %d\n", idle_state);
+   return -EINVAL;
+   }

[PATCH v13 05/10] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-04-13 Thread Peter Rosin
Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 591eba737678..4af912305d2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6360,6 +6360,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v13 09/10] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-04-13 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v13 07/10] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-04-13 Thread Peter Rosin
Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v13 01/10] devres: trivial whitespace fix

2017-04-13 Thread Peter Rosin
Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index bf34d5b3a733..efb8200819d6 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v13 00/10] mux controller abstraction and iio/i2c muxes

2017-04-13 Thread Peter Rosin
NFIG_MUX_GPIO depend on CONFIG_GPIOLIB.
- keep track of the number of mux states in the mux core.
- since the iio channel number is used as mux state, it was possible
  to drop the state member from the mux_child struct.
- cleanup dt bindings for i2c-mux-simple, it had some of copy-paste
  problems from ots origin (i2c-mux-gpio).
- select the mux control subsystem in config for the i2c-mux-simple driver.
- add entries to MAINTAINERS and my sign-off, I'm now satisfied and know
  nothing in this to be ashamed of.

v1 -> v2 changes
- fixup export of mux_control_put reported by kbuild
- drop devicetree iio-ext-info property as noted by Lars-Peter,
  and replace the functionality by exposing all ext_info
  attributes of the parent channel for each of the muxed
  channels. A cache on top of that and each muxed channel
  gets its own view of the ext_info of the parent channel.
- implement idle-state for muxes
- clear out the cache on failure in order to force a mux
  update on the following use
- cleanup the probe of i2c-mux-simple driver
- fix a bug in the i2c-mux-simple driver, where failure in
  the selection of the mux caused a deadlock when the mux
  was later unconditionally deselected.


Old background:

I have a piece of hardware that is using the same 3 GPIO pins
to control four 8-way muxes. Three of them control ADC lines
to an ADS1015 chip with an iio driver, and the last one
controls the SDA line of an i2c bus. We have some deployed
code to handle this, but you do not want to see it or ever
hear about it. I'm not sure why I even mention it. Anyway,
the situation has nagged me to no end for quite some time.

So, after first getting more intimate with the i2c muxing code
and later discovering the drivers/iio/inkern.c file and
writing a couple of drivers making use of it, I came up with
what I think is an acceptable solution; add a generic mux
controller driver (and subsystem) that is shared between all
instances, and combine that with an iio mux driver and a new
general purpose i2c mux driver that is only hooking the i2c
muxing and the new mux controller.

One thing that I would like to do, but don't see a solution
for, is to move the mux control code that is present in
various drivers in drivers/i2c/muxes to this new minimalistic
muxing subsystem, thus converting all present i2c muxes (but
perhaps not gates and arbitrators).

I'm using an rwsem to lock a mux, but that isn't really a
perfect fit. Is there a better locking primitive that I don't
know about that fits better? I had a mutex at one point, but
that didn't allow any concurrent accesses at all. At least
the rwsem allows concurrent access as long as all users
agree on the mux state, but I suspect that the rwsem will
degrade to the mutex situation pretty quickly if there is
any contention.

Also, the "mux" name feels a bit ambitious, there are many muxes
in the world, and this tiny bit of code is probably not good
enough to be a nice fit for all...

Cheers,
peda

Peter Rosin (10):
  devres: trivial whitespace fix
  dt-bindings: document devicetree bindings for mux-controllers and
gpio-mux
  mux: minimal mux subsystem and gpio-based mux controller
  iio: inkern: api for manipulating ext_info of iio channels
  dt-bindings: iio: io-channel-mux: document io-channel-mux bindings
  iio: multiplexer: new iio category and iio-mux driver
  dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings
  i2c: i2c-mux-gpmux: new driver
  dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G
mux
  mux: adg792a: add mux controller driver for ADG792A/G

 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  |  99 +
 .../bindings/iio/multiplexer/io-channel-mux.txt|  39 ++
 .../devicetree/bindings/mux/adi,adg792a.txt|  75 
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 
 .../devicetree/bindings/mux/mux-controller.txt | 157 +++
 Documentation/driver-model/devres.txt  |  10 +-
 MAINTAINERS|  15 +
 drivers/Kconfig|   2 +
 drivers/Makefile   |   1 +
 drivers/i2c/muxes/Kconfig  |  13 +
 drivers/i2c/muxes/Makefile |   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c  | 173 
 drivers/iio/Kconfig|   1 +
 drivers/iio/Makefile   |   1 +
 drivers/iio/inkern.c   |  60 +++
 drivers/iio/multiplexer/Kconfig|  18 +
 drivers/iio/multiplexer/Makefile   |   6 +
 drivers/iio/multiplexer/iio-mux.c  | 459 +
 drivers/mux/Kconfig|  46 +++
 drivers/mux/Makefile   |   7 +
 drivers/mux/mux-adg792a.c  | 141 +++
 drivers/mux/mux-core.c | 422 ++

Re: [PATCH v12 00/10] mux controller abstraction and iio/i2c muxes

2017-03-30 Thread Peter Rosin
On 2017-03-27 16:21, Peter Rosin wrote:
> Hi Greg!
> 
> Please apply.
>

*snip snip*

> v10 -> v11 changes
> - added a new patch (12) with a fix for messed up error path reported
>   by Paul Gortmaker.

Oops, should be Dan Carpenter. Sorry about that...

And, I forgot to high-light this:

> v4 -> v5 changes
> - driver for Analog Devices ADG792A/G, literally the first mux chip
>   I found on the Internet with an i2c interface (that was not a
>   dedicated i2c multiplexer like PCA9547) which I used to verify
>   that the abstractions in the mux core are up to the task. Untested,
>   just proof of concept that at least looks pretty and compiles...

Maybe the patches related to adg792 (last two patches in v12) should
not be applied? I don't care much either way, your call Greg...

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 06/10] iio: multiplexer: new iio category and iio-mux driver

2017-03-27 Thread Peter Rosin
When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 459 ++
 6 files changed, 486 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4af912305d2c..23cfd5bc2158 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6365,6 +6365,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..70a044510686
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..bab9e6902090
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,459 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   ssize_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   const char *attr = chan->ext_info[i].name;
+   

[PATCH v12 01/10] devres: trivial whitespace fix

2017-03-27 Thread Peter Rosin
Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index bf34d5b3a733..efb8200819d6 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 02/10] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-03-27 Thread Peter Rosin
Allow specifying that a single multiplexer controller can be used to
control several parallel multiplexers, thus enabling sharing of the
multiplexer controller by different consumers.

Add a binding for a first mux controller in the form of a GPIO based mux
controller.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +
 .../devicetree/bindings/mux/mux-controller.txt | 157 +
 MAINTAINERS|   6 +
 include/dt-bindings/mux/mux.h  |  16 +++
 4 files changed, 248 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 include/dt-bindings/mux/mux.h

diff --git a/Documentation/devicetree/bindings/mux/gpio-mux.txt 
b/Documentation/devicetree/bindings/mux/gpio-mux.txt
new file mode 100644
index ..b8f746344d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/gpio-mux.txt
@@ -0,0 +1,69 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "gpio-mux"
+- mux-gpios : list of gpios used to control the multiplexer, least
+ significant bit first.
+- #mux-control-cells : <0>
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-state : if present, the state the mux will have when idle. The
+  special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state is defined as the number represented by the
+multiplexer GPIO pins, where the first pin is the least significant
+bit. An active pin is a binary 1, an inactive pin is a binary 0.
+
+Example:
+
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "in", "out", "sync-2";
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   /* ... */
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   /* ... */
+   };
+   };
+   };
diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt 
b/Documentation/devicetree/bindings/mux/mux-controller.txt
new file mode 100644
index ..4f47e4bd2fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
@@ -0,0 +1,157 @@
+Common multiplexer controller bindings
+==
+
+A multiplexer (or mux) controller will have one, or several, consumer devices
+that uses the mux controller. Thus, a mux controller can possibly control
+several parallel multiplexers. Presumably there will be at least one
+multiplexer needed by each consumer, but a single mux controller can of course
+control several multiplexers for a single consumer.
+
+A mux controller provides a number of states to its consumers, and the state
+space is a simple zero-based enumeration. I.e. 0-1 for a 2-way multiplexer,
+0-7 for an 8-way multiplexer, etc.
+
+
+Consumers
+-
+
+Mux controller consumers should specify a list of mux controllers that they
+want to use with a property containing a 'mux-ctrl-list':
+
+   mux-ctrl-list ::=  [mux-ctrl-list]
+   single-mux-ctrl ::=  [mux-ctrl-specifier]
+   mux-ctrl-phandle : phandle to mux controller node
+   mux-ctrl-specifier : array of #mux-control-cells specifying the
+given mux controller (controller specific)
+
+Mux controller properties should be named "mux-controls". The exact meaning of
+each mux controller property must be documented in the device tree bind

[PATCH v12 03/10] mux: minimal mux subsystem and gpio-based mux controller

2017-03-27 Thread Peter Rosin
Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

This new mux controller subsystem initially comes with a single backend
driver that controls gpio based multiplexers. Even though not needed by
this initial driver, the mux controller subsystem is prepared to handle
chips with multiple (independent) mux controllers.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt |   8 +
 MAINTAINERS   |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  34 +++
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-core.c| 422 ++
 drivers/mux/mux-gpio.c| 114 +
 include/linux/mux.h   | 252 
 9 files changed, 841 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/linux/mux.h

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index efb8200819d6..e2343d9cbec7 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,14 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_free()
+  devm_mux_chip_register()
+  devm_mux_chip_unregister()
+  devm_mux_control_get()
+  devm_mux_control_put()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fc06739c8ad..591eba737678 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8563,6 +8563,8 @@ M:    Peter Rosin <p...@axentia.se>
 S: Maintained
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux.h
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 117ca14ccf85..a7ea13e1b869 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2eced9afba53..c0436f6dd5a9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -177,3 +177,4 @@ obj-$(CONFIG_ANDROID)   += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..41dfe08ead84
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,34 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.
+
+ To compile the subsystem as a module, choose M here: the module will
+ be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on OF && GPIOLIB
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index ..bb16953f6290
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for multiplexer devices.
+#
+
+obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
new fil

[PATCH v12 04/10] iio: inkern: api for manipulating ext_info of iio channels

2017-03-27 Thread Peter Rosin
Extend the inkern api with functions for reading and writing ext_info
of iio channels.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/inkern.c | 60 
 include/linux/iio/consumer.h | 37 +++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..8292ad4435ea 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -869,3 +869,63 @@ int iio_write_channel_raw(struct iio_channel *chan, int 
val)
return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+   unsigned int i = 0;
+
+   if (!chan->channel->ext_info)
+   return i;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
+   ++i;
+
+   return i;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+
+static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
+   const struct iio_channel *chan,
+   const char *attr)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   if (!chan->channel->ext_info)
+   return NULL;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+   if (!strcmp(attr, ext_info->name))
+   return ext_info;
+   }
+
+   return NULL;
+}
+
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->read(chan->indio_dev, ext_info->private,
+ chan->channel, buf);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->write(chan->indio_dev, ext_info->private,
+  chan->channel, buf, len);
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 47eeec3218b5..5e347a9805fd 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -312,4 +312,41 @@ int iio_read_channel_scale(struct iio_channel *chan, int 
*val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);
 
+/**
+ * iio_get_channel_ext_info_count() - get number of ext_info attributes
+ *   connected to the channel.
+ * @chan:  The channel being queried
+ *
+ * Returns the number of ext_info attributes
+ */
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
+
+/**
+ * iio_read_channel_ext_info() - read ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   Where to store the attribute value. Assumed to hold
+ * at least PAGE_SIZE bytes.
+ *
+ * Returns the number of bytes written to buf (perhaps w/o zero termination;
+ * it need not even be a string), or an error code.
+ */
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf);
+
+/**
+ * iio_write_channel_ext_info() - write ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   The new attribute value. Strings needs to be zero-
+ * terminated, but the terminator should not be included
+ * in the below len.
+ * @len:   The size of the new attribute value.
+ *
+ * Returns the number of accepted bytes, which should be the same as len.
+ * An error code can also be returned.
+ */
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len);
+
 #endif
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 07/10] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-03-27 Thread Peter Rosin
Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 05/10] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-03-27 Thread Peter Rosin
Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 591eba737678..4af912305d2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6360,6 +6360,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 10/10] mux: adg792a: add mux controller driver for ADG792A/G

2017-03-27 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 140 ++
 3 files changed, 153 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 41dfe08ead84..86668b4d2fc5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on OF && GPIOLIB
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..4820f82e849c
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,140 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESET  BIT(1)
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return i2c_smbus_write_byte_data(i2c, cmd, ADG792A_LDSW);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   u32 cells;
+   int ret;
+   int i;
+
+   ret = of_property_read_u32(dev->of_node, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (!mux_chip)
+   return -ENOMEM;
+
+   mux_chip->ops = _ops;
+
+   ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL,
+   ADG792A_RESET | ADG792A_LDSW);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux = _chip->mux[i];
+   s32 idle_state;
+
+   mux->states = 4;
+
+   ret = of_property_read_u32_index(dev->of_node, "idle-state", i,
+(s32 *)_state);
+   if (ret < 0)
+   continue;
+
+   switch (idle_state) {
+   case 0 ... 4:
+   case MUX_IDLE_DISCONNECT:
+   mux_chip->mux[i].idle_state = idle_state;
+   break;
+   case MUX_IDLE_AS_IS:
+   break;
+   default:
+   dev_err(dev, "invalid idle-state %d\n", idle_state);
+   return -EINVAL;
+   }
+   }
+
+   ret = devm_mux_chip_register(dev, mux_chip);
+   if (ret &l

[PATCH v12 08/10] i2c: i2c-mux-gpmux: new driver

2017-03-27 Thread Peter Rosin
This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 10b3d17ae3ea..5fb34f24 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 9948fa45037f..af43c6c3e861 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..fb23b2278462
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+   return PTR_ERR(mux->control);
+   }
+
+   

[PATCH v12 09/10] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-03-27 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 00/10] mux controller abstraction and iio/i2c muxes

2017-03-27 Thread Peter Rosin
p
  I found on the Internet with an i2c interface (that was not a
  dedicated i2c multiplexer like PCA9547) which I used to verify
  that the abstractions in the mux core are up to the task. Untested,
  just proof of concept that at least looks pretty and compiles...
- various touch-ups.

v3 -> v4 changes
- rebased onto next-20161122 (depends on recent _available iio changes).
- added support for having the mux-controller in a child node of a
  mux-consumer if it is a sole consumer, to hopefully even further satisfy
  the complaint from Rob (and later Lars-Peter) about dt complexity.
- the above came at the cost of some rather horrible refcounting code,
  please review and suggest how it should be done...
- changed to register a device class instead of a bus.
- pass in the parent device into mux_control_alloc and require less
  work from mux-control drivers.
- changed device names from mux:control%d to mux%d
- move kernel-doc from mux-core.c to mux.h (and add some bits).
- give the gpio driver a chance to update all mux pins at once.
- factor out iio ext_info lookup into new helper function. /Lars-Peter
- use an unsigned type for the iio ext_info count. /Lars-Peter
- unified "brag strings" in the file headers.

v2 -> v3 changes
- have the mux-controller in the parent node of any mux-controller consumer,
  to hopefully satisfy complaint from Rob about dt complexity.
- improve commit message of the mux subsystem commit, making it more
  general, as requested by Jonathan.
- remove priv member from struct mux_control and calculate it on the
  fly. /Jonathan
- make the function comments in mux-core.c kernel doc. /Jonathan
- add devm_mux_control_* to Documentation/driver.model/devres.txt. /Jonathan
- add common dt bindings for mux-controllers, refer to them from the
  mux-gpio bindings. /Rob
- clarify how the gpio pins map to the mux state. /Rob
- separate CONFIG_ variables for the mux core and the mux gpio driver.
- improve Kconfig help texts.
- make CONFIG_MUX_GPIO depend on CONFIG_GPIOLIB.
- keep track of the number of mux states in the mux core.
- since the iio channel number is used as mux state, it was possible
  to drop the state member from the mux_child struct.
- cleanup dt bindings for i2c-mux-simple, it had some of copy-paste
  problems from ots origin (i2c-mux-gpio).
- select the mux control subsystem in config for the i2c-mux-simple driver.
- add entries to MAINTAINERS and my sign-off, I'm now satisfied and know
  nothing in this to be ashamed of.

v1 -> v2 changes
- fixup export of mux_control_put reported by kbuild
- drop devicetree iio-ext-info property as noted by Lars-Peter,
  and replace the functionality by exposing all ext_info
  attributes of the parent channel for each of the muxed
  channels. A cache on top of that and each muxed channel
  gets its own view of the ext_info of the parent channel.
- implement idle-state for muxes
- clear out the cache on failure in order to force a mux
  update on the following use
- cleanup the probe of i2c-mux-simple driver
- fix a bug in the i2c-mux-simple driver, where failure in
  the selection of the mux caused a deadlock when the mux
  was later unconditionally deselected.

I have a piece of hardware that is using the same 3 GPIO pins
to control four 8-way muxes. Three of them control ADC lines
to an ADS1015 chip with an iio driver, and the last one
controls the SDA line of an i2c bus. We have some deployed
code to handle this, but you do not want to see it or ever
hear about it. I'm not sure why I even mention it. Anyway,
the situation has nagged me to no end for quite some time.

So, after first getting more intimate with the i2c muxing code
and later discovering the drivers/iio/inkern.c file and
writing a couple of drivers making use of it, I came up with
what I think is an acceptable solution; add a generic mux
controller driver (and subsystem) that is shared between all
instances, and combine that with an iio mux driver and a new
general purpose i2c mux driver that is only hooking the i2c
muxing and the new mux controller.

One thing that I would like to do, but don't see a solution
for, is to move the mux control code that is present in
various drivers in drivers/i2c/muxes to this new minimalistic
muxing subsystem, thus converting all present i2c muxes (but
perhaps not gates and arbitrators).

I'm using an rwsem to lock a mux, but that isn't really a
perfect fit. Is there a better locking primitive that I don't
know about that fits better? I had a mutex at one point, but
that didn't allow any concurrent accesses at all. At least
the rwsem allows concurrent access as long as all users
agree on the mux state, but I suspect that the rwsem will
degrade to the mutex situation pretty quickly if there is
any contention.

Also, the "mux" name feels a bit ambitious, there are many muxes
in the world, and this tiny bit of code is probably not good
enough to be a nice fit for all...

Cheers,
peda

Peter Rosin (10):
  devres: t

Re: [PATCH v11 11/12] iio: multiplexer: fix unsigned check with less than zero

2017-03-27 Thread Peter Rosin
On 2017-03-27 15:06, Johan Hovold wrote:
> On Mon, Mar 27, 2017 at 02:17:48PM +0200, Peter Rosin wrote:
>> Comparing a size_t with less than zero is always false as size_t
>> is unsigned. So, change the type of the variable to ssize_t and
>> replicate the size check from mux_configure_channel() into
>> mux_write_ext_info() thus ensuring that the size will fit in the
>> ssize_t variable.
>>
>> Detected by CoverityScan, CID#1415278 ("Unsigned compared against 0")
>>
>> Fixes: 1da8e16d2812 ("iio: multiplexer: new iio category and iio-mux driver")
> 
> You should fold this one and the next patch into the patches that they
> fix up instead fixing stuff that's not yet merged incrementally like you
> do here (specifically, the SHA id above will have no matching commit).
> 
> Johan

I forgot about that. And similar for the next patch. But how do you
propose that I attribute the reporters and CoverityScan? Crap, it
would have been so much easier if the series was just pulled they
way I expected it...

Greg, how do you want to play this? Can you perhaps update the fixes
tag here and in 12/12 if/when you apply the series?

Cheers,
peda

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 08/12] i2c: i2c-mux-gpmux: new driver

2017-03-27 Thread Peter Rosin
This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 10b3d17ae3ea..5fb34f24 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 9948fa45037f..af43c6c3e861 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..fb23b2278462
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+   return PTR_ERR(mux->control);
+   }
+
+   

[PATCH v11 12/12] mux: core: fix error handling in devm_mux_chip_alloc

2017-03-27 Thread Peter Rosin
The error handling is mixed up. mux_chip_alloc() doesn't return an error
pointer (just NULL on failure), so check for NULL instead of using IS_ERR.
devm_mux_chip_alloc is documented to return NULL on failure, so fix that
as well.

All users of devm_mux_chip_alloc() are coded according to documentation.

Fixes: d47598cc669b ("mux: minimal mux subsystem and gpio-based mux controller")
Reported-by: Dan Carpenter <dan.carpen...@oracle.com>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/mux-core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
index 900b88526f97..66a8bccfc3d7 100644
--- a/drivers/mux/mux-core.c
+++ b/drivers/mux/mux-core.c
@@ -166,12 +166,12 @@ struct mux_chip *devm_mux_chip_alloc(struct device *dev,
 
ptr = devres_alloc(devm_mux_chip_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
-   return ERR_PTR(-ENOMEM);
+   return NULL;
 
mux_chip = mux_chip_alloc(dev, controllers, sizeof_priv);
-   if (IS_ERR(mux_chip)) {
+   if (!mux_chip) {
devres_free(ptr);
-   return mux_chip;
+   return NULL;
}
 
*ptr = mux_chip;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 04/12] iio: inkern: api for manipulating ext_info of iio channels

2017-03-27 Thread Peter Rosin
Extend the inkern api with functions for reading and writing ext_info
of iio channels.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/inkern.c | 60 
 include/linux/iio/consumer.h | 37 +++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..8292ad4435ea 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -869,3 +869,63 @@ int iio_write_channel_raw(struct iio_channel *chan, int 
val)
return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+   unsigned int i = 0;
+
+   if (!chan->channel->ext_info)
+   return i;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
+   ++i;
+
+   return i;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+
+static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
+   const struct iio_channel *chan,
+   const char *attr)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   if (!chan->channel->ext_info)
+   return NULL;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+   if (!strcmp(attr, ext_info->name))
+   return ext_info;
+   }
+
+   return NULL;
+}
+
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->read(chan->indio_dev, ext_info->private,
+ chan->channel, buf);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->write(chan->indio_dev, ext_info->private,
+  chan->channel, buf, len);
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 47eeec3218b5..5e347a9805fd 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -312,4 +312,41 @@ int iio_read_channel_scale(struct iio_channel *chan, int 
*val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);
 
+/**
+ * iio_get_channel_ext_info_count() - get number of ext_info attributes
+ *   connected to the channel.
+ * @chan:  The channel being queried
+ *
+ * Returns the number of ext_info attributes
+ */
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
+
+/**
+ * iio_read_channel_ext_info() - read ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   Where to store the attribute value. Assumed to hold
+ * at least PAGE_SIZE bytes.
+ *
+ * Returns the number of bytes written to buf (perhaps w/o zero termination;
+ * it need not even be a string), or an error code.
+ */
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf);
+
+/**
+ * iio_write_channel_ext_info() - write ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   The new attribute value. Strings needs to be zero-
+ * terminated, but the terminator should not be included
+ * in the below len.
+ * @len:   The size of the new attribute value.
+ *
+ * Returns the number of accepted bytes, which should be the same as len.
+ * An error code can also be returned.
+ */
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len);
+
 #endif
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 10/12] mux: adg792a: add mux controller driver for ADG792A/G

2017-03-27 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 140 ++
 3 files changed, 153 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 41dfe08ead84..86668b4d2fc5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on OF && GPIOLIB
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..4820f82e849c
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,140 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESET  BIT(1)
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return i2c_smbus_write_byte_data(i2c, cmd, ADG792A_LDSW);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   u32 cells;
+   int ret;
+   int i;
+
+   ret = of_property_read_u32(dev->of_node, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (!mux_chip)
+   return -ENOMEM;
+
+   mux_chip->ops = _ops;
+
+   ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL,
+   ADG792A_RESET | ADG792A_LDSW);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux = _chip->mux[i];
+   s32 idle_state;
+
+   mux->states = 4;
+
+   ret = of_property_read_u32_index(dev->of_node, "idle-state", i,
+(s32 *)_state);
+   if (ret < 0)
+   continue;
+
+   switch (idle_state) {
+   case 0 ... 4:
+   case MUX_IDLE_DISCONNECT:
+   mux_chip->mux[i].idle_state = idle_state;
+   break;
+   case MUX_IDLE_AS_IS:
+   break;
+   default:
+   dev_err(dev, "invalid idle-state %d\n", idle_state);
+   return -EINVAL;
+   }
+   }
+
+   ret = devm_mux_chip_register(dev, mux_chip);
+   if (ret &l

[PATCH v11 11/12] iio: multiplexer: fix unsigned check with less than zero

2017-03-27 Thread Peter Rosin
Comparing a size_t with less than zero is always false as size_t
is unsigned. So, change the type of the variable to ssize_t and
replicate the size check from mux_configure_channel() into
mux_write_ext_info() thus ensuring that the size will fit in the
ssize_t variable.

Detected by CoverityScan, CID#1415278 ("Unsigned compared against 0")

Fixes: 1da8e16d2812 ("iio: multiplexer: new iio category and iio-mux driver")
Reported-by: Colin Ian King <colin.k...@canonical.com>
Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/multiplexer/iio-mux.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
index 94d40f9bef4c..bab9e6902090 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -21,7 +21,7 @@
 
 struct mux_ext_info_cache {
char *data;
-   size_t size;
+   ssize_t size;
 };
 
 struct mux_child {
@@ -206,6 +206,9 @@ static ssize_t mux_write_ext_info(struct iio_dev 
*indio_dev, uintptr_t private,
char *new;
ssize_t ret;
 
+   if (len >= PAGE_SIZE)
+   return -EINVAL;
+
ret = iio_mux_select(mux, idx);
if (ret < 0)
return ret;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 09/12] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-03-27 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 05/12] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-03-27 Thread Peter Rosin
Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 591eba737678..4af912305d2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6360,6 +6360,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 02/12] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-03-27 Thread Peter Rosin
Allow specifying that a single multiplexer controller can be used to
control several parallel multiplexers, thus enabling sharing of the
multiplexer controller by different consumers.

Add a binding for a first mux controller in the form of a GPIO based mux
controller.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +
 .../devicetree/bindings/mux/mux-controller.txt | 157 +
 MAINTAINERS|   6 +
 include/dt-bindings/mux/mux.h  |  16 +++
 4 files changed, 248 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 include/dt-bindings/mux/mux.h

diff --git a/Documentation/devicetree/bindings/mux/gpio-mux.txt 
b/Documentation/devicetree/bindings/mux/gpio-mux.txt
new file mode 100644
index ..b8f746344d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/gpio-mux.txt
@@ -0,0 +1,69 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "gpio-mux"
+- mux-gpios : list of gpios used to control the multiplexer, least
+ significant bit first.
+- #mux-control-cells : <0>
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-state : if present, the state the mux will have when idle. The
+  special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state is defined as the number represented by the
+multiplexer GPIO pins, where the first pin is the least significant
+bit. An active pin is a binary 1, an inactive pin is a binary 0.
+
+Example:
+
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "in", "out", "sync-2";
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   /* ... */
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   /* ... */
+   };
+   };
+   };
diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt 
b/Documentation/devicetree/bindings/mux/mux-controller.txt
new file mode 100644
index ..4f47e4bd2fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
@@ -0,0 +1,157 @@
+Common multiplexer controller bindings
+==
+
+A multiplexer (or mux) controller will have one, or several, consumer devices
+that uses the mux controller. Thus, a mux controller can possibly control
+several parallel multiplexers. Presumably there will be at least one
+multiplexer needed by each consumer, but a single mux controller can of course
+control several multiplexers for a single consumer.
+
+A mux controller provides a number of states to its consumers, and the state
+space is a simple zero-based enumeration. I.e. 0-1 for a 2-way multiplexer,
+0-7 for an 8-way multiplexer, etc.
+
+
+Consumers
+-
+
+Mux controller consumers should specify a list of mux controllers that they
+want to use with a property containing a 'mux-ctrl-list':
+
+   mux-ctrl-list ::=  [mux-ctrl-list]
+   single-mux-ctrl ::=  [mux-ctrl-specifier]
+   mux-ctrl-phandle : phandle to mux controller node
+   mux-ctrl-specifier : array of #mux-control-cells specifying the
+given mux controller (controller specific)
+
+Mux controller properties should be named "mux-controls". The exact meaning of
+each mux controller property must be documented in the device tree bind

[PATCH v11 06/12] iio: multiplexer: new iio category and iio-mux driver

2017-03-27 Thread Peter Rosin
When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 456 ++
 6 files changed, 483 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4af912305d2c..23cfd5bc2158 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6365,6 +6365,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..70a044510686
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..94d40f9bef4c
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,456 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   size_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   const char *attr = chan->ext_info[i].name;
+   

[PATCH v11 07/12] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-03-27 Thread Peter Rosin
Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 03/12] mux: minimal mux subsystem and gpio-based mux controller

2017-03-27 Thread Peter Rosin
Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

This new mux controller subsystem initially comes with a single backend
driver that controls gpio based multiplexers. Even though not needed by
this initial driver, the mux controller subsystem is prepared to handle
chips with multiple (independent) mux controllers.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt |   8 +
 MAINTAINERS   |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  34 +++
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-core.c| 422 ++
 drivers/mux/mux-gpio.c| 114 +
 include/linux/mux.h   | 252 
 9 files changed, 841 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/linux/mux.h

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index efb8200819d6..e2343d9cbec7 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,14 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_free()
+  devm_mux_chip_register()
+  devm_mux_chip_unregister()
+  devm_mux_control_get()
+  devm_mux_control_put()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fc06739c8ad..591eba737678 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8563,6 +8563,8 @@ M:    Peter Rosin <p...@axentia.se>
 S: Maintained
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux.h
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 117ca14ccf85..a7ea13e1b869 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2eced9afba53..c0436f6dd5a9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -177,3 +177,4 @@ obj-$(CONFIG_ANDROID)   += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..41dfe08ead84
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,34 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.
+
+ To compile the subsystem as a module, choose M here: the module will
+ be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on OF && GPIOLIB
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index ..bb16953f6290
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for multiplexer devices.
+#
+
+obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
new fil

[PATCH v11 01/12] devres: trivial whitespace fix

2017-03-27 Thread Peter Rosin
Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index bf34d5b3a733..efb8200819d6 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v11 00/12] mux controller abstraction and iio/i2c muxes

2017-03-27 Thread Peter Rosin
n pretty quickly if there is
any contention.

Also, the "mux" name feels a bit ambitious, there are many muxes
in the world, and this tiny bit of code is probably not good
enough to be a nice fit for all...

Cheers,
peda

Peter Rosin (12):
  devres: trivial whitespace fix
  dt-bindings: document devicetree bindings for mux-controllers and
gpio-mux
  mux: minimal mux subsystem and gpio-based mux controller
  iio: inkern: api for manipulating ext_info of iio channels
  dt-bindings: iio: io-channel-mux: document io-channel-mux bindings
  iio: multiplexer: new iio category and iio-mux driver
  dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings
  i2c: i2c-mux-gpmux: new driver
  dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G
mux
  mux: adg792a: add mux controller driver for ADG792A/G
  iio: multiplexer: fix unsigned check with less than zero
  mux: core: fix error handling in devm_mux_chip_alloc

 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  |  99 +
 .../bindings/iio/multiplexer/io-channel-mux.txt|  39 ++
 .../devicetree/bindings/mux/adi,adg792a.txt|  75 
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 
 .../devicetree/bindings/mux/mux-controller.txt | 157 +++
 Documentation/driver-model/devres.txt  |  10 +-
 MAINTAINERS|  15 +
 drivers/Kconfig|   2 +
 drivers/Makefile   |   1 +
 drivers/i2c/muxes/Kconfig  |  13 +
 drivers/i2c/muxes/Makefile |   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c  | 173 
 drivers/iio/Kconfig|   1 +
 drivers/iio/Makefile   |   1 +
 drivers/iio/inkern.c   |  60 +++
 drivers/iio/multiplexer/Kconfig|  18 +
 drivers/iio/multiplexer/Makefile   |   6 +
 drivers/iio/multiplexer/iio-mux.c  | 459 +
 drivers/mux/Kconfig|  46 +++
 drivers/mux/Makefile   |   7 +
 drivers/mux/mux-adg792a.c  | 140 +++
 drivers/mux/mux-core.c | 422 +++
 drivers/mux/mux-gpio.c | 114 +
 include/dt-bindings/mux/mux.h  |  16 +
 include/linux/iio/consumer.h   |  37 ++
 include/linux/mux.h| 252 +++
 26 files changed, 2232 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-adg792a.c
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/linux/mux.h

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v10 03/11] mux: minimal mux subsystem and gpio-based mux controller

2017-03-15 Thread Peter Rosin
On 2017-03-10 12:09, Peter Rosin wrote:
> Add a new minimalistic subsystem that handles multiplexer controllers.
> When multiplexers are used in various places in the kernel, and the
> same multiplexer controller can be used for several independent things,
> there should be one place to implement support for said multiplexer
> controller.
> 
> A single multiplexer controller can also be used to control several
> parallel multiplexers, that are in turn used by different subsystems
> in the kernel, leading to a need to coordinate multiplexer accesses.
> The multiplexer subsystem handles this coordination.
> 
> This new mux controller subsystem initially comes with a single backend
> driver that controls gpio based multiplexers. Even though not needed by
> this initial driver, the mux controller subsystem is prepared to handle
> chips with multiple (independent) mux controllers.
> 
> Reviewed-by: Jonathan Cameron <ji...@kernel.org>
> Signed-off-by: Peter Rosin <p...@axentia.se>

I would like to mention a bugfix patch that I have added to the end of
the series in response to feedback from Dan Carpenter. Can be found
here: https://lkml.org/lkml/2017/3/14/700

And I have also amended the below editorials to this patch.

Cheers,
peda

diff --git a/include/linux/mux.h b/include/linux/mux.h
index 7ef0864c8f38..febdde4246df 100644
--- a/include/linux/mux.h
+++ b/include/linux/mux.h
@@ -20,6 +20,10 @@ struct mux_chip;
 struct mux_control;
 struct platform_device;

+/**
+ * struct mux_control_ops -Mux controller operations for a mux chip.
+ * @set:   Set the state of the given mux controller.
+ */
 struct mux_control_ops {
int (*set)(struct mux_control *mux, int state);
 };
@@ -29,7 +33,7 @@ struct mux_control_ops {
 #define MUX_IDLE_DISCONNECT (-2)

 /**
- * struct mux_control - Represents a mux controller.
+ * struct mux_control -Represents a mux controller.
  * @lock:  Protects the mux controller state.
  * @chip:  The mux chip that is handling this mux controller.
  * @states:The number of mux controller states.
@@ -50,7 +54,7 @@ struct mux_control {
 /**
  * struct mux_chip -   Represents a chip holding mux controllers.
  * @controllers:   Number of mux controllers handled by the chip.
- * @mux:   Array of mux controllers that is handled.
+ * @mux:   Array of mux controllers that are handled.
  * @dev:   Device structure.
  * @id:Used to identify the device internally.
  * @ops:   Mux controller operations.
@@ -176,7 +180,7 @@ void devm_mux_chip_free(struct device *dev, struct mux_chip 
*mux_chip);
  * mux_control_deselect() if mux_control_select() fails.
  *
  * Return: 0 if the requested state was already active, or 1 it the
- * mux-control state was changed to the requested state. Or a negavive
+ * mux-control state was changed to the requested state. Or a negative
  * errno on error.
  *
  * Note that the difference in return value of zero or one is of
@@ -192,13 +196,13 @@ int mux_control_select(struct mux_control *mux, int 
state);
  *
  * Return: 0 on success and a negative errno on error. An error can only
  * occur if the mux has an idle state. Note that even if an error occurs, the
- * mux-control is unlocked for others to access.
+ * mux-control is unlocked and is thus free for the next access.
  */
 int mux_control_deselect(struct mux_control *mux);

 /**
  * mux_control_get_index() - Get the index of the given mux controller
- * @mux: The mux-control to the the index for.
+ * @mux: The mux-control to get the index for.
  *
  * Return: The index of the mux controller within the mux chip the mux
  * controller is a part of.

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 03/11] mux: minimal mux subsystem and gpio-based mux controller

2017-03-10 Thread Peter Rosin
Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

This new mux controller subsystem initially comes with a single backend
driver that controls gpio based multiplexers. Even though not needed by
this initial driver, the mux controller subsystem is prepared to handle
chips with multiple (independent) mux controllers.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt |   8 +
 MAINTAINERS   |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  34 +++
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-core.c| 422 ++
 drivers/mux/mux-gpio.c| 114 +
 include/linux/mux.h   | 248 
 9 files changed, 837 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-core.c
 create mode 100644 drivers/mux/mux-gpio.c
 create mode 100644 include/linux/mux.h

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index efb8200819d6..e2343d9cbec7 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -337,6 +337,14 @@ MEM
 MFD
   devm_mfd_add_devices()
 
+MUX
+  devm_mux_chip_alloc()
+  devm_mux_chip_free()
+  devm_mux_chip_register()
+  devm_mux_chip_unregister()
+  devm_mux_control_get()
+  devm_mux_control_put()
+
 PER-CPU MEM
   devm_alloc_percpu()
   devm_free_percpu()
diff --git a/MAINTAINERS b/MAINTAINERS
index 7fc06739c8ad..591eba737678 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8563,6 +8563,8 @@ M:    Peter Rosin <p...@axentia.se>
 S: Maintained
 F: Documentation/devicetree/bindings/mux/
 F: include/linux/dt-bindings/mux/
+F: include/linux/mux.h
+F: drivers/mux/
 
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath <andre...@usa.net>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 117ca14ccf85..a7ea13e1b869 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2eced9afba53..c0436f6dd5a9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -177,3 +177,4 @@ obj-$(CONFIG_ANDROID)   += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_FSI)  += fsi/
+obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index ..41dfe08ead84
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,34 @@
+#
+# Multiplexer devices
+#
+
+menuconfig MULTIPLEXER
+   tristate "Multiplexer subsystem"
+   help
+ Multiplexer controller subsystem. Multiplexers are used in a
+ variety of settings, and this subsystem abstracts their use
+ so that the rest of the kernel sees a common interface. When
+ multiple parallel multiplexers are controlled by one single
+ multiplexer controller, this subsystem also coordinates the
+ multiplexer accesses.
+
+ To compile the subsystem as a module, choose M here: the module will
+ be called mux-core.
+
+if MULTIPLEXER
+
+config MUX_GPIO
+   tristate "GPIO-controlled Multiplexer"
+   depends on OF && GPIOLIB
+   help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers, which in that case will be operated in parallel.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-gpio.
+
+endif
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index ..bb16953f6290
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for multiplexer devices.
+#
+
+obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
new fil

[PATCH v10 05/11] dt-bindings: iio: io-channel-mux: document io-channel-mux bindings

2017-03-10 Thread Peter Rosin
Describe how a multiplexer can be used to select which signal is fed to
an io-channel.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../bindings/iio/multiplexer/io-channel-mux.txt| 39 ++
 MAINTAINERS|  6 
 2 files changed, 45 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt

diff --git 
a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt 
b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
new file mode 100644
index ..c82794002595
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -0,0 +1,39 @@
+I/O channel multiplexer bindings
+
+If a multiplexer is used to select which hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "io-channel-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+   input.
+- io-channel-names : Should be "parent".
+- #address-cells = <1>;
+- #size-cells = <0>;
+- mux-controls : Mux controller node to use for operating the mux
+- channels : List of strings, labeling the mux controller states.
+
+For each non-empty string in the channels property, an io-channel will
+be created. The number of this io-channel is the same as the index into
+the list of strings in the channels property, and also matches the mux
+controller state. The mux controller state is described in
+../mux/mux-controller.txt
+
+Example:
+   mux: mux-controller {
+   compatible = "mux-gpio";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync", "in", "system-regulator";
+   };
diff --git a/MAINTAINERS b/MAINTAINERS
index 591eba737678..4af912305d2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6360,6 +6360,12 @@ F:   
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
 F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
 F: drivers/iio/adc/envelope-detector.c
 
+IIO MULTIPLEXER
+M: Peter Rosin <p...@axentia.se>
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
 R: Hartmut Knaack <knaac...@gmx.de>
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 10/11] mux: adg792a: add mux controller driver for ADG792A/G

2017-03-10 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/mux/Kconfig   |  12 
 drivers/mux/Makefile  |   1 +
 drivers/mux/mux-adg792a.c | 140 ++
 3 files changed, 153 insertions(+)
 create mode 100644 drivers/mux/mux-adg792a.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 41dfe08ead84..86668b4d2fc5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -17,6 +17,18 @@ menuconfig MULTIPLEXER
 
 if MULTIPLEXER
 
+config MUX_ADG792A
+   tristate "Analog Devices ADG792A/ADG792G Multiplexers"
+   depends on I2C
+   help
+ ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
+
+ The driver supports both operating the three multiplexers in
+ parallel and operating them independently.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-adg792a.
+
 config MUX_GPIO
tristate "GPIO-controlled Multiplexer"
depends on OF && GPIOLIB
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index bb16953f6290..b00a7d37d2fb 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
new file mode 100644
index ..4820f82e849c
--- /dev/null
+++ b/drivers/mux/mux-adg792a.c
@@ -0,0 +1,140 @@
+/*
+ * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define ADG792A_LDSW   BIT(0)
+#define ADG792A_RESET  BIT(1)
+#define ADG792A_DISABLE(mux)   (0x50 | (mux))
+#define ADG792A_DISABLE_ALL(0x5f)
+#define ADG792A_MUX(mux, state)(0xc0 | (((mux) + 1) << 2) | (state))
+#define ADG792A_MUX_ALL(state) (0xc0 | (state))
+
+static int adg792a_set(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 cmd;
+
+   if (mux->chip->controllers == 1) {
+   /* parallel mux controller operation */
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE_ALL;
+   else
+   cmd = ADG792A_MUX_ALL(state);
+   } else {
+   unsigned int controller = mux_control_get_index(mux);
+
+   if (state == MUX_IDLE_DISCONNECT)
+   cmd = ADG792A_DISABLE(controller);
+   else
+   cmd = ADG792A_MUX(controller, state);
+   }
+
+   return i2c_smbus_write_byte_data(i2c, cmd, ADG792A_LDSW);
+}
+
+static const struct mux_control_ops adg792a_ops = {
+   .set = adg792a_set,
+};
+
+static int adg792a_probe(struct i2c_client *i2c,
+const struct i2c_device_id *id)
+{
+   struct device *dev = >dev;
+   struct mux_chip *mux_chip;
+   u32 cells;
+   int ret;
+   int i;
+
+   ret = of_property_read_u32(dev->of_node, "#mux-control-cells", );
+   if (ret < 0)
+   return ret;
+   if (cells >= 2)
+   return -EINVAL;
+
+   mux_chip = devm_mux_chip_alloc(dev, cells ? 3 : 1, 0);
+   if (!mux_chip)
+   return -ENOMEM;
+
+   mux_chip->ops = _ops;
+
+   ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL,
+   ADG792A_RESET | ADG792A_LDSW);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < mux_chip->controllers; ++i) {
+   struct mux_control *mux = _chip->mux[i];
+   s32 idle_state;
+
+   mux->states = 4;
+
+   ret = of_property_read_u32_index(dev->of_node, "idle-state", i,
+(s32 *)_state);
+   if (ret < 0)
+   continue;
+
+   switch (idle_state) {
+   case 0 ... 4:
+   case MUX_IDLE_DISCONNECT:
+   mux_chip->mux[i].idle_state = idle_state;
+   break;
+   case MUX_IDLE_AS_IS:
+   break;
+   default:
+   dev_err(dev, "invalid idle-state %d\n", idle_state);
+   return -EINVAL;
+   }
+   }
+
+   ret = devm_mux_chip_register(dev, mux_chip);
+   if (ret &l

[PATCH v10 09/11] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux

2017-03-10 Thread Peter Rosin
Analog Devices ADG792A/G is a triple 4:1 mux.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/mux/adi,adg792a.txt| 75 ++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/adi,adg792a.txt

diff --git a/Documentation/devicetree/bindings/mux/adi,adg792a.txt 
b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
new file mode 100644
index ..96b787a69f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/adi,adg792a.txt
@@ -0,0 +1,75 @@
+Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
+
+Required properties:
+- compatible : "adi,adg792a" or "adi,adg792g"
+- #mux-control-cells : <0> if parallel (the three muxes are bound together
+  with a single mux controller controlling all three muxes), or <1> if
+  not (one mux controller for each mux).
+* Standard mux-controller bindings as described in mux-controller.txt
+
+Optional properties for ADG792G:
+- gpio-controller : if present, #gpio-cells below is required.
+- #gpio-cells : should be <2>
+ - First cell is the GPO line number, i.e. 0 or 1
+ - Second cell is used to specify active high (0)
+   or active low (1)
+
+Optional properties:
+- idle-state : if present, array of states that the mux controllers will have
+  when idle. The special state MUX_IDLE_AS_IS is the default and
+  MUX_IDLE_DISCONNECT is also supported.
+
+States 0 through 3 correspond to signals A through D in the datasheet.
+
+Example:
+
+   /*
+* Three independent mux controllers (of which one is used).
+* Mux 0 is disconnected when idle, mux 1 idles in the previously
+* selected state and mux 2 idles with signal B.
+*/
+{
+   mux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <1>;
+
+   idle-state = ;
+   };
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = < 2>;
+
+   channels = "sync-1", "", "out";
+   };
+
+
+   /*
+* Three parallel muxes with one mux controller, useful e.g. if
+* the adc is differential, thus needing two signals to be muxed
+* simultaneously for correct operation.
+*/
+{
+   pmux: mux-controller@50 {
+   compatible = "adi,adg792a";
+   reg = <0x50>;
+   #mux-control-cells = <0>;
+
+   idle-state = <1>;
+   };
+   };
+
+   diff-adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "", "out";
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 07/11] dt-bindings: i2c: i2c-mux: document general purpose i2c-mux bindings

2017-03-10 Thread Peter Rosin
Describe how a general purpose multiplexer controller is used to mux an
i2c bus.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpmux.txt  | 99 ++
 1 file changed, 99 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
new file mode 100644
index ..2907dab56298
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt
@@ -0,0 +1,99 @@
+General Purpose I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses a mux controller
+from the mux subsystem to route the I2C signals.
+
+  .-.  .-.
+  | dev |  | dev |
+..'-'  '-'
+| SoC|   ||
+||  .+'
+|   .--. |  .--+child bus A, on MUX value set to 0
+|   | I2C  |-|--| Mux  |
+|   '--' |  '--+---+child bus B, on MUX value set to 1
+|   .--. | |'--++.
+|   | MUX- | | |   |||
+|   | Ctrl |-|-+.-.  .-.  .-.
+|   '--' |  | dev |  | dev |  | dev |
+''  '-'  '-'  '-'
+
+Required properties:
+- compatible: i2c-mux
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-controls: The phandle of the mux controller to use for operating the
+  mux.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
+  is also the mux-controller state described in ../mux/mux-controller.txt
+
+Optional properties:
+- mux-locked: If present, explicitly allow unrelated I2C transactions on the
+  parent I2C adapter at these times:
+   + during setup of the multiplexer
+   + between setup of the multiplexer and the child bus I2C transaction
+   + between the child bus I2C transaction and releasing of the multiplexer
+   + during releasing of the multiplexer
+  However, I2C transactions to devices behind all I2C multiplexers connected
+  to the same parent adapter that this multiplexer is connected to are blocked
+  for the full duration of the complete multiplexed I2C transaction (i.e.
+  including the times covered by the above list).
+  If mux-locked is not present, the multiplexer is assumed to be parent-locked.
+  This means that no unrelated I2C transactions are allowed on the parent I2C
+  adapter for the complete multiplexed I2C transaction.
+  The properties of mux-locked and parent-locked multiplexers are discussed
+  in more detail in Documentation/i2c/i2c-topology.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be set as the state in the
+mux controller.
+
+Example:
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   mux-locked;
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@1 {
+   reg = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   compatible = "solomon,ssd1307fb-i2c";
+   reg = <0x3c>;
+   pwms = < 4 3000>;
+   reset-gpios = < 7 1>;
+   reset-active-low;
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   compatible = "nxp,pca9555";
+   gpio-controller;
+   #gpio-cells = <2>;
+   reg = <0x20>;
+   };
+   };
+   };
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 04/11] iio: inkern: api for manipulating ext_info of iio channels

2017-03-10 Thread Peter Rosin
Extend the inkern api with functions for reading and writing ext_info
of iio channels.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/inkern.c | 60 
 include/linux/iio/consumer.h | 37 +++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..8292ad4435ea 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -869,3 +869,63 @@ int iio_write_channel_raw(struct iio_channel *chan, int 
val)
return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+   unsigned int i = 0;
+
+   if (!chan->channel->ext_info)
+   return i;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
+   ++i;
+
+   return i;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+
+static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
+   const struct iio_channel *chan,
+   const char *attr)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   if (!chan->channel->ext_info)
+   return NULL;
+
+   for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+   if (!strcmp(attr, ext_info->name))
+   return ext_info;
+   }
+
+   return NULL;
+}
+
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->read(chan->indio_dev, ext_info->private,
+ chan->channel, buf);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len)
+{
+   const struct iio_chan_spec_ext_info *ext_info;
+
+   ext_info = iio_lookup_ext_info(chan, attr);
+   if (!ext_info)
+   return -EINVAL;
+
+   return ext_info->write(chan->indio_dev, ext_info->private,
+  chan->channel, buf, len);
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 47eeec3218b5..5e347a9805fd 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -312,4 +312,41 @@ int iio_read_channel_scale(struct iio_channel *chan, int 
*val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);
 
+/**
+ * iio_get_channel_ext_info_count() - get number of ext_info attributes
+ *   connected to the channel.
+ * @chan:  The channel being queried
+ *
+ * Returns the number of ext_info attributes
+ */
+unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
+
+/**
+ * iio_read_channel_ext_info() - read ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   Where to store the attribute value. Assumed to hold
+ * at least PAGE_SIZE bytes.
+ *
+ * Returns the number of bytes written to buf (perhaps w/o zero termination;
+ * it need not even be a string), or an error code.
+ */
+ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
+ const char *attr, char *buf);
+
+/**
+ * iio_write_channel_ext_info() - write ext_info attribute from a given channel
+ * @chan:  The channel being queried.
+ * @attr:  The ext_info attribute to read.
+ * @buf:   The new attribute value. Strings needs to be zero-
+ * terminated, but the terminator should not be included
+ * in the below len.
+ * @len:   The size of the new attribute value.
+ *
+ * Returns the number of accepted bytes, which should be the same as len.
+ * An error code can also be returned.
+ */
+ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
+  const char *buf, size_t len);
+
 #endif
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 08/11] i2c: i2c-mux-gpmux: new driver

2017-03-10 Thread Peter Rosin
This is a general purpose i2c mux that uses a multiplexer controlled by
the multiplexer subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Wolfram Sang <w...@the-dreams.de>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/Kconfig |  13 +++
 drivers/i2c/muxes/Makefile|   1 +
 drivers/i2c/muxes/i2c-mux-gpmux.c | 173 ++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-gpmux.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 10b3d17ae3ea..5fb34f24 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,19 @@ config I2C_MUX_GPIO
  This driver can also be built as a module.  If so, the module
  will be called i2c-mux-gpio.
 
+config I2C_MUX_GPMUX
+   tristate "General Purpose I2C multiplexer"
+   select MULTIPLEXER
+   depends on OF
+   help
+ If you say yes to this option, support will be included for a
+ general purpose I2C multiplexer. This driver provides access to
+ I2C busses connected through a MUX, which in turn is controlled
+ by a MUX-controller from the MUX subsystem.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-mux-gpmux.
+
 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 9948fa45037f..af43c6c3e861 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)+= 
i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_GPMUX)+= i2c-mux-gpmux.o
 obj-$(CONFIG_I2C_MUX_MLXCPLD)  += i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)  += i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)  += i2c-mux-pca954x.o
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c 
b/drivers/i2c/muxes/i2c-mux-gpmux.c
new file mode 100644
index ..fb23b2278462
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -0,0 +1,173 @@
+/*
+ * General Purpose I2C multiplexer
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux {
+   struct mux_control *control;
+
+   bool do_not_deselect;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+   int ret;
+
+   ret = mux_control_select(mux->control, chan);
+   mux->do_not_deselect = ret < 0;
+
+   return ret;
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct mux *mux = i2c_mux_priv(muxc);
+
+   if (mux->do_not_deselect)
+   return 0;
+
+   return mux_control_deselect(mux->control);
+}
+
+static struct i2c_adapter *mux_parent_adapter(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct device_node *parent_np;
+   struct i2c_adapter *parent;
+
+   parent_np = of_parse_phandle(np, "i2c-parent", 0);
+   if (!parent_np) {
+   dev_err(dev, "Cannot parse i2c-parent\n");
+   return ERR_PTR(-ENODEV);
+   }
+   parent = of_find_i2c_adapter_by_node(parent_np);
+   of_node_put(parent_np);
+   if (!parent)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   return parent;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+   { .compatible = "i2c-mux", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   struct device_node *child;
+   struct i2c_mux_core *muxc;
+   struct mux *mux;
+   struct i2c_adapter *parent;
+   int children;
+   int ret;
+
+   if (!np)
+   return -ENODEV;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->control = devm_mux_control_get(dev, NULL);
+   if (IS_ERR(mux->control)) {
+   if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+   dev_err(dev, "failed to get control-mux\n");
+   return PTR_ERR(mux->control);
+   }
+
+   

[PATCH v10 06/11] iio: multiplexer: new iio category and iio-mux driver

2017-03-10 Thread Peter Rosin
When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
to create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer subsystem.

Cache any ext_info values from the parent iio channel, creating a private
copy of the ext_info attributes for each multiplexer state/channel.

Reviewed-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 MAINTAINERS   |   1 +
 drivers/iio/Kconfig   |   1 +
 drivers/iio/Makefile  |   1 +
 drivers/iio/multiplexer/Kconfig   |  18 ++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 456 ++
 6 files changed, 483 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4af912305d2c..23cfd5bc2158 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6365,6 +6365,7 @@ M:    Peter Rosin <p...@axentia.se>
 L: linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: drivers/iio/multiplexer/iio-mux.c
 
 IIO SUBSYSTEM AND DRIVERS
 M: Jonathan Cameron <ji...@kernel.org>
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a918270d6f54..b3c8c6ef0dff 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -83,6 +83,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 33fa4026f92c..93c769cd99bf 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -28,6 +28,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += potentiostat/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index ..70a044510686
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,18 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+   tristate "IIO multiplexer driver"
+   select MULTIPLEXER
+   depends on OF
+   help
+ Say yes here to build support for the IIO multiplexer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index ..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index ..94d40f9bef4c
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,456 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <p...@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mux_ext_info_cache {
+   char *data;
+   size_t size;
+};
+
+struct mux_child {
+   struct mux_ext_info_cache *ext_info_cache;
+};
+
+struct mux {
+   int cached_state;
+   struct mux_control *control;
+   struct iio_channel *parent;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec *chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+   struct mux_child *child = >child[idx];
+   struct iio_chan_spec const *chan = >chan[idx];
+   int ret;
+   int i;
+
+   ret = mux_control_select(mux->control, chan->channel);
+   if (ret < 0) {
+   mux->cached_state = -1;
+   return ret;
+   }
+
+   if (mux->cached_state == chan->channel)
+   return 0;
+
+   if (chan->ext_info) {
+   for (i = 0; chan->ext_info[i].name; ++i) {
+   const char *attr = chan->ext_info[i].name;
+   

[PATCH v10 11/11] iio: multiplexer: fix unsigned check with less than zero

2017-03-10 Thread Peter Rosin
Comparing a size_t with less than zero is always false as size_t
is unsigned. So, change the type of the variable to ssize_t and
replicate the size check from mux_configure_channel() into
mux_write_ext_info() thus ensuring that the size will fit in the
ssize_t variable.

Detected by CoverityScan, CID#1415278 ("Unsigned compared against 0")

Reported-by: Colin Ian King <colin.k...@canonical.com>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/multiplexer/iio-mux.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/multiplexer/iio-mux.c 
b/drivers/iio/multiplexer/iio-mux.c
index 94d40f9bef4c..bab9e6902090 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -21,7 +21,7 @@
 
 struct mux_ext_info_cache {
char *data;
-   size_t size;
+   ssize_t size;
 };
 
 struct mux_child {
@@ -206,6 +206,9 @@ static ssize_t mux_write_ext_info(struct iio_dev 
*indio_dev, uintptr_t private,
char *new;
ssize_t ret;
 
+   if (len >= PAGE_SIZE)
+   return -EINVAL;
+
ret = iio_mux_select(mux, idx);
if (ret < 0)
return ret;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v10 00/11] mux controller abstraction and iio/i2c muxes

2017-03-10 Thread Peter Rosin
he first mux chip
  I found on the Internet with an i2c interface (that was not a
  dedicated i2c multiplexer like PCA9547) which I used to verify
  that the abstractions in the mux core are up to the task. Untested,
  just proof of concept that at least looks pretty and compiles...
- various touch-ups.

v3 -> v4 changes
- rebased onto next-20161122 (depends on recent _available iio changes).
- added support for having the mux-controller in a child node of a
  mux-consumer if it is a sole consumer, to hopefully even further satisfy
  the complaint from Rob (and later Lars-Peter) about dt complexity.
- the above came at the cost of some rather horrible refcounting code,
  please review and suggest how it should be done...
- changed to register a device class instead of a bus.
- pass in the parent device into mux_control_alloc and require less
  work from mux-control drivers.
- changed device names from mux:control%d to mux%d
- move kernel-doc from mux-core.c to mux.h (and add some bits).
- give the gpio driver a chance to update all mux pins at once.
- factor out iio ext_info lookup into new helper function. /Lars-Peter
- use an unsigned type for the iio ext_info count. /Lars-Peter
- unified "brag strings" in the file headers.

v2 -> v3 changes
- have the mux-controller in the parent node of any mux-controller consumer,
  to hopefully satisfy complaint from Rob about dt complexity.
- improve commit message of the mux subsystem commit, making it more
  general, as requested by Jonathan.
- remove priv member from struct mux_control and calculate it on the
  fly. /Jonathan
- make the function comments in mux-core.c kernel doc. /Jonathan
- add devm_mux_control_* to Documentation/driver.model/devres.txt. /Jonathan
- add common dt bindings for mux-controllers, refer to them from the
  mux-gpio bindings. /Rob
- clarify how the gpio pins map to the mux state. /Rob
- separate CONFIG_ variables for the mux core and the mux gpio driver.
- improve Kconfig help texts.
- make CONFIG_MUX_GPIO depend on CONFIG_GPIOLIB.
- keep track of the number of mux states in the mux core.
- since the iio channel number is used as mux state, it was possible
  to drop the state member from the mux_child struct.
- cleanup dt bindings for i2c-mux-simple, it had some of copy-paste
  problems from ots origin (i2c-mux-gpio).
- select the mux control subsystem in config for the i2c-mux-simple driver.
- add entries to MAINTAINERS and my sign-off, I'm now satisfied and know
  nothing in this to be ashamed of.

v1 -> v2 changes
- fixup export of mux_control_put reported by kbuild
- drop devicetree iio-ext-info property as noted by Lars-Peter,
  and replace the functionality by exposing all ext_info
  attributes of the parent channel for each of the muxed
  channels. A cache on top of that and each muxed channel
  gets its own view of the ext_info of the parent channel.
- implement idle-state for muxes
- clear out the cache on failure in order to force a mux
  update on the following use
- cleanup the probe of i2c-mux-simple driver
- fix a bug in the i2c-mux-simple driver, where failure in
  the selection of the mux caused a deadlock when the mux
  was later unconditionally deselected.

I have a piece of hardware that is using the same 3 GPIO pins
to control four 8-way muxes. Three of them control ADC lines
to an ADS1015 chip with an iio driver, and the last one
controls the SDA line of an i2c bus. We have some deployed
code to handle this, but you do not want to see it or ever
hear about it. I'm not sure why I even mention it. Anyway,
the situation has nagged me to no end for quite some time.

So, after first getting more intimate with the i2c muxing code
and later discovering the drivers/iio/inkern.c file and
writing a couple of drivers making use of it, I came up with
what I think is an acceptable solution; add a generic mux
controller driver (and subsystem) that is shared between all
instances, and combine that with an iio mux driver and a new
general purpose i2c mux driver that is only hooking the i2c
muxing and the new mux controller.

One thing that I would like to do, but don't see a solution
for, is to move the mux control code that is present in
various drivers in drivers/i2c/muxes to this new minimalistic
muxing subsystem, thus converting all present i2c muxes (but
perhaps not gates and arbitrators).

I'm using an rwsem to lock a mux, but that isn't really a
perfect fit. Is there a better locking primitive that I don't
know about that fits better? I had a mutex at one point, but
that didn't allow any concurrent accesses at all. At least
the rwsem allows concurrent access as long as all users
agree on the mux state, but I suspect that the rwsem will
degrade to the mutex situation pretty quickly if there is
any contention.

Also, the "mux" name feels a bit ambitious, there are many muxes
in the world, and this tiny bit of code is probably not good
enough to be a nice fit for all...

Cheers,
peda

Peter Rosin (1

[PATCH v10 02/11] dt-bindings: document devicetree bindings for mux-controllers and gpio-mux

2017-03-10 Thread Peter Rosin
Allow specifying that a single multiplexer controller can be used to
control several parallel multiplexers, thus enabling sharing of the
multiplexer controller by different consumers.

Add a binding for a first mux controller in the form of a GPIO based mux
controller.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/devicetree/bindings/mux/gpio-mux.txt |  69 +
 .../devicetree/bindings/mux/mux-controller.txt | 157 +
 MAINTAINERS|   6 +
 include/dt-bindings/mux/mux.h  |  16 +++
 4 files changed, 248 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mux/gpio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/mux/mux-controller.txt
 create mode 100644 include/dt-bindings/mux/mux.h

diff --git a/Documentation/devicetree/bindings/mux/gpio-mux.txt 
b/Documentation/devicetree/bindings/mux/gpio-mux.txt
new file mode 100644
index ..b8f746344d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/gpio-mux.txt
@@ -0,0 +1,69 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "gpio-mux"
+- mux-gpios : list of gpios used to control the multiplexer, least
+ significant bit first.
+- #mux-control-cells : <0>
+* Standard mux-controller bindings as decribed in mux-controller.txt
+
+Optional properties:
+- idle-state : if present, the state the mux will have when idle. The
+  special state MUX_IDLE_AS_IS is the default.
+
+The multiplexer state is defined as the number represented by the
+multiplexer GPIO pins, where the first pin is the least significant
+bit. An active pin is a binary 1, an inactive pin is a binary 0.
+
+Example:
+
+   mux: mux-controller {
+   compatible = "gpio-mux";
+   #mux-control-cells = <0>;
+
+   mux-gpios = < 0 GPIO_ACTIVE_HIGH>,
+   < 1 GPIO_ACTIVE_HIGH>;
+   };
+
+   adc-mux {
+   compatible = "io-channel-mux";
+   io-channels = < 0>;
+   io-channel-names = "parent";
+
+   mux-controls = <>;
+
+   channels = "sync-1", "in", "out", "sync-2";
+   };
+
+   i2c-mux {
+   compatible = "i2c-mux";
+   i2c-parent = <>;
+
+   mux-controls = <>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ssd1307: oled@3c {
+   /* ... */
+   };
+   };
+
+   i2c@3 {
+   reg = <3>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   pca9555: pca9555@20 {
+   /* ... */
+   };
+   };
+   };
diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt 
b/Documentation/devicetree/bindings/mux/mux-controller.txt
new file mode 100644
index ..4f47e4bd2fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
@@ -0,0 +1,157 @@
+Common multiplexer controller bindings
+==
+
+A multiplexer (or mux) controller will have one, or several, consumer devices
+that uses the mux controller. Thus, a mux controller can possibly control
+several parallel multiplexers. Presumably there will be at least one
+multiplexer needed by each consumer, but a single mux controller can of course
+control several multiplexers for a single consumer.
+
+A mux controller provides a number of states to its consumers, and the state
+space is a simple zero-based enumeration. I.e. 0-1 for a 2-way multiplexer,
+0-7 for an 8-way multiplexer, etc.
+
+
+Consumers
+-
+
+Mux controller consumers should specify a list of mux controllers that they
+want to use with a property containing a 'mux-ctrl-list':
+
+   mux-ctrl-list ::=  [mux-ctrl-list]
+   single-mux-ctrl ::=  [mux-ctrl-specifier]
+   mux-ctrl-phandle : phandle to mux controller node
+   mux-ctrl-specifier : array of #mux-control-cells specifying the
+given mux controller (controller specific)
+
+Mux controller properties should be named "mux-controls". The exact meaning of
+each mux controller property must be documented in the device tree bind

[PATCH v10 01/11] devres: trivial whitespace fix

2017-03-10 Thread Peter Rosin
Everything else is indented with two spaces, so fix the odd one out.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/driver-model/devres.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index bf34d5b3a733..efb8200819d6 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -335,7 +335,7 @@ MEM
   devm_kzalloc()
 
 MFD
- devm_mfd_add_devices()
+  devm_mfd_add_devices()
 
 PER-CPU MEM
   devm_alloc_percpu()
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   >