Re: [PATCH v7 01/12] devres: trivial whitespace fix
On 04/01/17 12:16, Peter Rosin wrote: > Signed-off-by: Peter Rosin Acked-by: Jonathan Cameron > --- > 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 ca9d1eb46bc0..dc51fb024190 100644 > --- a/Documentation/driver-model/devres.txt > +++ b/Documentation/driver-model/devres.txt > @@ -330,7 +330,7 @@ MEM >devm_kzalloc() > > MFD > - devm_mfd_add_devices() > + devm_mfd_add_devices() > > PER-CPU MEM >devm_alloc_percpu() > -- 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 v7 09/12] dt-bindings: i2c: i2c-mux-simple: document i2c-mux-simple bindings
On 04/01/17 12:16, Peter Rosin wrote: > Signed-off-by: Peter Rosin Looks good to me. Acked-by: Jonathan Cameron > --- > .../devicetree/bindings/i2c/i2c-mux-simple.txt | 81 > ++ > 1 file changed, 81 insertions(+) > create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt > > diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt > b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt > new file mode 100644 > index ..253d5027843b > --- /dev/null > +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt > @@ -0,0 +1,81 @@ > +Simple 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-simple,mux-locked or i2c-mux-simple,parent-locked > +- 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 > + > +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 = "mux-gpio"; > + #mux-control-cells = <0>; > + > + mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>, > + <&pioA 1 GPIO_ACTIVE_HIGH>; > + }; > + > + i2c-mux { > + compatible = "i2c-mux-simple,mux-locked"; > + i2c-parent = <&i2c1>; > + > + mux-controls = <&mux>; > + > + #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 = <&pwm 4 3000>; > + reset-gpios = <&gpio2 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>; > + }; > + }; > + }; > -- 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 v7 03/12] mux: minimal mux subsystem and gpio-based mux controller
On 04/01/17 12:16, 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. > > Signed-off-by: Peter Rosin Reviewed-by: Jonathan Cameron > --- > Documentation/driver-model/devres.txt | 8 + > MAINTAINERS | 2 + > drivers/Kconfig | 2 + > drivers/Makefile | 1 + > drivers/mux/Kconfig | 33 +++ > drivers/mux/Makefile | 6 + > drivers/mux/mux-core.c| 398 > ++ > drivers/mux/mux-gpio.c| 120 ++ > include/linux/mux.h | 244 + > 9 files changed, 814 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 dc51fb024190..1e9ae701a587 100644 > --- a/Documentation/driver-model/devres.txt > +++ b/Documentation/driver-model/devres.txt > @@ -332,6 +332,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 32abef2b6d05..ebe96f3e25a0 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -8442,6 +8442,8 @@ MULTIPLEXER SUBSYSTEM > M: Peter Rosin > S: Maintained > F: Documentation/devicetree/bindings/mux/ > +F: include/linux/mux.h > +F: drivers/mux/ > > MULTISOUND SOUND DRIVER > M: Andrew Veliath > diff --git a/drivers/Kconfig b/drivers/Kconfig > index e1e2066cecdb..993aeb65affa 100644 > --- a/drivers/Kconfig > +++ b/drivers/Kconfig > @@ -76,6 +76,8 @@ source "drivers/hwmon/Kconfig" > > source "drivers/thermal/Kconfig" > > +source "drivers/mux/Kconfig" > + Why this location in the list? I think the convention for new subystems is to just go last in the list. > source "drivers/watchdog/Kconfig" > > source "drivers/ssb/Kconfig" > diff --git a/drivers/Makefile b/drivers/Makefile > index 060026a02f59..d089baa57965 100644 > --- a/drivers/Makefile > +++ b/drivers/Makefile > @@ -112,6 +112,7 @@ obj-$(CONFIG_W1) += w1/ > obj-y+= power/ > obj-$(CONFIG_HWMON) += hwmon/ > obj-$(CONFIG_THERMAL)+= thermal/ > +obj-$(CONFIG_MULTIPLEXER)+= mux/ > obj-$(CONFIG_WATCHDOG) += watchdog/ > obj-$(CONFIG_MD) += md/ > obj-$(CONFIG_BT) += bluetooth/ > diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig > new file mode 100644 > index ..de5a35ffe7af > --- /dev/null > +++ b/drivers/mux/Kconfig > @@ -0,0 +1,33 @@ > +# > +# Multiplexer devices > +# > + > +menuconfig MULTIPLEXER > + bool "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. > + > + If unsure, say no. > + > +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 this 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 10
Re: [PATCH v7 04/12] dt-bindings: simplified bindings for single-user gpio mux
On 04/01/17 12:16, Peter Rosin wrote: > Signed-off-by: Peter Rosin Looks neat and tidy to me. Acked-by: Jonathan Cameron > --- > .../devicetree/bindings/mux/mux-controller.txt | 26 > ++ > 1 file changed, 26 insertions(+) > > diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt > b/Documentation/devicetree/bindings/mux/mux-controller.txt > index 42b2177e5ae1..4e89df8b2392 100644 > --- a/Documentation/devicetree/bindings/mux/mux-controller.txt > +++ b/Documentation/devicetree/bindings/mux/mux-controller.txt > @@ -125,3 +125,29 @@ An example mux controller might look like this: > reg = <0x50>; > #mux-control-cells = <1>; > }; > + > + > +Combinded controller and consumer of a GPIO mux > +--- > + > +For the common case of a single consumer of a GPIO controlled mux, there is > +a simplified binding which will instantiate an implicit mux controller. Just > +specify a mux-gpios property with the same interpretation as in mux-gpio.txt. > +Note that other properties described in mux-gpio.txt are not available in > +this simplified form and that the mux controller is unnamed. If you need > +more than one mux controller, a shared mux controller or if you need a > +specific idle-state, use the more flexible binding with the mux controller > +in its own node. > + > +Example: > + > + adc-mux { > + compatible = "io-channel-mux"; > + io-channels = <&adc 0>; > + io-channel-names = "parent"; > + > + mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>, > + <&pioA 1 GPIO_ACTIVE_HIGH>; > + > + channels = "sync-1", "in", "out", "sync-2"; > + }; > -- 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 v7 07/12] dt-bindings: iio: iio-mux: document iio-mux bindings
On 04/01/17 12:16, Peter Rosin wrote: > Signed-off-by: Peter Rosin Acked-by: Jonathan Cameron > --- > .../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 = <&pioA 0 GPIO_ACTIVE_HIGH>, > + <&pioA 1 GPIO_ACTIVE_HIGH>; > + }; > + > + adc-mux { > + compatible = "io-channel-mux"; > + io-channels = <&adc 0>; > + io-channel-names = "parent"; > + > + mux-controls = <&mux>; > + > + channels = "sync", "in", "system-regulator"; > + }; > diff --git a/MAINTAINERS b/MAINTAINERS > index ebe96f3e25a0..91775f2be209 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -6274,6 +6274,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 > +L: linux-...@vger.kernel.org > +S: Maintained > +F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt > + > IIO SUBSYSTEM AND DRIVERS > M: Jonathan Cameron > R: Hartmut Knaack > -- 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 v7 05/12] mux: support simplified bindings for single-user gpio mux
On 05/01/17 16:21, Peter Rosin wrote: > On 2017-01-04 13:16, Peter Rosin wrote: >> Signed-off-by: Peter Rosin >> --- >> drivers/mux/mux-core.c | 81 >> -- >> drivers/mux/mux-gpio.c | 56 ++ >> include/linux/mux.h| 7 + >> 3 files changed, 89 insertions(+), 55 deletions(-) >> >> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c >> index 21da15a264ad..d887ae1c0e55 100644 >> --- a/drivers/mux/mux-core.c >> +++ b/drivers/mux/mux-core.c >> @@ -15,6 +15,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -288,6 +289,63 @@ static struct mux_chip *of_find_mux_chip_by_node(struct >> device_node *np) >> return dev ? to_mux_chip(dev) : NULL; >> } >> >> +#ifdef CONFIG_MUX_GPIO >> + >> +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, >> +}; >> + >> +struct mux_chip *mux_gpio_alloc(struct device *dev) >> +{ >> +struct mux_chip *mux_chip; >> +struct mux_gpio *mux_gpio; >> +int pins; >> +int ret; >> + >> +pins = gpiod_count(dev, "mux"); >> +if (pins < 0) >> +return ERR_PTR(pins); >> + >> +mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) + >> + pins * sizeof(*mux_gpio->val)); >> +if (!mux_chip) >> +return ERR_PTR(-ENOMEM); >> + >> +mux_gpio = mux_chip_priv(mux_chip); >> +mux_gpio->val = (int *)(mux_gpio + 1); >> +mux_chip->ops = &mux_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 ERR_PTR(ret); >> +} >> +WARN_ON(pins != mux_gpio->gpios->ndescs); >> +mux_chip->mux->states = 1 << pins; >> + >> +return mux_chip; >> +} >> +EXPORT_SYMBOL_GPL(mux_gpio_alloc); >> + >> +#endif /* CONFIG_MUX_GPIO */ >> + >> struct mux_control *mux_control_get(struct device *dev, const char >> *mux_name) >> { >> struct device_node *np = dev->of_node; >> @@ -307,9 +365,28 @@ struct mux_control *mux_control_get(struct device *dev, >> const char *mux_name) >> ret = of_parse_phandle_with_args(np, >> "mux-controls", "#mux-control-cells", >> index, &args); >> + >> +#ifdef CONFIG_MUX_GPIO >> +if (ret == -ENOENT && !mux_name && gpiod_count(dev, "mux") > 0) { >> +mux_chip = mux_gpio_alloc(dev); >> +if (!IS_ERR(mux_chip)) { >> +ret = devm_mux_chip_register(dev, mux_chip); >> +if (ret < 0) { >> +dev_err(dev, "failed to register mux-chip\n"); >> +return ERR_PTR(ret); >> +} >> +get_device(&mux_chip->dev); >> +return mux_chip->mux; >> +} >> + >> +ret = PTR_ERR(mux_chip); >> +} >> +#endif >> + >> if (ret) { >> -dev_err(dev, "%s: failed to get mux-control %s(%i)\n", >> -np->full_name, mux_name ?: "", index); >> +if (ret != -EPROBE_DEFER) >> +dev_err(dev, "%s: failed to get mux-control %s(%i)\n", >> +np->full_name, mux_name ?: "", index); >> return ERR_PTR(ret); >> } >> >> diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c >> index 76b52bc63470..8a7bfbc0c4bb 100644 >> --- a/drivers/mux/mux-gpio.c >> +++ b/drivers/mux/mux-gpio.c >> @@ -11,37 +11,12 @@ >> */ >> >> #include >> -#include >> #include >> #include >> #include >> #include >> #include > > Instead of moving the mux-gpio guts from mux-gpio.c to mux-core.c, I > will instead make CONFIG_MUX_GPIO a bool option (no module possible) > and call it from the mux-core. That will be cleaner and less of a > break of abstractions in my opinion. Hmm. I wonder if the balance is right here or whether we should just not have the simplified binding at all as it breaks the assumption that all muxes are of the same level... I like the binding, but it is causing significant complexity in here. > > Cheers, > Peter > >> -struct mux_gpio { >> -struct gpio_descs *gpios; >> -int *val; >> -}; >> - >> -static int mux_gpio_set(struct mux_contr
Re: [PATCH v7 11/12] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux
On 04/01/17 12:16, Peter Rosin wrote: > Analog Devices ADG792A/G is a triple 4:1 mux. > > Signed-off-by: Peter Rosin I think this is about as neat as we can make it. Acked-by: Jonathan Cameron > --- > .../devicetree/bindings/mux/mux-adg792a.txt| 79 > ++ > 1 file changed, 79 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mux/mux-adg792a.txt > > diff --git a/Documentation/devicetree/bindings/mux/mux-adg792a.txt > b/Documentation/devicetree/bindings/mux/mux-adg792a.txt > new file mode 100644 > index ..0b26dd11f070 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mux/mux-adg792a.txt > @@ -0,0 +1,79 @@ > +Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers > + > +Required properties: > +- compatible : "adi,adg792a" or "adi,adg792g" > +- #mux-control-cells : <0> if parallel, or <1> if not. > +* Standard mux-controller bindings as decribed 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: > +- adi,parallel : if present, the three muxes are bound together with a single > + mux controller, controlling all three muxes in parallel. > +- adi,idle-state : if present, array of 2-tuples with mux controller number > + and state that mux controllers will have when idle. States 0 through 3 > + correspond to signals A through D in the datasheet. > +- adi,idle-high-impedance : if present, array of mux controller numbers that > + should be in the disconnected high-impedance state when idle. > + > +Mux controller states 0 through 3 correspond to signals A through D in the > +datasheet. If a mux controller is mentioned in neither adi,idle-state nor > +adi,idle-high-impedance it is left in its previously selected state when > idle. > + > +Example: > + > + /* > + * Three independent mux controllers (of which one is used). > + * Mux 0 is disconnected when idle, mux 1 idles with signal C > + * and mux 2 idles with signal A. > + */ > + &i2c0 { > + mux: adg792a@50 { > + compatible = "adi,adg792a"; > + reg = <0x50>; > + #mux-control-cells = <1>; > + > + adi,idle-high-impedance = <0>; > + adi,idle-state = <1 2>, <2 0>; > + }; > + }; > + > + adc-mux { > + compatible = "io-channel-mux"; > + io-channels = <&adc 0>; > + io-channel-names = "parent"; > + > + mux-controls = <&mux 1>; > + > + 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. > + */ > + &i2c0 { > + pmux: adg792a@50 { > + compatible = "adi,adg792a"; > + reg = <0x50>; > + #mux-control-cells = <0>; > + adi,parallel; > + }; > + }; > + > + diff-adc-mux { > + compatible = "io-channel-mux"; > + io-channels = <&adc 0>; > + io-channel-names = "parent"; > + > + mux-controls = <&pmux>; > + > + channels = "sync-1", "", "out"; > + }; > -- 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 v7 12/12] mux: adg792a: add mux controller driver for ADG792A/G
On 04/01/17 12:16, Peter Rosin wrote: > Analog Devices ADG792A/G is a triple 4:1 mux. > > Signed-off-by: Peter Rosin Reviewed-by: Jonathan Cameron A nice little driver. Hopefully this example will do the job of convincing people a subsystem makes sense! Jonathan > --- > drivers/mux/Kconfig | 12 > drivers/mux/Makefile | 1 + > drivers/mux/mux-adg792a.c | 169 > ++ > 3 files changed, 182 insertions(+) > create mode 100644 drivers/mux/mux-adg792a.c > > diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig > index de5a35ffe7af..39b06e19aa96 100644 > --- a/drivers/mux/Kconfig > +++ b/drivers/mux/Kconfig > @@ -16,6 +16,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 facc43da3648..fddbb073fc77 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 ..c6d5c4571e7c > --- /dev/null > +++ b/drivers/mux/mux-adg792a.c > @@ -0,0 +1,169 @@ > +/* > + * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux > + * > + * Copyright (C) 2016 Axentia Technologies AB > + * > + * Author: Peter Rosin > + * > + * 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_RESETBIT(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)) > + > +#define ADG792A_DISABLE_STATE(4) > + > +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 == ADG792A_DISABLE_STATE) > + cmd = ADG792A_DISABLE_ALL; > + else > + cmd = ADG792A_MUX_ALL(state); > + } else { > + unsigned int controller = mux_control_get_index(mux); > + > + if (state == ADG792A_DISABLE_STATE) > + 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 = &i2c->dev; > + struct mux_chip *mux_chip; > + bool parallel; > + int count; > + int ret; > + int i; > + > + parallel = of_property_read_bool(i2c->dev.of_node, "adi,parallel"); > + > + mux_chip = devm_mux_chip_alloc(dev, parallel ? 1 : 3, 0); > + if (!mux_chip) > + return -ENOMEM; > + > + mux_chip->ops = &adg792a_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 = &mux_chip->mux[i]; > + > + mux->states = 4; > + } > + > + count = of_property_count_u32_elems(dev->of_node, "adi,idle-state"); > + for (i = 0; i < count; i += 2) { > + u32 index; > + u32 idle_state; > + > + ret = of_property_read_u32_index(dev->of_node, > + "adi,idle-state", i, > + &index); > + if (ret < 0) > + return ret; > + if (index >= mux_chip->controllers) { > + dev_err(dev, "invalid mux %u\n", index); > + return -EINVAL; > +
Re: [PATCH v7 10/12] i2c: i2c-mux-simple: new driver
On Wed, Jan 04, 2017 at 01:16:25PM +0100, Peter Rosin wrote: > This is a generic simple i2c mux that uses the generic 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 > Signed-off-by: Peter Rosin Acked-by: Wolfram Sang signature.asc Description: PGP signature
Re: [PATCH v7 00/12] mux controller abstraction and iio/i2c muxes
Hi peda, > 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) to be i2c-mux-simple muxes. In a few lines, what is preventing that? > 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. Maybe ask this question in a seperate email thread on lkml cc-ing the locking gurus (with a pointer to this thread)? > 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... "... and it probably never will support anything other than AT-harddisks, as that's all I have..." ;)) Thanks for this work! Wolfram signature.asc Description: PGP signature
Re: [PATCH v7 00/12] mux controller abstraction and iio/i2c muxes
On 2017-01-08 11:51, Wolfram Sang wrote: > Hi peda, > >> 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) to be i2c-mux-simple muxes. > > In a few lines, what is preventing that? i2c-mux-gpio has the auto-detect for mux-/parent-locked and (old style?) support for specifying what gpios to use with platform data from code (i.e. not from dt/acpi). All of that gets messier if someone else (the mux) owns the gpios. i2c-mux-pinctrl has similar issues. i2c-mux-reg has the platform data from code issue, plus a read-write mode (mux is write only, at least as-is). i2c-mux-pca954x has things going on like irqs (not applied yet) and a reset gpio that makes it a poor candidate for something generic. i2c-mux-mlxcplc could probably be converted (I don't think it existed when I wrote the quoted paragraph). So, since there are issues with just about all of the i2c muxes, the only way forward that I see would be to instantiate the mux locally and feed it to the generic i2c-mux-simple, but what would be the point of that? There would still be a handful of i2c-mux drivers under drivers/i2c/muxes. Maybe some of the above are non-issues and maybe I have failed to see some issue? I didn't think too hard about it... >> 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. > > Maybe ask this question in a seperate email thread on lkml cc-ing the > locking gurus (with a pointer to this thread)? I don't think there is a suitable primitive. In order to get something that really matches, I think the users need to hint how long they (think they) are going to lock the mux. And then it no longer a primitive, methinks. It something that is much heavier... >> 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... > > "... and it probably never will support anything other than > AT-harddisks, as that's all I have..." ;)) :-) > Thanks for this work! And thanks for looking! 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 v7 05/12] mux: support simplified bindings for single-user gpio mux
On 2017-01-08 11:28, Jonathan Cameron wrote: > On 05/01/17 16:21, Peter Rosin wrote: >> On 2017-01-04 13:16, Peter Rosin wrote: >>> Signed-off-by: Peter Rosin >>> --- >>> drivers/mux/mux-core.c | 81 >>> -- >>> drivers/mux/mux-gpio.c | 56 ++ >>> include/linux/mux.h| 7 + >>> 3 files changed, 89 insertions(+), 55 deletions(-) >>> >>> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c >>> index 21da15a264ad..d887ae1c0e55 100644 >>> --- a/drivers/mux/mux-core.c >>> +++ b/drivers/mux/mux-core.c >>> @@ -15,6 +15,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> #include >>> #include >>> #include >>> @@ -288,6 +289,63 @@ static struct mux_chip >>> *of_find_mux_chip_by_node(struct device_node *np) >>> return dev ? to_mux_chip(dev) : NULL; >>> } >>> >>> +#ifdef CONFIG_MUX_GPIO >>> + >>> +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, >>> +}; >>> + >>> +struct mux_chip *mux_gpio_alloc(struct device *dev) >>> +{ >>> + struct mux_chip *mux_chip; >>> + struct mux_gpio *mux_gpio; >>> + int pins; >>> + int ret; >>> + >>> + pins = gpiod_count(dev, "mux"); >>> + if (pins < 0) >>> + return ERR_PTR(pins); >>> + >>> + mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) + >>> + pins * sizeof(*mux_gpio->val)); >>> + if (!mux_chip) >>> + return ERR_PTR(-ENOMEM); >>> + >>> + mux_gpio = mux_chip_priv(mux_chip); >>> + mux_gpio->val = (int *)(mux_gpio + 1); >>> + mux_chip->ops = &mux_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 ERR_PTR(ret); >>> + } >>> + WARN_ON(pins != mux_gpio->gpios->ndescs); >>> + mux_chip->mux->states = 1 << pins; >>> + >>> + return mux_chip; >>> +} >>> +EXPORT_SYMBOL_GPL(mux_gpio_alloc); >>> + >>> +#endif /* CONFIG_MUX_GPIO */ >>> + >>> struct mux_control *mux_control_get(struct device *dev, const char >>> *mux_name) >>> { >>> struct device_node *np = dev->of_node; >>> @@ -307,9 +365,28 @@ struct mux_control *mux_control_get(struct device >>> *dev, const char *mux_name) >>> ret = of_parse_phandle_with_args(np, >>> "mux-controls", "#mux-control-cells", >>> index, &args); >>> + >>> +#ifdef CONFIG_MUX_GPIO >>> + if (ret == -ENOENT && !mux_name && gpiod_count(dev, "mux") > 0) { >>> + mux_chip = mux_gpio_alloc(dev); >>> + if (!IS_ERR(mux_chip)) { >>> + ret = devm_mux_chip_register(dev, mux_chip); >>> + if (ret < 0) { >>> + dev_err(dev, "failed to register mux-chip\n"); >>> + return ERR_PTR(ret); >>> + } >>> + get_device(&mux_chip->dev); >>> + return mux_chip->mux; >>> + } >>> + >>> + ret = PTR_ERR(mux_chip); >>> + } >>> +#endif >>> + >>> if (ret) { >>> - dev_err(dev, "%s: failed to get mux-control %s(%i)\n", >>> - np->full_name, mux_name ?: "", index); >>> + if (ret != -EPROBE_DEFER) >>> + dev_err(dev, "%s: failed to get mux-control %s(%i)\n", >>> + np->full_name, mux_name ?: "", index); >>> return ERR_PTR(ret); >>> } >>> >>> diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c >>> index 76b52bc63470..8a7bfbc0c4bb 100644 >>> --- a/drivers/mux/mux-gpio.c >>> +++ b/drivers/mux/mux-gpio.c >>> @@ -11,37 +11,12 @@ >>> */ >>> >>> #include >>> -#include >>> #include >>> #include >>> #include >>> #include >>> #include >> >> Instead of moving the mux-gpio guts from mux-gpio.c to mux-core.c, I >> will instead make CONFIG_MUX_GPIO a bool option (no module possible) >> and call it from the mux-core. That will be cleaner and less of a >> break of abstractions in my opinion. > Hmm. I wonder if the balance is right here or whether we should just not have > the > simplified binding at all as it breaks the assumption that all muxes are of > the > same level... > > I like the binding, but it is causing significant complexity in here. Yes, in this
Re: [PATCH v7 03/12] mux: minimal mux subsystem and gpio-based mux controller
On 2017-01-08 11:23, Jonathan Cameron wrote: > On 04/01/17 12:16, 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. >> >> Signed-off-by: Peter Rosin > Reviewed-by: Jonathan Cameron >> --- >> Documentation/driver-model/devres.txt | 8 + >> MAINTAINERS | 2 + >> drivers/Kconfig | 2 + >> drivers/Makefile | 1 + >> drivers/mux/Kconfig | 33 +++ >> drivers/mux/Makefile | 6 + >> drivers/mux/mux-core.c| 398 >> ++ >> drivers/mux/mux-gpio.c| 120 ++ >> include/linux/mux.h | 244 + >> 9 files changed, 814 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 dc51fb024190..1e9ae701a587 100644 >> --- a/Documentation/driver-model/devres.txt >> +++ b/Documentation/driver-model/devres.txt >> @@ -332,6 +332,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 32abef2b6d05..ebe96f3e25a0 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -8442,6 +8442,8 @@ MULTIPLEXER SUBSYSTEM >> M: Peter Rosin >> S: Maintained >> F: Documentation/devicetree/bindings/mux/ >> +F: include/linux/mux.h >> +F: drivers/mux/ >> >> MULTISOUND SOUND DRIVER >> M: Andrew Veliath >> diff --git a/drivers/Kconfig b/drivers/Kconfig >> index e1e2066cecdb..993aeb65affa 100644 >> --- a/drivers/Kconfig >> +++ b/drivers/Kconfig >> @@ -76,6 +76,8 @@ source "drivers/hwmon/Kconfig" >> >> source "drivers/thermal/Kconfig" >> >> +source "drivers/mux/Kconfig" >> + > > Why this location in the list? I think the convention for new subystems is > to just go last in the list. Oh. I'll move it to the end... Thanks for all your acks/reviews! 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 linux 2/6] hwmon: occ: Add sysfs interface
On Sat, 2017-01-07 at 09:15 -0800, Guenter Roeck wrote: > On 01/06/2017 02:17 PM, Edward James wrote: > > [ ... ] > > > > > +} > > > > + > > > > +static DEVICE_ATTR(online, S_IWUSR | S_IRUGO, show_occ_online, > > > > + store_occ_online); > > > > + > > > > +struct occ_sysfs *occ_sysfs_start(struct device *dev, struct occ *occ, > > > > + struct occ_sysfs_config *config) > > > > +{ > > > > + struct occ_sysfs *hwmon = devm_kzalloc(dev, sizeof(struct > > > > occ_sysfs), > > > > + GFP_KERNEL); > > > > + int rc; > > > > + > > > > + if (!hwmon) > > > > + return ERR_PTR(-ENOMEM); > > > > + > > > > + hwmon->occ = occ; > > > > + hwmon->num_caps_fields = config->num_caps_fields; > > > > + hwmon->caps_names = config->caps_names; > > > > + > > > > + dev_set_drvdata(dev, hwmon); > > > > + > > > > + rc = device_create_file(dev, &dev_attr_online); > > > > + if (rc) > > > > + return ERR_PTR(rc); > > > > + > > > > + return hwmon; > > > > +} > > > > +EXPORT_SYMBOL(occ_sysfs_start); > > > > + > > > > +int occ_sysfs_stop(struct device *dev, struct occ_sysfs *driver) > > > > +{ > > > > + if (driver->dev) { > > > > + occ_remove_hwmon_attrs(driver); > > > > + hwmon_device_unregister(driver->dev); > > > > + } > > > > + > > > > + device_remove_file(driver->dev, &dev_attr_online); > > > > + > > > > + devm_kfree(dev, driver); > > > > > > Thw point of using devm_ functions is not to require remove/free > > > functions. > > > Something is completely wrong here if you need that call. > > > > > > Overall, this is architectually completely wrong. One does not register > > > or instantiate drivers based on writing into sysfs attributes. Please > > > reconsider your approach. > > > > We had some trouble designing this driver because the BMC only has > > access to the OCC once the processor is powered on. This will happen > > sometime after the BMC boots (this driver runs only on the BMC). With > > no access to the OCC, we don't know what sensors are present on the > > system without a large static enumeration. Also any sysfs files created > > before we have OCC access won't be able to return any data. > > > > Instead of the "online" attribute, what do you think about using the > > "bind"/"unbind" API to probe the device from user space once the system > > is powered on? All the hwmon registration would take place in the probe > > function, it would just occur some time after boot. > > > > A more common approach would be to have a platform driver. That platform > driver would need a means to detect if the OCC is up and running, and > instantiate everything else once it is. > > A trigger from user space is problematic because there is no guarantee > that the OCC is really up (or that it even exists). This is true in general, but for the BMC case we have more information: The host CPU power supply is controlled by several GPIOs from userspace. Once we receive the "power-good" signal for the host CPU we can bind the OCC driver and trigger the probe. Alternatively, in the style of your first para, we could push the host CPU state management into the kernel and expose a boot/reboot/power-off API to userspace. That would give us a place to hook calls for configuring and cleaning up any host-dependent drivers on the BMC. The solution to the host-power-state problem is also applicable to the OpenFSI patches that were recently sent out: https://lkml.org/lkml/2016/12/6/732 The OpenFSI infra needs to re-scan for CFAMs when the host is powered up. > > An alternative might be to have the hwmon driver poll for the OCC, > but that would be a bit more difficult and might require a kernel thread > or maybe asynchronous probing. This was our thought as a fallback solution. Andrew > > Guenter > signature.asc Description: This is a digitally signed message part
Re: [PATCH 0/3] PM / docs: linux/pm.h kerneldocs update and conversion of two docs to reST
On Fri, Jan 06, 2017 at 02:38:13AM +0100, Rafael J. Wysocki wrote: > I sent patches [1-2/3] previosly a couple of weeks ago and there have not > been any comments since then, so either they are fine by everybody or the > timing was particularly bad and no one had the time to look at them. So far I was only able to peruse the "Device Power Management Data Types" section (which is generated from include/linux/pm.h) and came across the following: The description for the ->prepare hook says: If the transition is a suspend to memory or standby (that is, not related to hibernation), the return value of @prepare() may be used to indicate to the PM core to leave the device in runtime suspend if applicable. Maybe I'm missing something but in the places where the direct_complete flag is calculated (e.g. in pci_dev_keep_suspended()) or where it's checked, I don't see that we're differentiating anywhere whether we're going through a suspend-to-RAM versus suspend-to-disk transition. So in the above snippet, the portion "If the transition is a suspend to memory or standby (that is, not related to hibernation)" seems wrong and should probably be removed. I know you're not touching this paragraph in the present commits, it's just something that caught my eye while going over the rendered output. Furthermore, the description for the ->freeze hook says: Analogous to @suspend(), but it should not enable the device to signal wakeup events or change its power state. However looking at the PCI core it looks like this constraint isn't satisfied, pci_dev_keep_suspended() (which gets called from ->prepare) disables PME only if: if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold && !device_may_wakeup(dev)) __pci_pme_active(pci_dev, false); Shouldn't this be something like: if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold && (!device_may_wakeup(dev) || (system_entering_hibernation() && system_state != SYSTEM_POWER_OFF))) __pci_pme_active(pci_dev, false); So that PME is disabled before entering the freeze phase for direct_complete devices, but not before entering the poweroff phase. Thanks, Lukas -- 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