^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) I2C muxes and complex topologies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) There are a couple of reasons for building more complex I2C topologies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) than a straight-forward I2C bus with one adapter and one or more devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) 1. A mux may be needed on the bus to prevent address collisions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) 2. The bus may be accessible from some external bus master, and arbitration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) may be needed to determine if it is ok to access the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) 3. A device (particularly RF tuners) may want to avoid the digital noise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) from the I2C bus, at least most of the time, and sits behind a gate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) that has to be operated before the device can be accessed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) Etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) ===
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) These constructs are represented as I2C adapter trees by Linux, where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) each adapter has a parent adapter (except the root adapter) and zero or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) more child adapters. The root adapter is the actual adapter that issues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) I2C transfers, and all adapters with a parent are part of an "i2c-mux"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) object (quoted, since it can also be an arbitrator or a gate).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) Depending of the particular mux driver, something happens when there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) an I2C transfer on one of its child adapters. The mux driver can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) obviously operate a mux, but it can also do arbitration with an external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) bus master or open a gate. The mux driver has two operations for this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) select and deselect. select is called before the transfer and (the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) optional) deselect is called after the transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) Locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) =======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) There are two variants of locking available to I2C muxes, they can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) mux-locked or parent-locked muxes. As is evident from below, it can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) useful to know if a mux is mux-locked or if it is parent-locked. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) following list was correct at the time of writing:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) In drivers/i2c/muxes/:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ====================== =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) i2c-arb-gpio-challenge Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) i2c-mux-gpio Normally parent-locked, mux-locked iff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) all involved gpio pins are controlled by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) same I2C root adapter that they mux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) i2c-mux-gpmux Normally parent-locked, mux-locked iff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) specified in device-tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) i2c-mux-ltc4306 Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) i2c-mux-mlxcpld Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) i2c-mux-pca9541 Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) i2c-mux-pca954x Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) i2c-mux-pinctrl Normally parent-locked, mux-locked iff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) all involved pinctrl devices are controlled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) by the same I2C root adapter that they mux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) i2c-mux-reg Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ====================== =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) In drivers/iio/:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ====================== =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) gyro/mpu3050 Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) imu/inv_mpu6050/ Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ====================== =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) In drivers/media/:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ======================= =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dvb-frontends/lgdt3306a Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dvb-frontends/m88ds3103 Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dvb-frontends/rtl2830 Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dvb-frontends/rtl2832 Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dvb-frontends/si2168 Mux-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) usb/cx231xx/ Parent-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ======================= =============================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) Mux-locked muxes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) Mux-locked muxes does not lock the entire parent adapter during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) full select-transfer-deselect transaction, only the muxes on the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) adapter are locked. Mux-locked muxes are mostly interesting if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) select and/or deselect operations must use I2C transfers to complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) their tasks. Since the parent adapter is not fully locked during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) full transaction, unrelated I2C transfers may interleave the different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) stages of the transaction. This has the benefit that the mux driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) may be easier and cleaner to implement, but it has some caveats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ==== =====================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ML1. If you build a topology with a mux-locked mux being the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) of a parent-locked mux, this might break the expectation from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) parent-locked mux that the root adapter is locked during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) transaction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ML2. It is not safe to build arbitrary topologies with two (or more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) mux-locked muxes that are not siblings, when there are address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) collisions between the devices on the child adapters of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) non-sibling muxes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) I.e. the select-transfer-deselect transaction targeting e.g. device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) address 0x42 behind mux-one may be interleaved with a similar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) operation targeting device address 0x42 behind mux-two. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) intension with such a topology would in this hypothetical example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) be that mux-one and mux-two should not be selected simultaneously,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) but mux-locked muxes do not guarantee that in all topologies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ML3. A mux-locked mux cannot be used by a driver for auto-closing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) gates/muxes, i.e. something that closes automatically after a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) number (one, in most cases) of I2C transfers. Unrelated I2C transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) may creep in and close prematurely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ML4. If any non-I2C operation in the mux driver changes the I2C mux state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) the driver has to lock the root adapter during that operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) Otherwise garbage may appear on the bus as seen from devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) behind the mux, when an unrelated I2C transfer is in flight during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) the non-I2C mux-changing operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ==== =====================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) Mux-locked Example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .--------. | mux- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) | root |--+--| locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) '--------' | | mux M1 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) When there is an access to D1, this happens:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 1. Someone issues an I2C transfer to D1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 2. M1 locks muxes on its parent (the root adapter in this case).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 3. M1 calls ->select to ready the mux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 4. M1 (presumably) does some I2C transfers as part of its select.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) These transfers are normal I2C transfers that locks the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 5. M1 feeds the I2C transfer from step 1 to its parent adapter as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) normal I2C transfer that locks the parent adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 6. M1 calls ->deselect, if it has one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 7. Same rules as in step 4, but for ->deselect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 8. M1 unlocks muxes on its parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) This means that accesses to D2 are lockout out for the full duration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) of the entire operation. But accesses to D3 are possibly interleaved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) at any point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) Parent-locked muxes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) -------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) Parent-locked muxes lock the parent adapter during the full select-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) transfer-deselect transaction. The implication is that the mux driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) has to ensure that any and all I2C transfers through that parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) adapter during the transaction are unlocked I2C transfers (using e.g.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) __i2c_transfer), or a deadlock will follow. There are a couple of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) caveats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ==== ====================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) PL1. If you build a topology with a parent-locked mux being the child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) of another mux, this might break a possible assumption from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) child mux that the root adapter is unused between its select op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) and the actual transfer (e.g. if the child mux is auto-closing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) and the parent mux issues I2C transfers as part of its select).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) This is especially the case if the parent mux is mux-locked, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) it may also happen if the parent mux is parent-locked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) PL2. If select/deselect calls out to other subsystems such as gpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pinctrl, regmap or iio, it is essential that any I2C transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) caused by these subsystems are unlocked. This can be convoluted to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) accomplish, maybe even impossible if an acceptably clean solution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) is sought.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ==== ====================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) Parent-locked Example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .--------. | parent- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) | root |--+--| locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) '--------' | | mux M1 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) When there is an access to D1, this happens:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 1. Someone issues an I2C transfer to D1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 2. M1 locks muxes on its parent (the root adapter in this case).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 3. M1 locks its parent adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 4. M1 calls ->select to ready the mux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 5. If M1 does any I2C transfers (on this root adapter) as part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) its select, those transfers must be unlocked I2C transfers so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) that they do not deadlock the root adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 6. M1 feeds the I2C transfer from step 1 to the root adapter as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unlocked I2C transfer, so that it does not deadlock the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 7. M1 calls ->deselect, if it has one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 8. Same rules as in step 5, but for ->deselect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 9. M1 unlocks its parent adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 10. M1 unlocks muxes on its parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) This means that accesses to both D2 and D3 are locked out for the full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) duration of the entire operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) Complex Examples
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) Parent-locked mux as parent of parent-locked mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) This is a useful topology, but it can be bad::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .----------. .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .--------. | parent- |-----| parent- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) | root |--+--| locked | | locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) '--------' | | mux M1 |--. | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) | '----------' | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) | .--------. | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) '--| dev D4 | '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) '--------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) When any device is accessed, all other devices are locked out for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) the full duration of the operation (both muxes lock their parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) and specifically when M2 requests its parent to lock, M1 passes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) the buck to the root adapter).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) This topology is bad if M2 is an auto-closing mux and M1->select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) issues any unlocked I2C transfers on the root adapter that may leak
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) through and be seen by the M2 adapter, thus closing M2 prematurely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) Mux-locked mux as parent of mux-locked mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) This is a good topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .----------. .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .--------. | mux- |-----| mux- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) | root |--+--| locked | | locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) '--------' | | mux M1 |--. | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) | '----------' | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) | .--------. | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) '--| dev D4 | '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) '--------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) When device D1 is accessed, accesses to D2 are locked out for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) full duration of the operation (muxes on the top child adapter of M1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) are locked). But accesses to D3 and D4 are possibly interleaved at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) any point. Accesses to D3 locks out D1 and D2, but accesses to D4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) are still possibly interleaved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) Mux-locked mux as parent of parent-locked mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ---------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) This is probably a bad topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .----------. .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .--------. | mux- |-----| parent- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) | root |--+--| locked | | locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) '--------' | | mux M1 |--. | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) | '----------' | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) | .--------. | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) '--| dev D4 | '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) '--------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) When device D1 is accessed, accesses to D2 and D3 are locked out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) for the full duration of the operation (M1 locks child muxes on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) root adapter). But accesses to D4 are possibly interleaved at any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) This kind of topology is generally not suitable and should probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) be avoided. The reason is that M2 probably assumes that there will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) be no I2C transfers during its calls to ->select and ->deselect, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if there are, any such transfers might appear on the slave side of M2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) as partial I2C transfers, i.e. garbage or worse. This might cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) device lockups and/or other problems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) The topology is especially troublesome if M2 is an auto-closing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) mux. In that case, any interleaved accesses to D4 might close M2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) prematurely, as might any I2C transfers part of M1->select.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) But if M2 is not making the above stated assumption, and if M2 is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) auto-closing, the topology is fine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) Parent-locked mux as parent of mux-locked mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ---------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) This is a good topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .----------. .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .--------. | parent- |-----| mux- |-----| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) | root |--+--| locked | | locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) '--------' | | mux M1 |--. | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) | '----------' | '----------' '--| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) | .--------. | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) '--| dev D4 | '--| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) '--------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) When D1 is accessed, accesses to D2 are locked out for the full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) duration of the operation (muxes on the top child adapter of M1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) are locked). Accesses to D3 and D4 are possibly interleaved at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) any point, just as is expected for mux-locked muxes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) When D3 or D4 are accessed, everything else is locked out. For D3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) accesses, M1 locks the root adapter. For D4 accesses, the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) adapter is locked directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) Two mux-locked sibling muxes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ----------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) This is a good topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .----------. .--| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) | mux- |--' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .--| locked | .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) | | mux M1 |-----| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) | '----------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) | .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .--------. | | mux- |-----| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) | root |--+--| locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) '--------' | | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) | '----------' '--| dev D4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) '--| dev D5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) When D1 is accessed, accesses to D2, D3 and D4 are locked out. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) accesses to D5 may be interleaved at any time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) Two parent-locked sibling muxes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) -------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) This is a good topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .----------. .--| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) | parent- |--' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .--| locked | .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) | | mux M1 |-----| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) | '----------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) | .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .--------. | | parent- |-----| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) | root |--+--| locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) '--------' | | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) | '----------' '--| dev D4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) '--| dev D5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) When any device is accessed, accesses to all other devices are locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) Mux-locked and parent-locked sibling muxes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) This is a good topology::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .----------. .--| dev D1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) | mux- |--' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .--| locked | .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) | | mux M1 |-----| dev D2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) | '----------' '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) | .----------. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .--------. | | parent- |-----| dev D3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) | root |--+--| locked | '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) '--------' | | mux M2 |--. .--------.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) | '----------' '--| dev D4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) | .--------. '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) '--| dev D5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) '--------'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) When D1 or D2 are accessed, accesses to D3 and D4 are locked out while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) accesses to D5 may interleave. When D3 or D4 are accessed, accesses to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) all other devices are locked out.