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