1*a076a860SLuca Ceresoli.. SPDX-License-Identifier: GPL-2.0 2*a076a860SLuca Ceresoli 3*a076a860SLuca Ceresoli======================= 4*a076a860SLuca CeresoliI2C Address Translators 5*a076a860SLuca Ceresoli======================= 6*a076a860SLuca Ceresoli 7*a076a860SLuca CeresoliAuthor: Luca Ceresoli <luca@lucaceresoli.net> 8*a076a860SLuca CeresoliAuthor: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> 9*a076a860SLuca Ceresoli 10*a076a860SLuca CeresoliDescription 11*a076a860SLuca Ceresoli----------- 12*a076a860SLuca Ceresoli 13*a076a860SLuca CeresoliAn I2C Address Translator (ATR) is a device with an I2C slave parent 14*a076a860SLuca Ceresoli("upstream") port and N I2C master child ("downstream") ports, and 15*a076a860SLuca Ceresoliforwards transactions from upstream to the appropriate downstream port 16*a076a860SLuca Ceresoliwith a modified slave address. The address used on the parent bus is 17*a076a860SLuca Ceresolicalled the "alias" and is (potentially) different from the physical 18*a076a860SLuca Ceresolislave address of the child bus. Address translation is done by the 19*a076a860SLuca Ceresolihardware. 20*a076a860SLuca Ceresoli 21*a076a860SLuca CeresoliAn ATR looks similar to an i2c-mux except: 22*a076a860SLuca Ceresoli - the address on the parent and child busses can be different 23*a076a860SLuca Ceresoli - there is normally no need to select the child port; the alias used on the 24*a076a860SLuca Ceresoli parent bus implies it 25*a076a860SLuca Ceresoli 26*a076a860SLuca CeresoliThe ATR functionality can be provided by a chip with many other features. 27*a076a860SLuca CeresoliThe kernel i2c-atr provides a helper to implement an ATR within a driver. 28*a076a860SLuca Ceresoli 29*a076a860SLuca CeresoliThe ATR creates a new I2C "child" adapter on each child bus. Adding 30*a076a860SLuca Ceresolidevices on the child bus ends up in invoking the driver code to select 31*a076a860SLuca Ceresolian available alias. Maintaining an appropriate pool of available aliases 32*a076a860SLuca Ceresoliand picking one for each new device is up to the driver implementer. The 33*a076a860SLuca CeresoliATR maintains a table of currently assigned alias and uses it to modify 34*a076a860SLuca Ceresoliall I2C transactions directed to devices on the child buses. 35*a076a860SLuca Ceresoli 36*a076a860SLuca CeresoliA typical example follows. 37*a076a860SLuca Ceresoli 38*a076a860SLuca CeresoliTopology:: 39*a076a860SLuca Ceresoli 40*a076a860SLuca Ceresoli Slave X @ 0x10 41*a076a860SLuca Ceresoli .-----. | 42*a076a860SLuca Ceresoli .-----. | |---+---- B 43*a076a860SLuca Ceresoli | CPU |--A--| ATR | 44*a076a860SLuca Ceresoli `-----' | |---+---- C 45*a076a860SLuca Ceresoli `-----' | 46*a076a860SLuca Ceresoli Slave Y @ 0x10 47*a076a860SLuca Ceresoli 48*a076a860SLuca CeresoliAlias table: 49*a076a860SLuca Ceresoli 50*a076a860SLuca CeresoliA, B and C are three physical I2C busses, electrically independent from 51*a076a860SLuca Ceresolieach other. The ATR receives the transactions initiated on bus A and 52*a076a860SLuca Ceresolipropagates them on bus B or bus C or none depending on the device address 53*a076a860SLuca Ceresoliin the transaction and based on the alias table. 54*a076a860SLuca Ceresoli 55*a076a860SLuca CeresoliAlias table: 56*a076a860SLuca Ceresoli 57*a076a860SLuca Ceresoli.. table:: 58*a076a860SLuca Ceresoli 59*a076a860SLuca Ceresoli =============== ===== 60*a076a860SLuca Ceresoli Client Alias 61*a076a860SLuca Ceresoli =============== ===== 62*a076a860SLuca Ceresoli X (bus B, 0x10) 0x20 63*a076a860SLuca Ceresoli Y (bus C, 0x10) 0x30 64*a076a860SLuca Ceresoli =============== ===== 65*a076a860SLuca Ceresoli 66*a076a860SLuca CeresoliTransaction: 67*a076a860SLuca Ceresoli 68*a076a860SLuca Ceresoli - Slave X driver requests a transaction (on adapter B), slave address 0x10 69*a076a860SLuca Ceresoli - ATR driver finds slave X is on bus B and has alias 0x20, rewrites 70*a076a860SLuca Ceresoli messages with address 0x20, forwards to adapter A 71*a076a860SLuca Ceresoli - Physical I2C transaction on bus A, slave address 0x20 72*a076a860SLuca Ceresoli - ATR chip detects transaction on address 0x20, finds it in table, 73*a076a860SLuca Ceresoli propagates transaction on bus B with address translated to 0x10, 74*a076a860SLuca Ceresoli keeps clock streched on bus A waiting for reply 75*a076a860SLuca Ceresoli - Slave X chip (on bus B) detects transaction at its own physical 76*a076a860SLuca Ceresoli address 0x10 and replies normally 77*a076a860SLuca Ceresoli - ATR chip stops clock stretching and forwards reply on bus A, 78*a076a860SLuca Ceresoli with address translated back to 0x20 79*a076a860SLuca Ceresoli - ATR driver receives the reply, rewrites messages with address 0x10 80*a076a860SLuca Ceresoli as they were initially 81*a076a860SLuca Ceresoli - Slave X driver gets back the msgs[], with reply and address 0x10 82*a076a860SLuca Ceresoli 83*a076a860SLuca CeresoliUsage: 84*a076a860SLuca Ceresoli 85*a076a860SLuca Ceresoli 1. In the driver (typically in the probe function) add an ATR by 86*a076a860SLuca Ceresoli calling i2c_atr_new() passing attach/detach callbacks 87*a076a860SLuca Ceresoli 2. When the attach callback is called pick an appropriate alias, 88*a076a860SLuca Ceresoli configure it in the chip and return the chosen alias in the 89*a076a860SLuca Ceresoli alias_id parameter 90*a076a860SLuca Ceresoli 3. When the detach callback is called, deconfigure the alias from 91*a076a860SLuca Ceresoli the chip and put the alias back in the pool for later usage 92*a076a860SLuca Ceresoli 93*a076a860SLuca CeresoliI2C ATR functions and data structures 94*a076a860SLuca Ceresoli------------------------------------- 95*a076a860SLuca Ceresoli 96*a076a860SLuca Ceresoli.. kernel-doc:: include/linux/i2c-atr.h 97