sb/intel/common: Change some local SMBus function signatures
Change-Id: I82be883e08ca58fa454b4ad73d20dde2d40a8e3b Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/38220 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
bd65985a63
commit
5e9ae0c2bc
|
@ -72,17 +72,17 @@ static void smbus_delay(void)
|
||||||
inb(0x80);
|
inb(0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void host_outb(unsigned int base, u8 reg, u8 value)
|
static void host_outb(uintptr_t base, u8 reg, u8 value)
|
||||||
{
|
{
|
||||||
outb(value, base + reg);
|
outb(value, base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 host_inb(unsigned int base, u8 reg)
|
static u8 host_inb(uintptr_t base, u8 reg)
|
||||||
{
|
{
|
||||||
return inb(base + reg);
|
return inb(base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void host_and_or(unsigned int base, u8 reg, u8 mask, u8 or)
|
static void host_and_or(uintptr_t base, u8 reg, u8 mask, u8 or)
|
||||||
{
|
{
|
||||||
u8 value;
|
u8 value;
|
||||||
value = host_inb(base, reg);
|
value = host_inb(base, reg);
|
||||||
|
@ -102,7 +102,7 @@ static int host_completed(u8 status)
|
||||||
return status != 0;
|
return status != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recover_master(int smbus_base, int ret)
|
static int recover_master(uintptr_t base, int ret)
|
||||||
{
|
{
|
||||||
/* TODO: Depending of the failure, drive KILL transaction
|
/* TODO: Depending of the failure, drive KILL transaction
|
||||||
* or force soft reset on SMBus master controller.
|
* or force soft reset on SMBus master controller.
|
||||||
|
@ -123,40 +123,39 @@ static int cb_err_from_stat(u8 status)
|
||||||
return SMBUS_ERROR;
|
return SMBUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_command(unsigned int smbus_base, u8 ctrl, u8 xmitadd)
|
static int setup_command(uintptr_t base, u8 ctrl, u8 xmitadd)
|
||||||
{
|
{
|
||||||
unsigned int loops = SMBUS_TIMEOUT;
|
unsigned int loops = SMBUS_TIMEOUT;
|
||||||
u8 host_busy;
|
u8 host_busy;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
smbus_delay();
|
smbus_delay();
|
||||||
host_busy = host_inb(smbus_base, SMBHSTSTAT) & SMBHSTSTS_HOST_BUSY;
|
host_busy = host_inb(base, SMBHSTSTAT) & SMBHSTSTS_HOST_BUSY;
|
||||||
} while (--loops && host_busy);
|
} while (--loops && host_busy);
|
||||||
|
|
||||||
if (loops == 0)
|
if (loops == 0)
|
||||||
return recover_master(smbus_base,
|
return recover_master(base, SMBUS_WAIT_UNTIL_READY_TIMEOUT);
|
||||||
SMBUS_WAIT_UNTIL_READY_TIMEOUT);
|
|
||||||
|
|
||||||
/* Clear any lingering errors, so the transaction will run. */
|
/* Clear any lingering errors, so the transaction will run. */
|
||||||
host_and_or(smbus_base, SMBHSTSTAT, 0xff, 0);
|
host_and_or(base, SMBHSTSTAT, 0xff, 0);
|
||||||
|
|
||||||
/* Set up transaction */
|
/* Set up transaction */
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
host_outb(smbus_base, SMBHSTCTL, ctrl);
|
host_outb(base, SMBHSTCTL, ctrl);
|
||||||
|
|
||||||
/* Set the device I'm talking to. */
|
/* Set the device I'm talking to. */
|
||||||
host_outb(smbus_base, SMBXMITADD, xmitadd);
|
host_outb(base, SMBXMITADD, xmitadd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int execute_command(unsigned int smbus_base)
|
static int execute_command(uintptr_t base)
|
||||||
{
|
{
|
||||||
unsigned int loops = SMBUS_TIMEOUT;
|
unsigned int loops = SMBUS_TIMEOUT;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
|
||||||
/* Start the command. */
|
/* Start the command. */
|
||||||
host_and_or(smbus_base, SMBHSTCTL, 0xff, SMBHSTCNT_START);
|
host_and_or(base, SMBHSTCTL, 0xff, SMBHSTCNT_START);
|
||||||
|
|
||||||
/* Poll for it to start. */
|
/* Poll for it to start. */
|
||||||
do {
|
do {
|
||||||
|
@ -165,103 +164,101 @@ static int execute_command(unsigned int smbus_base)
|
||||||
/* If we poll too slow, we could miss HOST_BUSY flag
|
/* If we poll too slow, we could miss HOST_BUSY flag
|
||||||
* set and detect INTR or x_ERR flags instead here.
|
* set and detect INTR or x_ERR flags instead here.
|
||||||
*/
|
*/
|
||||||
status = host_inb(smbus_base, SMBHSTSTAT);
|
status = host_inb(base, SMBHSTSTAT);
|
||||||
status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
|
status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
|
||||||
} while (--loops && status == 0);
|
} while (--loops && status == 0);
|
||||||
|
|
||||||
if (loops == 0)
|
if (loops == 0)
|
||||||
return recover_master(smbus_base,
|
return recover_master(base,
|
||||||
SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT);
|
SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int complete_command(unsigned int smbus_base)
|
static int complete_command(uintptr_t base)
|
||||||
{
|
{
|
||||||
unsigned int loops = SMBUS_TIMEOUT;
|
unsigned int loops = SMBUS_TIMEOUT;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
smbus_delay();
|
smbus_delay();
|
||||||
status = host_inb(smbus_base, SMBHSTSTAT);
|
status = host_inb(base, SMBHSTSTAT);
|
||||||
} while (--loops && !host_completed(status));
|
} while (--loops && !host_completed(status));
|
||||||
|
|
||||||
if (loops == 0)
|
if (loops == 0)
|
||||||
return recover_master(smbus_base,
|
return recover_master(base,
|
||||||
SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
|
SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
|
||||||
|
|
||||||
return cb_err_from_stat(status);
|
return cb_err_from_stat(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smbus_read_cmd(unsigned int smbus_base, u8 ctrl, u8 device,
|
static int smbus_read_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address)
|
||||||
unsigned int address)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u16 word;
|
u16 word;
|
||||||
|
|
||||||
/* Set up for a byte data read. */
|
/* Set up for a byte data read. */
|
||||||
ret = setup_command(smbus_base, ctrl, XMIT_READ(device));
|
ret = setup_command(base, ctrl, XMIT_READ(device));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Set the command/address... */
|
/* Set the command/address... */
|
||||||
host_outb(smbus_base, SMBHSTCMD, address);
|
host_outb(base, SMBHSTCMD, address);
|
||||||
|
|
||||||
/* Clear the data bytes... */
|
/* Clear the data bytes... */
|
||||||
host_outb(smbus_base, SMBHSTDAT0, 0);
|
host_outb(base, SMBHSTDAT0, 0);
|
||||||
host_outb(smbus_base, SMBHSTDAT1, 0);
|
host_outb(base, SMBHSTDAT1, 0);
|
||||||
|
|
||||||
/* Start the command */
|
/* Start the command */
|
||||||
ret = execute_command(smbus_base);
|
ret = execute_command(base);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Poll for transaction completion */
|
/* Poll for transaction completion */
|
||||||
ret = complete_command(smbus_base);
|
ret = complete_command(base);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Read results of transaction */
|
/* Read results of transaction */
|
||||||
word = host_inb(smbus_base, SMBHSTDAT0);
|
word = host_inb(base, SMBHSTDAT0);
|
||||||
if (ctrl == I801_WORD_DATA)
|
if (ctrl == I801_WORD_DATA)
|
||||||
word |= host_inb(smbus_base, SMBHSTDAT1) << 8;
|
word |= host_inb(base, SMBHSTDAT1) << 8;
|
||||||
|
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smbus_write_cmd(unsigned int smbus_base, u8 ctrl, u8 device,
|
static int smbus_write_cmd(uintptr_t base, u8 ctrl, u8 device, u8 address, u16 data)
|
||||||
unsigned int address, unsigned int data)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Set up for a byte data write. */
|
/* Set up for a byte data write. */
|
||||||
ret = setup_command(smbus_base, ctrl, XMIT_WRITE(device));
|
ret = setup_command(base, ctrl, XMIT_WRITE(device));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Set the command/address... */
|
/* Set the command/address... */
|
||||||
host_outb(smbus_base, SMBHSTCMD, address);
|
host_outb(base, SMBHSTCMD, address);
|
||||||
|
|
||||||
/* Set the data bytes... */
|
/* Set the data bytes... */
|
||||||
host_outb(smbus_base, SMBHSTDAT0, data & 0xff);
|
host_outb(base, SMBHSTDAT0, data & 0xff);
|
||||||
if (ctrl == I801_WORD_DATA)
|
if (ctrl == I801_WORD_DATA)
|
||||||
host_outb(smbus_base, SMBHSTDAT1, data >> 8);
|
host_outb(base, SMBHSTDAT1, data >> 8);
|
||||||
|
|
||||||
/* Start the command */
|
/* Start the command */
|
||||||
ret = execute_command(smbus_base);
|
ret = execute_command(base);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Poll for transaction completion */
|
/* Poll for transaction completion */
|
||||||
return complete_command(smbus_base);
|
return complete_command(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int block_cmd_loop(unsigned int smbus_base,
|
static int block_cmd_loop(uintptr_t base, u8 *buf, size_t max_bytes, int flags)
|
||||||
u8 *buf, const unsigned int max_bytes, int flags)
|
|
||||||
{
|
{
|
||||||
u8 status;
|
u8 status;
|
||||||
unsigned int loops = SMBUS_TIMEOUT;
|
unsigned int loops = SMBUS_TIMEOUT;
|
||||||
int ret, bytes = 0;
|
int ret;
|
||||||
|
size_t bytes = 0;
|
||||||
int is_write_cmd = flags & BLOCK_WRITE;
|
int is_write_cmd = flags & BLOCK_WRITE;
|
||||||
int sw_drives_nak = flags & BLOCK_I2C;
|
int sw_drives_nak = flags & BLOCK_I2C;
|
||||||
|
|
||||||
|
@ -274,41 +271,41 @@ static int block_cmd_loop(unsigned int smbus_base,
|
||||||
* was really updated with the transaction. */
|
* was really updated with the transaction. */
|
||||||
if (!sw_drives_nak) {
|
if (!sw_drives_nak) {
|
||||||
if (is_write_cmd)
|
if (is_write_cmd)
|
||||||
host_outb(smbus_base, SMBHSTDAT0, max_bytes);
|
host_outb(base, SMBHSTDAT0, max_bytes);
|
||||||
else
|
else
|
||||||
host_outb(smbus_base, SMBHSTDAT0, 0);
|
host_outb(base, SMBHSTDAT0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send first byte from buffer, bytes_sent increments after
|
/* Send first byte from buffer, bytes_sent increments after
|
||||||
* hardware acknowledges it.
|
* hardware acknowledges it.
|
||||||
*/
|
*/
|
||||||
if (is_write_cmd)
|
if (is_write_cmd)
|
||||||
host_outb(smbus_base, SMBBLKDAT, *buf++);
|
host_outb(base, SMBBLKDAT, *buf++);
|
||||||
|
|
||||||
/* Start the command */
|
/* Start the command */
|
||||||
ret = execute_command(smbus_base);
|
ret = execute_command(base);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Poll for transaction completion */
|
/* Poll for transaction completion */
|
||||||
do {
|
do {
|
||||||
status = host_inb(smbus_base, SMBHSTSTAT);
|
status = host_inb(base, SMBHSTSTAT);
|
||||||
|
|
||||||
if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
|
if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
|
||||||
|
|
||||||
if (is_write_cmd) {
|
if (is_write_cmd) {
|
||||||
bytes++;
|
bytes++;
|
||||||
if (bytes < max_bytes)
|
if (bytes < max_bytes)
|
||||||
host_outb(smbus_base, SMBBLKDAT, *buf++);
|
host_outb(base, SMBBLKDAT, *buf++);
|
||||||
} else {
|
} else {
|
||||||
if (bytes < max_bytes)
|
if (bytes < max_bytes)
|
||||||
*buf++ = host_inb(smbus_base, SMBBLKDAT);
|
*buf++ = host_inb(base, SMBBLKDAT);
|
||||||
bytes++;
|
bytes++;
|
||||||
|
|
||||||
/* Indicate that next byte is the last one. */
|
/* Indicate that next byte is the last one. */
|
||||||
if (sw_drives_nak && (bytes + 1 >= max_bytes)) {
|
if (sw_drives_nak && (bytes + 1 >= max_bytes)) {
|
||||||
host_and_or(smbus_base, SMBHSTCTL,
|
host_and_or(base, SMBHSTCTL, 0xff,
|
||||||
0xff, SMBHSTCNT_LAST_BYTE);
|
SMBHSTCNT_LAST_BYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -317,17 +314,16 @@ static int block_cmd_loop(unsigned int smbus_base,
|
||||||
* and clears HOST_BUSY flag once the byte count
|
* and clears HOST_BUSY flag once the byte count
|
||||||
* has been reached or LAST_BYTE was set.
|
* has been reached or LAST_BYTE was set.
|
||||||
*/
|
*/
|
||||||
host_outb(smbus_base, SMBHSTSTAT, SMBHSTSTS_BYTE_DONE);
|
host_outb(base, SMBHSTSTAT, SMBHSTSTS_BYTE_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (--loops && !host_completed(status));
|
} while (--loops && !host_completed(status));
|
||||||
|
|
||||||
dprintk("%s: status = %02x, len = %d / %d, loops = %d\n",
|
dprintk("%s: status = %02x, len = %zd / %zd, loops = %d\n",
|
||||||
__func__, status, bytes, max_bytes, SMBUS_TIMEOUT - loops);
|
__func__, status, bytes, max_bytes, SMBUS_TIMEOUT - loops);
|
||||||
|
|
||||||
if (loops == 0)
|
if (loops == 0)
|
||||||
return recover_master(smbus_base,
|
return recover_master(base, SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
|
||||||
SMBUS_WAIT_UNTIL_DONE_TIMEOUT);
|
|
||||||
|
|
||||||
ret = cb_err_from_stat(status);
|
ret = cb_err_from_stat(status);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
Loading…
Reference in New Issue