I2C bus multiplexing
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.
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).
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 thread for further info).
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! :)
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:
+------------+ segment 0 | controller |-------+--------+----------+--- +------------+ | | | | | | | +-------+ +-------+ | | dev A | | dev B | | +-------+ +-------+ | | +-------+ +-------+ | | dev C | | dev D | | +-------+ +-------+ | | | +-----+ segment 1 | | | |----------------+--- | | MUX | | | |---------------------------+--- +-----+ segment 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
deselect() 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
driver_unregister()from the mutex
This step should be quite correct since, during driver registration, current locking scheme do the same with the function
driver_unregister(). It seems that only the function
class_for_each_device()needs such mutex protection...
- The function
i2c_scan_static_board_infomust be called for each new adapter defined into the system so, during adapters registration, we have several readers of that info.
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.
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.
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.
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 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
my-linux-i2c-mux-clone 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.
Patches can be applied with the following sequence:
$ cd your-linux-source-tree $ patch -p1 < <file_dot_patch>
RodolfoGiometti 11:37, 20 February 2009 (UTC)