code:
.. SPDX-License-Identifier: GPL-2.0

===============
Linux I2C Sysfs
===============

Overview
========

I2C topology can be complex because of the existence of I2C MUX
(I2C Multiplexer). The Linux
kernel abstracts the MUX channels into logical I2C bus numbers. However, there
is a gap of knowledge to map from the I2C bus physical number and MUX topology
to logical I2C bus number. This doc is aimed to fill in this gap, so the
audience (hardware engineers and new software developers for example) can learn
the concept of logical I2C buses in the kernel, by knowing the physical I2C
topology and navigating through the I2C sysfs in Linux shell. This knowledge is
useful and essential to use ``i2c-tools`` for the purpose of development and
debugging.

Target audience
---------------

People who need to use Linux shell to interact with I2C subsystem on a system
which the Linux is running on.

Prerequisites
-------------

1.  Knowledge of general Linux shell file system commands and operations.

2.  General knowledge of I2C, I2C MUX and I2C topology.

Location of I2C Sysfs
=====================

Typically, the Linux Sysfs filesystem is mounted at the ``/sys`` directory,
so you can find the I2C Sysfs under ``/sys/bus/i2c/devices``
where you can directly ``cd`` to it.
There is a list of symbolic links under that directory. The links that
start with ``i2c-`` are I2C buses, which may be either physical or logical. The
other links that begin with numbers and end with numbers are I2C devices, where
the first number is I2C bus number, and the second number is I2C address.

Google Pixel 3 phone for example::

  blueline:/sys/bus/i2c/devices $ ls
  0-0008  0-0061  1-0028  3-0043  4-0036  4-0041  i2c-1  i2c-3
  0-000c  0-0066  2-0049  4-000b  4-0040  i2c-0   i2c-2  i2c-4

``i2c-2`` is an I2C bus whose number is 2, and ``2-0049`` is an I2C device
on bus 2 address 0x49 bound with a kernel driver.

Terminology
===========

First, let us define some terms to avoid confusion in later sections.

(Physical) I2C Bus Controller
-----------------------------

The hardware system that the Linux kernel is running on may have multiple
physical I2C bus controllers. The controllers are hardware and physical, and the
system may define multiple registers in the memory space to manipulate the
controllers. Linux kernel has I2C bus drivers under source directory
``drivers/i2c/busses`` to translate kernel I2C API into register
operations for different systems. This terminology is not limited to Linux
kernel only.

I2C Bus Physical Number
-----------------------

For each physical I2C bus controller, the system vendor may assign a physical
number to each controller. For example, the first I2C bus controller which has
the lowest register addresses may be called ``I2C-0``.

Logical I2C Bus
---------------

Every I2C bus number you see in Linux I2C Sysfs is a logical I2C bus with a
number assigned. This is similar to the fact that software code is usually
written upon virtual memory space, instead of physical memory space.

Each logical I2C bus may be an abstraction of a physical I2C bus controller, or
an abstraction of a channel behind an I2C MUX. In case it is an abstraction of a
MUX channel, whenever we access an I2C device via a such logical bus, the kernel
will switch the I2C MUX for you to the proper channel as part of the
abstraction.

Physical I2C Bus
----------------

If the logical I2C bus is a direct abstraction of a physical I2C bus controller,
let us call it a physical I2C bus.

Caveat
------

This may be a confusing part for people who only know about the physical I2C
design of a board. It is actually possible to rename the I2C bus physical number
to a different number in logical I2C bus level in Device Tree Source (DTS) under
section ``aliases``. See ``arch/arm/boot/dts/nuvoton-npcm730-gsj.dts``
for an example of DTS file.

Best Practice: **(To kernel software developers)** It is better to keep the I2C
bus physical number the same as their corresponding logical I2C bus number,
instead of renaming or mapping them, so that it may be less confusing to other
users. These physical I2C buses can be served as good starting points for I2C
MUX fanouts. For the following examples, we will assume that the physical I2C
bus has a number same as their I2C bus physical number.

Walk through Logical I2C Bus
============================

For the following content, we will use a more complex I2C topology as an
example. Here is a brief graph for the I2C topology. If you do not understand
this graph at first glance, do not be afraid to continue reading this doc
and review it when you finish reading.

::

  i2c-7 (physical I2C bus controller 7)
  `-- 7-0071 (4-channel I2C MUX at 0x71)
      |-- i2c-60 (channel-0)
      |-- i2c-73 (channel-1)
      |   |-- 73-0040 (I2C sensor device with hwmon directory)
      |   |-- 73-0070 (I2C MUX at 0x70, exists in DTS, but failed to probe)
      |   `-- 73-0072 (8-channel I2C MUX at 0x72)
      |       |-- i2c-78 (channel-0)
      |       |-- ... (channel-1...6, i2c-79...i2c-84)
      |       `-- i2c-85 (channel-7)
      |-- i2c-86 (channel-2)
      `-- i2c-203 (channel-3)

Distinguish Physical and Logical I2C Bus
----------------------------------------

One simple way to distinguish between a physical I2C bus and a logical I2C bus,
is to read the symbolic link ``device`` under the I2C bus directory by using
command ``ls -l`` or ``readlink``.

An alternative symbolic link to check is ``mux_device``. This link only exists
in logical I2C bus directory which is fanned out from another I2C bus.
Reading this link will also tell you which I2C MUX device created
this logical I2C bus.

If the symbolic link points to a directory ending with ``.i2c``, it should be a
physical I2C bus, directly abstracting a physical I2C bus controller. For
example::

  $ readlink /sys/bus/i2c/devices/i2c-7/device
  ../../f0087000.i2c
  $ ls /sys/bus/i2c/devices/i2c-7/mux_device
  ls: /sys/bus/i2c/devices/i2c-7/mux_device: No such file or directory

In this case, ``i2c-7`` is a physical I2C bus, so it does not have the symbolic
link ``mux_device`` under its directory. And if the kernel software developer
follows the common practice by not renaming physical I2C buses, this should also
mean the physical I2C bus controller 7 of the system.

On the other hand, if the symbolic link points to another I2C bus, the I2C bus
presented by the current directory has to be a logical bus. The I2C bus pointed
by the link is the parent bus which may be either a physical I2C bus or a
logical one. In this case, the I2C bus presented by the current directory
abstracts an I2C MUX channel under the parent bus.

For example::

  $ readlink /sys/bus/i2c/devices/i2c-73/device
  ../../i2c-7
  $ readlink /sys/bus/i2c/devices/i2c-73/mux_device
  ../7-0071

``i2c-73`` is a logical bus fanout by an I2C MUX under ``i2c-7``
whose I2C address is 0x71.
Whenever we access an I2C device with bus 73, the kernel will always
switch the I2C MUX addressed 0x71 to the proper channel for you as part of the
abstraction.

