I2C bus multiplexing

From Linux i2c Wiki
(Difference between revisions)
Jump to: navigation, search
m (Spelling fix)
(Now that implementation is complete, present the implementation itself rather than the problems and work in progress)
 
Line 1: Line 1:
My implementation of I2C bus multiplexing tries to add to the I2C core the ability to handle multiplexed I2C bus topologies by presenting each multiplexed segment as an independent I2C adapter.
+
Support for I2C bus multiplexing was [http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0826374bff57411d239f2fcb15da3c35af0a93cd written by Rodolfo Giometti and Michael Lawnick] with the help of Jean Delvare. It was first available in kernel version 2.6.36.
  
For instance if your system has one physical controller and one two ways multiplexer, you will have tree adapters into your system: one physical and two "virtual" representing the two multiplexer's branches (note: googling on the net you can find old implementations of this project whose have been called "i2c-virtual-adapters", or similar, due the fact of this abstraction).
+
== Summary of Implementation ==
  
I'm currently using a separate kernel tree to propose my code since my modifications to i2c core should be carefully reviewed and tested before a complete kernel inclusion. Major obstacle to inclusion is the old i2c legacy drivers model which requires a complicated locking scheme who interferes with the recursive i2c adapters definition of my implementation (refer to this [http://www.mail-archive.com/linux-i2c@vger.kernel.org/msg00354.html thread] for further info).
+
This implementation lets the I2C core handle multiplexed I2C bus topologies by presenting each multiplexed segment as an independent I2C adapter. For instance if your system has one I2C controller and one two ways multiplexer, you will have tree adapters into your system: one representing the trunk and two representing the two multiplexer's branches.
  
However, despite these stuff I'm currently using this implementation on my custom PXA270 based board with a two ways i2c multiplexer (PCA9540). So use of this code is encouraged to test it and propose enhancements and/or bug fixes! :)
+
== Implementation Details ==
  
== The problem ==
+
If your system has one (or more) I2C controller(s) and one (or more) I2C multiplexer(s), you should be able to access each I2C device on any segment without doing "strange" operations but i2c classic ones. In other words, the user shouldn't have to know the I2C bus topology details nor the multiplexer internals. By considering each i2c multiplexer branch as an independent segment we can reach the goal, in fact the user simply can exchange data with an I2C device by accessing to the relevant segment.
 
+
As stated before, if into your system you have one (or more) i2c controller and one (or more) i2c multiplexer you should be able to access to each i2c devices on each segment without doing "strange" operations but i2c classic ones, that is without forcing the user to know the i2c bus topology nor the multiplexer internals. By considering each i2c multiplexer branch as an independent segment we can reach the goal, in fact the user simply can exchange data with an i2c device by accessing to the relevant segment.
+
  
 
ASCII art time:
 
ASCII art time:
  
  +------------+  segment 0  
+
  +------------+  segment 0 (i2c-0)
 
  | controller |-------+--------+----------+---
 
  | controller |-------+--------+----------+---
  +------------+      |        |          |        
+
  +------------+      |        |          |
                       |        |          |        
+
                       |        |          |
                       |    +-------+  +-------+  
+
                       |    +-------+  +-------+
                       |    | dev A |  | dev B |  
+
                       |    | dev A |  | dev B |
 
                       |    +-------+  +-------+
 
                       |    +-------+  +-------+
 
                       |
 
                       |
                       |               +-------+  +-------+
+
                       |                   +-------+  +-------+
                       |               | dev C |  | dev D |
+
                       |                   | dev C |  | dev D |
                       |               +-------+  +-------+
+
                       |                   +-------+  +-------+
                       |                   |          |
+
                       |                       |          |
                   +-----+  segment 1   |          |
+
                   +-----+  segment 1 (i2c-1) |          |
                   |    |----------------+---      |
+
                   |    |---------------------+---      |
                   | MUX |                           |
+
                   | MUX |                               |
                   |    |---------------------------+---
+
                   |    |--------------------------------+---
                   +-----+  segment 2
+
                   +-----+  segment 2 (i2c-2)
 
+
To access to device "A" the user simply refers to "adapter 0" witch in turn gets access to segment 0. Similarly, to access to device "D" the user refers to "adapter 2" which in turn gets access to segment 2. Simply, isn't it?
+
 
+
All issues related to the multiplexer internal settings, in order to manage the switching between branch 1 and 2, are managed internally by the driver and totally hide to the user. Core main functions of that magic are i2c-mux <code>select()</code> and <code>deselect()</code> whose are called by the core during each i2c transfer.
+
 
+
== Main steps to resolve the problem ==
+
 
+
To obtain the above target we need 4 main steps:
+
 
+
# During i2c driver deregistration we have to remove the function <code>driver_unregister()</code> from the mutex <code>core_lock</code> protection. <br>This step should be quite correct since, during driver registration, current locking scheme do the same with the function <code>driver_unregister()</code>. It seems that only the function <code>class_for_each_device()</code> needs such mutex protection...
+
# The function <code>i2c_scan_static_board_info</code> must be called for each new adapter defined into the system so, during adapters registration, we have several readers of that info. <br>A simple solution is to use rwsem locking instead of mutex one which allows multiple reader to get access without locks.
+
# During adapter removal we decide to ignore any active client detaching faults. <br>This is the main point of all my job. Old legacy drivers can blocks this removal by returning an error and this is a big deal during adapters removal. See below for further discussion.
+
# Adapters (de)registration should be protected by using a dedicated mutex instead of using global "core_lock" one. <br>This must be obtained in order to completely separate i2c adapters form i2c drivers.
+
 
+
Regarding the decision to ignore any active client detaching faults, I can add that is due two reasons:
+
 
+
# One (or more) active client may be switched off, so it cannot replay to the "adapter removed" event. <br> This is a very common case with multiplexers whose can be used as "electrical bus protectors" too.
+
# The fault shouldn't happen, and even if it happens it may be due a bus fault which can be resolved by resetting the adapter (most of them can be reseted simply by rmmod and then insmod the module again).
+
 
+
== Getting the code ==
+
 
+
The latest code is available via git.
+
 
+
You can browse the revision control history in your web browser by visiting the [http://gitweb.enneenne.com/?p=linux-i2c-mux;a=summary linux-i2c-mux gitweb].
+
 
+
=== Cloning my repository ===
+
 
+
The easiest way to get the code is to use git. It is strongly suggested to use git, contrary to popular belief, it is quite simple to use.
+
 
+
The simplest, but most time consuming, way to get the code is to clone the linux-i2c-mux git repository. You will need to do this if you want to use any of the git commands documented elsewhere in this wiki.
+
 
+
$ git clone git://git.enneenne.com/linux-i2c-mux my-linux-i2c-mux-clone
+
 
+
When this command completes, you will have a Linux kernel source tree in the <code>my-linux-i2c-mux-clone</code> directory, with the patches already integrated.
+
 
+
Whenever new patches are added to my repository, you can update your repository by giving the following commands:
+
 
+
$ cd my-linux-i2c-mux-clone
+
$ git pull
+
 
+
=== Using a patch ===
+
 
+
If you are unable to use git, you can use the old-style patch method to obtain the code.
+
 
+
'''NOTE:''' I have provided patches only for a few versions and kernels.
+
 
+
You can get the patches at the [http://ftp.enneenne.com/pub/misc/linux-i2c-mux/ linux-i2c-mux HTTP/FTP site]. Please refer to the [http://ftp.enneenne.com/pub/misc/linux-i2c-mux/README README file] for an explanation of which versions are available.
+
 
+
Patches can be applied with the following sequence:
+
 
+
$ cd your-linux-source-tree
+
$ patch -p1 < <file_dot_patch>
+
 
+
=== Contact us ===
+
  
If you have any questions or (better) patches for us, please send them to the [mailto:linux-i2c@vger.kernel.org Linux I2C mail list] and put [mailto:giometti@enneenne.com my address] into Cc.
+
To access to device "A" the user simply refers to adapter i2c-0 witch in turn gets access to segment 0. Similarly, to access to device "D" the user refers to i2c-2 which in turn gets access to segment 2. Simple, isn't it?
  
[[User:RodolfoGiometti|RodolfoGiometti]] 11:37, 20 February 2009 (UTC)
+
All issues related to the multiplexer internal settings, in order to manage the switching between branch 1 and 2, are managed internally by the multiplexer chip driver and are totally transparent for the user. Core main functions of that magic are i2c-mux <code>select()</code> and <code>deselect()</code> which are called by the core before and after each i2c transfer as appropriate.

Latest revision as of 08:48, 29 November 2012

Support for I2C bus multiplexing was written by Rodolfo Giometti and Michael Lawnick with the help of Jean Delvare. It was first available in kernel version 2.6.36.

[edit] Summary of Implementation

This implementation lets the I2C core handle multiplexed I2C bus topologies by presenting each multiplexed segment as an independent I2C adapter. For instance if your system has one I2C controller and one two ways multiplexer, you will have tree adapters into your system: one representing the trunk and two representing the two multiplexer's branches.

[edit] Implementation Details

If your system has one (or more) I2C controller(s) and one (or more) I2C multiplexer(s), you should be able to access each I2C device on any segment without doing "strange" operations but i2c classic ones. In other words, the user shouldn't have to know the I2C bus topology details nor the multiplexer internals. By considering each i2c multiplexer branch as an independent segment we can reach the goal, in fact the user simply can exchange data with an I2C device by accessing to the relevant segment.

ASCII art time:

+------------+   segment 0 (i2c-0)
| controller |-------+--------+----------+---
+------------+       |        |          |
                     |        |          |
                     |    +-------+  +-------+
                     |    | dev A |  | dev B |
                     |    +-------+  +-------+
                     |
                     |                    +-------+  +-------+
                     |                    | dev C |  | dev D |
                     |                    +-------+  +-------+
                     |                        |          |
                  +-----+   segment 1 (i2c-1) |          |
                  |     |---------------------+---       |
                  | MUX |                                |
                  |     |--------------------------------+---
                  +-----+   segment 2 (i2c-2)

To access to device "A" the user simply refers to adapter i2c-0 witch in turn gets access to segment 0. Similarly, to access to device "D" the user refers to i2c-2 which in turn gets access to segment 2. Simple, isn't it?

All issues related to the multiplexer internal settings, in order to manage the switching between branch 1 and 2, are managed internally by the multiplexer chip driver and are totally transparent for the user. Core main functions of that magic are i2c-mux select() and deselect() which are called by the core before and after each i2c transfer as appropriate.

Personal tools