diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-sirf.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 0ff22e29e7df..ff47a767f756 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c | |||
@@ -64,6 +64,8 @@ | |||
64 | #define SIRFSOC_I2C_START BIT(7) | 64 | #define SIRFSOC_I2C_START BIT(7) |
65 | 65 | ||
66 | #define SIRFSOC_I2C_DEFAULT_SPEED 100000 | 66 | #define SIRFSOC_I2C_DEFAULT_SPEED 100000 |
67 | #define SIRFSOC_I2C_ERR_NOACK 1 | ||
68 | #define SIRFSOC_I2C_ERR_TIMEOUT 2 | ||
67 | 69 | ||
68 | struct sirfsoc_i2c { | 70 | struct sirfsoc_i2c { |
69 | void __iomem *base; | 71 | void __iomem *base; |
@@ -142,14 +144,24 @@ static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id) | |||
142 | 144 | ||
143 | if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { | 145 | if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { |
144 | /* Error conditions */ | 146 | /* Error conditions */ |
145 | siic->err_status = 1; | 147 | siic->err_status = SIRFSOC_I2C_ERR_NOACK; |
146 | writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); | 148 | writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); |
147 | 149 | ||
148 | if (i2c_stat & SIRFSOC_I2C_STAT_NACK) | 150 | if (i2c_stat & SIRFSOC_I2C_STAT_NACK) |
149 | dev_err(&siic->adapter.dev, "ACK not received\n"); | 151 | dev_dbg(&siic->adapter.dev, "ACK not received\n"); |
150 | else | 152 | else |
151 | dev_err(&siic->adapter.dev, "I2C error\n"); | 153 | dev_err(&siic->adapter.dev, "I2C error\n"); |
152 | 154 | ||
155 | /* | ||
156 | * Due to hardware ANOMALY, we need to reset I2C earlier after | ||
157 | * we get NOACK while accessing non-existing clients, otherwise | ||
158 | * we will get errors even we access existing clients later | ||
159 | */ | ||
160 | writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, | ||
161 | siic->base + SIRFSOC_I2C_CTRL); | ||
162 | while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) | ||
163 | cpu_relax(); | ||
164 | |||
153 | complete(&siic->done); | 165 | complete(&siic->done); |
154 | } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { | 166 | } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { |
155 | /* CMD buffer execution complete */ | 167 | /* CMD buffer execution complete */ |
@@ -190,7 +202,6 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) | |||
190 | u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); | 202 | u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); |
191 | /* timeout waiting for the xfer to finish or fail */ | 203 | /* timeout waiting for the xfer to finish or fail */ |
192 | int timeout = msecs_to_jiffies((msg->len + 1) * 50); | 204 | int timeout = msecs_to_jiffies((msg->len + 1) * 50); |
193 | int ret = 0; | ||
194 | 205 | ||
195 | i2c_sirfsoc_set_address(siic, msg); | 206 | i2c_sirfsoc_set_address(siic, msg); |
196 | 207 | ||
@@ -199,7 +210,7 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) | |||
199 | i2c_sirfsoc_queue_cmd(siic); | 210 | i2c_sirfsoc_queue_cmd(siic); |
200 | 211 | ||
201 | if (wait_for_completion_timeout(&siic->done, timeout) == 0) { | 212 | if (wait_for_completion_timeout(&siic->done, timeout) == 0) { |
202 | siic->err_status = 1; | 213 | siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT; |
203 | dev_err(&siic->adapter.dev, "Transfer timeout\n"); | 214 | dev_err(&siic->adapter.dev, "Transfer timeout\n"); |
204 | } | 215 | } |
205 | 216 | ||
@@ -207,16 +218,14 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) | |||
207 | siic->base + SIRFSOC_I2C_CTRL); | 218 | siic->base + SIRFSOC_I2C_CTRL); |
208 | writel(0, siic->base + SIRFSOC_I2C_CMD_START); | 219 | writel(0, siic->base + SIRFSOC_I2C_CMD_START); |
209 | 220 | ||
210 | if (siic->err_status) { | 221 | /* i2c control doesn't response, reset it */ |
222 | if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) { | ||
211 | writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, | 223 | writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, |
212 | siic->base + SIRFSOC_I2C_CTRL); | 224 | siic->base + SIRFSOC_I2C_CTRL); |
213 | while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) | 225 | while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) |
214 | cpu_relax(); | 226 | cpu_relax(); |
215 | |||
216 | ret = -EIO; | ||
217 | } | 227 | } |
218 | 228 | return siic->err_status ? -EIO : 0; | |
219 | return ret; | ||
220 | } | 229 | } |
221 | 230 | ||
222 | static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) | 231 | static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) |