Finding out Logical I2C Bus Number
----------------------------------

In this section, we will describe how to find out the logical I2C bus number
representing certain I2C MUX channels based on the knowledge of physical
hardware I2C topology.

In this example, we have a system which has a physical I2C bus 7 and not renamed
in DTS. There is a 4-channel MUX at address 0x71 on that bus. There is another
8-channel MUX at address 0x72 behind the channel 1 of the 0x71 MUX. Let us
navigate through Sysfs and find out the logical I2C bus number of the channel 3
of the 0x72 MUX.

First of all, let us go to the directory of ``i2c-7``::

  ~$ cd /sys/bus/i2c/devices/i2c-7
  /sys/bus/i2c/devices/i2c-7$ ls
  7-0071         i2c-60         name           subsystem
  delete_device  i2c-73         new_device     uevent
  device         i2c-86         of_node
  i2c-203        i2c-dev        power

There, we see the 0x71 MUX as ``7-0071``. Go inside it::

  /sys/bus/i2c/devices/i2c-7$ cd 7-0071/
  /sys/bus/i2c/devices/i2c-7/7-0071$ ls -l
  channel-0   channel-3   modalias    power
  channel-1   driver      name        subsystem
  channel-2   idle_state  of_node     uevent

Read the link ``channel-1`` using ``readlink`` or ``ls -l``::

  /sys/bus/i2c/devices/i2c-7/7-0071$ readlink channel-1
  ../i2c-73

We find out that the channel 1 of 0x71 MUX on ``i2c-7`` is assigned
with a logical I2C bus number of 73.
Let us continue the journey to directory ``i2c-73`` in either ways::

  # cd to i2c-73 under I2C Sysfs root
  /sys/bus/i2c/devices/i2c-7/7-0071$ cd /sys/bus/i2c/devices/i2c-73
  /sys/bus/i2c/devices/i2c-73$

  # cd the channel symbolic link
  /sys/bus/i2c/devices/i2c-7/7-0071$ cd channel-1
  /sys/bus/i2c/devices/i2c-7/7-0071/channel-1$

  # cd the link content
  /sys/bus/i2c/devices/i2c-7/7-0071$ cd ../i2c-73
  /sys/bus/i2c/devices/i2c-7/i2c-73$

Either ways, you will end up in the directory of ``i2c-73``. Similar to above,
we can now find the 0x72 MUX and what logical I2C bus numbers
that its channels are assigned::

  /sys/bus/i2c/devices/i2c-73$ ls
  73-0040        device         i2c-83         new_device
  73-004e        i2c-78         i2c-84         of_node
  73-0050        i2c-79         i2c-85         power
  73-0070        i2c-80         i2c-dev        subsystem
  73-0072        i2c-81         mux_device     uevent
  delete_device  i2c-82         name
  /sys/bus/i2c/devices/i2c-73$ cd 73-0072
  /sys/bus/i2c/devices/i2c-73/73-0072$ ls
  channel-0   channel-4   driver      of_node
  channel-1   channel-5   idle_state  power
  channel-2   channel-6   modalias    subsystem
  channel-3   channel-7   name        uevent
  /sys/bus/i2c/devices/i2c-73/73-0072$ readlink channel-3
  ../i2c-81

There, we find out the logical I2C bus number of the channel 3 of the 0x72 MUX
is 81. We can later use this number to switch to its own I2C Sysfs directory or
issue ``i2c-tools`` commands.

Tip: Once you understand the I2C topology with MUX, command
`i2cdetect -l
<https://manpages.debian.org/unstable/i2c-tools/i2cdetect.8.en.html>`_
in
`I2C Tools
<https://i2c.wiki.kernel.org/index.php/I2C_Tools>`_
can give you
an overview of the I2C topology easily, if it is available on your system. For
example::

  $ i2cdetect -l | grep -e '\-73' -e _7 | sort -V
  i2c-7   i2c             npcm_i2c_7                              I2C adapter
  i2c-73  i2c             i2c-7-mux (chan_id 1)                   I2C adapter
  i2c-78  i2c             i2c-73-mux (chan_id 0)                  I2C adapter
  i2c-79  i2c             i2c-73-mux (chan_id 1)                  I2C adapter
  i2c-80  i2c             i2c-73-mux (chan_id 2)                  I2C adapter
  i2c-81  i2c             i2c-73-mux (chan_id 3)                  I2C adapter
  i2c-82  i2c             i2c-73-mux (chan_id 4)                  I2C adapter
  i2c-83  i2c             i2c-73-mux (chan_id 5)                  I2C adapter
  i2c-84  i2c             i2c-73-mux (chan_id 6)                  I2C adapter
  i2c-85  i2c             i2c-73-mux (chan_id 7)                  I2C adapter

Pinned Logical I2C Bus Number
-----------------------------

If not specified in DTS, when an I2C MUX driver is applied and the MUX device is
successfully probed, the kernel will assign the MUX channels with a logical bus
number based on the current biggest logical bus number incrementally. For
example, if the system has ``i2c-15`` as the highest logical bus number, and a
4-channel MUX is applied successfully, we will have ``i2c-16`` for the
MUX channel 0, and all the way to ``i2c-19`` for the MUX channel 3.

The kernel software developer is able to pin the fanout MUX channels to a static
logical I2C bus number in the DTS. This doc will not go through the details on
how to implement this in DTS, but we can see an example in:
``arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts``

In the above example, there is an 8-channel I2C MUX at address 0x70 on physical
I2C bus 2. The channel 2 of the MUX is defined as ``imux18`` in DTS,
and pinned to logical I2C bus number 18 with the line of ``i2c18 = &imux18;``
in section ``aliases``.

Take it further, it is possible to design a logical I2C bus number schema that
can be easily remembered by humans or calculated arithmetically. For example, we
can pin the fanout channels of a MUX on bus 3 to start at 30. So 30 will be the
logical bus number of the channel 0 of the MUX on bus 3, and 37 will be the
logical bus number of the channel 7 of the MUX on bus 3.

I2C Devices
===========

In previous sections, we mostly covered the I2C bus. In this section, let us see
what we can learn from the I2C device directory whose link name is in the format
of ``${bus}-${addr}``. The ``${bus}`` part in the name is a logical I2C bus
decimal number, while the ``${addr}`` part is a hex number of the I2C address
of each device.

I2C Device Directory Content
----------------------------

