blob: 857adf0428e9512fb6d30221924adc291c306f28 [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Julius Werner37d7ac82014-05-05 18:03:46 -07003
4#include <assert.h>
5#include <timer.h>
6#include <console/console.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02007#include <device/i2c_simple.h>
Julius Werner37d7ac82014-05-05 18:03:46 -07008
9/*
10 * The implementation is based on Wikipedia.
11 */
12
13#define DEBUG 0 /* Set to 1 for per-byte output */
14#define SPEW 0 /* Set to 1 for verbose bitwise/line-state output */
15#define DELAY_US 5 /* Default setup delay: 4us (+1 for timer inaccuracy) */
16#define TIMEOUT_US 50000 /* Maximum clock stretching time we want to allow */
17
18#define spew(...) do { if (SPEW) printk(BIOS_SPEW, ##__VA_ARGS__); } while (0)
19
Julius Werner6dc7b222018-04-30 17:57:08 -070020#define ERR_NACK -2
21#define ERR_TIMEOUT -3
22#define ERR_ARB -4
23#define ERR_WEDGE -5
24
Julius Werner37d7ac82014-05-05 18:03:46 -070025struct software_i2c_ops *software_i2c[SOFTWARE_I2C_MAX_BUS];
26
27/*
28 * Waits until either timeout_us have passed or (iff for_scl is set) until SCL
29 * goes high. Will report random line changes during the wait and return SCL.
30 */
Martin Roth38ddbfb2019-10-23 21:41:00 -060031static int __wait(unsigned int bus, int timeout_us, int for_scl)
Julius Werner37d7ac82014-05-05 18:03:46 -070032{
33 int us;
34 int sda = software_i2c[bus]->get_sda(bus);
35 int scl = software_i2c[bus]->get_scl(bus);
Aaron Durbin46ba4802014-09-23 16:34:40 -050036 struct stopwatch sw;
37
38 stopwatch_init_usecs_expire(&sw, timeout_us);
Julius Werner37d7ac82014-05-05 18:03:46 -070039
40 do {
41 int old_sda = sda;
42 int old_scl = scl;
Aaron Durbin46ba4802014-09-23 16:34:40 -050043
44 us = stopwatch_duration_usecs(&sw);
Julius Werner37d7ac82014-05-05 18:03:46 -070045
46 if (old_sda != (sda = software_i2c[bus]->get_sda(bus)))
47 spew("[SDA transitioned to %d after %dus] ", sda, us);
48 if (old_scl != (scl = software_i2c[bus]->get_scl(bus)))
49 spew("[SCL transitioned to %d after %dus] ", scl, us);
Aaron Durbin46ba4802014-09-23 16:34:40 -050050 } while (!stopwatch_expired(&sw) && (!for_scl || !scl));
Julius Werner37d7ac82014-05-05 18:03:46 -070051
52 return scl;
53}
54
55/* Waits the default DELAY_US to allow line state to stabilize. */
Martin Roth38ddbfb2019-10-23 21:41:00 -060056static void wait(unsigned int bus)
Julius Werner37d7ac82014-05-05 18:03:46 -070057{
58 __wait(bus, DELAY_US, 0);
59}
60
61/* Waits until SCL goes high. Prints a contextual error message on timeout. */
Martin Roth38ddbfb2019-10-23 21:41:00 -060062static int wait_for_scl(unsigned int bus, const char *error_context)
Julius Werner37d7ac82014-05-05 18:03:46 -070063{
64 if (!__wait(bus, TIMEOUT_US, 1)) {
65 printk(BIOS_ERR, "software_i2c(%d): ERROR: Clock stretching "
66 "timeout %s!\n", bus, error_context);
Julius Werner6dc7b222018-04-30 17:57:08 -070067 return ERR_TIMEOUT;
Julius Werner37d7ac82014-05-05 18:03:46 -070068 }
69
70 return 0;
71}
72
Martin Roth38ddbfb2019-10-23 21:41:00 -060073static int start_cond(unsigned int bus)
Julius Werner37d7ac82014-05-05 18:03:46 -070074{
75 spew("software_i2c(%d): Sending start condition... ", bus);
76
77 /* SDA might not yet be high if repeated start. */
78 software_i2c[bus]->set_sda(bus, 1);
79 wait(bus);
80
81 /* Might need to wait for clock stretching if repeated start. */
82 software_i2c[bus]->set_scl(bus, 1);
83 if (wait_for_scl(bus, "before start condition"))
Julius Werner6dc7b222018-04-30 17:57:08 -070084 return ERR_TIMEOUT;
Julius Werner37d7ac82014-05-05 18:03:46 -070085 wait(bus); /* Repeated start setup time, minimum 4.7us */
86
87 if (!software_i2c[bus]->get_sda(bus)) {
88 printk(BIOS_ERR, "software_i2c(%d): Arbitration lost trying "
89 "to send start condition!\n", bus);
Julius Werner6dc7b222018-04-30 17:57:08 -070090 return ERR_ARB;
Julius Werner37d7ac82014-05-05 18:03:46 -070091 }
92
93 /* SCL is high, transition SDA low as first part of start condition. */
94 software_i2c[bus]->set_sda(bus, 0);
95 wait(bus);
96 assert(software_i2c[bus]->get_scl(bus));
97
98 /* Pull SCL low to finish start condition (next pulse will be data). */
99 software_i2c[bus]->set_scl(bus, 0);
100
101 spew("Start condition transmitted!\n");
102 return 0;
103}
104
Martin Roth38ddbfb2019-10-23 21:41:00 -0600105static int stop_cond(unsigned int bus)
Julius Werner37d7ac82014-05-05 18:03:46 -0700106{
107 spew("software_i2c(%d): Sending stop condition... ", bus);
108
109 /* SDA is unknown, set it to low. SCL must be low. */
110 software_i2c[bus]->set_sda(bus, 0);
111 wait(bus);
112
113 /* Clock stretching */
114 assert(!software_i2c[bus]->get_scl(bus));
115 software_i2c[bus]->set_scl(bus, 1);
116 if (wait_for_scl(bus, "before stop condition"))
Julius Werner6dc7b222018-04-30 17:57:08 -0700117 return ERR_TIMEOUT;
Julius Werner37d7ac82014-05-05 18:03:46 -0700118 wait(bus); /* Stop bit setup time, minimum 4us */
119
120 /* SCL is high, transition SDA high to signal stop condition. */
121 software_i2c[bus]->set_sda(bus, 1);
122 wait(bus);
123 if (!software_i2c[bus]->get_sda(bus)) {
124 printk(BIOS_WARNING, "software_i2c(%d): WARNING: SDA low after "
125 "stop condition... access by another master or line "
126 "stuck from faulty slave?\n", bus);
127 /* Could theoretically happen with multi-master, so no -1. */
128 }
129
130 spew("Stop condition transmitted\n");
131 return 0;
132}
133
Martin Roth38ddbfb2019-10-23 21:41:00 -0600134static int out_bit(unsigned int bus, int bit)
Julius Werner37d7ac82014-05-05 18:03:46 -0700135{
136 spew("software_i2c(%d): Sending a %d bit... ", bus, bit);
137
138 software_i2c[bus]->set_sda(bus, bit);
139 wait(bus);
140
141 if (bit && !software_i2c[bus]->get_sda(bus)) {
142 printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low "
143 "by slave before clock pulse on transmit!\n", bus);
Julius Werner6dc7b222018-04-30 17:57:08 -0700144 return ERR_WEDGE;
Julius Werner37d7ac82014-05-05 18:03:46 -0700145 }
146
147 /* Clock stretching */
148 assert(!software_i2c[bus]->get_scl(bus));
149 software_i2c[bus]->set_scl(bus, 1);
150 if (wait_for_scl(bus, "on transmit"))
Julius Werner6dc7b222018-04-30 17:57:08 -0700151 return ERR_TIMEOUT;
Julius Werner37d7ac82014-05-05 18:03:46 -0700152 wait(bus);
153
154 if (bit && !software_i2c[bus]->get_sda(bus)) {
155 printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low "
156 "by slave after clock pulse on transmit!\n", bus);
Julius Werner6dc7b222018-04-30 17:57:08 -0700157 return ERR_WEDGE;
Julius Werner37d7ac82014-05-05 18:03:46 -0700158 }
159
160 assert(software_i2c[bus]->get_scl(bus));
161 software_i2c[bus]->set_scl(bus, 0);
162
163 spew("%d bit sent!\n", bit);
164 return 0;
165}
166
Martin Roth38ddbfb2019-10-23 21:41:00 -0600167static int in_bit(unsigned int bus)
Julius Werner37d7ac82014-05-05 18:03:46 -0700168{
169 int bit;
170
171 spew("software_i2c(%d): Receiving a bit... ", bus);
172
173 /* Let the slave drive data */
174 software_i2c[bus]->set_sda(bus, 1);
175 wait(bus);
176
177 /* Clock stretching */
178 assert(!software_i2c[bus]->get_scl(bus));
179 software_i2c[bus]->set_scl(bus, 1);
180 if (wait_for_scl(bus, "on receive"))
Julius Werner6dc7b222018-04-30 17:57:08 -0700181 return ERR_TIMEOUT;
Julius Werner37d7ac82014-05-05 18:03:46 -0700182
183 /* SCL is high, now data is valid */
184 bit = software_i2c[bus]->get_sda(bus);
185 wait(bus);
186 assert(software_i2c[bus]->get_scl(bus));
187 software_i2c[bus]->set_scl(bus, 0);
188
189 spew("Received a %d!\n", bit);
190
191 return bit;
192}
193
194/* Write a byte to I2C bus. Return 0 if ack by the slave. */
Martin Roth38ddbfb2019-10-23 21:41:00 -0600195static int out_byte(unsigned int bus, u8 byte)
Julius Werner37d7ac82014-05-05 18:03:46 -0700196{
Martin Roth38ddbfb2019-10-23 21:41:00 -0600197 unsigned int bit;
Julius Werner6dc7b222018-04-30 17:57:08 -0700198 int nack, ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700199
200 for (bit = 0; bit < 8; bit++)
Julius Werner6dc7b222018-04-30 17:57:08 -0700201 if ((ret = out_bit(bus, (byte >> (7 - bit)) & 0x1)) < 0)
202 return ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700203
204 nack = in_bit(bus);
205
206 if (DEBUG && nack >= 0)
207 printk(BIOS_DEBUG, "software_i2c(%d): wrote byte 0x%02x, "
208 "received %s\n", bus, byte, nack ? "NAK" : "ACK");
209
Julius Werner6dc7b222018-04-30 17:57:08 -0700210 return nack > 0 ? ERR_NACK : nack;
Julius Werner37d7ac82014-05-05 18:03:46 -0700211}
212
Martin Roth38ddbfb2019-10-23 21:41:00 -0600213static int in_byte(unsigned int bus, int ack)
Julius Werner37d7ac82014-05-05 18:03:46 -0700214{
215 u8 byte = 0;
Julius Werner6dc7b222018-04-30 17:57:08 -0700216 int i, ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700217 for (i = 0; i < 8; ++i) {
218 int bit = in_bit(bus);
219 if (bit < 0)
Julius Werner6dc7b222018-04-30 17:57:08 -0700220 return bit;
Julius Werner37d7ac82014-05-05 18:03:46 -0700221 byte = (byte << 1) | bit;
222 }
223
Julius Werner6dc7b222018-04-30 17:57:08 -0700224 if ((ret = out_bit(bus, !ack)) < 0)
225 return ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700226
227 if (DEBUG)
228 printk(BIOS_DEBUG, "software_i2c(%d): read byte 0x%02x, "
229 "sent %s\n", bus, byte, ack ? "ACK" : "NAK");
230
231 return byte;
232}
233
Martin Roth38ddbfb2019-10-23 21:41:00 -0600234int software_i2c_transfer(unsigned int bus, struct i2c_msg *segments, int count)
Julius Werner37d7ac82014-05-05 18:03:46 -0700235{
Julius Werner6dc7b222018-04-30 17:57:08 -0700236 int i, ret;
Nico Huber029dfff2017-07-12 17:59:16 +0200237 struct i2c_msg *seg;
Julius Werner37d7ac82014-05-05 18:03:46 -0700238
239 for (seg = segments; seg - segments < count; seg++) {
Julius Werner6dc7b222018-04-30 17:57:08 -0700240 if ((ret = start_cond(bus)) < 0)
241 return ret;
Nico Huber029dfff2017-07-12 17:59:16 +0200242 const u8 addr_dir = seg->slave << 1 | !!(seg->flags & I2C_M_RD);
Julius Werner6dc7b222018-04-30 17:57:08 -0700243 if ((ret = out_byte(bus, addr_dir)) < 0)
244 return ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700245 for (i = 0; i < seg->len; i++) {
Nico Huber029dfff2017-07-12 17:59:16 +0200246 if (seg->flags & I2C_M_RD) {
Julius Werner37d7ac82014-05-05 18:03:46 -0700247 ret = in_byte(bus, i < seg->len - 1);
248 seg->buf[i] = (u8)ret;
249 } else {
250 ret = out_byte(bus, seg->buf[i]);
251 }
252 if (ret < 0)
Julius Werner6dc7b222018-04-30 17:57:08 -0700253 return ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700254 }
255 }
Julius Werner6dc7b222018-04-30 17:57:08 -0700256 if ((ret = stop_cond(bus)) < 0)
257 return ret;
Julius Werner37d7ac82014-05-05 18:03:46 -0700258
259 return 0;
260}
261
Martin Roth38ddbfb2019-10-23 21:41:00 -0600262void software_i2c_wedge_ack(unsigned int bus, u8 chip)
Julius Werner37d7ac82014-05-05 18:03:46 -0700263{
264 int i;
265
266 /* Start a command to 'chip'... */
267 start_cond(bus);
268
269 /* Send the address bits but don't yet read the ACK. */
270 chip <<= 1;
271 for (i = 0; i < 8; ++i)
272 out_bit(bus, (chip >> (7 - i)) & 0x1);
273
274 /* Let the slave drive it's ACK but keep the clock high forever. */
275 software_i2c[bus]->set_sda(bus, 1);
276 wait(bus);
277 software_i2c[bus]->set_scl(bus, 1);
278 wait_for_scl(bus, "on wedge_ack()");
279
280 printk(BIOS_INFO, "software_i2c(%d): wedged address write on slave "
281 "ACK. SDA %d, SCL %d\n", bus, software_i2c[bus]->get_sda(bus),
282 software_i2c[bus]->get_scl(bus));
283}
284
Martin Roth38ddbfb2019-10-23 21:41:00 -0600285void software_i2c_wedge_read(unsigned int bus, u8 chip, u8 reg, int bits)
Julius Werner37d7ac82014-05-05 18:03:46 -0700286{
287 int i;
288
289 /* Start a command to 'chip'... */
290 start_cond(bus);
291 out_byte(bus, chip << 1);
292 /* ...for register 'reg'. */
293 out_byte(bus, reg);
294
295 /* Start a read command... */
296 start_cond(bus);
297 out_byte(bus, chip << 1 | 1);
298
299 /* Read bit_count bits and stop */
300 for (i = 0; i < bits; ++i)
301 in_bit(bus);
302
303 /* Let the slave drive SDA but keep the clock high forever. */
304 software_i2c[bus]->set_sda(bus, 1);
305 wait(bus);
306 software_i2c[bus]->set_scl(bus, 1);
307 wait_for_scl(bus, "on wedge_read()");
308
309 printk(BIOS_INFO, "software_i2c(%d): wedged data read after %d bits. "
310 "SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus),
311 software_i2c[bus]->get_scl(bus));
312}
313
Martin Roth38ddbfb2019-10-23 21:41:00 -0600314void software_i2c_wedge_write(unsigned int bus, u8 chip, u8 reg, int bits)
Julius Werner37d7ac82014-05-05 18:03:46 -0700315{
316 int i;
317
318 /* Start a command to 'chip'... */
319 start_cond(bus);
320 out_byte(bus, chip << 1);
321
322 /* Write bit_count register bits and stop */
323 for (i = 0; i < bits; ++i)
324 out_bit(bus, (reg >> (7 - i)) & 0x1);
325
326 /* Pretend to write another 1 bit but keep the clock high forever. */
327 software_i2c[bus]->set_sda(bus, 1);
328 wait(bus);
329 software_i2c[bus]->set_scl(bus, 1);
330 wait_for_scl(bus, "on wedge_write()");
331
332 printk(BIOS_INFO, "software_i2c(%d): wedged data write after %d bits. "
333 "SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus),
334 software_i2c[bus]->get_scl(bus));
335}