]>
Commit | Line | Data |
---|---|---|
0826374b ML |
1 | /* |
2 | * Multiplexed I2C bus driver. | |
3 | * | |
4 | * Copyright (c) 2008-2009 Rodolfo Giometti <[email protected]> | |
5 | * Copyright (c) 2008-2009 Eurotech S.p.A. <[email protected]> | |
6 | * Copyright (c) 2009-2010 NSN GmbH & Co KG <[email protected]> | |
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 <[email protected]> | |
14 | * i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc. | |
15 | * i2c-virtual.c from Brian Kuschak <[email protected]> | |
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 | ||
51714932 | 22 | #include <linux/acpi.h> |
0826374b ML |
23 | #include <linux/i2c.h> |
24 | #include <linux/i2c-mux.h> | |
51714932 WS |
25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | |
bc45449b | 27 | #include <linux/of.h> |
51714932 | 28 | #include <linux/slab.h> |
0826374b ML |
29 | |
30 | /* multiplexer per channel data */ | |
31 | struct i2c_mux_priv { | |
32 | struct i2c_adapter adap; | |
33 | struct i2c_algorithm algo; | |
a7ab7239 | 34 | struct i2c_mux_core *muxc; |
13377848 | 35 | u32 chan_id; |
0826374b ML |
36 | }; |
37 | ||
6ef91fcc PR |
38 | static int __i2c_mux_master_xfer(struct i2c_adapter *adap, |
39 | struct i2c_msg msgs[], int num) | |
40 | { | |
41 | struct i2c_mux_priv *priv = adap->algo_data; | |
42 | struct i2c_mux_core *muxc = priv->muxc; | |
43 | struct i2c_adapter *parent = muxc->parent; | |
44 | int ret; | |
45 | ||
46 | /* Switch to the right mux port and perform the transfer. */ | |
47 | ||
48 | ret = muxc->select(muxc, priv->chan_id); | |
49 | if (ret >= 0) | |
50 | ret = __i2c_transfer(parent, msgs, num); | |
51 | if (muxc->deselect) | |
52 | muxc->deselect(muxc, priv->chan_id); | |
53 | ||
54 | return ret; | |
55 | } | |
56 | ||
0826374b ML |
57 | static int i2c_mux_master_xfer(struct i2c_adapter *adap, |
58 | struct i2c_msg msgs[], int num) | |
59 | { | |
60 | struct i2c_mux_priv *priv = adap->algo_data; | |
a7ab7239 PR |
61 | struct i2c_mux_core *muxc = priv->muxc; |
62 | struct i2c_adapter *parent = muxc->parent; | |
0826374b ML |
63 | int ret; |
64 | ||
65 | /* Switch to the right mux port and perform the transfer. */ | |
66 | ||
a7ab7239 | 67 | ret = muxc->select(muxc, priv->chan_id); |
0826374b | 68 | if (ret >= 0) |
6ef91fcc PR |
69 | ret = i2c_transfer(parent, msgs, num); |
70 | if (muxc->deselect) | |
71 | muxc->deselect(muxc, priv->chan_id); | |
72 | ||
73 | return ret; | |
74 | } | |
75 | ||
76 | static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap, | |
77 | u16 addr, unsigned short flags, | |
78 | char read_write, u8 command, | |
79 | int size, union i2c_smbus_data *data) | |
80 | { | |
81 | struct i2c_mux_priv *priv = adap->algo_data; | |
82 | struct i2c_mux_core *muxc = priv->muxc; | |
83 | struct i2c_adapter *parent = muxc->parent; | |
84 | int ret; | |
85 | ||
86 | /* Select the right mux port and perform the transfer. */ | |
87 | ||
88 | ret = muxc->select(muxc, priv->chan_id); | |
89 | if (ret >= 0) | |
25184082 PR |
90 | ret = __i2c_smbus_xfer(parent, addr, flags, |
91 | read_write, command, size, data); | |
a7ab7239 PR |
92 | if (muxc->deselect) |
93 | muxc->deselect(muxc, priv->chan_id); | |
0826374b ML |
94 | |
95 | return ret; | |
96 | } | |
97 | ||
98 | static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, | |
99 | u16 addr, unsigned short flags, | |
100 | char read_write, u8 command, | |
101 | int size, union i2c_smbus_data *data) | |
102 | { | |
103 | struct i2c_mux_priv *priv = adap->algo_data; | |
a7ab7239 PR |
104 | struct i2c_mux_core *muxc = priv->muxc; |
105 | struct i2c_adapter *parent = muxc->parent; | |
0826374b ML |
106 | int ret; |
107 | ||
108 | /* Select the right mux port and perform the transfer. */ | |
109 | ||
a7ab7239 | 110 | ret = muxc->select(muxc, priv->chan_id); |
0826374b | 111 | if (ret >= 0) |
6ef91fcc PR |
112 | ret = i2c_smbus_xfer(parent, addr, flags, |
113 | read_write, command, size, data); | |
a7ab7239 PR |
114 | if (muxc->deselect) |
115 | muxc->deselect(muxc, priv->chan_id); | |
0826374b ML |
116 | |
117 | return ret; | |
118 | } | |
119 | ||
120 | /* Return the parent's functionality */ | |
121 | static u32 i2c_mux_functionality(struct i2c_adapter *adap) | |
122 | { | |
123 | struct i2c_mux_priv *priv = adap->algo_data; | |
a7ab7239 | 124 | struct i2c_adapter *parent = priv->muxc->parent; |
0826374b ML |
125 | |
126 | return parent->algo->functionality(parent); | |
127 | } | |
128 | ||
eee543e8 JD |
129 | /* Return all parent classes, merged */ |
130 | static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent) | |
131 | { | |
132 | unsigned int class = 0; | |
133 | ||
134 | do { | |
135 | class |= parent->class; | |
136 | parent = i2c_parent_is_i2c_adapter(parent); | |
137 | } while (parent); | |
138 | ||
139 | return class; | |
140 | } | |
141 | ||
6ef91fcc PR |
142 | static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags) |
143 | { | |
144 | struct i2c_mux_priv *priv = adapter->algo_data; | |
145 | struct i2c_adapter *parent = priv->muxc->parent; | |
146 | ||
7b94ea50 | 147 | rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter)); |
6ef91fcc PR |
148 | if (!(flags & I2C_LOCK_ROOT_ADAPTER)) |
149 | return; | |
150 | i2c_lock_bus(parent, flags); | |
151 | } | |
152 | ||
153 | static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) | |
154 | { | |
155 | struct i2c_mux_priv *priv = adapter->algo_data; | |
156 | struct i2c_adapter *parent = priv->muxc->parent; | |
157 | ||
158 | if (!rt_mutex_trylock(&parent->mux_lock)) | |
159 | return 0; /* mux_lock not locked, failure */ | |
160 | if (!(flags & I2C_LOCK_ROOT_ADAPTER)) | |
161 | return 1; /* we only want mux_lock, success */ | |
fb79e09a | 162 | if (i2c_trylock_bus(parent, flags)) |
6ef91fcc PR |
163 | return 1; /* parent locked too, success */ |
164 | rt_mutex_unlock(&parent->mux_lock); | |
165 | return 0; /* parent not locked, failure */ | |
166 | } | |
167 | ||
168 | static void i2c_mux_unlock_bus(struct i2c_adapter *adapter, unsigned int flags) | |
169 | { | |
170 | struct i2c_mux_priv *priv = adapter->algo_data; | |
171 | struct i2c_adapter *parent = priv->muxc->parent; | |
172 | ||
173 | if (flags & I2C_LOCK_ROOT_ADAPTER) | |
174 | i2c_unlock_bus(parent, flags); | |
175 | rt_mutex_unlock(&parent->mux_lock); | |
176 | } | |
177 | ||
fa96f0cb PR |
178 | static void i2c_parent_lock_bus(struct i2c_adapter *adapter, |
179 | unsigned int flags) | |
180 | { | |
181 | struct i2c_mux_priv *priv = adapter->algo_data; | |
182 | struct i2c_adapter *parent = priv->muxc->parent; | |
183 | ||
7b94ea50 | 184 | rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter)); |
6ef91fcc | 185 | i2c_lock_bus(parent, flags); |
fa96f0cb PR |
186 | } |
187 | ||
188 | static int i2c_parent_trylock_bus(struct i2c_adapter *adapter, | |
189 | unsigned int flags) | |
190 | { | |
191 | struct i2c_mux_priv *priv = adapter->algo_data; | |
192 | struct i2c_adapter *parent = priv->muxc->parent; | |
193 | ||
6ef91fcc PR |
194 | if (!rt_mutex_trylock(&parent->mux_lock)) |
195 | return 0; /* mux_lock not locked, failure */ | |
fb79e09a | 196 | if (i2c_trylock_bus(parent, flags)) |
6ef91fcc PR |
197 | return 1; /* parent locked too, success */ |
198 | rt_mutex_unlock(&parent->mux_lock); | |
199 | return 0; /* parent not locked, failure */ | |
fa96f0cb PR |
200 | } |
201 | ||
202 | static void i2c_parent_unlock_bus(struct i2c_adapter *adapter, | |
203 | unsigned int flags) | |
204 | { | |
205 | struct i2c_mux_priv *priv = adapter->algo_data; | |
206 | struct i2c_adapter *parent = priv->muxc->parent; | |
207 | ||
6ef91fcc PR |
208 | i2c_unlock_bus(parent, flags); |
209 | rt_mutex_unlock(&parent->mux_lock); | |
fa96f0cb PR |
210 | } |
211 | ||
6ef91fcc PR |
212 | struct i2c_adapter *i2c_root_adapter(struct device *dev) |
213 | { | |
214 | struct device *i2c; | |
215 | struct i2c_adapter *i2c_root; | |
216 | ||
217 | /* | |
218 | * Walk up the device tree to find an i2c adapter, indicating | |
219 | * that this is an i2c client device. Check all ancestors to | |
220 | * handle mfd devices etc. | |
221 | */ | |
222 | for (i2c = dev; i2c; i2c = i2c->parent) { | |
223 | if (i2c->type == &i2c_adapter_type) | |
224 | break; | |
225 | } | |
226 | if (!i2c) | |
227 | return NULL; | |
228 | ||
229 | /* Continue up the tree to find the root i2c adapter */ | |
230 | i2c_root = to_i2c_adapter(i2c); | |
231 | while (i2c_parent_is_i2c_adapter(i2c_root)) | |
232 | i2c_root = i2c_parent_is_i2c_adapter(i2c_root); | |
233 | ||
234 | return i2c_root; | |
235 | } | |
236 | EXPORT_SYMBOL_GPL(i2c_root_adapter); | |
237 | ||
a7ab7239 PR |
238 | struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, |
239 | struct device *dev, int max_adapters, | |
240 | int sizeof_priv, u32 flags, | |
241 | int (*select)(struct i2c_mux_core *, u32), | |
242 | int (*deselect)(struct i2c_mux_core *, u32)) | |
243 | { | |
244 | struct i2c_mux_core *muxc; | |
245 | ||
246 | muxc = devm_kzalloc(dev, sizeof(*muxc) | |
247 | + max_adapters * sizeof(muxc->adapter[0]) | |
248 | + sizeof_priv, GFP_KERNEL); | |
249 | if (!muxc) | |
250 | return NULL; | |
251 | if (sizeof_priv) | |
252 | muxc->priv = &muxc->adapter[max_adapters]; | |
253 | ||
254 | muxc->parent = parent; | |
255 | muxc->dev = dev; | |
6ef91fcc PR |
256 | if (flags & I2C_MUX_LOCKED) |
257 | muxc->mux_locked = true; | |
b2d57b56 PR |
258 | if (flags & I2C_MUX_ARBITRATOR) |
259 | muxc->arbitrator = true; | |
260 | if (flags & I2C_MUX_GATE) | |
261 | muxc->gate = true; | |
a7ab7239 PR |
262 | muxc->select = select; |
263 | muxc->deselect = deselect; | |
264 | muxc->max_adapters = max_adapters; | |
265 | ||
266 | return muxc; | |
267 | } | |
268 | EXPORT_SYMBOL_GPL(i2c_mux_alloc); | |
269 | ||
d1ed7985 PR |
270 | static const struct i2c_lock_operations i2c_mux_lock_ops = { |
271 | .lock_bus = i2c_mux_lock_bus, | |
272 | .trylock_bus = i2c_mux_trylock_bus, | |
273 | .unlock_bus = i2c_mux_unlock_bus, | |
274 | }; | |
275 | ||
276 | static const struct i2c_lock_operations i2c_parent_lock_ops = { | |
277 | .lock_bus = i2c_parent_lock_bus, | |
278 | .trylock_bus = i2c_parent_trylock_bus, | |
279 | .unlock_bus = i2c_parent_unlock_bus, | |
280 | }; | |
281 | ||
a7ab7239 PR |
282 | int i2c_mux_add_adapter(struct i2c_mux_core *muxc, |
283 | u32 force_nr, u32 chan_id, | |
284 | unsigned int class) | |
285 | { | |
286 | struct i2c_adapter *parent = muxc->parent; | |
0826374b | 287 | struct i2c_mux_priv *priv; |
c9449aff | 288 | char symlink_name[20]; |
0826374b ML |
289 | int ret; |
290 | ||
a7ab7239 PR |
291 | if (muxc->num_adapters >= muxc->max_adapters) { |
292 | dev_err(muxc->dev, "No room for more i2c-mux adapters\n"); | |
293 | return -EINVAL; | |
294 | } | |
295 | ||
296 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
0826374b | 297 | if (!priv) |
a7ab7239 | 298 | return -ENOMEM; |
0826374b ML |
299 | |
300 | /* Set up private adapter data */ | |
a7ab7239 | 301 | priv->muxc = muxc; |
0826374b | 302 | priv->chan_id = chan_id; |
0826374b ML |
303 | |
304 | /* Need to do algo dynamically because we don't know ahead | |
305 | * of time what sort of physical adapter we'll be dealing with. | |
306 | */ | |
6ef91fcc PR |
307 | if (parent->algo->master_xfer) { |
308 | if (muxc->mux_locked) | |
309 | priv->algo.master_xfer = i2c_mux_master_xfer; | |
310 | else | |
311 | priv->algo.master_xfer = __i2c_mux_master_xfer; | |
312 | } | |
313 | if (parent->algo->smbus_xfer) { | |
314 | if (muxc->mux_locked) | |
315 | priv->algo.smbus_xfer = i2c_mux_smbus_xfer; | |
316 | else | |
317 | priv->algo.smbus_xfer = __i2c_mux_smbus_xfer; | |
318 | } | |
0826374b ML |
319 | priv->algo.functionality = i2c_mux_functionality; |
320 | ||
321 | /* Now fill out new adapter structure */ | |
322 | snprintf(priv->adap.name, sizeof(priv->adap.name), | |
323 | "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); | |
324 | priv->adap.owner = THIS_MODULE; | |
0826374b ML |
325 | priv->adap.algo = &priv->algo; |
326 | priv->adap.algo_data = priv; | |
327 | priv->adap.dev.parent = &parent->dev; | |
2212a852 EDB |
328 | priv->adap.retries = parent->retries; |
329 | priv->adap.timeout = parent->timeout; | |
dc362d50 | 330 | priv->adap.quirks = parent->quirks; |
d1ed7985 PR |
331 | if (muxc->mux_locked) |
332 | priv->adap.lock_ops = &i2c_mux_lock_ops; | |
333 | else | |
334 | priv->adap.lock_ops = &i2c_parent_lock_ops; | |
0826374b | 335 | |
eee543e8 JD |
336 | /* Sanity check on class */ |
337 | if (i2c_mux_parent_classes(parent) & class) | |
338 | dev_err(&parent->dev, | |
339 | "Segment %d behind mux can't share classes with ancestors\n", | |
340 | chan_id); | |
341 | else | |
342 | priv->adap.class = class; | |
343 | ||
bc45449b DD |
344 | /* |
345 | * Try to populate the mux adapter's of_node, expands to | |
346 | * nothing if !CONFIG_OF. | |
347 | */ | |
a7ab7239 | 348 | if (muxc->dev->of_node) { |
b2d57b56 PR |
349 | struct device_node *dev_node = muxc->dev->of_node; |
350 | struct device_node *mux_node, *child = NULL; | |
bc45449b DD |
351 | u32 reg; |
352 | ||
b2d57b56 PR |
353 | if (muxc->arbitrator) |
354 | mux_node = of_get_child_by_name(dev_node, "i2c-arb"); | |
355 | else if (muxc->gate) | |
356 | mux_node = of_get_child_by_name(dev_node, "i2c-gate"); | |
357 | else | |
358 | mux_node = of_get_child_by_name(dev_node, "i2c-mux"); | |
359 | ||
360 | if (mux_node) { | |
361 | /* A "reg" property indicates an old-style DT entry */ | |
362 | if (!of_property_read_u32(mux_node, "reg", ®)) { | |
363 | of_node_put(mux_node); | |
364 | mux_node = NULL; | |
365 | } | |
366 | } | |
367 | ||
368 | if (!mux_node) | |
369 | mux_node = of_node_get(dev_node); | |
370 | else if (muxc->arbitrator || muxc->gate) | |
371 | child = of_node_get(mux_node); | |
372 | ||
373 | if (!child) { | |
374 | for_each_child_of_node(mux_node, child) { | |
375 | ret = of_property_read_u32(child, "reg", ®); | |
376 | if (ret) | |
377 | continue; | |
378 | if (chan_id == reg) | |
379 | break; | |
bc45449b DD |
380 | } |
381 | } | |
b2d57b56 PR |
382 | |
383 | priv->adap.dev.of_node = child; | |
384 | of_node_put(mux_node); | |
bc45449b DD |
385 | } |
386 | ||
8eb5c87a DB |
387 | /* |
388 | * Associate the mux channel with an ACPI node. | |
389 | */ | |
a7ab7239 PR |
390 | if (has_acpi_companion(muxc->dev)) |
391 | acpi_preset_companion(&priv->adap.dev, | |
392 | ACPI_COMPANION(muxc->dev), | |
8eb5c87a DB |
393 | chan_id); |
394 | ||
0826374b ML |
395 | if (force_nr) { |
396 | priv->adap.nr = force_nr; | |
397 | ret = i2c_add_numbered_adapter(&priv->adap); | |
9fce894d PR |
398 | if (ret < 0) { |
399 | dev_err(&parent->dev, | |
400 | "failed to add mux-adapter %u as bus %u (error=%d)\n", | |
401 | chan_id, force_nr, ret); | |
402 | goto err_free_priv; | |
403 | } | |
0826374b ML |
404 | } else { |
405 | ret = i2c_add_adapter(&priv->adap); | |
9fce894d PR |
406 | if (ret < 0) { |
407 | dev_err(&parent->dev, | |
408 | "failed to add mux-adapter %u (error=%d)\n", | |
409 | chan_id, ret); | |
410 | goto err_free_priv; | |
411 | } | |
0826374b ML |
412 | } |
413 | ||
a7ab7239 PR |
414 | WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj, |
415 | "mux_device"), | |
416 | "can't create symlink to mux device\n"); | |
51cf3b0e | 417 | |
c9449aff | 418 | snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id); |
a7ab7239 PR |
419 | WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj, |
420 | symlink_name), | |
f657c9fe | 421 | "can't create symlink to channel %u\n", chan_id); |
0826374b ML |
422 | dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", |
423 | i2c_adapter_id(&priv->adap)); | |
424 | ||
a7ab7239 PR |
425 | muxc->adapter[muxc->num_adapters++] = &priv->adap; |
426 | return 0; | |
9fce894d PR |
427 | |
428 | err_free_priv: | |
429 | kfree(priv); | |
430 | return ret; | |
0826374b | 431 | } |
a7ab7239 | 432 | EXPORT_SYMBOL_GPL(i2c_mux_add_adapter); |
0826374b | 433 | |
a7ab7239 | 434 | void i2c_mux_del_adapters(struct i2c_mux_core *muxc) |
0826374b | 435 | { |
c9449aff GF |
436 | char symlink_name[20]; |
437 | ||
a7ab7239 PR |
438 | while (muxc->num_adapters) { |
439 | struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters]; | |
440 | struct i2c_mux_priv *priv = adap->algo_data; | |
2e1e4949 | 441 | struct device_node *np = adap->dev.of_node; |
a7ab7239 PR |
442 | |
443 | muxc->adapter[muxc->num_adapters] = NULL; | |
444 | ||
445 | snprintf(symlink_name, sizeof(symlink_name), | |
446 | "channel-%u", priv->chan_id); | |
447 | sysfs_remove_link(&muxc->dev->kobj, symlink_name); | |
448 | ||
449 | sysfs_remove_link(&priv->adap.dev.kobj, "mux_device"); | |
450 | i2c_del_adapter(adap); | |
2e1e4949 | 451 | of_node_put(np); |
a7ab7239 PR |
452 | kfree(priv); |
453 | } | |
454 | } | |
455 | EXPORT_SYMBOL_GPL(i2c_mux_del_adapters); | |
456 | ||
0826374b ML |
457 | MODULE_AUTHOR("Rodolfo Giometti <[email protected]>"); |
458 | MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); | |
459 | MODULE_LICENSE("GPL v2"); |