|
@@ -495,6 +495,37 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int poll_busy(struct sh_mobile_i2c_data *pd)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 1000; i; i--) {
|
|
|
+ u_int8_t val = iic_rd(pd, ICSR);
|
|
|
+
|
|
|
+ dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
|
|
|
+
|
|
|
+ /* the interrupt handler may wake us up before the
|
|
|
+ * transfer is finished, so poll the hardware
|
|
|
+ * until we're done.
|
|
|
+ */
|
|
|
+ if (!(val & ICSR_BUSY)) {
|
|
|
+ /* handle missing acknowledge and arbitration lost */
|
|
|
+ if ((val | pd->sr) & (ICSR_TACK | ICSR_AL))
|
|
|
+ return -EIO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ udelay(10);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!i) {
|
|
|
+ dev_err(pd->dev, "Polling timed out\n");
|
|
|
+ return -ETIMEDOUT;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
|
|
struct i2c_msg *msgs,
|
|
|
int num)
|
|
@@ -502,8 +533,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
|
|
struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
|
|
|
struct i2c_msg *msg;
|
|
|
int err = 0;
|
|
|
- u_int8_t val;
|
|
|
- int i, k, retry_count;
|
|
|
+ int i, k;
|
|
|
|
|
|
activate_ch(pd);
|
|
|
|
|
@@ -527,31 +557,9 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- retry_count = 1000;
|
|
|
-again:
|
|
|
- val = iic_rd(pd, ICSR);
|
|
|
-
|
|
|
- dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
|
|
|
-
|
|
|
- /* the interrupt handler may wake us up before the
|
|
|
- * transfer is finished, so poll the hardware
|
|
|
- * until we're done.
|
|
|
- */
|
|
|
- if (val & ICSR_BUSY) {
|
|
|
- udelay(10);
|
|
|
- if (retry_count--)
|
|
|
- goto again;
|
|
|
-
|
|
|
- err = -EIO;
|
|
|
- dev_err(pd->dev, "Polling timed out\n");
|
|
|
+ err = poll_busy(pd);
|
|
|
+ if (err < 0)
|
|
|
break;
|
|
|
- }
|
|
|
-
|
|
|
- /* handle missing acknowledge and arbitration lost */
|
|
|
- if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
|
|
|
- err = -EIO;
|
|
|
- break;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
deactivate_ch(pd);
|