Lee Leahy has uploaded this change for review. ( https://review.coreboot.org/20422
Change subject: soc/intel/quark: Add I2C debugging ......................................................................
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 --- M src/soc/intel/quark/Kconfig M src/soc/intel/quark/i2c.c 2 files changed, 83 insertions(+), 7 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/22/20422/1
diff --git a/src/soc/intel/quark/Kconfig b/src/soc/intel/quark/Kconfig index bbb1927..d1950a3 100644 --- a/src/soc/intel/quark/Kconfig +++ b/src/soc/intel/quark/Kconfig @@ -316,4 +316,14 @@ default n 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 diff --git a/src/soc/intel/quark/i2c.c b/src/soc/intel/quark/i2c.c index 3988bbe..bc4451b 100644 --- a/src/soc/intel/quark/i2c.c +++ b/src/soc/intel/quark/i2c.c @@ -68,12 +68,21 @@ if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER | IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) { 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; }
/* 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; + }
/* Receive any available data */ status = regs->ic_status; @@ -134,12 +143,21 @@ if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER | IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) { 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; }
/* 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; + }
/* Receive any available data */ status = regs->ic_status; @@ -175,6 +193,7 @@ uint8_t chip; uint32_t cmd; int data_bytes; + int index; int length; I2C_REGS *regs; uint32_t restart; @@ -185,6 +204,22 @@ int total_bytes; uint8_t *tx_buffer; 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]:\n", index); + printk(BIOS_ERR, " 0x%08x: read\n", + segment[index].read); + printk(BIOS_ERR, " 0x%08x: chip\n", + segment[index].chip); + printk(BIOS_ERR, " 0x%p: buf\n", segment[index].buf); + printk(BIOS_ERR, " 0x%08x: len\n", segment[index].len); + printk(BIOS_ERR, "I2C %s\n", + (++index >= seg_count) ? "Stop" : "Restart"); + } + }
regs = get_i2c_address();
@@ -228,7 +263,8 @@ bytes_transferred = 0; rx_buffer = NULL; restart = 0; - while (seg_count-- > 0) { + index = 0; + while (index++ < seg_count) { length = segment->len; total_bytes += length; ASSERT(segment->buf != NULL); @@ -236,7 +272,7 @@ ASSERT(segment->chip == chip);
/* 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 */ if (segment->read) { @@ -246,8 +282,13 @@ length, stop, &timeout);
/* 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; + } bytes_transferred += data_bytes; } else { /* Write the data into the FIFO */ @@ -257,8 +298,13 @@ length, stop, rx_buffer, &timeout);
/* 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; + } bytes_transferred += data_bytes; } segment++; @@ -284,12 +330,29 @@ if (status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER | IC_INTR_TX_ABRT | IC_INTR_TX_OVER)) { 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; }
/* 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; + }
/* Delay for a while */ udelay(1); @@ -299,5 +362,8 @@ regs->ic_tar = 0;
/* 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; }