soc/intel/quark: Add I2C debugging
Add I2C debugging support: * Add I2C_DEBUG Kconfig value to enable debugging * Display I2C segments before the transfer * Display errors that occur during the transfer * Display the number of bytes transferred for successful transfers TEST=Build and run on Galileo Gen2 Change-Id: Ia17be8b4213b13fd6c6a367d081414d0f21fbb0f Signed-off-by: Lee Leahy <Leroy.P.Leahy@intel.com> Reviewed-on: https://review.coreboot.org/20422 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com> Reviewed-by: Sumeet R Pawnikar <sumeet.r.pawnikar@intel.com>
This commit is contained in:
parent
12bed18951
commit
5764cbbf91
|
@ -316,4 +316,14 @@ config STORAGE_LOG
|
||||||
default n
|
default n
|
||||||
depends on STORAGE_TEST
|
depends on STORAGE_TEST
|
||||||
|
|
||||||
|
#####
|
||||||
|
# I2C debug support
|
||||||
|
#####
|
||||||
|
|
||||||
|
config I2C_DEBUG
|
||||||
|
bool "Enable I2C debugging"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Display the I2C segments and controller errors
|
||||||
|
|
||||||
endif # SOC_INTEL_QUARK
|
endif # SOC_INTEL_QUARK
|
||||||
|
|
|
@ -68,12 +68,21 @@ static int platform_i2c_write(uint32_t restart, uint8_t *tx_buffer, int length,
|
||||||
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
||||||
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
||||||
i2c_disable(regs);
|
i2c_disable(regs);
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C write error!\n",
|
||||||
|
status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for timeout */
|
/* Check for timeout */
|
||||||
if (stopwatch_expired(timeout))
|
if (stopwatch_expired(timeout)) {
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C write timeout!\n",
|
||||||
|
status);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Receive any available data */
|
/* Receive any available data */
|
||||||
status = regs->ic_status;
|
status = regs->ic_status;
|
||||||
|
@ -134,12 +143,21 @@ static int platform_i2c_read(uint32_t restart, uint8_t *rx_buffer, int length,
|
||||||
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
||||||
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
||||||
i2c_disable(regs);
|
i2c_disable(regs);
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C read error!\n",
|
||||||
|
status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for timeout */
|
/* Check for timeout */
|
||||||
if (stopwatch_expired(timeout))
|
if (stopwatch_expired(timeout)) {
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C read timeout!\n",
|
||||||
|
status);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Receive any available data */
|
/* Receive any available data */
|
||||||
status = regs->ic_status;
|
status = regs->ic_status;
|
||||||
|
@ -175,6 +193,7 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
uint8_t chip;
|
uint8_t chip;
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
int data_bytes;
|
int data_bytes;
|
||||||
|
int index;
|
||||||
int length;
|
int length;
|
||||||
I2C_REGS *regs;
|
I2C_REGS *regs;
|
||||||
uint32_t restart;
|
uint32_t restart;
|
||||||
|
@ -186,6 +205,23 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
uint8_t *tx_buffer;
|
uint8_t *tx_buffer;
|
||||||
int tx_bytes;
|
int tx_bytes;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG)) {
|
||||||
|
for (index = 0; index < seg_count;) {
|
||||||
|
if (index == 0)
|
||||||
|
printk(BIOS_ERR, "I2C Start\n");
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"I2C segment[%d]: %s 0x%02x %s 0x%p, 0x%08x bytes\n",
|
||||||
|
index,
|
||||||
|
segment[index].read ? "Read from" : "Write to",
|
||||||
|
segment[index].chip,
|
||||||
|
segment[index].read ? "to " : "from",
|
||||||
|
segment[index].buf,
|
||||||
|
segment[index].len);
|
||||||
|
printk(BIOS_ERR, "I2C %s\n",
|
||||||
|
(++index >= seg_count) ? "Stop" : "Restart");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
regs = get_i2c_address();
|
regs = get_i2c_address();
|
||||||
|
|
||||||
/* Disable the I2C controller to get access to the registers */
|
/* Disable the I2C controller to get access to the registers */
|
||||||
|
@ -228,7 +264,8 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
bytes_transferred = 0;
|
bytes_transferred = 0;
|
||||||
rx_buffer = NULL;
|
rx_buffer = NULL;
|
||||||
restart = 0;
|
restart = 0;
|
||||||
while (seg_count-- > 0) {
|
index = 0;
|
||||||
|
while (index++ < seg_count) {
|
||||||
length = segment->len;
|
length = segment->len;
|
||||||
total_bytes += length;
|
total_bytes += length;
|
||||||
ASSERT(segment->buf != NULL);
|
ASSERT(segment->buf != NULL);
|
||||||
|
@ -236,7 +273,7 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
ASSERT(segment->chip == chip);
|
ASSERT(segment->chip == chip);
|
||||||
|
|
||||||
/* Determine if this is the last segment of the transaction */
|
/* Determine if this is the last segment of the transaction */
|
||||||
stop = (seg_count == 0) ? IC_DATA_CMD_STOP : 0;
|
stop = (index == seg_count) ? IC_DATA_CMD_STOP : 0;
|
||||||
|
|
||||||
/* Fill the FIFO with the necessary command bytes */
|
/* Fill the FIFO with the necessary command bytes */
|
||||||
if (segment->read) {
|
if (segment->read) {
|
||||||
|
@ -246,8 +283,13 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
length, stop, &timeout);
|
length, stop, &timeout);
|
||||||
|
|
||||||
/* Return any detected error */
|
/* Return any detected error */
|
||||||
if (data_bytes < 0)
|
if (data_bytes < 0) {
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"I2C segment[%d] failed\n",
|
||||||
|
index);
|
||||||
return data_bytes;
|
return data_bytes;
|
||||||
|
}
|
||||||
bytes_transferred += data_bytes;
|
bytes_transferred += data_bytes;
|
||||||
} else {
|
} else {
|
||||||
/* Write the data into the FIFO */
|
/* Write the data into the FIFO */
|
||||||
|
@ -257,8 +299,13 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
length, stop, rx_buffer, &timeout);
|
length, stop, rx_buffer, &timeout);
|
||||||
|
|
||||||
/* Return any detected error */
|
/* Return any detected error */
|
||||||
if (data_bytes < 0)
|
if (data_bytes < 0) {
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"I2C segment[%d] failed\n",
|
||||||
|
index);
|
||||||
return data_bytes;
|
return data_bytes;
|
||||||
|
}
|
||||||
bytes_transferred += data_bytes;
|
bytes_transferred += data_bytes;
|
||||||
}
|
}
|
||||||
segment++;
|
segment++;
|
||||||
|
@ -284,12 +331,29 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
|
||||||
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
| IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) {
|
||||||
i2c_disable(regs);
|
i2c_disable(regs);
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG)) {
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C read error!\n",
|
||||||
|
status);
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"I2C segment[%d] failed\n",
|
||||||
|
seg_count - 1);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for timeout */
|
/* Check for timeout */
|
||||||
if (stopwatch_expired(&timeout))
|
if (stopwatch_expired(&timeout)) {
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG)) {
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"0x%08x: ic_raw_intr_stat, I2C read timeout!\n",
|
||||||
|
status);
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"I2C segment[%d] failed\n",
|
||||||
|
seg_count - 1);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Delay for a while */
|
/* Delay for a while */
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
@ -299,5 +363,8 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment,
|
||||||
regs->ic_tar = 0;
|
regs->ic_tar = 0;
|
||||||
|
|
||||||
/* Return the number of bytes transferred */
|
/* Return the number of bytes transferred */
|
||||||
|
if (IS_ENABLED(CONFIG_I2C_DEBUG))
|
||||||
|
printk(BIOS_ERR, "0x%08x: bytes transferred\n",
|
||||||
|
bytes_transferred);
|
||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue