xref: /aosp_15_r20/external/coreboot/src/southbridge/intel/common/smbus.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <device/smbus_def.h>
6 #include <device/smbus_host.h>
7 #include <types.h>
8 
9 #if CONFIG(DEBUG_SMBUS)
10 #define dprintk(args...) printk(BIOS_DEBUG, ##args)
11 #else
12 #define dprintk(args...) do {} while (0)
13 #endif
14 
15 /* SMBus register offsets. */
16 #define SMBHSTSTAT		0x0
17 #define SMBHSTCTL		0x2
18 #define SMBHSTCMD		0x3
19 #define SMBXMITADD		0x4
20 #define SMBHSTDAT0		0x5
21 #define SMBHSTDAT1		0x6
22 #define SMBBLKDAT		0x7
23 #define SMBTRNSADD		0x9
24 #define SMBSLVDATA		0xa
25 #define SMLINK_PIN_CTL		0xe
26 #define SMBUS_PIN_CTL		0xf
27 #define SMBSLVCMD		0x11
28 
29 #define SMB_RCV_SLVA		SMBTRNSADD
30 
31 /* I801 command constants */
32 #define I801_QUICK		(0 << 2)
33 #define I801_BYTE		(1 << 2)
34 #define I801_BYTE_DATA		(2 << 2)
35 #define I801_WORD_DATA		(3 << 2)
36 #define I801_PROCESS_CALL	(4 << 2)
37 #define I801_BLOCK_DATA		(5 << 2)
38 #define I801_I2C_BLOCK_DATA	(6 << 2) /* ICH5 and later */
39 
40 /* I801 Host Control register bits */
41 #define SMBHSTCNT_INTREN	(1 << 0)
42 #define SMBHSTCNT_KILL		(1 << 1)
43 #define SMBHSTCNT_LAST_BYTE	(1 << 5)
44 #define SMBHSTCNT_START		(1 << 6)
45 #define SMBHSTCNT_PEC_EN	(1 << 7) /* ICH3 and later */
46 
47 /* I801 Hosts Status register bits */
48 #define SMBHSTSTS_BYTE_DONE	(1 << 7)
49 #define SMBHSTSTS_INUSE_STS	(1 << 6)
50 #define SMBHSTSTS_SMBALERT_STS	(1 << 5)
51 #define SMBHSTSTS_FAILED	(1 << 4)
52 #define SMBHSTSTS_BUS_ERR	(1 << 3)
53 #define SMBHSTSTS_DEV_ERR	(1 << 2)
54 #define SMBHSTSTS_INTR		(1 << 1)
55 #define SMBHSTSTS_HOST_BUSY	(1 << 0)
56 
57 /* For SMBXMITADD register. */
58 #define XMIT_WRITE(dev)		(((dev) << 1) | 0)
59 #define XMIT_READ(dev)		(((dev) << 1) | 1)
60 
61 #define SMBUS_TIMEOUT		(10 * 1000 * 100)
62 #define SMBUS_BLOCK_MAXLEN	32
63 
64 /* block_cmd_loop flags */
65 #define BLOCK_READ	0
66 #define BLOCK_WRITE	(1 << 0)
67 #define BLOCK_I2C	(1 << 1)
68 
smbus_delay(void)69 static void smbus_delay(void)
70 {
71 	inb(0x80);
72 }
73 
host_outb(uintptr_t base,u8 reg,u8 value)74 static void host_outb(uintptr_t base, u8 reg, u8 value)
75 {
76 	outb(value, base + reg);
77 }
78 
host_inb(uintptr_t base,u8 reg)79 static u8 host_inb(uintptr_t base, u8 reg)
80 {
81 	return inb(base + reg);
82 }
83 
host_and_or(uintptr_t base,u8 reg,u8 mask,u8 or)84 static void host_and_or(uintptr_t base, u8 reg, u8 mask, u8 or)
85 {
86 	u8 value;
87 	value = host_inb(base, reg);
88 	value &= mask;
89 	value |= or;
90 	host_outb(base, reg, value);
91 }
92 
smbus_host_reset(uintptr_t base)93 void smbus_host_reset(uintptr_t base)
94 {
95 	/* Disable interrupt generation. */
96 	host_outb(base, SMBHSTCTL, 0);
97 
98 	/* Clear any lingering errors, so transactions can run. */
99 	host_and_or(base, SMBHSTSTAT, 0xff, 0);
100 }
101 
smbus_set_slave_addr(uintptr_t base,u8 slave_address)102 void smbus_set_slave_addr(uintptr_t base, u8 slave_address)
103 {
104 	host_outb(base, SMB_RCV_SLVA, slave_address);
105 }
106 
host_completed(u8 status)107 static int host_completed(u8 status)
108 {
109 	if (status & SMBHSTSTS_HOST_BUSY)
110 		return 0;
111 
112 	/* These status bits do not imply completion of transaction. */
113 	status &= ~(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INUSE_STS |
114 		    SMBHSTSTS_SMBALERT_STS);
115 	return status != 0;
116 }
117 
recover_master(uintptr_t base,int ret)118 static int recover_master(uintptr_t base, int ret)
119 {
120 	/* TODO: Depending of the failure, drive KILL transaction
121 	 * or force soft reset on SMBus master controller.
122 	 */
123 	printk(BIOS_ERR, "SMBus: Fatal master timeout (%d)\n", ret);
124 	return ret;
125 }
126 
cb_err_from_stat(u8 status)127 static int cb_err_from_stat(u8 status)
128 {
129 	/* These status bits do not imply errors. */
130 	status &= ~(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INUSE_STS |
131 		    SMBHSTSTS_SMBALERT_STS);
132 
133 	if (status == SMBHSTSTS_INTR)
134 		return 0;
135 
136 	return SMBUS_ERROR;
137 }
138 
setup_command(uintptr_t base,u8 ctrl,u8 xmitadd)139 static int setup_command(uintptr_t base, u8 ctrl, u8 xmitadd)
140 {
141 	unsigned int loops = SMBUS_TIMEOUT;
142 	u8 host_busy;
143 
144 	do {
145 		smbus_delay();
146 		host_busy = host_inb(base, SMBHSTSTAT) & SMBHSTSTS_HOST_BUSY;
147 	} while (--loops && host_busy);
148 
149 	if (loops == 0)
150 		return recover_master(base, SMBUS_WAIT_UNTIL_READY_TIMEOUT);
151 
152 	/* Clear any lingering errors, so the transaction will run. */
153 	host_and_or(base, SMBHSTSTAT, 0xff, 0);
154 
155 	/* Set up transaction */
156 	/* Disable interrupts */
157 	host_outb(base, SMBHSTCTL, ctrl);
158 
159 	/* Set the device I'm talking to. */
160 	host_outb(base, SMBXMITADD, xmitadd);
161 
162 	return 0;
163 }
164 
execute_command(uintptr_t base)165 static int execute_command(uintptr_t base)
166 {
167 	unsigned int loops = SMBUS_TIMEOUT;
168 	u8 status;
169 
170 	/* Start the command. */
171 	host_and_or(base, SMBHSTCTL, 0xff, SMBHSTCNT_START);
172 
173 	/* Poll for it to start. */
174 	do {
175 		smbus_delay();
176 
177 		/* If we poll too slow, we could miss HOST_BUSY flag
178 		 * set and detect INTR or x_ERR flags instead here.
179 		 */
180 		status = host_inb(base, SMBHSTSTAT);
181 		status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
182 	} while (--loops && status == 0);
183 
184 	if (loops == 0)
185 		return recover_master(base,
186 				      SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT);
187 
188 	return 0;
189 }
190 
complete_command(uintptr_t base)191 static int complete_command(uintptr_t base)
192 {
193 	unsigned int loops = SMBUS_TIMEOUT;
194 	u8 status;
195 
196 	do {
197 		smbus_delay();
198 		status = host_inb(base, SMBHSTSTAT);
199 	} while (--loops && !host_completed(status));
200 
201 	if (loops == 0)
202 		return recover_master(base,
203 				      SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
204 
205 	return cb_err_from_stat(status);
206 }
207 
smbus_read_cmd(uintptr_t base,u8 ctrl,u8 device,u8 address)208 static int smbus_read_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address)
209 {
210 	int ret;
211 	u16 word;
212 
213 	/* Set up for a byte data read. */
214 	ret = setup_command(base, ctrl, XMIT_READ(device));
215 	if (ret < 0)
216 		return ret;
217 
218 	/* Set the command/address... */
219 	host_outb(base, SMBHSTCMD, address);
220 
221 	/* Clear the data bytes... */
222 	host_outb(base, SMBHSTDAT0, 0);
223 	host_outb(base, SMBHSTDAT1, 0);
224 
225 	/* Start the command */
226 	ret = execute_command(base);
227 	if (ret < 0)
228 		return ret;
229 
230 	/* Poll for transaction completion */
231 	ret = complete_command(base);
232 	if (ret < 0)
233 		return ret;
234 
235 	/* Read results of transaction */
236 	word = host_inb(base, SMBHSTDAT0);
237 	if (ctrl == I801_WORD_DATA)
238 		word |= host_inb(base, SMBHSTDAT1) << 8;
239 
240 	return word;
241 }
242 
smbus_write_cmd(uintptr_t base,u8 ctrl,u8 device,u8 address,u16 data)243 static int smbus_write_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address, u16 data)
244 {
245 	int ret;
246 
247 	/* Set up for a byte data write. */
248 	ret = setup_command(base, ctrl, XMIT_WRITE(device));
249 	if (ret < 0)
250 		return ret;
251 
252 	/* Set the command/address... */
253 	host_outb(base, SMBHSTCMD, address);
254 
255 	/* Set the data bytes... */
256 	if (ctrl >= I801_BYTE_DATA)
257 		host_outb(base, SMBHSTDAT0, data & 0xff);
258 	if (ctrl == I801_WORD_DATA)
259 		host_outb(base, SMBHSTDAT1, data >> 8);
260 
261 	/* Start the command */
262 	ret = execute_command(base);
263 	if (ret < 0)
264 		return ret;
265 
266 	/* Poll for transaction completion */
267 	return complete_command(base);
268 }
269 
block_cmd_loop(uintptr_t base,u8 * buf,size_t max_bytes,int flags)270 static int block_cmd_loop(uintptr_t base, u8 *buf, size_t max_bytes, int flags)
271 {
272 	u8 status;
273 	unsigned int loops = SMBUS_TIMEOUT;
274 	int ret;
275 	size_t bytes = 0;
276 	int is_write_cmd = flags & BLOCK_WRITE;
277 	int sw_drives_nak = flags & BLOCK_I2C;
278 
279 	/* Hardware limitations. */
280 	if (flags == (BLOCK_WRITE | BLOCK_I2C))
281 		return SMBUS_ERROR;
282 
283 	/* Set number of bytes to transfer. */
284 	/* Reset number of bytes to transfer so we notice later it
285 	 * was really updated with the transaction. */
286 	if (!sw_drives_nak) {
287 		if (is_write_cmd)
288 			host_outb(base, SMBHSTDAT0, max_bytes);
289 		else
290 			host_outb(base, SMBHSTDAT0, 0);
291 	}
292 
293 	/* Send first byte from buffer, bytes_sent increments after
294 	 * hardware acknowledges it.
295 	 */
296 	if (is_write_cmd)
297 		host_outb(base, SMBBLKDAT, *buf++);
298 
299 	/* Start the command */
300 	ret = execute_command(base);
301 	if (ret < 0)
302 		return ret;
303 
304 	/* Poll for transaction completion */
305 	do {
306 		status = host_inb(base, SMBHSTSTAT);
307 
308 		if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
309 
310 			if (is_write_cmd) {
311 				bytes++;
312 				if (bytes < max_bytes)
313 					host_outb(base, SMBBLKDAT, *buf++);
314 			} else {
315 				if (bytes < max_bytes)
316 					*buf++ = host_inb(base, SMBBLKDAT);
317 				bytes++;
318 
319 				/* Indicate that next byte is the last one. */
320 				if (sw_drives_nak && (bytes + 1 >= max_bytes)) {
321 					host_and_or(base, SMBHSTCTL, 0xff,
322 						    SMBHSTCNT_LAST_BYTE);
323 				}
324 			}
325 
326 			/* Engine internally completes the transaction
327 			 * and clears HOST_BUSY flag once the byte count
328 			 * has been reached or LAST_BYTE was set.
329 			 */
330 			host_outb(base, SMBHSTSTAT, SMBHSTSTS_BYTE_DONE);
331 		}
332 
333 	} while (--loops && !host_completed(status));
334 
335 	dprintk("%s: status = %02x, len = %zd / %zd, loops = %d\n",
336 		__func__, status, bytes, max_bytes, SMBUS_TIMEOUT - loops);
337 
338 	if (loops == 0)
339 		return recover_master(base, SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
340 
341 	ret = cb_err_from_stat(status);
342 	if (ret < 0)
343 		return ret;
344 
345 	return bytes;
346 }
347 
do_smbus_read_byte(uintptr_t base,u8 device,u8 address)348 int do_smbus_read_byte(uintptr_t base, u8 device, u8 address)
349 {
350 	return smbus_read_cmd(base, I801_BYTE_DATA, device, address);
351 }
352 
do_smbus_read_word(uintptr_t base,u8 device,u8 address)353 int do_smbus_read_word(uintptr_t base, u8 device, u8 address)
354 {
355 	return smbus_read_cmd(base, I801_WORD_DATA, device, address);
356 }
357 
do_smbus_send_byte(uintptr_t base,u8 device,u8 data)358 int do_smbus_send_byte(uintptr_t base, u8 device, u8 data)
359 {
360 	return smbus_write_cmd(base, I801_BYTE, device, data, 0x00);
361 }
362 
do_smbus_write_byte(uintptr_t base,u8 device,u8 address,u8 data)363 int do_smbus_write_byte(uintptr_t base, u8 device, u8 address, u8 data)
364 {
365 	return smbus_write_cmd(base, I801_BYTE_DATA, device, address, data);
366 }
367 
do_smbus_write_word(uintptr_t base,u8 device,u8 address,u16 data)368 int do_smbus_write_word(uintptr_t base, u8 device, u8 address, u16 data)
369 {
370 	return smbus_write_cmd(base, I801_WORD_DATA, device, address, data);
371 }
372 
do_smbus_block_read(uintptr_t base,u8 device,u8 cmd,size_t max_bytes,u8 * buf)373 int do_smbus_block_read(uintptr_t base, u8 device, u8 cmd, size_t max_bytes, u8 *buf)
374 {
375 	int ret, slave_bytes;
376 
377 	max_bytes = MIN(SMBUS_BLOCK_MAXLEN, max_bytes);
378 
379 	/* Set up for a block data read. */
380 	ret = setup_command(base, I801_BLOCK_DATA, XMIT_READ(device));
381 	if (ret < 0)
382 		return ret;
383 
384 	/* Set the command/address... */
385 	host_outb(base, SMBHSTCMD, cmd);
386 
387 	/* Execute block transaction. */
388 	ret = block_cmd_loop(base, buf, max_bytes, BLOCK_READ);
389 	if (ret < 0)
390 		return ret;
391 
392 	/* Post-check we received complete message. */
393 	slave_bytes = host_inb(base, SMBHSTDAT0);
394 	if (ret < slave_bytes)
395 		return SMBUS_ERROR;
396 
397 	return ret;
398 }
399 
400 /*
401  * The caller is responsible of settings HOSTC I2C_EN bit prior to making this
402  * call!
403  */
do_smbus_process_call(uintptr_t base,u8 device,u8 cmd,u16 data,u16 * buf)404 int do_smbus_process_call(uintptr_t base, u8 device, u8 cmd, u16 data, u16 *buf)
405 {
406 	int ret;
407 
408 	/* Set up for process call */
409 	ret = setup_command(base, I801_PROCESS_CALL, XMIT_WRITE(device));
410 	if (ret < 0)
411 		return ret;
412 
413 	/* cmd will only be send if I2C_EN is zero */
414 	host_outb(base, SMBHSTCMD, cmd);
415 
416 	host_outb(base, SMBHSTDAT0, data & 0x00ff);
417 	host_outb(base, SMBHSTDAT1, (data & 0xff00) >> 8);
418 
419 	/* Start the command */
420 	ret = execute_command(base);
421 	if (ret < 0)
422 		return ret;
423 
424 	/* Poll for transaction completion */
425 	ret = complete_command(base);
426 	if (ret < 0)
427 		return ret;
428 
429 	/* Read results of transaction */
430 	*buf = host_inb(base, SMBHSTDAT0);
431 	*buf |= (host_inb(base, SMBHSTDAT1) << 8);
432 
433 	return ret;
434 }
435 
do_smbus_block_write(uintptr_t base,u8 device,u8 cmd,const size_t bytes,const u8 * buf)436 int do_smbus_block_write(uintptr_t base, u8 device, u8 cmd, const size_t bytes, const u8 *buf)
437 {
438 	int ret;
439 
440 	if (bytes > SMBUS_BLOCK_MAXLEN)
441 		return SMBUS_ERROR;
442 
443 	/* Set up for a block data write. */
444 	ret = setup_command(base, I801_BLOCK_DATA, XMIT_WRITE(device));
445 	if (ret < 0)
446 		return ret;
447 
448 	/* Set the command/address... */
449 	host_outb(base, SMBHSTCMD, cmd);
450 
451 	/* Execute block transaction. */
452 	ret = block_cmd_loop(base, (u8 *)buf, bytes, BLOCK_WRITE);
453 	if (ret < 0)
454 		return ret;
455 
456 	if (ret < bytes)
457 		return SMBUS_ERROR;
458 
459 	return ret;
460 }
461 
462 /* Only since ICH5 */
has_i2c_read_command(void)463 static int has_i2c_read_command(void)
464 {
465 	if (CONFIG(SOUTHBRIDGE_INTEL_I82371EB) ||
466 	    CONFIG(SOUTHBRIDGE_INTEL_I82801DX))
467 		return 0;
468 	return 1;
469 }
470 
do_i2c_eeprom_read(uintptr_t base,u8 device,u8 offset,const size_t bytes,u8 * buf)471 int do_i2c_eeprom_read(uintptr_t base, u8 device, u8 offset, const size_t bytes, u8 *buf)
472 {
473 	int ret;
474 
475 	if (!has_i2c_read_command())
476 		return SMBUS_ERROR;
477 
478 	/* Set up for a i2c block data read.
479 	 *
480 	 * FIXME: Address parameter changes to XMIT_READ(device) with
481 	 * some revision of PCH. Presumably hardware revisions that
482 	 * do not have i2c block write support internally set LSB.
483 	 */
484 	ret = setup_command(base, I801_I2C_BLOCK_DATA,
485 			    XMIT_WRITE(device));
486 	if (ret < 0)
487 		return ret;
488 
489 	/* device offset */
490 	host_outb(base, SMBHSTDAT1, offset);
491 
492 	/* Execute block transaction. */
493 	ret = block_cmd_loop(base, buf, bytes, BLOCK_READ | BLOCK_I2C);
494 	if (ret < 0)
495 		return ret;
496 
497 	/* Post-check we received complete message. */
498 	if (ret < bytes)
499 		return SMBUS_ERROR;
500 
501 	return ret;
502 }
503 
504 /*
505  * The caller is responsible of settings HOSTC I2C_EN bit prior to making this
506  * call!
507  */
do_i2c_block_write(uintptr_t base,u8 device,size_t bytes,u8 * buf)508 int do_i2c_block_write(uintptr_t base, u8 device, size_t bytes, u8 *buf)
509 {
510 	u8 cmd;
511 	int ret;
512 
513 	if (!CONFIG(SOC_INTEL_BRASWELL))
514 		return SMBUS_ERROR;
515 
516 	if (!bytes || (bytes > SMBUS_BLOCK_MAXLEN))
517 		return SMBUS_ERROR;
518 
519 	/* Set up for a block data write. */
520 	ret = setup_command(base, I801_BLOCK_DATA, XMIT_WRITE(device));
521 	if (ret < 0)
522 		return ret;
523 
524 	/*
525 	 * In i2c mode SMBus controller sequence on bus will be:
526 	 * <SMBXINTADD> <SMBHSTDAT1> <SMBBLKDAT> .. <SMBBLKDAT>
527 	 * The SMBHSTCMD must be written also to ensure the SMBUs controller
528 	 * will generate the i2c sequence.
529 	*/
530 	cmd = *buf++;
531 	bytes--;
532 	host_outb(base, SMBHSTCMD, cmd);
533 	host_outb(base, SMBHSTDAT1, cmd);
534 
535 	/* Execute block transaction. */
536 	ret = block_cmd_loop(base, buf, bytes, BLOCK_WRITE);
537 	if (ret < 0)
538 		return ret;
539 
540 	if (ret < bytes)
541 		return SMBUS_ERROR;
542 
543 	ret++; /* 1st byte has been written using SMBHSTDAT1 */
544 	return ret;
545 }
546