Lines Matching +full:data +full:- +full:pins
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * Helper code to recover a hung i2c bus by bit-banging a recovery sequence.
34 * An i2c bus can be hung by a slave driving the clock (rare) or data lines low.
35 * The most common cause is a partially-completed transaction such as rebooting
36 * while a slave is sending a byte of data. Because i2c allows the clock to
38 * data line until power is removed, or the clock cycles enough times to
42 * Any i2c driver which is able to manually set the level of the clock and data
44 * embedded i2c controllers, the i2c pins can be temporarily reassigned as gpio
45 * pins to do the bus recovery, then can be assigned back to the i2c hardware.
58 iic_recover_bus(struct iicrb_pin_access *pins) in iic_recover_bus() argument
65 * Start with clock and data high. in iic_recover_bus()
67 pins->setsda(pins->ctx, 1); in iic_recover_bus()
68 pins->setscl(pins->ctx, 1); in iic_recover_bus()
72 * bus is doing clock-stretching and we should wait a while. If that in iic_recover_bus()
75 * cheap eeprom has a max post-write delay of only 10ms), and also long in iic_recover_bus()
79 if (pins->getscl(pins->ctx)) in iic_recover_bus()
89 * the data line low waiting for more clock pulses to finish the byte. in iic_recover_bus()
90 * Cycle the clock until we see the data line go high, but only up to 9 in iic_recover_bus()
93 * bit, after which the slave must not be driving the data line anymore. in iic_recover_bus()
96 if (pins->getsda(pins->ctx)) in iic_recover_bus()
100 pins->setscl(pins->ctx, 0); in iic_recover_bus()
102 pins->setscl(pins->ctx, 1); in iic_recover_bus()
107 * At this point we should be in control of both the clock and data in iic_recover_bus()
111 * - START: SDA transitions high->low while SCL remains high. in iic_recover_bus()
112 * - STOP: SDA transitions low->high while SCL remains high. in iic_recover_bus()
114 * data line no faster than it would change state with a 100khz clock. in iic_recover_bus()
116 pins->setsda(pins->ctx, 0); in iic_recover_bus()
118 pins->setsda(pins->ctx, 1); in iic_recover_bus()