Inside each I2C device directory, there is a file named ``name``.
This file tells what device name it was used for the kernel driver to
probe this device. Use command ``cat`` to read its content. For example::

  /sys/bus/i2c/devices/i2c-73$ cat 73-0040/name
  ina230
  /sys/bus/i2c/devices/i2c-73$ cat 73-0070/name
  pca9546
  /sys/bus/i2c/devices/i2c-73$ cat 73-0072/name
  pca9547

There is a symbolic link named ``driver`` to tell what Linux kernel driver was
used to probe this device::

  /sys/bus/i2c/devices/i2c-73$ readlink -f 73-0040/driver
  /sys/bus/i2c/drivers/ina2xx
  /sys/bus/i2c/devices/i2c-73$ readlink -f 73-0072/driver
  /sys/bus/i2c/drivers/pca954x

But if the link ``driver`` does not exist at the first place,
it may mean that the kernel driver failed to probe this device due to
some errors. The error may be found in ``dmesg``::

  /sys/bus/i2c/devices/i2c-73$ ls 73-0070/driver
  ls: 73-0070/driver: No such file or directory
  /sys/bus/i2c/devices/i2c-73$ dmesg | grep 73-0070
  pca954x 73-0070: probe failed
  pca954x 73-0070: probe failed

Depending on what the I2C device is and what kernel driver was used to probe the
device, we may have different content in the device directory.

I2C MUX Device
--------------

While you may be already aware of this in previous sections, an I2C MUX device
will have symbolic link ``channel-*`` inside its device directory.
These symbolic links point to their logical I2C bus directories::

  /sys/bus/i2c/devices/i2c-73$ ls -l 73-0072/channel-*
  lrwxrwxrwx ... 73-0072/channel-0 -> ../i2c-78
  lrwxrwxrwx ... 73-0072/channel-1 -> ../i2c-79
  lrwxrwxrwx ... 73-0072/channel-2 -> ../i2c-80
  lrwxrwxrwx ... 73-0072/channel-3 -> ../i2c-81
  lrwxrwxrwx ... 73-0072/channel-4 -> ../i2c-82
  lrwxrwxrwx ... 73-0072/channel-5 -> ../i2c-83
  lrwxrwxrwx ... 73-0072/channel-6 -> ../i2c-84
  lrwxrwxrwx ... 73-0072/channel-7 -> ../i2c-85

I2C Sensor Device / Hwmon
-------------------------

I2C sensor device is also common to see. If they are bound by a kernel hwmon
(Hardware Monitoring) driver successfully, you will see a ``hwmon`` directory
inside the I2C device directory. Keep digging into it, you will find the Hwmon
Sysfs for the I2C sensor device::

  /sys/bus/i2c/devices/i2c-73/73-0040/hwmon/hwmon17$ ls
  curr1_input        in0_lcrit_alarm    name               subsystem
  device             in1_crit           power              uevent
  in0_crit           in1_crit_alarm     power1_crit        update_interval
  in0_crit_alarm     in1_input          power1_crit_alarm
  in0_input          in1_lcrit          power1_input
  in0_lcrit          in1_lcrit_alarm    shunt_resistor

For more info on the Hwmon Sysfs, refer to the doc:

../hwmon/sysfs-interface.rst

Instantiate I2C Devices in I2C Sysfs
------------------------------------

Refer to section "Method 4: Instantiate from user-space" of instantiating-devices.rst


code:
================================
I2C muxes and complex topologies
================================

There are a couple of reasons for building more complex I2C topologies
than a straight-forward I2C bus with one adapter and one or more devices.

Some example use cases are:

1. A mux may be needed on the bus to prevent address collisions.

2. The bus may be accessible from some external bus master, and arbitration
   may be needed to determine if it is ok to access the bus.

3. A device (particularly RF tuners) may want to avoid the digital noise
   from the I2C bus, at least most of the time, and sits behind a gate
   that has to be operated before the device can be accessed.

Several types of hardware components such as I2C muxes, I2C gates and I2C
arbitrators allow to handle such needs.

These components are represented as I2C adapter trees by Linux, where
each adapter has a parent adapter (except the root adapter) and zero or
more child adapters. The root adapter is the actual adapter that issues
I2C transfers, and all adapters with a parent are part of an "i2c-mux"
object (quoted, since it can also be an arbitrator or a gate).

Depending of the particular mux driver, something happens when there is
an I2C transfer on one of its child adapters. The mux driver can
obviously operate a mux, but it can also do arbitration with an external
bus master or open a gate. The mux driver has two operations for this,
select and deselect. select is called before the transfer and (the
optional) deselect is called after the transfer.

Locking
=======

There are two variants of locking available to I2C muxes, they can be
mux-locked or parent-locked muxes.

Mux-locked muxes
----------------

Mux-locked muxes does not lock the entire parent adapter during the
full select-transfer-deselect transaction, only the muxes on the parent
adapter are locked. Mux-locked muxes are mostly interesting if the
select and/or deselect operations must use I2C transfers to complete
their tasks. Since the parent adapter is not fully locked during the
full transaction, unrelated I2C transfers may interleave the different
stages of the transaction. This has the benefit that the mux driver
may be easier and cleaner to implement, but it has some caveats.

Mux-locked Example
~~~~~~~~~~~~~~~~~~

::

                   .----------.     .--------.
    .--------.     |   mux-   |-----| dev D1 |
    |  root  |--+--|  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  .--------.
                |  '----------'  '--| dev D2 |
                |  .--------.       '--------'
                '--| dev D3 |
                   '--------'

When there is an access to D1, this happens:

 1. Someone issues an I2C transfer to D1.
 2. M1 locks muxes on its parent (the root adapter in this case).
 3. M1 calls ->select to ready the mux.
 4. M1 (presumably) does some I2C transfers as part of its select.
    These transfers are normal I2C transfers that locks the parent
    adapter.
 5. M1 feeds the I2C transfer from step 1 to its parent adapter as a
    normal I2C transfer that locks the parent adapter.
 6. M1 calls ->deselect, if it has one.
 7. Same rules as in step 4, but for ->deselect.
 8. M1 unlocks muxes on its parent.

This means that accesses to D2 are lockout out for the full duration
of the entire operation. But accesses to D3 are possibly interleaved
at any point.

Mux-locked caveats
~~~~~~~~~~~~~~~~~~

When using a mux-locked mux, be aware of the following restrictions:

[ML1]
  If you build a topology with a mux-locked mux being the parent
  of a parent-locked mux, this might break the expectation from the
  parent-locked mux that the root adapter is locked during the
  transaction.

