diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-05-24 12:22:29 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-05-24 12:25:34 -0700 |
commit | b0fe45560828542ec3dd129db7d9cf59e92349d4 (patch) | |
tree | 6cd94842b16dc15546c1f847969cc75ac82f8486 | |
parent | 00360ddc17c5988d5c26a1bfa3dd8cfce08e1d71 (diff) | |
download | chrome-ec-b0fe45560828542ec3dd129db7d9cf59e92349d4.tar.gz |
Fix I2C port frequency calculation
Also fix 'i2cscan' output, and detect/ignore busy ports
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=chrome-os-partner:9928
TEST=manual
1) check i2cscan
i2cscan -> thermal port should report busy
gpioset enable_vs 1
i2cscan -> thermal port should show 4 devices
2) probe EC_SMB_CK[012] signals to verify clock frequency
Change-Id: I52e165de77eb9ed2619d648d84f251152772fe1c
-rw-r--r-- | chip/lm4/i2c.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c index 0d3f2ecf2b..be8b2067f9 100644 --- a/chip/lm4/i2c.c +++ b/chip/lm4/i2c.c @@ -16,6 +16,9 @@ #include "registers.h" #include "util.h" +#define CPUTS(outstr) cputs(CC_I2C, outstr) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) + #define NUM_PORTS 6 /* Number of physical ports */ #define LM4_I2C_MCS_RUN (1 << 0) @@ -266,9 +269,29 @@ static int i2c_freq_changed(void) int freq = clock_get_freq(); int i; - for (i = 0; i < I2C_PORTS_USED; i++) - LM4_I2C_MTPR(i2c_ports[i].port) = - (freq / (i2c_ports[i].kbps * 10 * 2)) - 1; + for (i = 0; i < I2C_PORTS_USED; i++) { + /* From datasheet: + * SCL_PRD = 2 * (1 + TPR) * (SCL_LP + SCL_HP) * CLK_PRD + * + * so: + * TPR = SCL_PRD / (2 * (SCL_LP + SCL_HP) * CLK_PRD) - 1 + * + * converting from period to frequency: + * TPR = CLK_FREQ / (SCL_FREQ * 2 * (SCL_LP + SCL_HP)) - 1 + */ + const int d = 2 * (6 + 4) * (i2c_ports[i].kbps * 1000); + + /* Round TPR up, so desired kbps is an upper bound */ + const int tpr = (freq + d - 1) / d - 1; + +#ifdef PRINT_I2C_SPEEDS + const int f = freq / (2 * (1 + tpr) * (6 + 4)); + CPRINTF("[I2C%d clk=%d tpr=%d freq=%d]\n", + i2c_ports[i].port, freq, tpr, f); +#endif + + LM4_I2C_MTPR(i2c_ports[i].port) = tpr; + } return EC_SUCCESS; } @@ -282,7 +305,7 @@ static void handle_interrupt(int port) { int id = task_waiting_on_port[port]; - /* Clear the interrupt status*/ + /* Clear the interrupt status */ LM4_I2C_MICR(port) = LM4_I2C_MMIS(port); /* Wake up the task which was waiting on the interrupt, if any */ @@ -313,7 +336,16 @@ static void scan_bus(int port, const char *desc) int rv; int a; - ccprintf("Scanning %d %s\n", desc, port); + ccprintf("Scanning %d %s", port, desc); + + /* Don't scan a busy port, since reads will just fail / time out */ + a = LM4_I2C_MBMON(port); + if ((a & 0x03) != 0x03) { + ccprintf(": port busy (SDA=%d, SCL=%d)\n", + (LM4_I2C_MBMON(port) & 0x02) ? 1 : 0, + (LM4_I2C_MBMON(port) & 0x01) ? 1 : 0); + return; + } mutex_lock(port_mutex + port); @@ -325,7 +357,7 @@ static void scan_bus(int port, const char *desc) LM4_I2C_MCS(port) = 0x07; rv = wait_idle(port); if (rv == EC_SUCCESS) - ccprintf("0x%02x\n", a); + ccprintf("\n 0x%02x", a); } mutex_unlock(port_mutex + port); |