xref: /openbmc/linux/Documentation/i2c/i2c-address-translators.rst (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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