[ML2]
  It is not safe to build arbitrary topologies with two (or more)
  mux-locked muxes that are not siblings, when there are address
  collisions between the devices on the child adapters of these
  non-sibling muxes.

  I.e. the select-transfer-deselect transaction targeting e.g. device
  address 0x42 behind mux-one may be interleaved with a similar
  operation targeting device address 0x42 behind mux-two. The
  intent with such a topology would in this hypothetical example
  be that mux-one and mux-two should not be selected simultaneously,
  but mux-locked muxes do not guarantee that in all topologies.

[ML3]
  A mux-locked mux cannot be used by a driver for auto-closing
  gates/muxes, i.e. something that closes automatically after a given
  number (one, in most cases) of I2C transfers. Unrelated I2C transfers
  may creep in and close prematurely.

[ML4]
  If any non-I2C operation in the mux driver changes the I2C mux state,
  the driver has to lock the root adapter during that operation.
  Otherwise garbage may appear on the bus as seen from devices
  behind the mux, when an unrelated I2C transfer is in flight during
  the non-I2C mux-changing operation.

Parent-locked muxes
-------------------

Parent-locked muxes lock the parent adapter during the full select-
transfer-deselect transaction. The implication is that the mux driver
has to ensure that any and all I2C transfers through that parent
adapter during the transaction are unlocked I2C transfers (using e.g.
__i2c_transfer), or a deadlock will follow.

Parent-locked Example
~~~~~~~~~~~~~~~~~~~~~

::

                   .----------.     .--------.
    .--------.     |  parent- |-----| dev D1 |
    |  root  |--+--|  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  .--------.
                |  '----------'  '--| dev D2 |
                |  .--------.       '--------'
                '--| dev D3 |
                   '--------'

When there is an access to D1, this happens:

 1.  Someone issues an I2C transfer to D1.
 2.  M1 locks muxes on its parent (the root adapter in this case).
 3.  M1 locks its parent adapter.
 4.  M1 calls ->select to ready the mux.
 5.  If M1 does any I2C transfers (on this root adapter) as part of
     its select, those transfers must be unlocked I2C transfers so
     that they do not deadlock the root adapter.
 6.  M1 feeds the I2C transfer from step 1 to the root adapter as an
     unlocked I2C transfer, so that it does not deadlock the parent
     adapter.
 7.  M1 calls ->deselect, if it has one.
 8.  Same rules as in step 5, but for ->deselect.
 9.  M1 unlocks its parent adapter.
 10. M1 unlocks muxes on its parent.

This means that accesses to both D2 and D3 are locked out for the full
duration of the entire operation.

Parent-locked Caveats
~~~~~~~~~~~~~~~~~~~~~

When using a parent-locked mux, be aware of the following restrictions:

[PL1]
  If you build a topology with a parent-locked mux being the child
  of another mux, this might break a possible assumption from the
  child mux that the root adapter is unused between its select op
  and the actual transfer (e.g. if the child mux is auto-closing
  and the parent mux issues I2C transfers as part of its select).
  This is especially the case if the parent mux is mux-locked, but
  it may also happen if the parent mux is parent-locked.

[PL2]
  If select/deselect calls out to other subsystems such as gpio,
  pinctrl, regmap or iio, it is essential that any I2C transfers
  caused by these subsystems are unlocked. This can be convoluted to
  accomplish, maybe even impossible if an acceptably clean solution
  is sought.

Complex Examples
================

Parent-locked mux as parent of parent-locked mux
------------------------------------------------

This is a useful topology, but it can be bad::

                   .----------.     .----------.     .--------.
    .--------.     |  parent- |-----|  parent- |-----| dev D1 |
    |  root  |--+--|  locked  |     |  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
                |  '----------'  |  '----------'  '--| dev D2 |
                |  .--------.    |  .--------.       '--------'
                '--| dev D4 |    '--| dev D3 |
                   '--------'       '--------'

When any device is accessed, all other devices are locked out for
the full duration of the operation (both muxes lock their parent,
and specifically when M2 requests its parent to lock, M1 passes
the buck to the root adapter).

This topology is bad if M2 is an auto-closing mux and M1->select
issues any unlocked I2C transfers on the root adapter that may leak
through and be seen by the M2 adapter, thus closing M2 prematurely.

Mux-locked mux as parent of mux-locked mux
------------------------------------------

This is a good topology::

                   .----------.     .----------.     .--------.
    .--------.     |   mux-   |-----|   mux-   |-----| dev D1 |
    |  root  |--+--|  locked  |     |  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
                |  '----------'  |  '----------'  '--| dev D2 |
                |  .--------.    |  .--------.       '--------'
                '--| dev D4 |    '--| dev D3 |
                   '--------'       '--------'

When device D1 is accessed, accesses to D2 are locked out for the
full duration of the operation (muxes on the top child adapter of M1
are locked). But accesses to D3 and D4 are possibly interleaved at
any point.

Accesses to D3 locks out D1 and D2, but accesses to D4 are still possibly
interleaved.

Mux-locked mux as parent of parent-locked mux
---------------------------------------------

This is probably a bad topology::

                   .----------.     .----------.     .--------.
    .--------.     |   mux-   |-----|  parent- |-----| dev D1 |
    |  root  |--+--|  locked  |     |  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
                |  '----------'  |  '----------'  '--| dev D2 |
                |  .--------.    |  .--------.       '--------'
                '--| dev D4 |    '--| dev D3 |
                   '--------'       '--------'

When device D1 is accessed, accesses to D2 and D3 are locked out
for the full duration of the operation (M1 locks child muxes on the
root adapter). But accesses to D4 are possibly interleaved at any
point.

This kind of topology is generally not suitable and should probably
be avoided. The reason is that M2 probably assumes that there will
be no I2C transfers during its calls to ->select and ->deselect, and
if there are, any such transfers might appear on the slave side of M2
as partial I2C transfers, i.e. garbage or worse. This might cause
device lockups and/or other problems.

The topology is especially troublesome if M2 is an auto-closing
mux. In that case, any interleaved accesses to D4 might close M2
prematurely, as might any I2C transfers part of M1->select.

But if M2 is not making the above stated assumption, and if M2 is not
auto-closing, the topology is fine.

Parent-locked mux as parent of mux-locked mux
---------------------------------------------

This is a good topology::

                   .----------.     .----------.     .--------.
    .--------.     |  parent- |-----|   mux-   |-----| dev D1 |
    |  root  |--+--|  locked  |     |  locked  |     '--------'
    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
                |  '----------'  |  '----------'  '--| dev D2 |
                |  .--------.    |  .--------.       '--------'
                '--| dev D4 |    '--| dev D3 |
                   '--------'       '--------'

When D1 is accessed, accesses to D2 are locked out for the full
duration of the operation (muxes on the top child adapter of M1
are locked). Accesses to D3 and D4 are possibly interleaved at
any point, just as is expected for mux-locked muxes.

