162306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
262306a36Sopenharmony_ci%YAML 1.2
362306a36Sopenharmony_ci---
462306a36Sopenharmony_ci$id: http://devicetree.org/schemas/i2c/i2c-arb-gpio-challenge.yaml#
562306a36Sopenharmony_ci$schema: http://devicetree.org/meta-schemas/core.yaml#
662306a36Sopenharmony_ci
762306a36Sopenharmony_cititle: GPIO-based I2C Arbitration Using a Challenge & Response Mechanism
862306a36Sopenharmony_ci
962306a36Sopenharmony_cimaintainers:
1062306a36Sopenharmony_ci  - Doug Anderson <dianders@chromium.org>
1162306a36Sopenharmony_ci  - Peter Rosin <peda@axentia.se>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cidescription: |
1462306a36Sopenharmony_ci  This uses GPIO lines and a challenge & response mechanism to arbitrate who is
1562306a36Sopenharmony_ci  the master of an I2C bus in a multimaster situation.
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci  In many cases using GPIOs to arbitrate is not needed and a design can use the
1862306a36Sopenharmony_ci  standard I2C multi-master rules.  Using GPIOs is generally useful in the case
1962306a36Sopenharmony_ci  where there is a device on the bus that has errata and/or bugs that makes
2062306a36Sopenharmony_ci  standard multimaster mode not feasible.
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci  Note that this scheme works well enough but has some downsides:
2362306a36Sopenharmony_ci   * It is nonstandard (not using standard I2C multimaster)
2462306a36Sopenharmony_ci   * Having two masters on a bus in general makes it relatively hard to debug
2562306a36Sopenharmony_ci     problems (hard to tell if i2c issues were caused by one master, another,
2662306a36Sopenharmony_ci     or some device on the bus).
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci  Algorithm:
2962306a36Sopenharmony_ci  All masters on the bus have a 'bus claim' line which is an output that the
3062306a36Sopenharmony_ci  others can see. These are all active low with pull-ups enabled.  We'll
3162306a36Sopenharmony_ci  describe these lines as:
3262306a36Sopenharmony_ci   * OUR_CLAIM: output from us signaling to other hosts that we want the bus
3362306a36Sopenharmony_ci   * THEIR_CLAIMS: output from others signaling that they want the bus
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci  The basic algorithm is to assert your line when you want the bus, then make
3662306a36Sopenharmony_ci  sure that the other side doesn't want it also.  A detailed explanation is
3762306a36Sopenharmony_ci  best done with an example.
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci  Let's say we want to claim the bus.  We:
4062306a36Sopenharmony_ci  1. Assert OUR_CLAIM.
4162306a36Sopenharmony_ci  2. Waits a little bit for the other sides to notice (slew time, say 10
4262306a36Sopenharmony_ci     microseconds).
4362306a36Sopenharmony_ci  3. Check THEIR_CLAIMS.  If none are asserted then the we have the bus and we
4462306a36Sopenharmony_ci     are done.
4562306a36Sopenharmony_ci  4. Otherwise, wait for a few milliseconds and see if THEIR_CLAIMS are released.
4662306a36Sopenharmony_ci  5. If not, back off, release the claim and wait for a few more milliseconds.
4762306a36Sopenharmony_ci  6. Go back to 1 (until retry time has expired).
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciproperties:
5062306a36Sopenharmony_ci  compatible:
5162306a36Sopenharmony_ci    const: i2c-arb-gpio-challenge
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci  i2c-parent:
5462306a36Sopenharmony_ci    $ref: /schemas/types.yaml#/definitions/phandle
5562306a36Sopenharmony_ci    description:
5662306a36Sopenharmony_ci      The I2C bus that this multiplexer's master-side port is connected to.
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci  our-claim-gpios:
5962306a36Sopenharmony_ci    maxItems: 1
6062306a36Sopenharmony_ci    description:
6162306a36Sopenharmony_ci      The GPIO that we use to claim the bus.
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci  slew-delay-us:
6462306a36Sopenharmony_ci    default: 10
6562306a36Sopenharmony_ci    description:
6662306a36Sopenharmony_ci      Time to wait for a GPIO to go high.
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci  their-claim-gpios:
6962306a36Sopenharmony_ci    minItems: 1
7062306a36Sopenharmony_ci    maxItems: 8
7162306a36Sopenharmony_ci    description:
7262306a36Sopenharmony_ci      The GPIOs that the other sides use to claim the bus.  Note that some
7362306a36Sopenharmony_ci      implementations may only support a single other master.
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci  wait-free-us:
7662306a36Sopenharmony_ci    default: 50000
7762306a36Sopenharmony_ci    description:
7862306a36Sopenharmony_ci      We'll give up after this many microseconds.
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci  wait-retry-us:
8162306a36Sopenharmony_ci    default: 3000
8262306a36Sopenharmony_ci    description:
8362306a36Sopenharmony_ci      We'll attempt another claim after this many microseconds.
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci  i2c-arb:
8662306a36Sopenharmony_ci    type: object
8762306a36Sopenharmony_ci    $ref: /schemas/i2c/i2c-controller.yaml
8862306a36Sopenharmony_ci    unevaluatedProperties: false
8962306a36Sopenharmony_ci    description:
9062306a36Sopenharmony_ci      I2C arbitration bus node.
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cirequired:
9362306a36Sopenharmony_ci  - compatible
9462306a36Sopenharmony_ci  - i2c-arb
9562306a36Sopenharmony_ci  - our-claim-gpios
9662306a36Sopenharmony_ci  - their-claim-gpios
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciadditionalProperties: false
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciexamples:
10162306a36Sopenharmony_ci  - |
10262306a36Sopenharmony_ci    #include <dt-bindings/gpio/gpio.h>
10362306a36Sopenharmony_ci    #include <dt-bindings/interrupt-controller/irq.h>
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci    i2c-arbitrator {
10662306a36Sopenharmony_ci        compatible = "i2c-arb-gpio-challenge";
10762306a36Sopenharmony_ci        i2c-parent = <&i2c_4>;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci        our-claim-gpios = <&gpf0 3 GPIO_ACTIVE_LOW>;
11062306a36Sopenharmony_ci        their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
11162306a36Sopenharmony_ci        slew-delay-us = <10>;
11262306a36Sopenharmony_ci        wait-retry-us = <3000>;
11362306a36Sopenharmony_ci        wait-free-us = <50000>;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci        i2c-arb {
11662306a36Sopenharmony_ci            #address-cells = <1>;
11762306a36Sopenharmony_ci            #size-cells = <0>;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci            sbs-battery@b {
12062306a36Sopenharmony_ci                compatible = "sbs,sbs-battery";
12162306a36Sopenharmony_ci                reg = <0xb>;
12262306a36Sopenharmony_ci                sbs,poll-retry-count = <1>;
12362306a36Sopenharmony_ci            };
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci            embedded-controller@1e {
12662306a36Sopenharmony_ci                compatible = "google,cros-ec-i2c";
12762306a36Sopenharmony_ci                reg = <0x1e>;
12862306a36Sopenharmony_ci                interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
12962306a36Sopenharmony_ci                interrupt-parent = <&gpx1>;
13062306a36Sopenharmony_ci                pinctrl-names = "default";
13162306a36Sopenharmony_ci                pinctrl-0 = <&ec_irq>;
13262306a36Sopenharmony_ci                wakeup-source;
13362306a36Sopenharmony_ci            };
13462306a36Sopenharmony_ci        };
13562306a36Sopenharmony_ci    };
136