I2C bus multiplexing

From Linux i2c Wiki
Revision as of 07:46, 29 May 2009 by Jdelvare (Talk | contribs)

Jump to: navigation, search

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! :)

Contents

The problem

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 select() and 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:

  1. During i2c driver deregistration we have to remove the function driver_unregister() from the mutex core_lock protection.
    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...
  2. The function i2c_scan_static_board_info must 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.
  3. 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.
  4. 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:

  1. 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.
  2. 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.

You can get the patches at the linux-i2c-mux HTTP/FTP site. Please refer to the 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 Linux I2C mail list and put my address into Cc.

RodolfoGiometti 11:37, 20 February 2009 (UTC)

Personal tools