aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/scx200_acb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/scx200_acb.c')
-rw-r--r--drivers/i2c/busses/scx200_acb.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 22a3eda04166..eae9e81be375 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -184,21 +184,21 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
184 break; 184 break;
185 185
186 case state_read: 186 case state_read:
187 /* Set ACK if receiving the last byte */ 187 /* Set ACK if _next_ byte will be the last one */
188 if (iface->len == 1) 188 if (iface->len == 2)
189 outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); 189 outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
190 else 190 else
191 outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); 191 outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
192 192
193 *iface->ptr++ = inb(ACBSDA); 193 if (iface->len == 1) {
194 --iface->len;
195
196 if (iface->len == 0) {
197 iface->result = 0; 194 iface->result = 0;
198 iface->state = state_idle; 195 iface->state = state_idle;
199 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); 196 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
200 } 197 }
201 198
199 *iface->ptr++ = inb(ACBSDA);
200 --iface->len;
201
202 break; 202 break;
203 203
204 case state_write: 204 case state_write:
@@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
232 unsigned long timeout; 232 unsigned long timeout;
233 233
234 timeout = jiffies + POLL_TIMEOUT; 234 timeout = jiffies + POLL_TIMEOUT;
235 while (time_before(jiffies, timeout)) { 235 while (1) {
236 status = inb(ACBST); 236 status = inb(ACBST);
237 237
238 /* Reset the status register to avoid the hang */ 238 /* Reset the status register to avoid the hang */
@@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
242 scx200_acb_machine(iface, status); 242 scx200_acb_machine(iface, status);
243 return; 243 return;
244 } 244 }
245 yield(); 245 if (time_after(jiffies, timeout))
246 break;
247 cpu_relax();
248 cond_resched();
246 } 249 }
247 250
248 dev_err(&iface->adapter.dev, "timeout in state %s\n", 251 dev_err(&iface->adapter.dev, "timeout in state %s\n",
@@ -307,8 +310,12 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
307 buffer = (u8 *)&cur_word; 310 buffer = (u8 *)&cur_word;
308 break; 311 break;
309 312
310 case I2C_SMBUS_BLOCK_DATA: 313 case I2C_SMBUS_I2C_BLOCK_DATA:
314 if (rw == I2C_SMBUS_READ)
315 data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
311 len = data->block[0]; 316 len = data->block[0];
317 if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
318 return -EINVAL;
312 buffer = &data->block[1]; 319 buffer = &data->block[1];
313 break; 320 break;
314 321
@@ -372,7 +379,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
372{ 379{
373 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 380 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
374 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 381 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
375 I2C_FUNC_SMBUS_BLOCK_DATA; 382 I2C_FUNC_SMBUS_I2C_BLOCK;
376} 383}
377 384
378/* For now, we only handle combined mode (smbus) */ 385/* For now, we only handle combined mode (smbus) */