blob: 5ce1b0704cb59f838eddc845eef5ca33a318b9f4 [file] [log] [blame]
Michael Lawnick08263742010-08-11 18:21:02 +02001/*
2 * Multiplexed I2C bus driver.
3 *
4 * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
5 * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
6 * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com>
7 *
8 * Simplifies access to complex multiplexed I2C bus topologies, by presenting
9 * each multiplexed bus segment as an additional I2C adapter.
10 * Supports multi-level mux'ing (mux behind a mux).
11 *
12 * Based on:
13 * i2c-virt.c from Kumar Gala <galak@kernel.crashing.org>
14 * i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc.
15 * i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com>
16 *
17 * This file is licensed under the terms of the GNU General Public
18 * License version 2. This program is licensed "as is" without any
19 * warranty of any kind, whether express or implied.
20 */
21
Wolfram Sang51714932016-02-20 23:33:39 +010022#include <linux/acpi.h>
Michael Lawnick08263742010-08-11 18:21:02 +020023#include <linux/i2c.h>
24#include <linux/i2c-mux.h>
Wolfram Sang51714932016-02-20 23:33:39 +010025#include <linux/kernel.h>
26#include <linux/module.h>
David Daneybc454492012-04-12 14:14:23 -070027#include <linux/of.h>
Wolfram Sang51714932016-02-20 23:33:39 +010028#include <linux/slab.h>
Michael Lawnick08263742010-08-11 18:21:02 +020029
30/* multiplexer per channel data */
Peter Rosina7ab7232016-04-20 08:38:50 +020031struct i2c_mux_priv_old {
32 void *mux_priv;
33 int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
34 int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
35};
36
Michael Lawnick08263742010-08-11 18:21:02 +020037struct i2c_mux_priv {
38 struct i2c_adapter adap;
39 struct i2c_algorithm algo;
Peter Rosina7ab7232016-04-20 08:38:50 +020040 struct i2c_mux_core *muxc;
Wolfram Sang13377842015-04-23 10:29:09 +020041 u32 chan_id;
Michael Lawnick08263742010-08-11 18:21:02 +020042};
43
44static int i2c_mux_master_xfer(struct i2c_adapter *adap,
45 struct i2c_msg msgs[], int num)
46{
47 struct i2c_mux_priv *priv = adap->algo_data;
Peter Rosina7ab7232016-04-20 08:38:50 +020048 struct i2c_mux_core *muxc = priv->muxc;
49 struct i2c_adapter *parent = muxc->parent;
Michael Lawnick08263742010-08-11 18:21:02 +020050 int ret;
51
52 /* Switch to the right mux port and perform the transfer. */
53
Peter Rosina7ab7232016-04-20 08:38:50 +020054 ret = muxc->select(muxc, priv->chan_id);
Michael Lawnick08263742010-08-11 18:21:02 +020055 if (ret >= 0)
Alexander Sverdline766f332015-06-12 14:40:37 +020056 ret = __i2c_transfer(parent, msgs, num);
Peter Rosina7ab7232016-04-20 08:38:50 +020057 if (muxc->deselect)
58 muxc->deselect(muxc, priv->chan_id);
Michael Lawnick08263742010-08-11 18:21:02 +020059
60 return ret;
61}
62
63static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
64 u16 addr, unsigned short flags,
65 char read_write, u8 command,
66 int size, union i2c_smbus_data *data)
67{
68 struct i2c_mux_priv *priv = adap->algo_data;
Peter Rosina7ab7232016-04-20 08:38:50 +020069 struct i2c_mux_core *muxc = priv->muxc;
70 struct i2c_adapter *parent = muxc->parent;
Michael Lawnick08263742010-08-11 18:21:02 +020071 int ret;
72
73 /* Select the right mux port and perform the transfer. */
74
Peter Rosina7ab7232016-04-20 08:38:50 +020075 ret = muxc->select(muxc, priv->chan_id);
Michael Lawnick08263742010-08-11 18:21:02 +020076 if (ret >= 0)
77 ret = parent->algo->smbus_xfer(parent, addr, flags,
78 read_write, command, size, data);
Peter Rosina7ab7232016-04-20 08:38:50 +020079 if (muxc->deselect)
80 muxc->deselect(muxc, priv->chan_id);
Michael Lawnick08263742010-08-11 18:21:02 +020081
82 return ret;
83}
84
85/* Return the parent's functionality */
86static u32 i2c_mux_functionality(struct i2c_adapter *adap)
87{
88 struct i2c_mux_priv *priv = adap->algo_data;
Peter Rosina7ab7232016-04-20 08:38:50 +020089 struct i2c_adapter *parent = priv->muxc->parent;
Michael Lawnick08263742010-08-11 18:21:02 +020090
91 return parent->algo->functionality(parent);
92}
93
Jean Delvareeee543e2012-10-05 22:23:51 +020094/* Return all parent classes, merged */
95static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
96{
97 unsigned int class = 0;
98
99 do {
100 class |= parent->class;
101 parent = i2c_parent_is_i2c_adapter(parent);
102 } while (parent);
103
104 return class;
105}
106
Peter Rosina7ab7232016-04-20 08:38:50 +0200107static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
108{
109 struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
110
111 return priv->select(muxc->parent, priv->mux_priv, chan);
112}
113
114static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
115{
116 struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
117
118 return priv->deselect(muxc->parent, priv->mux_priv, chan);
119}
120
Michael Lawnick08263742010-08-11 18:21:02 +0200121struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
David Daney5a3ecd52012-04-12 14:14:22 -0700122 struct device *mux_dev,
123 void *mux_priv, u32 force_nr, u32 chan_id,
Jean Delvareeee543e2012-10-05 22:23:51 +0200124 unsigned int class,
Michael Lawnick08263742010-08-11 18:21:02 +0200125 int (*select) (struct i2c_adapter *,
126 void *, u32),
127 int (*deselect) (struct i2c_adapter *,
128 void *, u32))
129{
Peter Rosina7ab7232016-04-20 08:38:50 +0200130 struct i2c_mux_core *muxc;
131 struct i2c_mux_priv_old *priv;
132 int ret;
133
134 muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0,
135 i2c_mux_select, i2c_mux_deselect);
136 if (!muxc)
137 return NULL;
138
139 priv = i2c_mux_priv(muxc);
140 priv->select = select;
141 priv->deselect = deselect;
142 priv->mux_priv = mux_priv;
143
144 ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class);
145 if (ret) {
146 devm_kfree(mux_dev, muxc);
147 return NULL;
148 }
149
150 return muxc->adapter[0];
151}
152EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
153
154struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
155 struct device *dev, int max_adapters,
156 int sizeof_priv, u32 flags,
157 int (*select)(struct i2c_mux_core *, u32),
158 int (*deselect)(struct i2c_mux_core *, u32))
159{
160 struct i2c_mux_core *muxc;
161
162 muxc = devm_kzalloc(dev, sizeof(*muxc)
163 + max_adapters * sizeof(muxc->adapter[0])
164 + sizeof_priv, GFP_KERNEL);
165 if (!muxc)
166 return NULL;
167 if (sizeof_priv)
168 muxc->priv = &muxc->adapter[max_adapters];
169
170 muxc->parent = parent;
171 muxc->dev = dev;
172 muxc->select = select;
173 muxc->deselect = deselect;
174 muxc->max_adapters = max_adapters;
175
176 return muxc;
177}
178EXPORT_SYMBOL_GPL(i2c_mux_alloc);
179
180int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
181 u32 force_nr, u32 chan_id,
182 unsigned int class)
183{
184 struct i2c_adapter *parent = muxc->parent;
Michael Lawnick08263742010-08-11 18:21:02 +0200185 struct i2c_mux_priv *priv;
Gerlando Falautoc9449af2014-11-13 14:39:56 +0100186 char symlink_name[20];
Michael Lawnick08263742010-08-11 18:21:02 +0200187 int ret;
188
Peter Rosina7ab7232016-04-20 08:38:50 +0200189 if (muxc->num_adapters >= muxc->max_adapters) {
190 dev_err(muxc->dev, "No room for more i2c-mux adapters\n");
191 return -EINVAL;
192 }
193
194 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
Michael Lawnick08263742010-08-11 18:21:02 +0200195 if (!priv)
Peter Rosina7ab7232016-04-20 08:38:50 +0200196 return -ENOMEM;
Michael Lawnick08263742010-08-11 18:21:02 +0200197
198 /* Set up private adapter data */
Peter Rosina7ab7232016-04-20 08:38:50 +0200199 priv->muxc = muxc;
Michael Lawnick08263742010-08-11 18:21:02 +0200200 priv->chan_id = chan_id;
Michael Lawnick08263742010-08-11 18:21:02 +0200201
202 /* Need to do algo dynamically because we don't know ahead
203 * of time what sort of physical adapter we'll be dealing with.
204 */
205 if (parent->algo->master_xfer)
206 priv->algo.master_xfer = i2c_mux_master_xfer;
207 if (parent->algo->smbus_xfer)
208 priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
209 priv->algo.functionality = i2c_mux_functionality;
210
211 /* Now fill out new adapter structure */
212 snprintf(priv->adap.name, sizeof(priv->adap.name),
213 "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id);
214 priv->adap.owner = THIS_MODULE;
Michael Lawnick08263742010-08-11 18:21:02 +0200215 priv->adap.algo = &priv->algo;
216 priv->adap.algo_data = priv;
217 priv->adap.dev.parent = &parent->dev;
Elie De Brauwer2212a852013-12-09 19:48:28 +0100218 priv->adap.retries = parent->retries;
219 priv->adap.timeout = parent->timeout;
Alexander Sverdlindc362d52015-06-12 14:41:16 +0200220 priv->adap.quirks = parent->quirks;
Michael Lawnick08263742010-08-11 18:21:02 +0200221
Jean Delvareeee543e2012-10-05 22:23:51 +0200222 /* Sanity check on class */
223 if (i2c_mux_parent_classes(parent) & class)
224 dev_err(&parent->dev,
225 "Segment %d behind mux can't share classes with ancestors\n",
226 chan_id);
227 else
228 priv->adap.class = class;
229
David Daneybc454492012-04-12 14:14:23 -0700230 /*
231 * Try to populate the mux adapter's of_node, expands to
232 * nothing if !CONFIG_OF.
233 */
Peter Rosina7ab7232016-04-20 08:38:50 +0200234 if (muxc->dev->of_node) {
David Daneybc454492012-04-12 14:14:23 -0700235 struct device_node *child;
236 u32 reg;
237
Peter Rosina7ab7232016-04-20 08:38:50 +0200238 for_each_child_of_node(muxc->dev->of_node, child) {
David Daneybc454492012-04-12 14:14:23 -0700239 ret = of_property_read_u32(child, "reg", &reg);
240 if (ret)
241 continue;
242 if (chan_id == reg) {
243 priv->adap.dev.of_node = child;
244 break;
245 }
246 }
247 }
248
Dustin Byford8eb5c872015-10-23 12:27:07 -0700249 /*
250 * Associate the mux channel with an ACPI node.
251 */
Peter Rosina7ab7232016-04-20 08:38:50 +0200252 if (has_acpi_companion(muxc->dev))
253 acpi_preset_companion(&priv->adap.dev,
254 ACPI_COMPANION(muxc->dev),
Dustin Byford8eb5c872015-10-23 12:27:07 -0700255 chan_id);
256
Michael Lawnick08263742010-08-11 18:21:02 +0200257 if (force_nr) {
258 priv->adap.nr = force_nr;
259 ret = i2c_add_numbered_adapter(&priv->adap);
260 } else {
261 ret = i2c_add_adapter(&priv->adap);
262 }
263 if (ret < 0) {
264 dev_err(&parent->dev,
265 "failed to add mux-adapter (error=%d)\n",
266 ret);
267 kfree(priv);
Peter Rosina7ab7232016-04-20 08:38:50 +0200268 return ret;
Michael Lawnick08263742010-08-11 18:21:02 +0200269 }
270
Peter Rosina7ab7232016-04-20 08:38:50 +0200271 WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
272 "mux_device"),
273 "can't create symlink to mux device\n");
Wolfram Sang51cf3b02014-11-13 14:39:55 +0100274
Gerlando Falautoc9449af2014-11-13 14:39:56 +0100275 snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
Peter Rosina7ab7232016-04-20 08:38:50 +0200276 WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
277 symlink_name),
278 "can't create symlink for channel %u\n", chan_id);
Michael Lawnick08263742010-08-11 18:21:02 +0200279 dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
280 i2c_adapter_id(&priv->adap));
281
Peter Rosina7ab7232016-04-20 08:38:50 +0200282 muxc->adapter[muxc->num_adapters++] = &priv->adap;
283 return 0;
Michael Lawnick08263742010-08-11 18:21:02 +0200284}
Peter Rosina7ab7232016-04-20 08:38:50 +0200285EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
286
287void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
288{
289 char symlink_name[20];
290
291 while (muxc->num_adapters) {
292 struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
293 struct i2c_mux_priv *priv = adap->algo_data;
294
295 muxc->adapter[muxc->num_adapters] = NULL;
296
297 snprintf(symlink_name, sizeof(symlink_name),
298 "channel-%u", priv->chan_id);
299 sysfs_remove_link(&muxc->dev->kobj, symlink_name);
300
301 sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
302 i2c_del_adapter(adap);
303 kfree(priv);
304 }
305}
306EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
Michael Lawnick08263742010-08-11 18:21:02 +0200307
Lars-Peter Clausen51d95702013-03-09 08:16:49 +0000308void i2c_del_mux_adapter(struct i2c_adapter *adap)
Michael Lawnick08263742010-08-11 18:21:02 +0200309{
310 struct i2c_mux_priv *priv = adap->algo_data;
Peter Rosina7ab7232016-04-20 08:38:50 +0200311 struct i2c_mux_core *muxc = priv->muxc;
Gerlando Falautoc9449af2014-11-13 14:39:56 +0100312
Peter Rosina7ab7232016-04-20 08:38:50 +0200313 i2c_mux_del_adapters(muxc);
314 devm_kfree(muxc->dev, muxc);
Michael Lawnick08263742010-08-11 18:21:02 +0200315}
316EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
317
318MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
319MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
320MODULE_LICENSE("GPL v2");