Skip to content

Commit

Permalink
Merge branch 'i2c-mux-dt-3' of https://github.com/peda-r/i2c-mux into…
Browse files Browse the repository at this point in the history
… i2c/for-4.9

Signed-off-by: Wolfram Sang <[email protected]>
  • Loading branch information
Wolfram Sang committed Aug 25, 2016
2 parents 0317e6c + 8a191a7 commit 6d54f14
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ Required properties:
- our-claim-gpio: The GPIO that we use to claim the bus.
- their-claim-gpios: The GPIOs that the other sides use to claim the bus.
Note that some implementations may only support a single other master.
- Standard I2C mux properties. See i2c-mux.txt in this directory.
- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
- I2C arbitration bus node. See i2c-arb.txt in this directory.

Optional properties:
- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
Expand All @@ -63,8 +62,6 @@ Example:

i2c-arbitrator {
compatible = "i2c-arb-gpio-challenge";
#address-cells = <1>;
#size-cells = <0>;

i2c-parent = <&{/i2c@12CA0000}>;

Expand All @@ -74,8 +71,7 @@ Example:
wait-retry-us = <3000>;
wait-free-us = <50000>;

i2c@0 {
reg = <0>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;

Expand Down
35 changes: 35 additions & 0 deletions Documentation/devicetree/bindings/i2c/i2c-arb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Common i2c arbitration bus properties.

- i2c-arb child node

Required properties for the i2c-arb child node:
- #address-cells = <1>;
- #size-cells = <0>;

Optional properties for i2c-arb child node:
- Child nodes conforming to i2c bus binding


Example :

/*
An NXP pca9541 I2C bus master selector at address 0x74
with a NXP pca8574 GPIO expander attached.
*/

arb@74 {
compatible = "nxp,pca9541";
reg = <0x74>;

i2c-arb {
#address-cells = <1>;
#size-cells = <0>;

gpio@38 {
compatible = "nxp,pca8574";
reg = <0x38>;
#gpio-cells = <2>;
gpio-controller;
};
};
};
41 changes: 41 additions & 0 deletions Documentation/devicetree/bindings/i2c/i2c-gate.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
An i2c gate is useful to e.g. reduce the digital noise for RF tuners connected
to the i2c bus. Gates are similar to arbitrators in that you need to perform
some kind of operation to access the i2c bus past the arbitrator/gate, but
there are no competing masters to consider for gates and therefore there is
no arbitration happening for gates.

Common i2c gate properties.

- i2c-gate child node

Required properties for the i2c-gate child node:
- #address-cells = <1>;
- #size-cells = <0>;

Optional properties for i2c-gate child node:
- Child nodes conforming to i2c bus binding


Example :

/*
An Invensense mpu9150 at address 0x68 featuring an on-chip Asahi
Kasei ak8975 compass behind a gate.
*/

mpu9150@68 {
compatible = "invensense,mpu9150";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 1>;

i2c-gate {
#address-cells = <1>;
#size-cells = <0>;

ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
23 changes: 18 additions & 5 deletions Documentation/devicetree/bindings/i2c/i2c-mux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties.

An i2c bus multiplexer/switch will have several child busses that are
numbered uniquely in a device dependent manner. The nodes for an i2c bus
multiplexer/switch will have one child node for each child
bus.
multiplexer/switch will have one child node for each child bus.

Required properties:
Optional properties:
- #address-cells = <1>;
This property is required is the i2c-mux child node does not exist.

- #size-cells = <0>;
This property is required is the i2c-mux child node does not exist.

- i2c-mux
For i2c multiplexers/switches that have child nodes that are a mixture
of both i2c child busses and other child nodes, the 'i2c-mux' subnode
can be used for populating the i2c child busses. If an 'i2c-mux'
subnode is present, only subnodes of this will be considered as i2c
child busses.

Required properties for the i2c-mux child node:
- #address-cells = <1>;
- #size-cells = <0>;

Required properties for child nodes:
Required properties for i2c child bus nodes:
- #address-cells = <1>;
- #size-cells = <0>;
- reg : The sub-bus number.

Optional properties for child nodes:
Optional properties for i2c child bus nodes:
- Other properties specific to the multiplexer/switch hardware.
- Child nodes conforming to i2c bus binding

Expand Down
29 changes: 29 additions & 0 deletions Documentation/devicetree/bindings/i2c/nxp,pca9541.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
* NXP PCA9541 I2C bus master selector

Required Properties:

- compatible: Must be "nxp,pca9541"

- reg: The I2C address of the device.

The following required properties are defined externally:

- I2C arbitration bus node. See i2c-arb.txt in this directory.


Example:

i2c-arbitrator@74 {
compatible = "nxp,pca9541";
reg = <0x74>;

i2c-arb {
#address-cells = <1>;
#size-cells = <0>;

eeprom@54 {
compatible = "at,24c08";
reg = <0x54>;
};
};
};
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5675,6 +5675,8 @@ S: Maintained
F: Documentation/i2c/i2c-topology
F: Documentation/i2c/muxes/
F: Documentation/devicetree/bindings/i2c/i2c-mux*
F: Documentation/devicetree/bindings/i2c/i2c-arb*
F: Documentation/devicetree/bindings/i2c/i2c-gate*
F: drivers/i2c/i2c-mux.c
F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h
Expand Down
44 changes: 36 additions & 8 deletions drivers/i2c/i2c-mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
muxc->dev = dev;
if (flags & I2C_MUX_LOCKED)
muxc->mux_locked = true;
if (flags & I2C_MUX_ARBITRATOR)
muxc->arbitrator = true;
if (flags & I2C_MUX_GATE)
muxc->gate = true;
muxc->select = select;
muxc->deselect = deselect;
muxc->max_adapters = max_adapters;
Expand Down Expand Up @@ -335,18 +339,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
* nothing if !CONFIG_OF.
*/
if (muxc->dev->of_node) {
struct device_node *child;
struct device_node *dev_node = muxc->dev->of_node;
struct device_node *mux_node, *child = NULL;
u32 reg;

for_each_child_of_node(muxc->dev->of_node, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
continue;
if (chan_id == reg) {
priv->adap.dev.of_node = child;
break;
if (muxc->arbitrator)
mux_node = of_get_child_by_name(dev_node, "i2c-arb");
else if (muxc->gate)
mux_node = of_get_child_by_name(dev_node, "i2c-gate");
else
mux_node = of_get_child_by_name(dev_node, "i2c-mux");

if (mux_node) {
/* A "reg" property indicates an old-style DT entry */
if (!of_property_read_u32(mux_node, "reg", &reg)) {
of_node_put(mux_node);
mux_node = NULL;
}
}

if (!mux_node)
mux_node = of_node_get(dev_node);
else if (muxc->arbitrator || muxc->gate)
child = of_node_get(mux_node);

if (!child) {
for_each_child_of_node(mux_node, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
continue;
if (chan_id == reg)
break;
}
}

priv->adap.dev.of_node = child;
of_node_put(mux_node);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/muxes/i2c-arb-gpio-challenge.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return -EINVAL;
}

muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0,
muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR,
i2c_arbitrator_select, i2c_arbitrator_deselect);
if (!muxc)
return -ENOMEM;
Expand Down
11 changes: 10 additions & 1 deletion drivers/i2c/muxes/i2c-mux-pca9541.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = {

MODULE_DEVICE_TABLE(i2c, pca9541_id);

#ifdef CONFIG_OF
static const struct of_device_id pca9541_of_match[] = {
{ .compatible = "nxp,pca9541" },
{}
};
#endif

/*
* Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
* as they will try to lock the adapter a second time.
Expand Down Expand Up @@ -349,7 +356,8 @@ static int pca9541_probe(struct i2c_client *client,
force = 0;
if (pdata)
force = pdata->modes[0].adap_id;
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0,
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
I2C_MUX_ARBITRATOR,
pca9541_select_chan, pca9541_release_chan);
if (!muxc)
return -ENOMEM;
Expand Down Expand Up @@ -382,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client)
static struct i2c_driver pca9541_driver = {
.driver = {
.name = "pca9541",
.of_match_table = of_match_ptr(pca9541_of_match),
},
.probe = pca9541_probe,
.remove = pca9541_remove,
Expand Down
Loading

0 comments on commit 6d54f14

Please sign in to comment.