When D3 or D4 are accessed, everything else is locked out. For D3
accesses, M1 locks the root adapter. For D4 accesses, the root
adapter is locked directly.

Two mux-locked sibling muxes
----------------------------

This is a good topology::

                                    .--------.
                   .----------.  .--| dev D1 |
                   |   mux-   |--'  '--------'
                .--|  locked  |     .--------.
                |  |  mux M1  |-----| dev D2 |
                |  '----------'     '--------'
                |  .----------.     .--------.
    .--------.  |  |   mux-   |-----| dev D3 |
    |  root  |--+--|  locked  |     '--------'
    '--------'  |  |  mux M2  |--.  .--------.
                |  '----------'  '--| dev D4 |
                |  .--------.       '--------'
                '--| dev D5 |
                   '--------'

When D1 is accessed, accesses to D2, D3 and D4 are locked out. But
accesses to D5 may be interleaved at any time.

Two parent-locked sibling muxes
-------------------------------

This is a good topology::

                                    .--------.
                   .----------.  .--| dev D1 |
                   |  parent- |--'  '--------'
                .--|  locked  |     .--------.
                |  |  mux M1  |-----| dev D2 |
                |  '----------'     '--------'
                |  .----------.     .--------.
    .--------.  |  |  parent- |-----| dev D3 |
    |  root  |--+--|  locked  |     '--------'
    '--------'  |  |  mux M2  |--.  .--------.
                |  '----------'  '--| dev D4 |
                |  .--------.       '--------'
                '--| dev D5 |
                   '--------'

When any device is accessed, accesses to all other devices are locked
out.

Mux-locked and parent-locked sibling muxes
------------------------------------------

This is a good topology::

                                    .--------.
                   .----------.  .--| dev D1 |
                   |   mux-   |--'  '--------'
                .--|  locked  |     .--------.
                |  |  mux M1  |-----| dev D2 |
                |  '----------'     '--------'
                |  .----------.     .--------.
    .--------.  |  |  parent- |-----| dev D3 |
    |  root  |--+--|  locked  |     '--------'
    '--------'  |  |  mux M2  |--.  .--------.
                |  '----------'  '--| dev D4 |
                |  .--------.       '--------'
                '--| dev D5 |
                   '--------'

When D1 or D2 are accessed, accesses to D3 and D4 are locked out while
accesses to D5 may interleave. When D3 or D4 are accessed, accesses to
all other devices are locked out.

Mux type of existing device drivers
===================================

Whether a device is mux-locked or parent-locked depends on its
implementation. The following list was correct at the time of writing:

In drivers/i2c/muxes/:

======================    =============================================
i2c-arb-gpio-challenge    Parent-locked
i2c-mux-gpio              Normally parent-locked, mux-locked iff
                          all involved gpio pins are controlled by the
                          same I2C root adapter that they mux.
i2c-mux-gpmux             Normally parent-locked, mux-locked iff
                          specified in device-tree.
i2c-mux-ltc4306           Mux-locked
i2c-mux-mlxcpld           Parent-locked
i2c-mux-pca9541           Parent-locked
i2c-mux-pca954x           Parent-locked
i2c-mux-pinctrl           Normally parent-locked, mux-locked iff
                          all involved pinctrl devices are controlled
                          by the same I2C root adapter that they mux.
i2c-mux-reg               Parent-locked
======================    =============================================

In drivers/iio/:

======================    =============================================
gyro/mpu3050              Mux-locked
imu/inv_mpu6050/          Mux-locked
======================    =============================================

In drivers/media/:

=======================   =============================================
dvb-frontends/lgdt3306a   Mux-locked
dvb-frontends/m88ds3103   Parent-locked
dvb-frontends/rtl2830     Parent-locked
dvb-frontends/rtl2832     Mux-locked
dvb-frontends/si2168      Mux-locked
usb/cx231xx/              Parent-locked
=======================   =============================================

repo_name: angery/linux


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   sodipodi:docname="i2c_bus.svg"
   inkscape:version="0.92.3 (2405546, 2018-03-11)"
   version="1.1"
   id="svg2"
   viewBox="0 0 813.34215 261.01596"
   height="73.664505mm"
   width="229.54323mm">
  <defs
     id="defs4">
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="marker8861"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path8859"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker6165"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM"
       inkscape:collect="always">
      <path
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path6163"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker2713"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path2711"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="DotM"
       style="overflow:visible"
       inkscape:isstock="true"
       inkscape:collect="always">
      <path
         id="path1795"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker6389"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="Arrow2Mend">
      <path
         transform="scale(-0.6)"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         id="path6387"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="TriangleOutM"
       orient="auto"
       refY="0"
       refX="0"
       id="TriangleOutM"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path4107"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#008000;fill-opacity:1;fill-rule:evenodd;stroke:#008000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="scale(0.4)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="TriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="marker5333"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path5335"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="scale(0.8)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="TriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="TriangleOutL"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path5049"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="scale(0.8)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="DotS"
       orient="auto"
       refY="0"
       refX="0"
       id="DotS"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path9326"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#404040;fill-opacity:1;fill-rule:evenodd;stroke:#404040;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.2,0,0,0.2,1.48,0.2)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mstart"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mstart"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path9283"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(0.6)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path9097"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker8935"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path8937"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker8781"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path8783"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Lend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Lend"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path4700"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         id="path4502"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)"
         inkscape:connector-curvature="0" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-4"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-7"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-4-4"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-7-5"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-7"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-5"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-2"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-78"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-57"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-1"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-8"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-75"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="EmptyTriangleOutL"
       orient="auto"
       refY="0"
       refX="0"
       id="EmptyTriangleOutL-78-2"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4502-57-6"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.8,0,0,0.8,-4.8,0)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3-2"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5-6-1"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3-2-2"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5-7"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3-0"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-36"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-31"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-9"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5-7-5"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3-0-4"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-9-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-36-5"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mend-3-5-7-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4369-6-3-0-5"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-1"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-3-7"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-1-8"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-2"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-0"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-4"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-7"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4-4"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4-4-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5-3-2"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4-4-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5-3-8"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4-4-2"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5-3-7"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-6"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-6-5-4-4-6-5"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-1-5-5-3-8-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-27"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-09"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-27-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-09-2"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-27-0"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-09-23"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-7"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-4-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-7-7"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-4-6-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-7-7-5"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-4-6-2"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-7-7-9"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="TriangleOutM"
       orient="auto"
       refY="0"
       refX="0"
       id="TriangleOutM-2"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path4107-7"
         d="M 5.77,0 -2.88,5 V -5 Z"
         style="fill:#008000;fill-opacity:1;fill-rule:evenodd;stroke:#008000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="scale(0.4)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mstart"
       orient="auto"
       refY="0"
       refX="0"
       id="Arrow2Mstart-9"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9283-3"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(0.6)" />
    </marker>
    <marker
       inkscape:stockid="Arrow2Mend"
       orient="auto"
       refY="0"
       refX="0"
       id="marker9095-1-5-4-6-6"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path9097-2-0-7-7-0"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
         transform="scale(-0.6)" />
    </marker>
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="DotM-3"
       style="overflow:visible"
       inkscape:isstock="true">
      <path
         inkscape:connector-curvature="0"
         id="path1795-7"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker2713-9"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         inkscape:connector-curvature="0"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path2711-2" />
    </marker>
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="DotM-2"
       style="overflow:visible"
       inkscape:isstock="true"
       inkscape:collect="always">
      <path
         inkscape:connector-curvature="0"
         id="path1795-8"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker2713-3"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         inkscape:connector-curvature="0"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path2711-6" />
    </marker>
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="DotM-1"
       style="overflow:visible"
       inkscape:isstock="true"
       inkscape:collect="always">
      <path
         inkscape:connector-curvature="0"
         id="path1795-2"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker2713-94"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         inkscape:connector-curvature="0"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path2711-7" />
    </marker>
    <marker
       inkscape:stockid="DotM"
       orient="auto"
       refY="0"
       refX="0"
       id="DotM-8"
       style="overflow:visible"
       inkscape:isstock="true"
       inkscape:collect="always">
      <path
         inkscape:connector-curvature="0"
         id="path1795-4"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker2713-36"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         inkscape:connector-curvature="0"
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path2711-1" />
    </marker>
    <marker
       inkscape:isstock="true"
       style="overflow:visible"
       id="marker6165-5"
       refX="0"
       refY="0"
       orient="auto"
       inkscape:stockid="DotM">
      <path
         transform="matrix(0.4,0,0,0.4,2.96,0.4)"
         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
         d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
         id="path6163-5"
         inkscape:connector-curvature="0" />
    </marker>
  </defs>
  <sodipodi:namedview
     showguides="true"
     inkscape:window-maximized="1"
     inkscape:window-y="0"
     inkscape:window-x="0"
     inkscape:window-height="1015"
     inkscape:window-width="1920"
     showgrid="true"
     inkscape:current-layer="layer1"
     inkscape:document-units="px"
     inkscape:cy="214.66765"
     inkscape:cx="-167.56857"
     inkscape:zoom="0.70710678"
     inkscape:pageshadow="2"
     inkscape:pageopacity="0.0"
     borderopacity="1.0"
     bordercolor="#666666"
     pagecolor="#ffffff"
     id="base"
     inkscape:snap-to-guides="true"
     inkscape:snap-grids="true"
     inkscape:snap-bbox="false"
     inkscape:object-nodes="true"
     fit-margin-top="5"
     fit-margin-left="5"
     fit-margin-right="5"
     fit-margin-bottom="5">
    <inkscape:grid
       type="xygrid"
       id="grid4451"
       originx="-93.377219"
       originy="-347.2523" />
  </sodipodi:namedview>
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
        <dc:creator>
          <cc:Agent>
            <dc:title>Luca Ceresoli</dc:title>
          </cc:Agent>
        </dc:creator>
        <dc:date>2020</dc:date>
        <cc:license
           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
      </cc:Work>
      <cc:License
         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
        <cc:permits
           rdf:resource="http://creativecommons.org/ns#Reproduction" />
        <cc:permits
           rdf:resource="http://creativecommons.org/ns#Distribution" />
        <cc:requires
           rdf:resource="http://creativecommons.org/ns#Notice" />
        <cc:requires
           rdf:resource="http://creativecommons.org/ns#Attribution" />
        <cc:permits
           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
        <cc:requires
           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
      </cc:License>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Livello 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(-93.377215,-444.09395)">
    <rect
       style="opacity:1;fill:#ffb9b9;fill-opacity:1;stroke:#f00000;stroke-width:2.8125;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect4424-3-2-9-7"
       width="112.5"
       height="113.75008"
       x="112.5"
       y="471.11221"
       rx="0"
       ry="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="167.5354"
       y="521.46259"
       id="text4349"><tspan
         sodipodi:role="line"
         x="167.5354"
         y="521.46259"
         style="font-size:25px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle"
         id="tspan1273">I2C</tspan><tspan
         sodipodi:role="line"
         x="167.5354"
         y="552.71259"
         style="font-size:25px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle"
         id="tspan1285">Master</tspan></text>
    <rect
       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#b9ffb9;fill-opacity:1;fill-rule:nonzero;stroke:#006400;stroke-width:2.8125;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
       id="rect4424-3-2-9-7-3-3-5-3"
       width="112.49998"
       height="112.50001"
       x="262.5"
       y="471.11218"
       rx="0"
       ry="0" />
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968767;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 112.50002,639.86223 c 712.50002,0 712.50002,0 712.50002,0"
       id="path4655-9-3-65-5-6"
       inkscape:connector-curvature="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="318.59131"
       y="520.83752"
       id="text4349-26"><tspan
         sodipodi:role="line"
         x="318.59131"
         y="520.83752"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1273-8">I2C</tspan><tspan
         sodipodi:role="line"
         x="318.59131"
         y="552.08752"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1287">Slave</tspan></text>
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968767;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 112.49995,677.36223 c 712.50005,0 712.50005,0 712.50005,0"
       id="path4655-9-3-65-5-6-2"
       inkscape:connector-curvature="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="861.07312"
       y="687.03937"
       id="text4349-7"><tspan
         sodipodi:role="line"
         x="861.07312"
         y="687.03937"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;writing-mode:lr-tb;direction:ltr;text-anchor:middle;stroke-width:1px"
         id="tspan1285-9">SCL</tspan></text>
    <flowRoot
       xml:space="preserve"
       id="flowRoot1627"
       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
         id="flowRegion1629"><rect
           id="rect1631"
           width="220"
           height="120"
           x="140"
           y="-126.29921" /></flowRegion><flowPara
         id="flowPara1633" /></flowRoot>    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="863.31921"
       y="648.96735"
       id="text4349-7-3"><tspan
         sodipodi:role="line"
         x="863.31921"
         y="648.96735"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1285-9-6">SDA</tspan></text>
    <rect
       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#b9ffb9;fill-opacity:1;fill-rule:nonzero;stroke:#006400;stroke-width:2.8125;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
       id="rect4424-3-2-9-7-3-3-5-3-0"
       width="112.49998"
       height="112.50002"
       x="412.5"
       y="471.11215"
       rx="0"
       ry="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="468.59131"
       y="520.83746"
       id="text4349-26-6"><tspan
         sodipodi:role="line"
         x="468.59131"
         y="520.83746"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1273-8-2">I2C</tspan><tspan
         sodipodi:role="line"
         x="468.59131"
         y="552.08746"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1287-6">Slave</tspan></text>
    <rect
       style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#b9ffb9;fill-opacity:1;fill-rule:nonzero;stroke:#006400;stroke-width:2.8125;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
       id="rect4424-3-2-9-7-3-3-5-3-1"
       width="112.49998"
       height="112.50002"
       x="562.5"
       y="471.11215"
       rx="0"
       ry="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="618.59131"
       y="520.83746"
       id="text4349-26-8"><tspan
         sodipodi:role="line"
         x="618.59131"
         y="520.83746"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1273-8-7">I2C</tspan><tspan
         sodipodi:role="line"
         x="618.59131"
         y="552.08746"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1287-9">Slave</tspan></text>
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#DotM)"
       d="m 150,583.61221 v 93.75"
       id="path4655-9-3-65-5-6-20"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker2713)"
       d="m 187.5,583.61221 v 56.25"
       id="path4655-9-3-65-5-6-20-2"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#DotM-2)"
       d="m 300,583.61221 v 93.75"
       id="path4655-9-3-65-5-6-20-9"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker2713-9)"
       d="m 337.5,583.61221 v 56.25"
       id="path4655-9-3-65-5-6-20-2-7"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#DotM-1)"
       d="m 450,583.61221 v 93.75"
       id="path4655-9-3-65-5-6-20-93"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker2713-3)"
       d="m 487.5,583.61221 v 56.25"
       id="path4655-9-3-65-5-6-20-2-1"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#DotM-8)"
       d="m 600,583.61221 v 93.75"
       id="path4655-9-3-65-5-6-20-5"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker2713-94)"
       d="m 637.5,583.61221 v 56.25"
       id="path4655-9-3-65-5-6-20-2-0"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6165);marker-end:url(#marker6165)"
       d="m 750,471.11221 v 28.125 l 9.375,9.375 -18.74999,18.75 18.74999,18.75 -18.74999,18.75 18.74999,18.75 -9.375,9.375 v 28.125 0 0 56.25"
       id="path6135"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cccccccccccc" />
    <path
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968743;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker8861);marker-end:url(#marker6165-5)"
       d="m 787.49999,471.11221 v 28.125 l 9.375,9.375 -18.74999,18.75 18.74999,18.75 -18.74999,18.75 18.74999,18.75 -9.375,9.375 v 28.125 0 0 18.75001"
       id="path6135-4"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cccccccccccc" />
    <path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.99968719;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 712.5,471.11221 c 112.49999,0 112.49999,0 112.49999,0"
       id="path4655-9-3-65-5-6-7"
       inkscape:connector-curvature="0" />
    <text
       xml:space="preserve"
       style="font-style:normal;font-weight:normal;font-size:12px;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       x="859.94275"
       y="480.03558"
       id="text4349-7-3-6"><tspan
         sodipodi:role="line"
         x="859.94275"
         y="480.03558"
         style="font-size:25.00000191px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;stroke-width:1px"
         id="tspan1285-9-6-5">V<tspan
   style="font-size:64.99999762%;baseline-shift:sub"
   id="tspan9307">DD</tspan></tspan></text>
  </g>
</svg>


code:
.. SPDX-License-Identifier: GPL-2.0

===================
I2C/SMBus Subsystem
===================

Introduction
============

.. toctree::
   :maxdepth: 1

   summary
   i2c-protocol
   smbus-protocol
   instantiating-devices
   busses/index
   i2c-topology
   muxes/i2c-mux-gpio
   i2c-sysfs

Writing device drivers
======================

.. toctree::
   :maxdepth: 1

   writing-clients
   dev-interface
   dma-considerations
   fault-codes
   functionality

Debugging
=========

.. toctree::
   :maxdepth: 1

   gpio-fault-injection
   i2c-stub

Slave I2C
=========

.. toctree::
   :maxdepth: 1

   slave-interface
   slave-eeprom-backend
   slave-testunit-backend

Advanced topics
===============

.. toctree::
   :maxdepth: 1

   ten-bit-addresses

Legacy documentation
====================

.. toctree::
   :maxdepth: 1

   old-module-parameters

.. only::  subproject and html

   Indices
   =======

   * :ref:`genindex`


code:
==============================
How to instantiate I2C devices
==============================

Unlike PCI or USB devices, I2C devices are not enumerated at the hardware
level. Instead, the software must know which devices are connected on each
I2C bus segment, and what address these devices are using. For this
reason, the kernel code must instantiate I2C devices explicitly. There are
several ways to achieve this, depending on the context and requirements.

Method 1: Declare the I2C devices statically
--------------------------------------------

This method is appropriate when the I2C bus is a system bus as is the case
for many embedded systems. On such systems, each I2C bus has a number which
is known in advance. It is thus possible to pre-declare the I2C devices
which live on this bus.

This information is provided to the kernel in a different way on different
architectures: device tree, ACPI or board files.

When the I2C bus in question is registered, the I2C devices will be
instantiated automatically by i2c-core. The devices will be automatically
unbound and destroyed when the I2C bus they sit on goes away (if ever).

Declare the I2C devices via devicetree
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

On platforms using devicetree, the declaration of I2C devices is done in
subnodes of the master controller.

Example:

.. code-block:: dts

	i2c1: i2c@400a0000 {
		/* ... master properties skipped ... */
		clock-frequency = <100000>;

		flash@50 {
			compatible = "atmel,24c256";
			reg = <0x50>;
		};

		pca9532: gpio@60 {
			compatible = "nxp,pca9532";
			gpio-controller;
			#gpio-cells = <2>;
			reg = <0x60>;
		};
	};

Here, two devices are attached to the bus using a speed of 100kHz. For
additional properties which might be needed to set up the device, please refer
to its devicetree documentation in Documentation/devicetree/bindings/.

Declare the I2C devices via ACPI
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

ACPI can also describe I2C devices. There is special documentation for this
which is currently located at Documentation/firmware-guide/acpi/enumeration.rst.

Declare the I2C devices in board files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In many embedded architectures, devicetree has replaced the old hardware
description based on board files, but the latter are still used in old
code. Instantiating I2C devices via board files is done with an array of
struct i2c_board_info which is registered by calling
i2c_register_board_info().

Example (from omap2 h4):

.. code-block:: c

  static struct i2c_board_info h4_i2c_board_info[] __initdata = {
	{
		I2C_BOARD_INFO("isp1301_omap", 0x2d),
		.irq		= OMAP_GPIO_IRQ(125),
	},
	{	/* EEPROM on mainboard */
		I2C_BOARD_INFO("24c01", 0x52),
		.platform_data	= &m24c01,
	},
	{	/* EEPROM on cpu card */
		I2C_BOARD_INFO("24c01", 0x57),
		.platform_data	= &m24c01,
	},
  };

  static void __init omap_h4_init(void)
  {
	(...)
	i2c_register_board_info(1, h4_i2c_board_info,
			ARRAY_SIZE(h4_i2c_board_info));
	(...)
  }

The above code declares 3 devices on I2C bus 1, including their respective
addresses and custom data needed by their drivers.

Method 2: Instantiate the devices explicitly
--------------------------------------------

This method is appropriate when a larger device uses an I2C bus for
internal communication. A typical case is TV adapters. These can have a
tuner, a video decoder, an audio decoder, etc. usually connected to the
main chip by the means of an I2C bus. You won't know the number of the I2C
bus in advance, so the method 1 described above can't be used. Instead,
you can instantiate your I2C devices explicitly. This is done by filling
a struct i2c_board_info and calling i2c_new_client_device().

Example (from the sfe4001 network driver):

.. code-block:: c

  static struct i2c_board_info sfe4001_hwmon_info = {
	I2C_BOARD_INFO("max6647", 0x4e),
  };

  int sfe4001_init(struct efx_nic *efx)
  {
	(...)
	efx->board_info.hwmon_client =
		i2c_new_client_device(&efx->i2c_adap, &sfe4001_hwmon_info);

	(...)
  }

The above code instantiates 1 I2C device on the I2C bus which is on the
network adapter in question.

A variant of this is when you don't know for sure if an I2C device is
present or not (for example for an optional feature which is not present
on cheap variants of a board but you have no way to tell them apart), or
it may have different addresses from one board to the next (manufacturer
changing its design without notice). In this case, you can call
i2c_new_scanned_device() instead of i2c_new_client_device().

Example (from the nxp OHCI driver):

.. code-block:: c

  static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };

  static int usb_hcd_nxp_probe(struct platform_device *pdev)
  {
	(...)
	struct i2c_adapter *i2c_adap;
	struct i2c_board_info i2c_info;

	(...)
	i2c_adap = i2c_get_adapter(2);
	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
	strscpy(i2c_info.type, "isp1301_nxp", sizeof(i2c_info.type));
	isp1301_i2c_client = i2c_new_scanned_device(i2c_adap, &i2c_info,
						    normal_i2c, NULL);
	i2c_put_adapter(i2c_adap);
	(...)
  }

The above code instantiates up to 1 I2C device on the I2C bus which is on
the OHCI adapter in question. It first tries at address 0x2c, if nothing
is found there it tries address 0x2d, and if still nothing is found, it
simply gives up.

The driver which instantiated the I2C device is responsible for destroying
it on cleanup. This is done by calling i2c_unregister_device() on the
pointer that was earlier returned by i2c_new_client_device() or
i2c_new_scanned_device().

Method 3: Probe an I2C bus for certain devices
----------------------------------------------

Sometimes you do not have enough information about an I2C device, not even
to call i2c_new_scanned_device(). The typical case is hardware monitoring
chips on PC mainboards. There are several dozen models, which can live
at 25 different addresses. Given the huge number of mainboards out there,
it is next to impossible to build an exhaustive list of the hardware
monitoring chips being used. Fortunately, most of these chips have
manufacturer and device ID registers, so they can be identified by
probing.

In that case, I2C devices are neither declared nor instantiated
explicitly. Instead, i2c-core will probe for such devices as soon as their
drivers are loaded, and if any is found, an I2C device will be
instantiated automatically. In order to prevent any misbehavior of this
mechanism, the following restrictions apply:

* The I2C device driver must implement the detect() method, which
  identifies a supported device by reading from arbitrary registers.
* Only buses which are likely to have a supported device and agree to be
  probed, will be probed. For example this avoids probing for hardware
  monitoring chips on a TV adapter.

Example:
See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c

I2C devices instantiated as a result of such a successful probe will be
destroyed automatically when the driver which detected them is removed,
or when the underlying I2C bus is itself destroyed, whichever happens
first.

Those of you familiar with the I2C subsystem of 2.4 kernels and early 2.6
kernels will find out that this method 3 is essentially similar to what
was done there. Two significant differences are:

* Probing is only one way to instantiate I2C devices now, while it was the
  only way back then. Where possible, methods 1 and 2 should be preferred.
  Method 3 should only be used when there is no other way, as it can have
  undesirable side effects.
* I2C buses must now explicitly say which I2C driver classes can probe
  them (by the means of the class bitfield), while all I2C buses were
  probed by default back then. The default is an empty class which means
  that no probing happens. The purpose of the class bitfield is to limit
  the aforementioned undesirable side effects.

Once again, method 3 should be avoided wherever possible. Explicit device
instantiation (methods 1 and 2) is much preferred for it is safer and
faster.

Method 4: Instantiate from user-space
-------------------------------------

In general, the kernel should know which I2C devices are connected and
what addresses they live at. However, in certain cases, it does not, so a
sysfs interface was added to let the user provide the information. This
interface is made of 2 attribute files which are created in every I2C bus
directory: ``new_device`` and ``delete_device``. Both files are write
only and you must write the right parameters to them in order to properly
instantiate, respectively delete, an I2C device.

File ``new_device`` takes 2 parameters: the name of the I2C device (a
string) and the address of the I2C device (a number, typically expressed
in hexadecimal starting with 0x, but can also be expressed in decimal.)

File ``delete_device`` takes a single parameter: the address of the I2C
device. As no two devices can live at the same address on a given I2C
segment, the address is sufficient to uniquely identify the device to be
deleted.

Example::

  # echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device

While this interface should only be used when in-kernel device declaration
can't be done, there is a variety of cases where it can be helpful:

* The I2C driver usually detects devices (method 3 above) but the bus
  segment your device lives on doesn't have the proper class bit set and
  thus detection doesn't trigger.
* The I2C driver usually detects devices, but your device lives at an
  unexpected address.
* The I2C driver usually detects devices, but your device is not detected,
  either because the detection routine is too strict, or because your
  device is not officially supported yet but you know it is compatible.
* You are developing a driver on a test board, where you soldered the I2C
  device yourself.

This interface is a replacement for the force_* module parameters some I2C
drivers implement. Being implemented in i2c-core rather than in each
device driver individually, it is much more efficient, and also has the
advantage that you do not have to reload the driver to change a setting.
You can also instantiate the device before the driver is loaded or even
available, and you don't need to know what driver the device needs.