xref: /OK3568_Linux_fs/kernel/Documentation/i2c/gpio-fault-injection.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun=========================
2*4882a593SmuzhiyunLinux I2C fault injection
3*4882a593Smuzhiyun=========================
4*4882a593Smuzhiyun
5*4882a593SmuzhiyunThe GPIO based I2C bus master driver can be configured to provide fault
6*4882a593Smuzhiyuninjection capabilities. It is then meant to be connected to another I2C bus
7*4882a593Smuzhiyunwhich is driven by the I2C bus master driver under test. The GPIO fault
8*4882a593Smuzhiyuninjection driver can create special states on the bus which the other I2C bus
9*4882a593Smuzhiyunmaster driver should handle gracefully.
10*4882a593Smuzhiyun
11*4882a593SmuzhiyunOnce the Kconfig option I2C_GPIO_FAULT_INJECTOR is enabled, there will be an
12*4882a593Smuzhiyun'i2c-fault-injector' subdirectory in the Kernel debugfs filesystem, usually
13*4882a593Smuzhiyunmounted at /sys/kernel/debug. There will be a separate subdirectory per GPIO
14*4882a593Smuzhiyundriven I2C bus. Each subdirectory will contain files to trigger the fault
15*4882a593Smuzhiyuninjection. They will be described now along with their intended use-cases.
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunWire states
18*4882a593Smuzhiyun===========
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun"scl"
21*4882a593Smuzhiyun-----
22*4882a593Smuzhiyun
23*4882a593SmuzhiyunBy reading this file, you get the current state of SCL. By writing, you can
24*4882a593Smuzhiyunchange its state to either force it low or to release it again. So, by using
25*4882a593Smuzhiyun"echo 0 > scl" you force SCL low and thus, no communication will be possible
26*4882a593Smuzhiyunbecause the bus master under test will not be able to clock. It should detect
27*4882a593Smuzhiyunthe condition of SCL being unresponsive and report an error to the upper
28*4882a593Smuzhiyunlayers.
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun"sda"
31*4882a593Smuzhiyun-----
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunBy reading this file, you get the current state of SDA. By writing, you can
34*4882a593Smuzhiyunchange its state to either force it low or to release it again. So, by using
35*4882a593Smuzhiyun"echo 0 > sda" you force SDA low and thus, data cannot be transmitted. The bus
36*4882a593Smuzhiyunmaster under test should detect this condition and trigger a bus recovery (see
37*4882a593SmuzhiyunI2C specification version 4, section 3.1.16) using the helpers of the Linux I2C
38*4882a593Smuzhiyuncore (see 'struct bus_recovery_info'). However, the bus recovery will not
39*4882a593Smuzhiyunsucceed because SDA is still pinned low until you manually release it again
40*4882a593Smuzhiyunwith "echo 1 > sda". A test with an automatic release can be done with the
41*4882a593Smuzhiyun"incomplete transfers" class of fault injectors.
42*4882a593Smuzhiyun
43*4882a593SmuzhiyunIncomplete transfers
44*4882a593Smuzhiyun====================
45*4882a593Smuzhiyun
46*4882a593SmuzhiyunThe following fault injectors create situations where SDA will be held low by a
47*4882a593Smuzhiyundevice. Bus recovery should be able to fix these situations. But please note:
48*4882a593Smuzhiyunthere are I2C client devices which detect a stuck SDA on their side and release
49*4882a593Smuzhiyunit on their own after a few milliseconds. Also, there might be an external
50*4882a593Smuzhiyundevice deglitching and monitoring the I2C bus. It could also detect a stuck SDA
51*4882a593Smuzhiyunand will init a bus recovery on its own. If you want to implement bus recovery
52*4882a593Smuzhiyunin a bus master driver, make sure you checked your hardware setup for such
53*4882a593Smuzhiyundevices before. And always verify with a scope or logic analyzer!
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun"incomplete_address_phase"
56*4882a593Smuzhiyun--------------------------
57*4882a593Smuzhiyun
58*4882a593SmuzhiyunThis file is write only and you need to write the address of an existing I2C
59*4882a593Smuzhiyunclient device to it. Then, a read transfer to this device will be started, but
60*4882a593Smuzhiyunit will stop at the ACK phase after the address of the client has been
61*4882a593Smuzhiyuntransmitted. Because the device will ACK its presence, this results in SDA
62*4882a593Smuzhiyunbeing pulled low by the device while SCL is high. So, similar to the "sda" file
63*4882a593Smuzhiyunabove, the bus master under test should detect this condition and try a bus
64*4882a593Smuzhiyunrecovery. This time, however, it should succeed and the device should release
65*4882a593SmuzhiyunSDA after toggling SCL.
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun"incomplete_write_byte"
68*4882a593Smuzhiyun-----------------------
69*4882a593Smuzhiyun
70*4882a593SmuzhiyunSimilar to above, this file is write only and you need to write the address of
71*4882a593Smuzhiyunan existing I2C client device to it.
72*4882a593Smuzhiyun
73*4882a593SmuzhiyunThe injector will again stop at one ACK phase, so the device will keep SDA low
74*4882a593Smuzhiyunbecause it acknowledges data. However, there are two differences compared to
75*4882a593Smuzhiyun'incomplete_address_phase':
76*4882a593Smuzhiyun
77*4882a593Smuzhiyuna) the message sent out will be a write message
78*4882a593Smuzhiyunb) after the address byte, a 0x00 byte will be transferred. Then, stop at ACK.
79*4882a593Smuzhiyun
80*4882a593SmuzhiyunThis is a highly delicate state, the device is set up to write any data to
81*4882a593Smuzhiyunregister 0x00 (if it has registers) when further clock pulses happen on SCL.
82*4882a593SmuzhiyunThis is why bus recovery (up to 9 clock pulses) must either check SDA or send
83*4882a593Smuzhiyunadditional STOP conditions to ensure the bus has been released. Otherwise
84*4882a593Smuzhiyunrandom data will be written to a device!
85*4882a593Smuzhiyun
86*4882a593SmuzhiyunLost arbitration
87*4882a593Smuzhiyun================
88*4882a593Smuzhiyun
89*4882a593SmuzhiyunHere, we want to simulate the condition where the master under test loses the
90*4882a593Smuzhiyunbus arbitration against another master in a multi-master setup.
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun"lose_arbitration"
93*4882a593Smuzhiyun------------------
94*4882a593Smuzhiyun
95*4882a593SmuzhiyunThis file is write only and you need to write the duration of the arbitration
96*4882a593Smuzhiyunintereference (in µs, maximum is 100ms). The calling process will then sleep
97*4882a593Smuzhiyunand wait for the next bus clock. The process is interruptible, though.
98*4882a593Smuzhiyun
99*4882a593SmuzhiyunArbitration lost is achieved by waiting for SCL going down by the master under
100*4882a593Smuzhiyuntest and then pulling SDA low for some time. So, the I2C address sent out
101*4882a593Smuzhiyunshould be corrupted and that should be detected properly. That means that the
102*4882a593Smuzhiyunaddress sent out should have a lot of '1' bits to be able to detect corruption.
103*4882a593SmuzhiyunThere doesn't need to be a device at this address because arbitration lost
104*4882a593Smuzhiyunshould be detected beforehand. Also note, that SCL going down is monitored
105*4882a593Smuzhiyunusing interrupts, so the interrupt latency might cause the first bits to be not
106*4882a593Smuzhiyuncorrupted. A good starting point for using this fault injector on an otherwise
107*4882a593Smuzhiyunidle bus is::
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun  # echo 200 > lose_arbitration &
110*4882a593Smuzhiyun  # i2cget -y <bus_to_test> 0x3f
111*4882a593Smuzhiyun
112*4882a593SmuzhiyunPanic during transfer
113*4882a593Smuzhiyun=====================
114*4882a593Smuzhiyun
115*4882a593SmuzhiyunThis fault injector will create a Kernel panic once the master under test
116*4882a593Smuzhiyunstarted a transfer. This usually means that the state machine of the bus master
117*4882a593Smuzhiyundriver will be ungracefully interrupted and the bus may end up in an unusual
118*4882a593Smuzhiyunstate. Use this to check if your shutdown/reboot/boot code can handle this
119*4882a593Smuzhiyunscenario.
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun"inject_panic"
122*4882a593Smuzhiyun--------------
123*4882a593Smuzhiyun
124*4882a593SmuzhiyunThis file is write only and you need to write the delay between the detected
125*4882a593Smuzhiyunstart of a transmission and the induced Kernel panic (in µs, maximum is 100ms).
126*4882a593SmuzhiyunThe calling process will then sleep and wait for the next bus clock. The
127*4882a593Smuzhiyunprocess is interruptible, though.
128*4882a593Smuzhiyun
129*4882a593SmuzhiyunStart of a transfer is detected by waiting for SCL going down by the master
130*4882a593Smuzhiyununder test.  A good starting point for using this fault injector is::
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun  # echo 0 > inject_panic &
133*4882a593Smuzhiyun  # i2cget -y <bus_to_test> <some_address>
134*4882a593Smuzhiyun
135*4882a593SmuzhiyunNote that there doesn't need to be a device listening to the address you are
136*4882a593Smuzhiyunusing. Results may vary depending on that, though.
137