162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci======================= 462306a36Sopenharmony_ciI2C Address Translators 562306a36Sopenharmony_ci======================= 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciAuthor: Luca Ceresoli <luca@lucaceresoli.net> 862306a36Sopenharmony_ciAuthor: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciDescription 1162306a36Sopenharmony_ci----------- 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciAn I2C Address Translator (ATR) is a device with an I2C slave parent 1462306a36Sopenharmony_ci("upstream") port and N I2C master child ("downstream") ports, and 1562306a36Sopenharmony_ciforwards transactions from upstream to the appropriate downstream port 1662306a36Sopenharmony_ciwith a modified slave address. The address used on the parent bus is 1762306a36Sopenharmony_cicalled the "alias" and is (potentially) different from the physical 1862306a36Sopenharmony_cislave address of the child bus. Address translation is done by the 1962306a36Sopenharmony_cihardware. 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciAn ATR looks similar to an i2c-mux except: 2262306a36Sopenharmony_ci - the address on the parent and child busses can be different 2362306a36Sopenharmony_ci - there is normally no need to select the child port; the alias used on the 2462306a36Sopenharmony_ci parent bus implies it 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciThe ATR functionality can be provided by a chip with many other features. 2762306a36Sopenharmony_ciThe kernel i2c-atr provides a helper to implement an ATR within a driver. 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciThe ATR creates a new I2C "child" adapter on each child bus. Adding 3062306a36Sopenharmony_cidevices on the child bus ends up in invoking the driver code to select 3162306a36Sopenharmony_cian available alias. Maintaining an appropriate pool of available aliases 3262306a36Sopenharmony_ciand picking one for each new device is up to the driver implementer. The 3362306a36Sopenharmony_ciATR maintains a table of currently assigned alias and uses it to modify 3462306a36Sopenharmony_ciall I2C transactions directed to devices on the child buses. 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciA typical example follows. 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciTopology:: 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci Slave X @ 0x10 4162306a36Sopenharmony_ci .-----. | 4262306a36Sopenharmony_ci .-----. | |---+---- B 4362306a36Sopenharmony_ci | CPU |--A--| ATR | 4462306a36Sopenharmony_ci `-----' | |---+---- C 4562306a36Sopenharmony_ci `-----' | 4662306a36Sopenharmony_ci Slave Y @ 0x10 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciAlias table: 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciA, B and C are three physical I2C busses, electrically independent from 5162306a36Sopenharmony_cieach other. The ATR receives the transactions initiated on bus A and 5262306a36Sopenharmony_cipropagates them on bus B or bus C or none depending on the device address 5362306a36Sopenharmony_ciin the transaction and based on the alias table. 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciAlias table: 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci.. table:: 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci =============== ===== 6062306a36Sopenharmony_ci Client Alias 6162306a36Sopenharmony_ci =============== ===== 6262306a36Sopenharmony_ci X (bus B, 0x10) 0x20 6362306a36Sopenharmony_ci Y (bus C, 0x10) 0x30 6462306a36Sopenharmony_ci =============== ===== 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciTransaction: 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci - Slave X driver requests a transaction (on adapter B), slave address 0x10 6962306a36Sopenharmony_ci - ATR driver finds slave X is on bus B and has alias 0x20, rewrites 7062306a36Sopenharmony_ci messages with address 0x20, forwards to adapter A 7162306a36Sopenharmony_ci - Physical I2C transaction on bus A, slave address 0x20 7262306a36Sopenharmony_ci - ATR chip detects transaction on address 0x20, finds it in table, 7362306a36Sopenharmony_ci propagates transaction on bus B with address translated to 0x10, 7462306a36Sopenharmony_ci keeps clock streched on bus A waiting for reply 7562306a36Sopenharmony_ci - Slave X chip (on bus B) detects transaction at its own physical 7662306a36Sopenharmony_ci address 0x10 and replies normally 7762306a36Sopenharmony_ci - ATR chip stops clock stretching and forwards reply on bus A, 7862306a36Sopenharmony_ci with address translated back to 0x20 7962306a36Sopenharmony_ci - ATR driver receives the reply, rewrites messages with address 0x10 8062306a36Sopenharmony_ci as they were initially 8162306a36Sopenharmony_ci - Slave X driver gets back the msgs[], with reply and address 0x10 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciUsage: 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci 1. In the driver (typically in the probe function) add an ATR by 8662306a36Sopenharmony_ci calling i2c_atr_new() passing attach/detach callbacks 8762306a36Sopenharmony_ci 2. When the attach callback is called pick an appropriate alias, 8862306a36Sopenharmony_ci configure it in the chip and return the chosen alias in the 8962306a36Sopenharmony_ci alias_id parameter 9062306a36Sopenharmony_ci 3. When the detach callback is called, deconfigure the alias from 9162306a36Sopenharmony_ci the chip and put the alias back in the pool for later usage 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciI2C ATR functions and data structures 9462306a36Sopenharmony_ci------------------------------------- 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci.. kernel-doc:: include/linux/i2c-atr.h 97