Revert "mb/aopen/dxplplusu: Remove board"
[coreboot.git] / src / southbridge / intel / common / smbus.c
blob8b19b7d90003664f82a09f791fc2258bd690405a
1 /* SPDX-License-Identifier: GPL-2.0-only */
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>
9 #if CONFIG(DEBUG_SMBUS)
10 #define dprintk(args...) printk(BIOS_DEBUG, ##args)
11 #else
12 #define dprintk(args...) do {} while (0)
13 #endif
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
29 #define SMB_RCV_SLVA SMBTRNSADD
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 */
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 */
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)
57 /* For SMBXMITADD register. */
58 #define XMIT_WRITE(dev) (((dev) << 1) | 0)
59 #define XMIT_READ(dev) (((dev) << 1) | 1)
61 #define SMBUS_TIMEOUT (10 * 1000 * 100)
62 #define SMBUS_BLOCK_MAXLEN 32
64 /* block_cmd_loop flags */
65 #define BLOCK_READ 0
66 #define BLOCK_WRITE (1 << 0)
67 #define BLOCK_I2C (1 << 1)
69 static void smbus_delay(void)
71 inb(0x80);
74 static void host_outb(uintptr_t base, u8 reg, u8 value)
76 outb(value, base + reg);
79 static u8 host_inb(uintptr_t base, u8 reg)
81 return inb(base + reg);
84 static void host_and_or(uintptr_t base, u8 reg, u8 mask, u8 or)
86 u8 value;
87 value = host_inb(base, reg);
88 value &= mask;
89 value |= or;
90 host_outb(base, reg, value);
93 void smbus_host_reset(uintptr_t base)
95 /* Disable interrupt generation. */
96 host_outb(base, SMBHSTCTL, 0);
98 /* Clear any lingering errors, so transactions can run. */
99 host_and_or(base, SMBHSTSTAT, 0xff, 0);
102 void smbus_set_slave_addr(uintptr_t base, u8 slave_address)
104 host_outb(base, SMB_RCV_SLVA, slave_address);
107 static int host_completed(u8 status)
109 if (status & SMBHSTSTS_HOST_BUSY)
110 return 0;
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;
118 static int recover_master(uintptr_t base, int ret)
120 /* TODO: Depending of the failure, drive KILL transaction
121 * or force soft reset on SMBus master controller.
123 printk(BIOS_ERR, "SMBus: Fatal master timeout (%d)\n", ret);
124 return ret;
127 static int cb_err_from_stat(u8 status)
129 /* These status bits do not imply errors. */
130 status &= ~(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INUSE_STS |
131 SMBHSTSTS_SMBALERT_STS);
133 if (status == SMBHSTSTS_INTR)
134 return 0;
136 return SMBUS_ERROR;
139 static int setup_command(uintptr_t base, u8 ctrl, u8 xmitadd)
141 unsigned int loops = SMBUS_TIMEOUT;
142 u8 host_busy;
144 do {
145 smbus_delay();
146 host_busy = host_inb(base, SMBHSTSTAT) & SMBHSTSTS_HOST_BUSY;
147 } while (--loops && host_busy);
149 if (loops == 0)
150 return recover_master(base, SMBUS_WAIT_UNTIL_READY_TIMEOUT);
152 /* Clear any lingering errors, so the transaction will run. */
153 host_and_or(base, SMBHSTSTAT, 0xff, 0);
155 /* Set up transaction */
156 /* Disable interrupts */
157 host_outb(base, SMBHSTCTL, ctrl);
159 /* Set the device I'm talking to. */
160 host_outb(base, SMBXMITADD, xmitadd);
162 return 0;
165 static int execute_command(uintptr_t base)
167 unsigned int loops = SMBUS_TIMEOUT;
168 u8 status;
170 /* Start the command. */
171 host_and_or(base, SMBHSTCTL, 0xff, SMBHSTCNT_START);
173 /* Poll for it to start. */
174 do {
175 smbus_delay();
177 /* If we poll too slow, we could miss HOST_BUSY flag
178 * set and detect INTR or x_ERR flags instead here.
180 status = host_inb(base, SMBHSTSTAT);
181 status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
182 } while (--loops && status == 0);
184 if (loops == 0)
185 return recover_master(base,
186 SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT);
188 return 0;
191 static int complete_command(uintptr_t base)
193 unsigned int loops = SMBUS_TIMEOUT;
194 u8 status;
196 do {
197 smbus_delay();
198 status = host_inb(base, SMBHSTSTAT);
199 } while (--loops && !host_completed(status));
201 if (loops == 0)
202 return recover_master(base,
203 SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
205 return cb_err_from_stat(status);
208 static int smbus_read_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address)
210 int ret;
211 u16 word;
213 /* Set up for a byte data read. */
214 ret = setup_command(base, ctrl, XMIT_READ(device));
215 if (ret < 0)
216 return ret;
218 /* Set the command/address... */
219 host_outb(base, SMBHSTCMD, address);
221 /* Clear the data bytes... */
222 host_outb(base, SMBHSTDAT0, 0);
223 host_outb(base, SMBHSTDAT1, 0);
225 /* Start the command */
226 ret = execute_command(base);
227 if (ret < 0)
228 return ret;
230 /* Poll for transaction completion */
231 ret = complete_command(base);
232 if (ret < 0)
233 return ret;
235 /* Read results of transaction */
236 word = host_inb(base, SMBHSTDAT0);
237 if (ctrl == I801_WORD_DATA)
238 word |= host_inb(base, SMBHSTDAT1) << 8;
240 return word;
243 static int smbus_write_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address, u16 data)
245 int ret;
247 /* Set up for a byte data write. */
248 ret = setup_command(base, ctrl, XMIT_WRITE(device));
249 if (ret < 0)
250 return ret;
252 /* Set the command/address... */
253 host_outb(base, SMBHSTCMD, address);
255 /* Set the data bytes... */
256 host_outb(base, SMBHSTDAT0, data & 0xff);
257 if (ctrl == I801_WORD_DATA)
258 host_outb(base, SMBHSTDAT1, data >> 8);
260 /* Start the command */
261 ret = execute_command(base);
262 if (ret < 0)
263 return ret;
265 /* Poll for transaction completion */
266 return complete_command(base);
269 static int block_cmd_loop(uintptr_t base, u8 *buf, size_t max_bytes, int flags)
271 u8 status;
272 unsigned int loops = SMBUS_TIMEOUT;
273 int ret;
274 size_t bytes = 0;
275 int is_write_cmd = flags & BLOCK_WRITE;
276 int sw_drives_nak = flags & BLOCK_I2C;
278 /* Hardware limitations. */
279 if (flags == (BLOCK_WRITE | BLOCK_I2C))
280 return SMBUS_ERROR;
282 /* Set number of bytes to transfer. */
283 /* Reset number of bytes to transfer so we notice later it
284 * was really updated with the transaction. */
285 if (!sw_drives_nak) {
286 if (is_write_cmd)
287 host_outb(base, SMBHSTDAT0, max_bytes);
288 else
289 host_outb(base, SMBHSTDAT0, 0);
292 /* Send first byte from buffer, bytes_sent increments after
293 * hardware acknowledges it.
295 if (is_write_cmd)
296 host_outb(base, SMBBLKDAT, *buf++);
298 /* Start the command */
299 ret = execute_command(base);
300 if (ret < 0)
301 return ret;
303 /* Poll for transaction completion */
304 do {
305 status = host_inb(base, SMBHSTSTAT);
307 if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
309 if (is_write_cmd) {
310 bytes++;
311 if (bytes < max_bytes)
312 host_outb(base, SMBBLKDAT, *buf++);
313 } else {
314 if (bytes < max_bytes)
315 *buf++ = host_inb(base, SMBBLKDAT);
316 bytes++;
318 /* Indicate that next byte is the last one. */
319 if (sw_drives_nak && (bytes + 1 >= max_bytes)) {
320 host_and_or(base, SMBHSTCTL, 0xff,
321 SMBHSTCNT_LAST_BYTE);
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.
330 host_outb(base, SMBHSTSTAT, SMBHSTSTS_BYTE_DONE);
333 } while (--loops && !host_completed(status));
335 dprintk("%s: status = %02x, len = %zd / %zd, loops = %d\n",
336 __func__, status, bytes, max_bytes, SMBUS_TIMEOUT - loops);
338 if (loops == 0)
339 return recover_master(base, SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
341 ret = cb_err_from_stat(status);
342 if (ret < 0)
343 return ret;
345 return bytes;
348 int do_smbus_read_byte(uintptr_t base, u8 device, u8 address)
350 return smbus_read_cmd(base, I801_BYTE_DATA, device, address);
353 int do_smbus_read_word(uintptr_t base, u8 device, u8 address)
355 return smbus_read_cmd(base, I801_WORD_DATA, device, address);
358 int do_smbus_write_byte(uintptr_t base, u8 device, u8 address, u8 data)
360 return smbus_write_cmd(base, I801_BYTE_DATA, device, address, data);
363 int do_smbus_write_word(uintptr_t base, u8 device, u8 address, u16 data)
365 return smbus_write_cmd(base, I801_WORD_DATA, device, address, data);
368 int do_smbus_block_read(uintptr_t base, u8 device, u8 cmd, size_t max_bytes, u8 *buf)
370 int ret, slave_bytes;
372 max_bytes = MIN(SMBUS_BLOCK_MAXLEN, max_bytes);
374 /* Set up for a block data read. */
375 ret = setup_command(base, I801_BLOCK_DATA, XMIT_READ(device));
376 if (ret < 0)
377 return ret;
379 /* Set the command/address... */
380 host_outb(base, SMBHSTCMD, cmd);
382 /* Execute block transaction. */
383 ret = block_cmd_loop(base, buf, max_bytes, BLOCK_READ);
384 if (ret < 0)
385 return ret;
387 /* Post-check we received complete message. */
388 slave_bytes = host_inb(base, SMBHSTDAT0);
389 if (ret < slave_bytes)
390 return SMBUS_ERROR;
392 return ret;
396 * The caller is responsible of settings HOSTC I2C_EN bit prior to making this
397 * call!
399 int do_smbus_process_call(uintptr_t base, u8 device, u8 cmd, u16 data, u16 *buf)
401 int ret;
403 /* Set up for process call */
404 ret = setup_command(base, I801_PROCESS_CALL, XMIT_WRITE(device));
405 if (ret < 0)
406 return ret;
408 /* cmd will only be send if I2C_EN is zero */
409 host_outb(base, SMBHSTCMD, cmd);
411 host_outb(base, SMBHSTDAT0, data & 0x00ff);
412 host_outb(base, SMBHSTDAT1, (data & 0xff00) >> 8);
414 /* Start the command */
415 ret = execute_command(base);
416 if (ret < 0)
417 return ret;
419 /* Poll for transaction completion */
420 ret = complete_command(base);
421 if (ret < 0)
422 return ret;
424 /* Read results of transaction */
425 *buf = host_inb(base, SMBHSTDAT0);
426 *buf |= (host_inb(base, SMBHSTDAT1) << 8);
428 return ret;
431 int do_smbus_block_write(uintptr_t base, u8 device, u8 cmd, const size_t bytes, const u8 *buf)
433 int ret;
435 if (bytes > SMBUS_BLOCK_MAXLEN)
436 return SMBUS_ERROR;
438 /* Set up for a block data write. */
439 ret = setup_command(base, I801_BLOCK_DATA, XMIT_WRITE(device));
440 if (ret < 0)
441 return ret;
443 /* Set the command/address... */
444 host_outb(base, SMBHSTCMD, cmd);
446 /* Execute block transaction. */
447 ret = block_cmd_loop(base, (u8 *)buf, bytes, BLOCK_WRITE);
448 if (ret < 0)
449 return ret;
451 if (ret < bytes)
452 return SMBUS_ERROR;
454 return ret;
457 /* Only since ICH5 */
458 static int has_i2c_read_command(void)
460 if (CONFIG(SOUTHBRIDGE_INTEL_I82371EB) ||
461 CONFIG(SOUTHBRIDGE_INTEL_I82801DX))
462 return 0;
463 return 1;
466 int do_i2c_eeprom_read(uintptr_t base, u8 device, u8 offset, const size_t bytes, u8 *buf)
468 int ret;
470 if (!has_i2c_read_command())
471 return SMBUS_ERROR;
473 /* Set up for a i2c block data read.
475 * FIXME: Address parameter changes to XMIT_READ(device) with
476 * some revision of PCH. Presumably hardware revisions that
477 * do not have i2c block write support internally set LSB.
479 ret = setup_command(base, I801_I2C_BLOCK_DATA,
480 XMIT_WRITE(device));
481 if (ret < 0)
482 return ret;
484 /* device offset */
485 host_outb(base, SMBHSTDAT1, offset);
487 /* Execute block transaction. */
488 ret = block_cmd_loop(base, buf, bytes, BLOCK_READ | BLOCK_I2C);
489 if (ret < 0)
490 return ret;
492 /* Post-check we received complete message. */
493 if (ret < bytes)
494 return SMBUS_ERROR;
496 return ret;
500 * The caller is responsible of settings HOSTC I2C_EN bit prior to making this
501 * call!
503 int do_i2c_block_write(uintptr_t base, u8 device, size_t bytes, u8 *buf)
505 u8 cmd;
506 int ret;
508 if (!CONFIG(SOC_INTEL_BRASWELL))
509 return SMBUS_ERROR;
511 if (!bytes || (bytes > SMBUS_BLOCK_MAXLEN))
512 return SMBUS_ERROR;
514 /* Set up for a block data write. */
515 ret = setup_command(base, I801_BLOCK_DATA, XMIT_WRITE(device));
516 if (ret < 0)
517 return ret;
520 * In i2c mode SMBus controller sequence on bus will be:
521 * <SMBXINTADD> <SMBHSTDAT1> <SMBBLKDAT> .. <SMBBLKDAT>
522 * The SMBHSTCMD must be written also to ensure the SMBUs controller
523 * will generate the i2c sequence.
525 cmd = *buf++;
526 bytes--;
527 host_outb(base, SMBHSTCMD, cmd);
528 host_outb(base, SMBHSTDAT1, cmd);
530 /* Execute block transaction. */
531 ret = block_cmd_loop(base, buf, bytes, BLOCK_WRITE);
532 if (ret < 0)
533 return ret;
535 if (ret < bytes)
536 return SMBUS_ERROR;
538 ret++; /* 1st byte has been written using SMBHSTDAT1 */
539 return ret;