/ src / device / software_i2c.c
software_i2c.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <assert.h>
  4  #include <timer.h>
  5  #include <console/console.h>
  6  #include <device/i2c_simple.h>
  7  
  8  /*
  9   * The implementation is based on Wikipedia.
 10   */
 11  
 12  #define DEBUG 0		/* Set to 1 for per-byte output */
 13  #define SPEW 0		/* Set to 1 for verbose bitwise/line-state output */
 14  #define DELAY_US 5	/* Default setup delay: 4us (+1 for timer inaccuracy) */
 15  #define TIMEOUT_US 50000 /* Maximum clock stretching time we want to allow */
 16  
 17  #define spew(...) do { if (SPEW) printk(BIOS_SPEW, ##__VA_ARGS__); } while (0)
 18  
 19  #define ERR_NACK	-2
 20  #define ERR_TIMEOUT	-3
 21  #define ERR_ARB		-4
 22  #define ERR_WEDGE	-5
 23  
 24  struct software_i2c_ops *software_i2c[SOFTWARE_I2C_MAX_BUS];
 25  
 26  /*
 27   * Waits until either timeout_us have passed or (iff for_scl is set) until SCL
 28   * goes high. Will report random line changes during the wait and return SCL.
 29   */
 30  static int __wait(unsigned int bus, int timeout_us, int for_scl)
 31  {
 32  	int us;
 33  	int sda = software_i2c[bus]->get_sda(bus);
 34  	int scl = software_i2c[bus]->get_scl(bus);
 35  	struct stopwatch sw;
 36  
 37  	stopwatch_init_usecs_expire(&sw, timeout_us);
 38  
 39  	do {
 40  		int old_sda = sda;
 41  		int old_scl = scl;
 42  
 43  		us = stopwatch_duration_usecs(&sw);
 44  
 45  		if (old_sda != (sda = software_i2c[bus]->get_sda(bus)))
 46  			spew("[SDA transitioned to %d after %dus] ", sda, us);
 47  		if (old_scl != (scl = software_i2c[bus]->get_scl(bus)))
 48  			spew("[SCL transitioned to %d after %dus] ", scl, us);
 49  	} while (!stopwatch_expired(&sw) && (!for_scl || !scl));
 50  
 51  	return scl;
 52  }
 53  
 54  /* Waits the default DELAY_US to allow line state to stabilize. */
 55  static void wait(unsigned int bus)
 56  {
 57  	__wait(bus, DELAY_US, 0);
 58  }
 59  
 60  /* Waits until SCL goes high. Prints a contextual error message on timeout. */
 61  static int wait_for_scl(unsigned int bus, const char *error_context)
 62  {
 63  	if (!__wait(bus, TIMEOUT_US, 1)) {
 64  		printk(BIOS_ERR, "software_i2c(%d): ERROR: Clock stretching "
 65  				 "timeout %s!\n", bus, error_context);
 66  		return ERR_TIMEOUT;
 67  	}
 68  
 69  	return 0;
 70  }
 71  
 72  static int start_cond(unsigned int bus)
 73  {
 74  	spew("software_i2c(%d): Sending start condition... ", bus);
 75  
 76  	/* SDA might not yet be high if repeated start. */
 77  	software_i2c[bus]->set_sda(bus, 1);
 78  	wait(bus);
 79  
 80  	/* Might need to wait for clock stretching if repeated start. */
 81  	software_i2c[bus]->set_scl(bus, 1);
 82  	if (wait_for_scl(bus, "before start condition"))
 83  		return ERR_TIMEOUT;
 84  	wait(bus);	/* Repeated start setup time, minimum 4.7us */
 85  
 86  	if (!software_i2c[bus]->get_sda(bus)) {
 87  		printk(BIOS_ERR, "software_i2c(%d): Arbitration lost trying "
 88  			"to send start condition!\n", bus);
 89  		return ERR_ARB;
 90  	}
 91  
 92  	/* SCL is high, transition SDA low as first part of start condition. */
 93  	software_i2c[bus]->set_sda(bus, 0);
 94  	wait(bus);
 95  	assert(software_i2c[bus]->get_scl(bus));
 96  
 97  	/* Pull SCL low to finish start condition (next pulse will be data). */
 98  	software_i2c[bus]->set_scl(bus, 0);
 99  
100  	spew("Start condition transmitted!\n");
101  	return 0;
102  }
103  
104  static int stop_cond(unsigned int bus)
105  {
106  	spew("software_i2c(%d): Sending stop condition... ", bus);
107  
108  	/* SDA is unknown, set it to low. SCL must be low. */
109  	software_i2c[bus]->set_sda(bus, 0);
110  	wait(bus);
111  
112  	/* Clock stretching */
113  	assert(!software_i2c[bus]->get_scl(bus));
114  	software_i2c[bus]->set_scl(bus, 1);
115  	if (wait_for_scl(bus, "before stop condition"))
116  		return ERR_TIMEOUT;
117  	wait(bus);	/* Stop bit setup time, minimum 4us */
118  
119  	/* SCL is high, transition SDA high to signal stop condition. */
120  	software_i2c[bus]->set_sda(bus, 1);
121  	wait(bus);
122  	if (!software_i2c[bus]->get_sda(bus)) {
123  		printk(BIOS_WARNING, "software_i2c(%d): WARNING: SDA low after "
124  			"stop condition... access by another master or line "
125  			"stuck from faulty slave?\n", bus);
126  		/* Could theoretically happen with multi-master, so no -1. */
127  	}
128  
129  	spew("Stop condition transmitted\n");
130  	return 0;
131  }
132  
133  static int out_bit(unsigned int bus, int bit)
134  {
135  	spew("software_i2c(%d): Sending a %d bit... ", bus, bit);
136  
137  	software_i2c[bus]->set_sda(bus, bit);
138  	wait(bus);
139  
140  	if (bit && !software_i2c[bus]->get_sda(bus)) {
141  		printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low "
142  			"by slave before clock pulse on transmit!\n", bus);
143  		return ERR_WEDGE;
144  	}
145  
146  	/* Clock stretching */
147  	assert(!software_i2c[bus]->get_scl(bus));
148  	software_i2c[bus]->set_scl(bus, 1);
149  	if (wait_for_scl(bus, "on transmit"))
150  		return ERR_TIMEOUT;
151  	wait(bus);
152  
153  	if (bit && !software_i2c[bus]->get_sda(bus)) {
154  		printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low "
155  			"by slave after clock pulse on transmit!\n", bus);
156  		return ERR_WEDGE;
157  	}
158  
159  	assert(software_i2c[bus]->get_scl(bus));
160  	software_i2c[bus]->set_scl(bus, 0);
161  
162  	spew("%d bit sent!\n", bit);
163  	return 0;
164  }
165  
166  static int in_bit(unsigned int bus)
167  {
168  	int bit;
169  
170  	spew("software_i2c(%d): Receiving a bit... ", bus);
171  
172  	/* Let the slave drive data */
173  	software_i2c[bus]->set_sda(bus, 1);
174  	wait(bus);
175  
176  	/* Clock stretching */
177  	assert(!software_i2c[bus]->get_scl(bus));
178  	software_i2c[bus]->set_scl(bus, 1);
179  	if (wait_for_scl(bus, "on receive"))
180  		return ERR_TIMEOUT;
181  
182  	/* SCL is high, now data is valid */
183  	bit = software_i2c[bus]->get_sda(bus);
184  	wait(bus);
185  	assert(software_i2c[bus]->get_scl(bus));
186  	software_i2c[bus]->set_scl(bus, 0);
187  
188  	spew("Received a %d!\n", bit);
189  
190  	return bit;
191  }
192  
193  /* Write a byte to I2C bus. Return 0 if ack by the slave. */
194  static int out_byte(unsigned int bus, u8 byte)
195  {
196  	unsigned int bit;
197  	int nack, ret;
198  
199  	for (bit = 0; bit < 8; bit++)
200  		if ((ret = out_bit(bus, (byte >> (7 - bit)) & 0x1)) < 0)
201  			return ret;
202  
203  	nack = in_bit(bus);
204  
205  	if (DEBUG && nack >= 0)
206  		printk(BIOS_DEBUG, "software_i2c(%d): wrote byte 0x%02x, "
207  			"received %s\n", bus, byte, nack ? "NAK" : "ACK");
208  
209  	return nack > 0 ? ERR_NACK : nack;
210  }
211  
212  static int in_byte(unsigned int bus, int ack)
213  {
214  	u8 byte = 0;
215  	int i, ret;
216  	for (i = 0; i < 8; ++i) {
217  		int bit = in_bit(bus);
218  		if (bit < 0)
219  			return bit;
220  		byte = (byte << 1) | bit;
221  	}
222  
223  	if ((ret = out_bit(bus, !ack)) < 0)
224  		return ret;
225  
226  	if (DEBUG)
227  		printk(BIOS_DEBUG, "software_i2c(%d): read byte 0x%02x, "
228  			"sent %s\n", bus, byte, ack ? "ACK" : "NAK");
229  
230  	return byte;
231  }
232  
233  int software_i2c_transfer(unsigned int bus, struct i2c_msg *segments, int count)
234  {
235  	int i, ret;
236  	struct i2c_msg *seg;
237  
238  	for (seg = segments; seg - segments < count; seg++) {
239  		if ((ret = start_cond(bus)) < 0)
240  			return ret;
241  		const u8 addr_dir = seg->slave << 1 | !!(seg->flags & I2C_M_RD);
242  		if ((ret = out_byte(bus, addr_dir)) < 0)
243  			return ret;
244  		for (i = 0; i < seg->len; i++) {
245  			if (seg->flags & I2C_M_RD) {
246  				ret = in_byte(bus, i < seg->len - 1);
247  				seg->buf[i] = (u8)ret;
248  			} else {
249  				ret = out_byte(bus, seg->buf[i]);
250  			}
251  			if (ret < 0)
252  				return ret;
253  		}
254  	}
255  	if ((ret = stop_cond(bus)) < 0)
256  		return ret;
257  
258  	return 0;
259  }
260  
261  void software_i2c_wedge_ack(unsigned int bus, u8 chip)
262  {
263  	int i;
264  
265  	/* Start a command to 'chip'... */
266  	start_cond(bus);
267  
268  	/* Send the address bits but don't yet read the ACK. */
269  	chip <<= 1;
270  	for (i = 0; i < 8; ++i)
271  		out_bit(bus, (chip >> (7 - i)) & 0x1);
272  
273  	/* Let the slave drive it's ACK but keep the clock high forever. */
274  	software_i2c[bus]->set_sda(bus, 1);
275  	wait(bus);
276  	software_i2c[bus]->set_scl(bus, 1);
277  	wait_for_scl(bus, "on wedge_ack()");
278  
279  	printk(BIOS_INFO, "software_i2c(%d): wedged address write on slave "
280  		"ACK. SDA %d, SCL %d\n", bus, software_i2c[bus]->get_sda(bus),
281  		software_i2c[bus]->get_scl(bus));
282  }
283  
284  void software_i2c_wedge_read(unsigned int bus, u8 chip, u8 reg, int bits)
285  {
286  	int i;
287  
288  	/* Start a command to 'chip'... */
289  	start_cond(bus);
290  	out_byte(bus, chip << 1);
291  	/* ...for register 'reg'. */
292  	out_byte(bus, reg);
293  
294  	/* Start a read command... */
295  	start_cond(bus);
296  	out_byte(bus, chip << 1 | 1);
297  
298  	/* Read bit_count bits and stop */
299  	for (i = 0; i < bits; ++i)
300  		in_bit(bus);
301  
302  	/* Let the slave drive SDA but keep the clock high forever. */
303  	software_i2c[bus]->set_sda(bus, 1);
304  	wait(bus);
305  	software_i2c[bus]->set_scl(bus, 1);
306  	wait_for_scl(bus, "on wedge_read()");
307  
308  	printk(BIOS_INFO, "software_i2c(%d): wedged data read after %d bits. "
309  		"SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus),
310  		software_i2c[bus]->get_scl(bus));
311  }
312  
313  void software_i2c_wedge_write(unsigned int bus, u8 chip, u8 reg, int bits)
314  {
315  	int i;
316  
317  	/* Start a command to 'chip'... */
318  	start_cond(bus);
319  	out_byte(bus, chip << 1);
320  
321  	/* Write bit_count register bits and stop */
322  	for (i = 0; i < bits; ++i)
323  		out_bit(bus, (reg >> (7 - i)) & 0x1);
324  
325  	/* Pretend to write another 1 bit but keep the clock high forever. */
326  	software_i2c[bus]->set_sda(bus, 1);
327  	wait(bus);
328  	software_i2c[bus]->set_scl(bus, 1);
329  	wait_for_scl(bus, "on wedge_write()");
330  
331  	printk(BIOS_INFO, "software_i2c(%d): wedged data write after %d bits. "
332  		"SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus),
333  		software_i2c[bus]->get_scl(bus));
334  }