diff options
Diffstat (limited to 'Documentation/i2c')
-rw-r--r-- | Documentation/i2c/busses/i2c-i801.rst | 2 | ||||
-rw-r--r-- | Documentation/i2c/busses/i2c-piix4.rst | 63 | ||||
-rw-r--r-- | Documentation/i2c/i2c_bus.svg | 15 | ||||
-rw-r--r-- | Documentation/i2c/slave-testunit-backend.rst | 237 | ||||
-rw-r--r-- | Documentation/i2c/summary.rst | 79 | ||||
-rw-r--r-- | Documentation/i2c/writing-clients.rst | 3 |
6 files changed, 316 insertions, 83 deletions
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst index 10eced6c2e46..47e8ac5b7099 100644 --- a/Documentation/i2c/busses/i2c-i801.rst +++ b/Documentation/i2c/busses/i2c-i801.rst @@ -48,6 +48,8 @@ Supported adapters: * Intel Raptor Lake (PCH) * Intel Meteor Lake (SOC and PCH) * Intel Birch Stream (SOC) + * Intel Arrow Lake (SOC) + * Intel Panther Lake (SOC) Datasheets: Publicly available at the Intel website diff --git a/Documentation/i2c/busses/i2c-piix4.rst b/Documentation/i2c/busses/i2c-piix4.rst index 07fe6f6f4b18..94e20b18c59a 100644 --- a/Documentation/i2c/busses/i2c-piix4.rst +++ b/Documentation/i2c/busses/i2c-piix4.rst @@ -109,3 +109,66 @@ which can easily get corrupted due to a state machine bug. These are mostly Thinkpad laptops, but desktop systems may also be affected. We have no list of all affected systems, so the only safe solution was to prevent access to the SMBus on all IBM systems (detected using DMI data.) + + +Description in the ACPI code +---------------------------- + +Device driver for the PIIX4 chip creates a separate I2C bus for each of its +ports:: + + $ i2cdetect -l + ... + i2c-7 unknown SMBus PIIX4 adapter port 0 at 0b00 N/A + i2c-8 unknown SMBus PIIX4 adapter port 2 at 0b00 N/A + i2c-9 unknown SMBus PIIX4 adapter port 1 at 0b20 N/A + ... + +Therefore if you want to access one of these busses in the ACPI code, port +subdevices are needed to be declared inside the PIIX device:: + + Scope (\_SB_.PCI0.SMBS) + { + Name (_ADR, 0x00140000) + + Device (SMB0) { + Name (_ADR, 0) + } + Device (SMB1) { + Name (_ADR, 1) + } + Device (SMB2) { + Name (_ADR, 2) + } + } + +If this is not the case for your UEFI firmware and you don't have access to the +source code, you can use ACPI SSDT Overlays to provide the missing parts. Just +keep in mind that in this case you would need to load your extra SSDT table +before the piix4 driver starts, i.e. you should provide SSDT via initrd or EFI +variable methods and not via configfs. + +As an example of usage here is the ACPI snippet code that would assign jc42 +driver to the 0x1C device on the I2C bus created by the PIIX port 0:: + + Device (JC42) { + Name (_HID, "PRP0001") + Name (_DDN, "JC42 Temperature sensor") + Name (_CRS, ResourceTemplate () { + I2cSerialBusV2 ( + 0x001c, + ControllerInitiated, + 100000, + AddressingMode7Bit, + "\\_SB.PCI0.SMBS.SMB0", + 0 + ) + }) + + Name (_DSD, Package () { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () { + Package () { "compatible", Package() { "jedec,jc-42.4-temp" } }, + } + }) + } diff --git a/Documentation/i2c/i2c_bus.svg b/Documentation/i2c/i2c_bus.svg index 3170de976373..45801de4af7d 100644 --- a/Documentation/i2c/i2c_bus.svg +++ b/Documentation/i2c/i2c_bus.svg @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> +<!-- Updated to inclusive terminology by Wolfram Sang --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" @@ -1120,7 +1121,7 @@ <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" + width="134.5" height="113.75008" x="112.5" y="471.11221" @@ -1133,15 +1134,15 @@ y="521.46259" id="text4349"><tspan sodipodi:role="line" - x="167.5354" + x="178.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" + x="178.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> + id="tspan1285">Controller</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" @@ -1171,7 +1172,7 @@ 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> + id="tspan1287">Target</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" @@ -1233,7 +1234,7 @@ 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> + id="tspan1287-6">Target</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" @@ -1258,7 +1259,7 @@ 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> + id="tspan1287-9">Target</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" diff --git a/Documentation/i2c/slave-testunit-backend.rst b/Documentation/i2c/slave-testunit-backend.rst index ecfc2abec32d..d752f433be07 100644 --- a/Documentation/i2c/slave-testunit-backend.rst +++ b/Documentation/i2c/slave-testunit-backend.rst @@ -16,24 +16,41 @@ Note that this is a device for testing and debugging. It should not be enabled in a production build. And while there is some versioning and we try hard to keep backward compatibility, there is no stable ABI guaranteed! -Instantiating the device is regular. Example for bus 0, address 0x30: +Instantiating the device is regular. Example for bus 0, address 0x30:: -# echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device + # echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device -After that, you will have a write-only device listening. Reads will just return -an 8-bit version number of the testunit. When writing, the device consists of 4 -8-bit registers and, except for some "partial" commands, all registers must be -written to start a testcase, i.e. you usually write 4 bytes to the device. The -registers are: +Or using firmware nodes. Here is a devicetree example (note this is only a +debug device, so there are no official DT bindings):: -0x00 CMD - which test to trigger -0x01 DATAL - configuration byte 1 for the test -0x02 DATAH - configuration byte 2 for the test -0x03 DELAY - delay in n * 10ms until test is started + &i2c0 { + ... -Using 'i2cset' from the i2c-tools package, the generic command looks like: + testunit@30 { + compatible = "slave-testunit"; + reg = <(0x30 | I2C_OWN_SLAVE_ADDRESS)>; + }; + }; -# i2cset -y <bus_num> <testunit_address> <CMD> <DATAL> <DATAH> <DELAY> i +After that, you will have the device listening. Reading will return a single +byte. Its value is 0 if the testunit is idle, otherwise the command number of +the currently running command. + +When writing, the device consists of 4 8-bit registers and, except for some +"partial" commands, all registers must be written to start a testcase, i.e. you +usually write 4 bytes to the device. The registers are: + +.. csv-table:: + :header: "Offset", "Name", "Description" + + 0x00, CMD, which test to trigger + 0x01, DATAL, configuration byte 1 for the test + 0x02, DATAH, configuration byte 2 for the test + 0x03, DELAY, delay in n * 10ms until test is started + +Using 'i2cset' from the i2c-tools package, the generic command looks like:: + + # i2cset -y <bus_num> <testunit_address> <CMD> <DATAL> <DATAH> <DELAY> i DELAY is a generic parameter which will delay the execution of the test in CMD. While a command is running (including the delay), new commands will not be @@ -45,44 +62,174 @@ result in the transfer not being acknowledged. Commands -------- -0x00 NOOP (reserved for future use) +0x00 NOOP +~~~~~~~~~ + +Reserved for future use. + +0x01 READ_BYTES +~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x01 + - address to read data from (lower 7 bits, highest bit currently unused) + - number of bytes to read + - n * 10ms + +Also needs master mode. This is useful to test if your bus master driver is +handling multi-master correctly. You can trigger the testunit to read bytes +from another device on the bus. If the bus master under test also wants to +access the bus at the same time, the bus will be busy. Example to read 128 +bytes from device 0x50 after 50ms of delay:: + + # i2cset -y 0 0x30 1 0x50 0x80 5 i + +0x02 SMBUS_HOST_NOTIFY +~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x02 + - low byte of the status word to send + - high byte of the status word to send + - n * 10ms + +Also needs master mode. This test will send an SMBUS_HOST_NOTIFY message to the +host. Note that the status word is currently ignored in the Linux Kernel. +Example to send a notification with status word 0x6442 after 10ms:: + + # i2cset -y 0 0x30 2 0x42 0x64 1 i + +If the host controller supports HostNotify, this message with debug level +should appear (Linux 6.11 and later):: + + Detected HostNotify from address 0x30 + +0x03 SMBUS_BLOCK_PROC_CALL +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x03 + - 0x01 (i.e. one further byte will be written) + - number of bytes to be sent back + - leave out, partial command! + +Partial command. This test will respond to a block process call as defined by +the SMBus specification. The one data byte written specifies how many bytes +will be sent back in the following read transfer. Note that in this read +transfer, the testunit will prefix the length of the bytes to follow. So, if +your host bus driver emulates SMBus calls like the majority does, it needs to +support the I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. +The returned data consists of the length first, and then of an array of bytes +from length-1 to 0. Here is an example which emulates +i2c_smbus_block_process_call() using i2ctransfer (you need i2c-tools v4.2 or +later):: + + # i2ctransfer -y 0 w3@0x30 3 1 0x10 r? + 0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00 + +0x04 GET_VERSION_WITH_REP_START +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x04 + - currently unused + - currently unused + - leave out, partial command! + +Partial command. After sending this command, the testunit will reply to a read +message with a NUL terminated version string based on UTS_RELEASE. The first +character is always a 'v' and the length of the version string is at maximum +128 bytes. However, it will only respond if the read message is connected to +the write message via repeated start. If your controller driver handles +repeated start correctly, this will work:: + + # i2ctransfer -y 0 w3@0x30 4 0 0 r128 + 0x76 0x36 0x2e 0x31 0x31 0x2e 0x30 0x2d 0x72 0x63 0x31 0x2d 0x30 0x30 0x30 0x30 ... + +If you have i2c-tools 4.4 or later, you can print out the data right away:: + + # i2ctransfer -y -b 0 w3@0x30 4 0 0 r128 + v6.11.0-rc1-00009-gd37a1b4d3fd0 + +STOP/START combinations between the two messages will *not* work because they +are not equivalent to a REPEATED START. As an example, this returns just the +default response:: + + # i2cset -y 0 0x30 4 0 0 i; i2cget -y 0 0x30 + 0x00 + +0x05 SMBUS_ALERT_REQUEST +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x05 + - response value (7 MSBs interpreted as I2C address) + - currently unused + - n * 10ms + +This test raises an interrupt via the SMBAlert pin which the host controller +must handle. The pin must be connected to the testunit as a GPIO. GPIO access +is not allowed to sleep. Currently, this can only be described using firmware +nodes. So, for devicetree, you would add something like this to the testunit +node:: -0x01 READ_BYTES (also needs master mode) - DATAL - address to read data from (lower 7 bits, highest bit currently unused) - DATAH - number of bytes to read + gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; -This is useful to test if your bus master driver is handling multi-master -correctly. You can trigger the testunit to read bytes from another device on -the bus. If the bus master under test also wants to access the bus at the same -time, the bus will be busy. Example to read 128 bytes from device 0x50 after -50ms of delay: +The following command will trigger the alert with a response of 0xc9 after 1 +second of delay:: -# i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i + # i2cset -y 0 0x30 5 0xc9 0x00 100 i -0x02 SMBUS_HOST_NOTIFY (also needs master mode) - DATAL - low byte of the status word to send - DATAH - high byte of the status word to send +If the host controller supports SMBusAlert, this message with debug level +should appear:: -This test will send an SMBUS_HOST_NOTIFY message to the host. Note that the -status word is currently ignored in the Linux Kernel. Example to send a -notification after 10ms: + smbus_alert 0-000c: SMBALERT# from dev 0x64, flag 1 -# i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i +This message may appear more than once because the testunit is software not +hardware and, thus, may not be able to react to the response of the host fast +enough. The interrupt count should increase only by one, though:: -0x03 SMBUS_BLOCK_PROC_CALL (partial command) - DATAL - must be '1', i.e. one further byte will be written - DATAH - number of bytes to be sent back - DELAY - not applicable, partial command! + # cat /proc/interrupts | grep smbus_alert + 93: 1 gpio-rcar 26 Edge smbus_alert -This test will respond to a block process call as defined by the SMBus -specification. The one data byte written specifies how many bytes will be sent -back in the following read transfer. Note that in this read transfer, the -testunit will prefix the length of the bytes to follow. So, if your host bus -driver emulates SMBus calls like the majority does, it needs to support the -I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. The returned -data consists of the length first, and then of an array of bytes from length-1 -to 0. Here is an example which emulates i2c_smbus_block_process_call() using -i2ctransfer (you need i2c-tools v4.2 or later): +If the host does not respond to the alert within 1 second, the test will be +aborted and the testunit will report an error. -# i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r? -0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00 +For this test, the testunit will shortly drop its assigned address and listen +on the SMBus Alert Response Address (0x0c). It will reassign its original +address afterwards. diff --git a/Documentation/i2c/summary.rst b/Documentation/i2c/summary.rst index 786c618ba3be..579a1c7df200 100644 --- a/Documentation/i2c/summary.rst +++ b/Documentation/i2c/summary.rst @@ -3,29 +3,27 @@ Introduction to I2C and SMBus ============================= I²C (pronounce: I squared C and written I2C in the kernel documentation) is -a protocol developed by Philips. It is a slow two-wire protocol (variable -speed, up to 400 kHz), with a high speed extension (3.4 MHz). It provides +a protocol developed by Philips. It is a two-wire protocol with variable +speed (typically up to 400 kHz, high speed modes up to 5 MHz). It provides an inexpensive bus for connecting many types of devices with infrequent or -low bandwidth communications needs. I2C is widely used with embedded -systems. Some systems use variants that don't meet branding requirements, +low bandwidth communications needs. I2C is widely used with embedded +systems. Some systems use variants that don't meet branding requirements, and so are not advertised as being I2C but come under different names, e.g. TWI (Two Wire Interface), IIC. -The latest official I2C specification is the `"I2C-bus specification and user -manual" (UM10204) <https://www.nxp.com/webapp/Download?colCode=UM10204>`_ -published by NXP Semiconductors. However, you need to log-in to the site to -access the PDF. An older version of the specification (revision 6) is archived -`here <https://web.archive.org/web/20210813122132/https://www.nxp.com/docs/en/user-guide/UM10204.pdf>`_. +The latest official I2C specification is the `"I²C-bus specification and user +manual" (UM10204) <https://www.nxp.com/docs/en/user-guide/UM10204.pdf>`_ +published by NXP Semiconductors, version 7 as of this writing. SMBus (System Management Bus) is based on the I2C protocol, and is mostly -a subset of I2C protocols and signaling. Many I2C devices will work on an +a subset of I2C protocols and signaling. Many I2C devices will work on an SMBus, but some SMBus protocols add semantics beyond what is required to -achieve I2C branding. Modern PC mainboards rely on SMBus. The most common +achieve I2C branding. Modern PC mainboards rely on SMBus. The most common devices connected through SMBus are RAM modules configured using I2C EEPROMs, and hardware monitoring chips. Because the SMBus is mostly a subset of the generalized I2C bus, we can -use its protocols on many I2C systems. However, there are systems that don't +use its protocols on many I2C systems. However, there are systems that don't meet both SMBus and I2C electrical constraints; and others which can't implement all the common SMBus protocol semantics or messages. @@ -33,29 +31,52 @@ implement all the common SMBus protocol semantics or messages. Terminology =========== -Using the terminology from the official documentation, the I2C bus connects -one or more *master* chips and one or more *slave* chips. +The I2C bus connects one or more controller chips and one or more target chips. .. kernel-figure:: i2c_bus.svg - :alt: Simple I2C bus with one master and 3 slaves + :alt: Simple I2C bus with one controller and 3 targets Simple I2C bus -A **master** chip is a node that starts communications with slaves. In the -Linux kernel implementation it is called an **adapter** or bus. Adapter -drivers are in the ``drivers/i2c/busses/`` subdirectory. +A **controller** chip is a node that starts communications with targets. In the +Linux kernel implementation it is also called an "adapter" or "bus". Controller +drivers are usually in the ``drivers/i2c/busses/`` subdirectory. -An **algorithm** contains general code that can be used to implement a -whole class of I2C adapters. Each specific adapter driver either depends on -an algorithm driver in the ``drivers/i2c/algos/`` subdirectory, or includes -its own implementation. +An **algorithm** contains general code that can be used to implement a whole +class of I2C controllers. Each specific controller driver either depends on an +algorithm driver in the ``drivers/i2c/algos/`` subdirectory, or includes its +own implementation. -A **slave** chip is a node that responds to communications when addressed -by the master. In Linux it is called a **client**. Client drivers are kept -in a directory specific to the feature they provide, for example -``drivers/media/gpio/`` for GPIO expanders and ``drivers/media/i2c/`` for +A **target** chip is a node that responds to communications when addressed by a +controller. In the Linux kernel implementation it is also called a "client". +While targets are usually separate external chips, Linux can also act as a +target (needs hardware support) and respond to another controller on the bus. +This is then called a **local target**. In contrast, an external chip is called +a **remote target**. + +Target drivers are kept in a directory specific to the feature they provide, +for example ``drivers/gpio/`` for GPIO expanders and ``drivers/media/i2c/`` for video-related chips. -For the example configuration in figure, you will need a driver for your -I2C adapter, and drivers for your I2C devices (usually one driver for each -device). +For the example configuration in the figure above, you will need one driver for +the I2C controller, and drivers for your I2C targets. Usually one driver for +each target. + +Synonyms +-------- + +As mentioned above, the Linux I2C implementation historically uses the terms +"adapter" for controller and "client" for target. A number of data structures +have these synonyms in their name. So, when discussing implementation details, +you should be aware of these terms as well. The official wording is preferred, +though. + +Outdated terminology +-------------------- + +In earlier I2C specifications, controller was named "master" and target was +named "slave". These terms have been obsoleted with v7 of the specification and +their use is also discouraged by the Linux Kernel Code of Conduct. You may +still find them in references to documentation which has not been updated. The +general attitude, however, is to use the inclusive terms: controller and +target. Work to replace the old terminology in the Linux Kernel is on-going. diff --git a/Documentation/i2c/writing-clients.rst b/Documentation/i2c/writing-clients.rst index 0b8439ea954c..121e618e72ec 100644 --- a/Documentation/i2c/writing-clients.rst +++ b/Documentation/i2c/writing-clients.rst @@ -31,12 +31,11 @@ driver model device node, and its I2C address. :: - static struct i2c_device_id foo_idtable[] = { + static const struct i2c_device_id foo_idtable[] = { { "foo", my_id_for_foo }, { "bar", my_id_for_bar }, { } }; - MODULE_DEVICE_TABLE(i2c, foo_idtable); static struct i2c_driver foo_driver = { |