aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/i2c-mux.c')
-rw-r--r--drivers/i2c/i2c-mux.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d7a4833be416..1038c381aea5 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -24,6 +24,8 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/i2c-mux.h> 26#include <linux/i2c-mux.h>
27#include <linux/of.h>
28#include <linux/of_i2c.h>
27 29
28/* multiplexer per channel data */ 30/* multiplexer per channel data */
29struct i2c_mux_priv { 31struct i2c_mux_priv {
@@ -31,11 +33,11 @@ struct i2c_mux_priv {
31 struct i2c_algorithm algo; 33 struct i2c_algorithm algo;
32 34
33 struct i2c_adapter *parent; 35 struct i2c_adapter *parent;
34 void *mux_dev; /* the mux chip/device */ 36 void *mux_priv; /* the mux chip/device */
35 u32 chan_id; /* the channel id */ 37 u32 chan_id; /* the channel id */
36 38
37 int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); 39 int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
38 int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); 40 int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
39}; 41};
40 42
41static int i2c_mux_master_xfer(struct i2c_adapter *adap, 43static int i2c_mux_master_xfer(struct i2c_adapter *adap,
@@ -47,11 +49,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
47 49
48 /* Switch to the right mux port and perform the transfer. */ 50 /* Switch to the right mux port and perform the transfer. */
49 51
50 ret = priv->select(parent, priv->mux_dev, priv->chan_id); 52 ret = priv->select(parent, priv->mux_priv, priv->chan_id);
51 if (ret >= 0) 53 if (ret >= 0)
52 ret = parent->algo->master_xfer(parent, msgs, num); 54 ret = parent->algo->master_xfer(parent, msgs, num);
53 if (priv->deselect) 55 if (priv->deselect)
54 priv->deselect(parent, priv->mux_dev, priv->chan_id); 56 priv->deselect(parent, priv->mux_priv, priv->chan_id);
55 57
56 return ret; 58 return ret;
57} 59}
@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
67 69
68 /* Select the right mux port and perform the transfer. */ 70 /* Select the right mux port and perform the transfer. */
69 71
70 ret = priv->select(parent, priv->mux_dev, priv->chan_id); 72 ret = priv->select(parent, priv->mux_priv, priv->chan_id);
71 if (ret >= 0) 73 if (ret >= 0)
72 ret = parent->algo->smbus_xfer(parent, addr, flags, 74 ret = parent->algo->smbus_xfer(parent, addr, flags,
73 read_write, command, size, data); 75 read_write, command, size, data);
74 if (priv->deselect) 76 if (priv->deselect)
75 priv->deselect(parent, priv->mux_dev, priv->chan_id); 77 priv->deselect(parent, priv->mux_priv, priv->chan_id);
76 78
77 return ret; 79 return ret;
78} 80}
@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap)
87} 89}
88 90
89struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, 91struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
90 void *mux_dev, u32 force_nr, u32 chan_id, 92 struct device *mux_dev,
93 void *mux_priv, u32 force_nr, u32 chan_id,
91 int (*select) (struct i2c_adapter *, 94 int (*select) (struct i2c_adapter *,
92 void *, u32), 95 void *, u32),
93 int (*deselect) (struct i2c_adapter *, 96 int (*deselect) (struct i2c_adapter *,
@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
102 105
103 /* Set up private adapter data */ 106 /* Set up private adapter data */
104 priv->parent = parent; 107 priv->parent = parent;
105 priv->mux_dev = mux_dev; 108 priv->mux_priv = mux_priv;
106 priv->chan_id = chan_id; 109 priv->chan_id = chan_id;
107 priv->select = select; 110 priv->select = select;
108 priv->deselect = deselect; 111 priv->deselect = deselect;
@@ -124,6 +127,25 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
124 priv->adap.algo_data = priv; 127 priv->adap.algo_data = priv;
125 priv->adap.dev.parent = &parent->dev; 128 priv->adap.dev.parent = &parent->dev;
126 129
130 /*
131 * Try to populate the mux adapter's of_node, expands to
132 * nothing if !CONFIG_OF.
133 */
134 if (mux_dev->of_node) {
135 struct device_node *child;
136 u32 reg;
137
138 for_each_child_of_node(mux_dev->of_node, child) {
139 ret = of_property_read_u32(child, "reg", &reg);
140 if (ret)
141 continue;
142 if (chan_id == reg) {
143 priv->adap.dev.of_node = child;
144 break;
145 }
146 }
147 }
148
127 if (force_nr) { 149 if (force_nr) {
128 priv->adap.nr = force_nr; 150 priv->adap.nr = force_nr;
129 ret = i2c_add_numbered_adapter(&priv->adap); 151 ret = i2c_add_numbered_adapter(&priv->adap);
@@ -141,6 +163,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
141 dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", 163 dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
142 i2c_adapter_id(&priv->adap)); 164 i2c_adapter_id(&priv->adap));
143 165
166 of_i2c_register_devices(&priv->adap);
167
144 return &priv->adap; 168 return &priv->adap;
145} 169}
146EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); 170EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);