Commit 6d54f144 authored by Wolfram Sang's avatar Wolfram Sang

Merge branch 'i2c-mux-dt-3' of https://github.com/peda-r/i2c-mux into i2c/for-4.9

Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parents 0317e6c0 8a191a7a
...@@ -44,8 +44,7 @@ Required properties: ...@@ -44,8 +44,7 @@ Required properties:
- our-claim-gpio: The GPIO that we use to claim the bus. - 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. - 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. Note that some implementations may only support a single other master.
- Standard I2C mux properties. See i2c-mux.txt in this directory. - I2C arbitration bus node. See i2c-arb.txt in this directory.
- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
Optional properties: Optional properties:
- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us. - slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
...@@ -63,8 +62,6 @@ Example: ...@@ -63,8 +62,6 @@ Example:
i2c-arbitrator { i2c-arbitrator {
compatible = "i2c-arb-gpio-challenge"; compatible = "i2c-arb-gpio-challenge";
#address-cells = <1>;
#size-cells = <0>;
i2c-parent = <&{/i2c@12CA0000}>; i2c-parent = <&{/i2c@12CA0000}>;
...@@ -74,8 +71,7 @@ Example: ...@@ -74,8 +71,7 @@ Example:
wait-retry-us = <3000>; wait-retry-us = <3000>;
wait-free-us = <50000>; wait-free-us = <50000>;
i2c@0 { i2c-arb {
reg = <0>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
......
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;
};
};
};
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>;
};
};
};
...@@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties. ...@@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties.
An i2c bus multiplexer/switch will have several child busses that are 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 numbered uniquely in a device dependent manner. The nodes for an i2c bus
multiplexer/switch will have one child node for each child multiplexer/switch will have one child node for each child bus.
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>; - #address-cells = <1>;
- #size-cells = <0>; - #size-cells = <0>;
Required properties for child nodes: Required properties for i2c child bus nodes:
- #address-cells = <1>; - #address-cells = <1>;
- #size-cells = <0>; - #size-cells = <0>;
- reg : The sub-bus number. - 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. - Other properties specific to the multiplexer/switch hardware.
- Child nodes conforming to i2c bus binding - Child nodes conforming to i2c bus binding
......
* 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>;
};
};
};
...@@ -5675,6 +5675,8 @@ S: Maintained ...@@ -5675,6 +5675,8 @@ S: Maintained
F: Documentation/i2c/i2c-topology F: Documentation/i2c/i2c-topology
F: Documentation/i2c/muxes/ F: Documentation/i2c/muxes/
F: Documentation/devicetree/bindings/i2c/i2c-mux* 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/i2c-mux.c
F: drivers/i2c/muxes/ F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h F: include/linux/i2c-mux.h
......
...@@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, ...@@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
muxc->dev = dev; muxc->dev = dev;
if (flags & I2C_MUX_LOCKED) if (flags & I2C_MUX_LOCKED)
muxc->mux_locked = true; muxc->mux_locked = true;
if (flags & I2C_MUX_ARBITRATOR)
muxc->arbitrator = true;
if (flags & I2C_MUX_GATE)
muxc->gate = true;
muxc->select = select; muxc->select = select;
muxc->deselect = deselect; muxc->deselect = deselect;
muxc->max_adapters = max_adapters; muxc->max_adapters = max_adapters;
...@@ -335,18 +339,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, ...@@ -335,18 +339,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
* nothing if !CONFIG_OF. * nothing if !CONFIG_OF.
*/ */
if (muxc->dev->of_node) { 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; u32 reg;
for_each_child_of_node(muxc->dev->of_node, child) { if (muxc->arbitrator)
ret = of_property_read_u32(child, "reg", &reg); mux_node = of_get_child_by_name(dev_node, "i2c-arb");
if (ret) else if (muxc->gate)
continue; mux_node = of_get_child_by_name(dev_node, "i2c-gate");
if (chan_id == reg) { else
priv->adap.dev.of_node = child; mux_node = of_get_child_by_name(dev_node, "i2c-mux");
break;
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);
} }
/* /*
......
...@@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) ...@@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return -EINVAL; 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); i2c_arbitrator_select, i2c_arbitrator_deselect);
if (!muxc) if (!muxc)
return -ENOMEM; return -ENOMEM;
......
...@@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = { ...@@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = {
MODULE_DEVICE_TABLE(i2c, 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() * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
* as they will try to lock the adapter a second time. * as they will try to lock the adapter a second time.
...@@ -349,7 +356,8 @@ static int pca9541_probe(struct i2c_client *client, ...@@ -349,7 +356,8 @@ static int pca9541_probe(struct i2c_client *client,
force = 0; force = 0;
if (pdata) if (pdata)
force = pdata->modes[0].adap_id; 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); pca9541_select_chan, pca9541_release_chan);
if (!muxc) if (!muxc)
return -ENOMEM; return -ENOMEM;
...@@ -382,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client) ...@@ -382,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client)
static struct i2c_driver pca9541_driver = { static struct i2c_driver pca9541_driver = {
.driver = { .driver = {
.name = "pca9541", .name = "pca9541",
.of_match_table = of_match_ptr(pca9541_of_match),
}, },
.probe = pca9541_probe, .probe = pca9541_probe,
.remove = pca9541_remove, .remove = pca9541_remove,
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/i2c/pca954x.h> #include <linux/i2c/pca954x.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -58,14 +59,6 @@ enum pca_type { ...@@ -58,14 +59,6 @@ enum pca_type {
pca_9548, pca_9548,
}; };
struct pca954x {
enum pca_type type;
u8 last_chan; /* last register value */
u8 deselect;
struct i2c_client *client;
};
struct chip_desc { struct chip_desc {
u8 nchans; u8 nchans;
u8 enable; /* used for muxes only */ u8 enable; /* used for muxes only */
...@@ -75,6 +68,14 @@ struct chip_desc { ...@@ -75,6 +68,14 @@ struct chip_desc {
} muxtype; } muxtype;
}; };
struct pca954x {
const struct chip_desc *chip;
u8 last_chan; /* last register value */
u8 deselect;
struct i2c_client *client;
};
/* Provide specs for the PCA954x types we know about */ /* Provide specs for the PCA954x types we know about */
static const struct chip_desc chips[] = { static const struct chip_desc chips[] = {
[pca_9540] = { [pca_9540] = {
...@@ -119,6 +120,20 @@ static const struct i2c_device_id pca954x_id[] = { ...@@ -119,6 +120,20 @@ static const struct i2c_device_id pca954x_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, pca954x_id); MODULE_DEVICE_TABLE(i2c, pca954x_id);
#ifdef CONFIG_OF
static const struct of_device_id pca954x_of_match[] = {
{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },
{ .compatible = "nxp,pca9542", .data = &chips[pca_9542] },
{ .compatible = "nxp,pca9543", .data = &chips[pca_9543] },
{ .compatible = "nxp,pca9544", .data = &chips[pca_9544] },
{ .compatible = "nxp,pca9545", .data = &chips[pca_9545] },
{ .compatible = "nxp,pca9546", .data = &chips[pca_9546] },
{ .compatible = "nxp,pca9547", .data = &chips[pca_9547] },
{ .compatible = "nxp,pca9548", .data = &chips[pca_9548] },
{}
};
#endif
/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
for this as they will try to lock adapter a second time */ for this as they will try to lock adapter a second time */
static int pca954x_reg_write(struct i2c_adapter *adap, static int pca954x_reg_write(struct i2c_adapter *adap,
...@@ -151,7 +166,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) ...@@ -151,7 +166,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
{ {
struct pca954x *data = i2c_mux_priv(muxc); struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
const struct chip_desc *chip = &chips[data->type]; const struct chip_desc *chip = data->chip;
u8 regval; u8 regval;
int ret = 0; int ret = 0;
...@@ -197,6 +212,7 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -197,6 +212,7 @@ static int pca954x_probe(struct i2c_client *client,
int num, force, class; int num, force, class;
struct i2c_mux_core *muxc; struct i2c_mux_core *muxc;
struct pca954x *data; struct pca954x *data;
const struct of_device_id *match;
int ret; int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
...@@ -226,14 +242,19 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -226,14 +242,19 @@ static int pca954x_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
data->type = id->driver_data; match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
data->last_chan = 0; /* force the first selection */ data->last_chan = 0; /* force the first selection */
idle_disconnect_dt = of_node && idle_disconnect_dt = of_node &&
of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
/* Now create an adapter for each channel */ /* Now create an adapter for each channel */
for (num = 0; num < chips[data->type].nchans; num++) { for (num = 0; num < data->chip->nchans; num++) {
bool idle_disconnect_pd = false; bool idle_disconnect_pd = false;
force = 0; /* dynamic adap number */ force = 0; /* dynamic adap number */
...@@ -263,7 +284,7 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -263,7 +284,7 @@ static int pca954x_probe(struct i2c_client *client,
dev_info(&client->dev, dev_info(&client->dev,
"registered %d multiplexed busses for I2C %s %s\n", "registered %d multiplexed busses for I2C %s %s\n",
num, chips[data->type].muxtype == pca954x_ismux num, data->chip->muxtype == pca954x_ismux
? "mux" : "switch", client->name); ? "mux" : "switch", client->name);
return 0; return 0;
...@@ -299,6 +320,7 @@ static struct i2c_driver pca954x_driver = { ...@@ -299,6 +320,7 @@ static struct i2c_driver pca954x_driver = {
.driver = { .driver = {
.name = "pca954x", .name = "pca954x",
.pm = &pca954x_pm, .pm = &pca954x_pm,
.of_match_table = of_match_ptr(pca954x_of_match),
}, },
.probe = pca954x_probe, .probe = pca954x_probe,
.remove = pca954x_remove, .remove = pca954x_remove,
......
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
struct i2c_mux_core { struct i2c_mux_core {
struct i2c_adapter *parent; struct i2c_adapter *parent;
struct device *dev; struct device *dev;
bool mux_locked; unsigned int mux_locked:1;
unsigned int arbitrator:1;
unsigned int gate:1;
void *priv; void *priv;
...@@ -51,7 +53,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, ...@@ -51,7 +53,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
int (*deselect)(struct i2c_mux_core *, u32)); int (*deselect)(struct i2c_mux_core *, u32));
/* flags for i2c_mux_alloc */ /* flags for i2c_mux_alloc */
#define I2C_MUX_LOCKED BIT(0) #define I2C_MUX_LOCKED BIT(0)
#define I2C_MUX_ARBITRATOR BIT(1)
#define I2C_MUX_GATE BIT(2)
static inline void *i2c_mux_priv(struct i2c_mux_core *muxc) static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment