Sonic,
Did you test these changes?
i2c-bfin-twi i2c-bfin-twi.0: Blackfin BF5xx on-chip I2C TWI Contoller,
regs_b...@ffc00700
schedule_timeout: wrong timeout value fffedda6
Hardware Trace:
0 Target : <0x00004c50> { __etext + 0xffe50890 }
IIRC:
Timeout is in jiffies but not jiffies + timeout.
Index: drivers/i2c/busses/i2c-bfin-twi.c
===================================================================
--- drivers/i2c/busses/i2c-bfin-twi.c (revision 6714)
+++ drivers/i2c/busses/i2c-bfin-twi.c (working copy)
@@ -335,7 +335,7 @@
while (!iface->result) {
if (!wait_for_completion_timeout(&iface->complete,
- jiffies + adap->timeout*HZ))
+ adap->timeout*HZ))
iface->result = -1;
}
@@ -551,7 +551,7 @@
while (!iface->result) {
if (!wait_for_completion_timeout(&iface->complete,
- jiffies + adap->timeout*HZ))
+ adap->timeout*HZ))
iface->result = -1;
}
With this being fixed - the kernel boots without an error messages.
However the ADXL34x driver doesn't work at all now.
-Michael
________________________________________
From: [email protected]
[mailto:[email protected]] On Behalf Of
[email protected]
Sent: Thursday, June 11, 2009 11:30 AM
To: [email protected]
Subject: [Linux-kernel-commits] [6649]
trunk/drivers/i2c/busses/i2c-bfin-twi.c: More replace timeout timer with
wait_for_completion_timeout
Revision
6649
Author
sonicz
Date
2009-06-11 04:29:59 -0500 (Thu, 11 Jun 2009)
Log Message
More replace timeout timer with wait_for_completion_timeout
1. retry i2c transfer according to user defined parameter retires in
struct i2c_adapter.
2. wait timeout based on user defined parameter timeout in struct
i2c_adapter.
3. wake up i2c transfer process in each twi interrupt.
Modified Paths
* trunk/drivers/i2c/busses/i2c-bfin-twi.c
Diff
Modified: trunk/drivers/i2c/busses/i2c-bfin-twi.c (6648 => 6649)
--- trunk/drivers/i2c/busses/i2c-bfin-twi.c 2009-06-11 09:26:47 UTC
(rev 6648)
+++ trunk/drivers/i2c/busses/i2c-bfin-twi.c 2009-06-11 09:29:59 UTC
(rev 6649)
@@ -23,8 +23,6 @@
#include <asm/portmux.h>
#include <asm/irq.h>
-#define POLL_TIMEOUT (20 * HZ)
-
/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 1
#define TWI_I2C_MODE_STANDARDSUB 2
@@ -165,16 +163,13 @@
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
- /* If it is a quick transfer, only address bug
no data,
+ /* If it is a quick transfer, only address
without data,
* not an err, return 1.
+ * If address is acknowledged return 1.
*/
- if (iface->writeNum == 0 && (mast_stat &
BUFRDERR))
+ if ((iface->writeNum == 0 && (mast_stat &
BUFRDERR))
+ || !(mast_stat & ANAK))
iface->result = 1;
- /* If address not acknowledged return -1,
- * else return 0.
- */
- else if (!(mast_stat & ANAK))
- iface->result = 0;
}
complete(&iface->complete);
return;
@@ -246,9 +241,9 @@
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
- complete(&iface->complete);
}
}
+ complete(&iface->complete);
}
/* Interrupt handler */
@@ -264,9 +259,9 @@
}
/*
- * Generic i2c master transfer entrypoint
+ * One i2c master transfer
*/
-static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
struct bfin_twi_iface *iface = adap->algo_data;
@@ -338,23 +333,41 @@
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
SSYNC();
- if (!wait_for_completion_timeout(&iface->complete,
- jiffies + POLL_TIMEOUT))
- iface->result = -1;
+ while (!iface->result) {
+ if (!wait_for_completion_timeout(&iface->complete,
+ jiffies + adap->timeout*HZ))
+ iface->result = -1;
+ }
- rc = iface->result;
+ if (iface->result == 1)
+ rc = iface->cur_msg + 1;
+ else
+ rc = iface->result;
- if (rc == 1)
- return num;
- else
- return rc;
+ return rc;
}
/*
- * SMBus type transfer entrypoint
+ * Generic i2c master transfer entrypoint
*/
+static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ int i, ret = 0;
-int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ for (i = 0; i < adap->retries; i++) {
+ ret = bfin_twi_do_master_xfer(adap, msgs, num);
+ if (ret > 0)
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * One I2C SMBus transfer
+ */
+int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data
*data)
{
@@ -536,9 +549,11 @@
}
SSYNC();
- if (!wait_for_completion_timeout(&iface->complete,
- jiffies + POLL_TIMEOUT))
- iface->result = -1;
+ while (!iface->result) {
+ if (!wait_for_completion_timeout(&iface->complete,
+ jiffies + adap->timeout*HZ))
+ iface->result = -1;
+ }
rc = (iface->result >= 0) ? 0 : -1;
@@ -546,6 +561,25 @@
}
/*
+ * Generic I2C SMBus transfer entrypoint
+ */
+int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data
*data)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < adap->retries; i++) {
+ ret = bfin_twi_do_smbus_xfer(adap, addr, flags,
+ read_write, command, size, data);
+ if (ret == 0)
+ break;
+ }
+
+ return ret;
+}
+
+/*
* Return what the adapter supports
*/
static u32 bfin_twi_functionality(struct i2c_adapter *adap)
@@ -643,6 +677,8 @@
p_adap->algo_data = iface;
p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
p_adap->dev.parent = &pdev->dev;
+ p_adap->timeout = 1;
+ p_adap->retries = 3;
rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
if (rc) {
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits