lm4 i2c: fixed lm4 i2c_xfer synchronization issue

Added atomic or/clear when modify a share register
LM4_SYSTEM_SRI2C_ADDR among different i2c ports.

BUG=None
BRANCH=ToT
TEST=Verified on Samus.

Signed-off-by: Sheng-Liang Song <ssl@chromium.org>
Change-Id: Ibf64b05a800ce2b8ddf9735bd3a762ab02031bc8
Reviewed-on: https://chromium-review.googlesource.com/213196
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Sheng-Liang Song
2014-08-19 16:24:11 -07:00
committed by chrome-internal-fetch
parent 0535178d29
commit 7467437097
2 changed files with 8 additions and 3 deletions

View File

@@ -5,6 +5,7 @@
/* I2C port module for Chrome EC */
#include "atomic.h"
#include "clock.h"
#include "common.h"
#include "console.h"
@@ -187,7 +188,9 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
(i2c_get_line_levels(port) != I2C_LINE_IDLE))) {
uint32_t tpr = LM4_I2C_MTPR(port);
CPRINTS("I2C%d bad status 0x%02x, SCL=%d, SDA=%d", port,
CPRINTS("I2C%d Addr:%02X bad status 0x%02x, SCL=%d, SDA=%d",
port,
slave_addr,
reg_mcs,
i2c_get_line_levels(port) & I2C_LINE_SCL_HIGH,
i2c_get_line_levels(port) & I2C_LINE_SDA_HIGH);
@@ -196,9 +199,9 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
i2c_unwedge(port);
/* Clock timeout or arbitration lost. Reset port to clear. */
LM4_SYSTEM_SRI2C |= (1 << port);
atomic_or(LM4_SYSTEM_SRI2C_ADDR, (1 << port));
clock_wait_cycles(3);
LM4_SYSTEM_SRI2C &= ~(1 << port);
atomic_clear(LM4_SYSTEM_SRI2C_ADDR, (1 << port));
clock_wait_cycles(3);
/* Restore settings */

View File

@@ -265,6 +265,8 @@ static inline int lm4_fan_addr(int ch, int offset)
#define LM4_SYSTEM_SRI2C REG32(0x400fe520)
#define LM4_SYSTEM_SREEPROM REG32(0x400fe558)
#define LM4_SYSTEM_SRI2C_ADDR ((uint32_t *)0x400fe520)
#define LM4_SYSTEM_RCGC_BASE ((volatile uint32_t *)0x400fe600)
#define LM4_SYSTEM_RCGCGPIO REG32(0x400fe608)
#define LM4_SYSTEM_SCGC_BASE ((volatile uint32_t *)0x400fe700)