1*aa1a8ff2SEmmanuel Vadot# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2*aa1a8ff2SEmmanuel Vadot%YAML 1.2 3*aa1a8ff2SEmmanuel Vadot--- 4*aa1a8ff2SEmmanuel Vadot$id: http://devicetree.org/schemas/i2c/i2c-arb-gpio-challenge.yaml# 5*aa1a8ff2SEmmanuel Vadot$schema: http://devicetree.org/meta-schemas/core.yaml# 6*aa1a8ff2SEmmanuel Vadot 7*aa1a8ff2SEmmanuel Vadottitle: GPIO-based I2C Arbitration Using a Challenge & Response Mechanism 8*aa1a8ff2SEmmanuel Vadot 9*aa1a8ff2SEmmanuel Vadotmaintainers: 10*aa1a8ff2SEmmanuel Vadot - Doug Anderson <dianders@chromium.org> 11*aa1a8ff2SEmmanuel Vadot - Peter Rosin <peda@axentia.se> 12*aa1a8ff2SEmmanuel Vadot 13*aa1a8ff2SEmmanuel Vadotdescription: | 14*aa1a8ff2SEmmanuel Vadot This uses GPIO lines and a challenge & response mechanism to arbitrate who is 15*aa1a8ff2SEmmanuel Vadot the master of an I2C bus in a multimaster situation. 16*aa1a8ff2SEmmanuel Vadot 17*aa1a8ff2SEmmanuel Vadot In many cases using GPIOs to arbitrate is not needed and a design can use the 18*aa1a8ff2SEmmanuel Vadot standard I2C multi-master rules. Using GPIOs is generally useful in the case 19*aa1a8ff2SEmmanuel Vadot where there is a device on the bus that has errata and/or bugs that makes 20*aa1a8ff2SEmmanuel Vadot standard multimaster mode not feasible. 21*aa1a8ff2SEmmanuel Vadot 22*aa1a8ff2SEmmanuel Vadot Note that this scheme works well enough but has some downsides: 23*aa1a8ff2SEmmanuel Vadot * It is nonstandard (not using standard I2C multimaster) 24*aa1a8ff2SEmmanuel Vadot * Having two masters on a bus in general makes it relatively hard to debug 25*aa1a8ff2SEmmanuel Vadot problems (hard to tell if i2c issues were caused by one master, another, 26*aa1a8ff2SEmmanuel Vadot or some device on the bus). 27*aa1a8ff2SEmmanuel Vadot 28*aa1a8ff2SEmmanuel Vadot Algorithm: 29*aa1a8ff2SEmmanuel Vadot All masters on the bus have a 'bus claim' line which is an output that the 30*aa1a8ff2SEmmanuel Vadot others can see. These are all active low with pull-ups enabled. We'll 31*aa1a8ff2SEmmanuel Vadot describe these lines as: 32*aa1a8ff2SEmmanuel Vadot * OUR_CLAIM: output from us signaling to other hosts that we want the bus 33*aa1a8ff2SEmmanuel Vadot * THEIR_CLAIMS: output from others signaling that they want the bus 34*aa1a8ff2SEmmanuel Vadot 35*aa1a8ff2SEmmanuel Vadot The basic algorithm is to assert your line when you want the bus, then make 36*aa1a8ff2SEmmanuel Vadot sure that the other side doesn't want it also. A detailed explanation is 37*aa1a8ff2SEmmanuel Vadot best done with an example. 38*aa1a8ff2SEmmanuel Vadot 39*aa1a8ff2SEmmanuel Vadot Let's say we want to claim the bus. We: 40*aa1a8ff2SEmmanuel Vadot 1. Assert OUR_CLAIM. 41*aa1a8ff2SEmmanuel Vadot 2. Waits a little bit for the other sides to notice (slew time, say 10 42*aa1a8ff2SEmmanuel Vadot microseconds). 43*aa1a8ff2SEmmanuel Vadot 3. Check THEIR_CLAIMS. If none are asserted then the we have the bus and we 44*aa1a8ff2SEmmanuel Vadot are done. 45*aa1a8ff2SEmmanuel Vadot 4. Otherwise, wait for a few milliseconds and see if THEIR_CLAIMS are released. 46*aa1a8ff2SEmmanuel Vadot 5. If not, back off, release the claim and wait for a few more milliseconds. 47*aa1a8ff2SEmmanuel Vadot 6. Go back to 1 (until retry time has expired). 48*aa1a8ff2SEmmanuel Vadot 49*aa1a8ff2SEmmanuel Vadotproperties: 50*aa1a8ff2SEmmanuel Vadot compatible: 51*aa1a8ff2SEmmanuel Vadot const: i2c-arb-gpio-challenge 52*aa1a8ff2SEmmanuel Vadot 53*aa1a8ff2SEmmanuel Vadot i2c-parent: 54*aa1a8ff2SEmmanuel Vadot $ref: /schemas/types.yaml#/definitions/phandle 55*aa1a8ff2SEmmanuel Vadot description: 56*aa1a8ff2SEmmanuel Vadot The I2C bus that this multiplexer's master-side port is connected to. 57*aa1a8ff2SEmmanuel Vadot 58*aa1a8ff2SEmmanuel Vadot our-claim-gpios: 59*aa1a8ff2SEmmanuel Vadot maxItems: 1 60*aa1a8ff2SEmmanuel Vadot description: 61*aa1a8ff2SEmmanuel Vadot The GPIO that we use to claim the bus. 62*aa1a8ff2SEmmanuel Vadot 63*aa1a8ff2SEmmanuel Vadot slew-delay-us: 64*aa1a8ff2SEmmanuel Vadot default: 10 65*aa1a8ff2SEmmanuel Vadot description: 66*aa1a8ff2SEmmanuel Vadot Time to wait for a GPIO to go high. 67*aa1a8ff2SEmmanuel Vadot 68*aa1a8ff2SEmmanuel Vadot their-claim-gpios: 69*aa1a8ff2SEmmanuel Vadot minItems: 1 70*aa1a8ff2SEmmanuel Vadot maxItems: 8 71*aa1a8ff2SEmmanuel Vadot description: 72*aa1a8ff2SEmmanuel Vadot The GPIOs that the other sides use to claim the bus. Note that some 73*aa1a8ff2SEmmanuel Vadot implementations may only support a single other master. 74*aa1a8ff2SEmmanuel Vadot 75*aa1a8ff2SEmmanuel Vadot wait-free-us: 76*aa1a8ff2SEmmanuel Vadot default: 50000 77*aa1a8ff2SEmmanuel Vadot description: 78*aa1a8ff2SEmmanuel Vadot We'll give up after this many microseconds. 79*aa1a8ff2SEmmanuel Vadot 80*aa1a8ff2SEmmanuel Vadot wait-retry-us: 81*aa1a8ff2SEmmanuel Vadot default: 3000 82*aa1a8ff2SEmmanuel Vadot description: 83*aa1a8ff2SEmmanuel Vadot We'll attempt another claim after this many microseconds. 84*aa1a8ff2SEmmanuel Vadot 85*aa1a8ff2SEmmanuel Vadot i2c-arb: 86*aa1a8ff2SEmmanuel Vadot type: object 87*aa1a8ff2SEmmanuel Vadot $ref: /schemas/i2c/i2c-controller.yaml 88*aa1a8ff2SEmmanuel Vadot unevaluatedProperties: false 89*aa1a8ff2SEmmanuel Vadot description: 90*aa1a8ff2SEmmanuel Vadot I2C arbitration bus node. 91*aa1a8ff2SEmmanuel Vadot 92*aa1a8ff2SEmmanuel Vadotrequired: 93*aa1a8ff2SEmmanuel Vadot - compatible 94*aa1a8ff2SEmmanuel Vadot - i2c-arb 95*aa1a8ff2SEmmanuel Vadot - our-claim-gpios 96*aa1a8ff2SEmmanuel Vadot - their-claim-gpios 97*aa1a8ff2SEmmanuel Vadot 98*aa1a8ff2SEmmanuel VadotadditionalProperties: false 99*aa1a8ff2SEmmanuel Vadot 100*aa1a8ff2SEmmanuel Vadotexamples: 101*aa1a8ff2SEmmanuel Vadot - | 102*aa1a8ff2SEmmanuel Vadot #include <dt-bindings/gpio/gpio.h> 103*aa1a8ff2SEmmanuel Vadot #include <dt-bindings/interrupt-controller/irq.h> 104*aa1a8ff2SEmmanuel Vadot 105*aa1a8ff2SEmmanuel Vadot i2c-arbitrator { 106*aa1a8ff2SEmmanuel Vadot compatible = "i2c-arb-gpio-challenge"; 107*aa1a8ff2SEmmanuel Vadot i2c-parent = <&i2c_4>; 108*aa1a8ff2SEmmanuel Vadot 109*aa1a8ff2SEmmanuel Vadot our-claim-gpios = <&gpf0 3 GPIO_ACTIVE_LOW>; 110*aa1a8ff2SEmmanuel Vadot their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>; 111*aa1a8ff2SEmmanuel Vadot slew-delay-us = <10>; 112*aa1a8ff2SEmmanuel Vadot wait-retry-us = <3000>; 113*aa1a8ff2SEmmanuel Vadot wait-free-us = <50000>; 114*aa1a8ff2SEmmanuel Vadot 115*aa1a8ff2SEmmanuel Vadot i2c-arb { 116*aa1a8ff2SEmmanuel Vadot #address-cells = <1>; 117*aa1a8ff2SEmmanuel Vadot #size-cells = <0>; 118*aa1a8ff2SEmmanuel Vadot 119*aa1a8ff2SEmmanuel Vadot sbs-battery@b { 120*aa1a8ff2SEmmanuel Vadot compatible = "sbs,sbs-battery"; 121*aa1a8ff2SEmmanuel Vadot reg = <0xb>; 122*aa1a8ff2SEmmanuel Vadot sbs,poll-retry-count = <1>; 123*aa1a8ff2SEmmanuel Vadot }; 124*aa1a8ff2SEmmanuel Vadot 125*aa1a8ff2SEmmanuel Vadot embedded-controller@1e { 126*aa1a8ff2SEmmanuel Vadot compatible = "google,cros-ec-i2c"; 127*aa1a8ff2SEmmanuel Vadot reg = <0x1e>; 128*aa1a8ff2SEmmanuel Vadot interrupts = <6 IRQ_TYPE_LEVEL_HIGH>; 129*aa1a8ff2SEmmanuel Vadot interrupt-parent = <&gpx1>; 130*aa1a8ff2SEmmanuel Vadot pinctrl-names = "default"; 131*aa1a8ff2SEmmanuel Vadot pinctrl-0 = <&ec_irq>; 132*aa1a8ff2SEmmanuel Vadot wakeup-source; 133*aa1a8ff2SEmmanuel Vadot }; 134*aa1a8ff2SEmmanuel Vadot }; 135*aa1a8ff2SEmmanuel Vadot }; 136