|  | .. SPDX-License-Identifier: GPL-2.0 | 
|  |  | 
|  | ======================= | 
|  | I2C Address Translators | 
|  | ======================= | 
|  |  | 
|  | Author: Luca Ceresoli <luca@lucaceresoli.net> | 
|  | Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> | 
|  |  | 
|  | Description | 
|  | ----------- | 
|  |  | 
|  | An I2C Address Translator (ATR) is a device with an I2C slave parent | 
|  | ("upstream") port and N I2C master child ("downstream") ports, and | 
|  | forwards transactions from upstream to the appropriate downstream port | 
|  | with a modified slave address. The address used on the parent bus is | 
|  | called the "alias" and is (potentially) different from the physical | 
|  | slave address of the child bus. Address translation is done by the | 
|  | hardware. | 
|  |  | 
|  | An ATR looks similar to an i2c-mux except: | 
|  | - the address on the parent and child busses can be different | 
|  | - there is normally no need to select the child port; the alias used on the | 
|  | parent bus implies it | 
|  |  | 
|  | The ATR functionality can be provided by a chip with many other features. | 
|  | The kernel i2c-atr provides a helper to implement an ATR within a driver. | 
|  |  | 
|  | The ATR creates a new I2C "child" adapter on each child bus. Adding | 
|  | devices on the child bus ends up in invoking the driver code to select | 
|  | an available alias. Maintaining an appropriate pool of available aliases | 
|  | and picking one for each new device is up to the driver implementer. The | 
|  | ATR maintains a table of currently assigned alias and uses it to modify | 
|  | all I2C transactions directed to devices on the child buses. | 
|  |  | 
|  | A typical example follows. | 
|  |  | 
|  | Topology:: | 
|  |  | 
|  | Slave X @ 0x10 | 
|  | .-----.   | | 
|  | .-----.     |     |---+---- B | 
|  | | CPU |--A--| ATR | | 
|  | `-----'     |     |---+---- C | 
|  | `-----'   | | 
|  | Slave Y @ 0x10 | 
|  |  | 
|  | Alias table: | 
|  |  | 
|  | A, B and C are three physical I2C busses, electrically independent from | 
|  | each other. The ATR receives the transactions initiated on bus A and | 
|  | propagates them on bus B or bus C or none depending on the device address | 
|  | in the transaction and based on the alias table. | 
|  |  | 
|  | Alias table: | 
|  |  | 
|  | .. table:: | 
|  |  | 
|  | ===============   ===== | 
|  | Client            Alias | 
|  | ===============   ===== | 
|  | X (bus B, 0x10)   0x20 | 
|  | Y (bus C, 0x10)   0x30 | 
|  | ===============   ===== | 
|  |  | 
|  | Transaction: | 
|  |  | 
|  | - Slave X driver requests a transaction (on adapter B), slave address 0x10 | 
|  | - ATR driver finds slave X is on bus B and has alias 0x20, rewrites | 
|  | messages with address 0x20, forwards to adapter A | 
|  | - Physical I2C transaction on bus A, slave address 0x20 | 
|  | - ATR chip detects transaction on address 0x20, finds it in table, | 
|  | propagates transaction on bus B with address translated to 0x10, | 
|  | keeps clock stretched on bus A waiting for reply | 
|  | - Slave X chip (on bus B) detects transaction at its own physical | 
|  | address 0x10 and replies normally | 
|  | - ATR chip stops clock stretching and forwards reply on bus A, | 
|  | with address translated back to 0x20 | 
|  | - ATR driver receives the reply, rewrites messages with address 0x10 | 
|  | as they were initially | 
|  | - Slave X driver gets back the msgs[], with reply and address 0x10 | 
|  |  | 
|  | Usage: | 
|  |  | 
|  | 1. In the driver (typically in the probe function) add an ATR by | 
|  | calling i2c_atr_new() passing attach/detach callbacks | 
|  | 2. When the attach callback is called pick an appropriate alias, | 
|  | configure it in the chip and return the chosen alias in the | 
|  | alias_id parameter | 
|  | 3. When the detach callback is called, deconfigure the alias from | 
|  | the chip and put the alias back in the pool for later usage | 
|  |  | 
|  | I2C ATR functions and data structures | 
|  | ------------------------------------- | 
|  |  | 
|  | .. kernel-doc:: include/linux/i2c-atr.h |