From 5764cbbf91cf80c21f7e6b819526ebd074049551 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Thu, 29 Jun 2017 17:29:07 -0700 Subject: 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 Reviewed-on: https://review.coreboot.org/20422 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth Reviewed-by: Sumeet R Pawnikar --- src/soc/intel/quark/Kconfig | 10 ++++++ src/soc/intel/quark/i2c.c | 81 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 7 deletions(-) (limited to 'src/soc/intel/quark') diff --git a/src/soc/intel/quark/Kconfig b/src/soc/intel/quark/Kconfig index bbb1927824..d1950a378a 100644 --- a/src/soc/intel/quark/Kconfig +++ b/src/soc/intel/quark/Kconfig @@ -316,4 +316,14 @@ config STORAGE_LOG 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 3988bbe836..26017389b8 100644 --- a/src/soc/intel/quark/i2c.c +++ b/src/soc/intel/quark/i2c.c @@ -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 | 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 @@ static int platform_i2c_read(uint32_t restart, uint8_t *rx_buffer, int length, 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 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, uint8_t chip; uint32_t cmd; int data_bytes; + int index; int length; I2C_REGS *regs; uint32_t restart; @@ -186,6 +205,23 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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]: %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(); /* 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; 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 +273,7 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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 +283,13 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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 +299,13 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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 +331,29 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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 +363,8 @@ int platform_i2c_transfer(unsigned int bus, struct i2c_seg *segment, 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; } -- cgit v1.2.3