Virtual i2c bus Brian Kuschak 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.