sb/intel/i82801gx: Add i2c_block_read to smbus.h
Using i2c_block_read speeds up reading SPD four to fivefold compared to sequential byte read. TESTED on Intel D945GCLF. Change-Id: I6d768a2ba128329168f26445a4fca6921c0c8642 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/18927 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph <siro@das-labor.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
parent
4f4410dcbc
commit
2a7c519c89
|
@ -54,3 +54,55 @@ int smbus_read_byte(unsigned int device, unsigned int address)
|
|||
{
|
||||
return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
|
||||
}
|
||||
|
||||
int i2c_block_read(unsigned int device, unsigned int offset, u32 bytes, u8 *buf)
|
||||
{
|
||||
u8 status;
|
||||
int bytes_read = 0;
|
||||
if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0)
|
||||
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
|
||||
|
||||
/* Setup transaction */
|
||||
/* Disable interrupts */
|
||||
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
|
||||
/* Set the device I'm talking to */
|
||||
outb((device & 0x7f) << 1, SMBUS_IO_BASE + SMBXMITADD);
|
||||
|
||||
/* SPD offset */
|
||||
outb(offset, SMBUS_IO_BASE + SMBHSTDAT1);
|
||||
|
||||
/* Set up for a i2c block data read */
|
||||
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xc3) | (0x6 << 2),
|
||||
(SMBUS_IO_BASE + SMBHSTCTL));
|
||||
|
||||
/* Clear any lingering errors, so the transaction will run */
|
||||
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
/* Start the command */
|
||||
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
|
||||
SMBUS_IO_BASE + SMBHSTCTL);
|
||||
|
||||
while (!(inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1))
|
||||
;
|
||||
/* Poll for transaction completion */
|
||||
do {
|
||||
status = inb(SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
if (status & ((1 << 4) | /* FAILED */
|
||||
(1 << 3) | /* BUS ERR */
|
||||
(1 << 2))) /* DEV ERR */
|
||||
return SMBUS_ERROR;
|
||||
|
||||
if (status & 0x80) { /* Byte done */
|
||||
*buf = inb(SMBUS_IO_BASE + SMBBLKDAT);
|
||||
buf++;
|
||||
bytes_read++;
|
||||
if (--bytes == 1) {
|
||||
/* indicate that next byte is the last one */
|
||||
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x20,
|
||||
SMBUS_IO_BASE + SMBHSTCTL);
|
||||
}
|
||||
outb(status, SMBUS_IO_BASE + SMBHSTSTAT);
|
||||
}
|
||||
} while (status & 0x01);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ void gpi_route_interrupt(u8 gpi, u8 mode);
|
|||
#else
|
||||
void enable_smbus(void);
|
||||
int smbus_read_byte(unsigned int device, unsigned int address);
|
||||
int i2c_block_read(unsigned int device, unsigned int cmd, unsigned int bytes,
|
||||
u8 *buf);
|
||||
int southbridge_detect_s3_resume(void);
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue