Virtual i2c bus
Brian Kuschak  <bkuschak@xxxxxxxxx>


I2C devices must have a unique 7 bit address on the bus to which they 
are attached.  Many I2C chips have one or more input lines which can be
used to configure one or more of their address bits.  This allows the
hardware designer to include multiple chips on a single bus by selecting
different addresses for each one.  However, some chips have fixed addresses
which present a problem if more than one of them are required on a board.
Also, sometimes there are more devices than there are selectable addresses.

A common solution is to break the i2c bus into disjoint segments, by using
a multiplexor or i2c bus switch.  This electrically isolates the individual
bus segments.  Then the devices with duplicate addresses are placed on 
separate bus segments, to prevent address conflicts.

This seems to be a very common approach in certain types of applications,
such as bladed chassis, where many identical 'blades' or cards are inserted
into a common backplane.  The I2C bus on each blade is then located behind
a mux or i2c bus switch.  This solution works great from the hardware 
perspective, but presents some complexities for software.

The 'virtual i2c adapter' driver is an attempt to provide a flexible software
abstraction to simiplify these issues, while minimizing the impact on 
existing code and fitting nicely into the i2c driver framework.


What is a 'virtual i2c adapter'
===============================

Think of this adapter as a layer above the existing algorithm and adapter
drivers.  The virtual i2c adapter is the handle by which you access a 
specific multiplexed bus segment.  Each disjoint bus segment becomes a new
virtual bus.  The virtual adapter is associated with a 'real' adapter and a 
set of multiplexor control variables.

For example: you have an i2c-0 bus with one multiplexor or i2c bus switch,
and the mux has four outputs which can be electrically connected to the
i2c-0 bus.  You would register four virtual i2c busses, one for each position
of the mux.  As part of the registration, you provide callback functions to
select and deselect the mux as well as the selector values to be passed to
these functions.

                     ---------  <-------->  i2c-1  virtual
                    | i2c mux | <-------->  i2c-2  virtual
   i2c-0 <------->  |         | <-------->  i2c-3  virtual
  ibm_ocp           |  0x74   | <-------->  i2c-4  virtual
                     ---------
                        ^ 
                        |
                        +---  (or externally controlled)

The mux may be i2c-controlled, in which case the mux_addr is set to the 
slave address (0x74) and the mux_val would be the port number to select (0-3).  
Alternatively, the mux could be controlled by some fixed memory-mapped register
in which case only the mux_val would be needed.  The callback functions
are hardware specific and written by the user.  

Once the virtual busses are registered, you may talk to any devices behind
the mux simply the using the i2c-1, i2c-2, i2c-3, etc. adapters instead of
the i2c-0 adapter.  This makes the mux essentially transparent to the 
i2c_client. 

The great advantage of course is that all the existing sensor drivers and
other i2c client drivers automatically work, and the mux becomes transparent
to them.


Additional capabilities
=======================

This driver also supports multiple levels of muxing, by allowing the
user to register a virtual bus which has a different virtual bus as its
'real' adapter.  In addition, each virtual bus may have different kinds of 
multiplexors, with each bus having its own set of callback functions.
This allows you to easily support some very complex topologies.

In addition to multiplexing, some systems require that you obtain hardware 
access to the bus behind the mux before talking on it.  (Again, bladed chassis
typically 'fence' other blades off the bus to prevent a crashed blade from 
bringing down the whole backplane.)  Before talking on this bus, you have to
arbitrate with the other blades to acquire exclusive access to the bus.  This
requirement is met by the addition of two new function pointers to the 
algorithm drivers, acquire_exclusive() and release_exclusive().  Traditional
adapters will not use these and they can safely be left NULL.  If they are
non-null, the virtual bus driver will call the acquire_exclusive() function 
before attempting any operations on that virtual bus.  This function may block,
and this is done before acquiring the lock on the underlying 'real' bus to
allow transactions on the real bus to continue unimpeded while waiting for
arbitrartion.  In addition the ownership is only held for as long as it takes
to complete the transfer.  


Files
=====

drivers/i2c/i2c-virtual.c: 	The 'algorithm' and 'adapter' driver
include/linux/i2c-virtual.h:	Header file with the mux control structure
                                and callback prototypes.


