* [PATCH v2 0/6] i2c: add bus recovery infrastructure
@ 2015-07-30 14:52 Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 1/6] " Jan Luebbe
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
This series ports the kernel's i2c bus recovery support to barebox.
Bus recovery is necessary when a slave device pulls the SDA line low because it
is in a wrong state. The fix is to toggle the SCL line, which move the slaves
into the idle state. Using the same structure and callbacks as the kernel makes
it easy to port the per-driver code to barebox.
Changes from v1:
- Let the driver configure the function pointers to avoid linking in
i2c_generic_gpio_recovery when it is not actually needed.
- Add recovery support to i2c-gpio.
Jan Luebbe (6):
i2c: add bus recovery infrastructure
i2c-omap: clear ARDY twice
i2c-omap: add bus recovery support
i2c: algo-bit: fix debug code
i2c: algo-bit: check if the bus is busy
i2c: gpio: add bus recovery support
drivers/i2c/algos/i2c-algo-bit.c | 44 ++++++++++---
drivers/i2c/busses/i2c-gpio.c | 10 +++
drivers/i2c/busses/i2c-omap.c | 88 +++++++++++++++++++++++++-
drivers/i2c/i2c.c | 130 +++++++++++++++++++++++++++++++++++++++
include/i2c/i2c.h | 45 ++++++++++++++
5 files changed, 307 insertions(+), 10 deletions(-)
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/6] i2c: add bus recovery infrastructure
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 2/6] i2c-omap: clear ARDY twice Jan Luebbe
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
This is based on the code introduced to the kernel in
5f9296ba21b3c395e53dd84e7ff9578f97f24295.
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/i2c.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/i2c/i2c.h | 45 +++++++++++++++++++
2 files changed, 175 insertions(+)
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index ebc7e23..73bbddb 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -23,6 +23,7 @@
#include <xfuncs.h>
#include <init.h>
#include <of.h>
+#include <gpio.h>
#include <i2c/i2c.h>
@@ -228,6 +229,135 @@ int i2c_write_reg(struct i2c_client *client, u32 addr, const u8 *buf, u16 count)
}
EXPORT_SYMBOL(i2c_write_reg);
+/* i2c bus recovery routines */
+int i2c_get_scl_gpio_value(struct i2c_adapter *adap)
+{
+ gpio_direction_input(adap->bus_recovery_info->scl_gpio);
+ return gpio_get_value(adap->bus_recovery_info->scl_gpio);
+}
+
+void i2c_set_scl_gpio_value(struct i2c_adapter *adap, int val)
+{
+ if (val)
+ gpio_direction_input(adap->bus_recovery_info->scl_gpio);
+ else
+ gpio_direction_output(adap->bus_recovery_info->scl_gpio, 0);
+}
+
+int i2c_get_sda_gpio_value(struct i2c_adapter *adap)
+{
+ return gpio_get_value(adap->bus_recovery_info->sda_gpio);
+}
+
+static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap)
+{
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+ struct device_d *dev = &adap->dev;
+ int ret = 0;
+
+ ret = gpio_request_one(bri->scl_gpio, GPIOF_IN, "i2c-scl");
+ if (ret) {
+ dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio);
+ return ret;
+ }
+
+ if (bri->get_sda) {
+ if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) {
+ /* work without SDA polling */
+ dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n",
+ bri->sda_gpio);
+ bri->get_sda = NULL;
+ }
+ }
+
+ return ret;
+}
+
+static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap)
+{
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+
+ if (bri->get_sda)
+ gpio_free(bri->sda_gpio);
+
+ gpio_free(bri->scl_gpio);
+}
+
+/*
+ * We are generating clock pulses. ndelay() determines durating of clk pulses.
+ * We will generate clock with rate 100 KHz and so duration of both clock levels
+ * is: delay in ns = (10^6 / 100) / 2
+ */
+#define RECOVERY_NDELAY 5000
+#define RECOVERY_CLK_CNT 9
+
+static int i2c_generic_recovery(struct i2c_adapter *adap)
+{
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+ int i = 0, val = 1, ret = 0;
+
+ if (bri->prepare_recovery)
+ bri->prepare_recovery(adap);
+
+ bri->set_scl(adap, val);
+ ndelay(RECOVERY_NDELAY);
+
+ /*
+ * By this time SCL is high, as we need to give 9 falling-rising edges
+ */
+ while (i++ < RECOVERY_CLK_CNT * 2) {
+ if (val) {
+ /* Break if SDA is high */
+ if (bri->get_sda && bri->get_sda(adap))
+ break;
+ /* SCL shouldn't be low here */
+ if (!bri->get_scl(adap)) {
+ dev_err(&adap->dev,
+ "SCL is stuck low, exit recovery\n");
+ ret = -EBUSY;
+ break;
+ }
+ }
+
+ val = !val;
+ bri->set_scl(adap, val);
+ ndelay(RECOVERY_NDELAY);
+ }
+
+ if (bri->unprepare_recovery)
+ bri->unprepare_recovery(adap);
+
+ return ret;
+}
+
+int i2c_generic_scl_recovery(struct i2c_adapter *adap)
+{
+ return i2c_generic_recovery(adap);
+}
+
+int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
+{
+ int ret;
+
+ ret = i2c_get_gpios_for_recovery(adap);
+ if (ret)
+ return ret;
+
+ ret = i2c_generic_recovery(adap);
+ i2c_put_gpios_for_recovery(adap);
+
+ return ret;
+}
+
+int i2c_recover_bus(struct i2c_adapter *adap)
+{
+ if (!adap->bus_recovery_info)
+ return -EOPNOTSUPP;
+
+ dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
+ return adap->bus_recovery_info->recover_bus(adap);
+}
+
/**
* i2c_new_device - instantiate one new I2C device
*
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 4696f43..12e4827 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -19,6 +19,8 @@
#include <driver.h>
#include <linux/types.h>
+struct i2c_adapter;
+
/*
* struct i2c_platform_data - structure of platform data for MXC I2C driver
* @param bitrate Bus speed measured in Hz
@@ -61,6 +63,47 @@ struct i2c_msg {
__u16 len; /**< Number of data bytes in @buf being read from or written to the I2C slave address. */
};
+/**
+ * struct i2c_bus_recovery_info - I2C bus recovery information
+ * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or
+ * i2c_generic_scl_recovery() or i2c_generic_gpio_recovery().
+ * @get_scl: This gets current value of SCL line. Mandatory for generic SCL
+ * recovery. Used internally for generic GPIO recovery.
+ * @set_scl: This sets/clears SCL line. Mandatory for generic SCL recovery. Used
+ * internally for generic GPIO recovery.
+ * @get_sda: This gets current value of SDA line. Optional for generic SCL
+ * recovery. Used internally, if sda_gpio is a valid GPIO, for generic GPIO
+ * recovery.
+ * @prepare_recovery: This will be called before starting recovery. Platform may
+ * configure padmux here for SDA/SCL line or something else they want.
+ * @unprepare_recovery: This will be called after completing recovery. Platform
+ * may configure padmux here for SDA/SCL line or something else they want.
+ * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery.
+ * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery.
+ */
+struct i2c_bus_recovery_info {
+ int (*recover_bus)(struct i2c_adapter *);
+
+ int (*get_scl)(struct i2c_adapter *);
+ void (*set_scl)(struct i2c_adapter *, int val);
+ int (*get_sda)(struct i2c_adapter *);
+
+ void (*prepare_recovery)(struct i2c_adapter *);
+ void (*unprepare_recovery)(struct i2c_adapter *);
+
+ /* gpio recovery */
+ int scl_gpio;
+ int sda_gpio;
+};
+
+int i2c_recover_bus(struct i2c_adapter *adap);
+
+/* Generic recovery routines */
+int i2c_get_scl_gpio_value(struct i2c_adapter *adap);
+void i2c_set_scl_gpio_value(struct i2c_adapter *adap, int val);
+int i2c_get_sda_gpio_value(struct i2c_adapter *adap);
+int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
+int i2c_generic_scl_recovery(struct i2c_adapter *adap);
/**
* i2c_adapter is the structure used to identify a physical i2c bus
@@ -74,6 +117,8 @@ struct i2c_adapter {
struct list_head list;
int retries;
void *algo_data;
+
+ struct i2c_bus_recovery_info *bus_recovery_info;
};
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/6] i2c-omap: clear ARDY twice
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 1/6] " Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 3/6] i2c-omap: add bus recovery support Jan Luebbe
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
This implements the fix from the kernel commit
4cdbf7d346e7461c3b93a26707c852e2c9db3753.
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/busses/i2c-omap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 330db98..58d2ec9 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -673,6 +673,10 @@ omap_i2c_isr(struct omap_i2c_struct *dev)
/*
* ProDB0017052: Clear ARDY bit twice
*/
+ if (stat & OMAP_I2C_STAT_ARDY)
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ARDY);
+
+
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
OMAP_I2C_STAT_AL)) {
omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/6] i2c-omap: add bus recovery support
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 1/6] " Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 2/6] i2c-omap: clear ARDY twice Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 4/6] i2c: algo-bit: fix debug code Jan Luebbe
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
This is based on commit 9dcb0e7b999db6c420c70fd32497a979a044fcdf from
the kernel with some additional fixes.
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/busses/i2c-omap.c | 84 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 81 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 58d2ec9..48c55da 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -107,16 +107,20 @@
#define OMAP_I2C_SCLH_HSSCLH 8
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
-#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
#define OMAP_I2C_SYSTEST_FREE (1 << 14) /* Free running mode */
#define OMAP_I2C_SYSTEST_TMODE_MASK (3 << 12) /* Test mode select */
#define OMAP_I2C_SYSTEST_TMODE_SHIFT (12) /* Test mode select */
+/* Functional mode */
+#define OMAP_I2C_SYSTEST_SCL_I_FUNC (1 << 8) /* SCL line input value */
+#define OMAP_I2C_SYSTEST_SCL_O_FUNC (1 << 7) /* SCL line output value */
+#define OMAP_I2C_SYSTEST_SDA_I_FUNC (1 << 6) /* SDA line input value */
+#define OMAP_I2C_SYSTEST_SDA_O_FUNC (1 << 5) /* SDA line output value */
+/* SDA/SCL IO mode */
#define OMAP_I2C_SYSTEST_SCL_I (1 << 3) /* SCL line sense in */
#define OMAP_I2C_SYSTEST_SCL_O (1 << 2) /* SCL line drive out */
#define OMAP_I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense in */
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
-#endif
/* OCP_SYSSTATUS bit definitions */
#define SYSS_RESETDONE_MASK (1 << 0)
@@ -492,7 +496,7 @@ static int omap_i2c_wait_for_bb(struct i2c_adapter *adapter)
while (omap_i2c_read_reg(i2c_omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (is_timeout(start, MSECOND)) {
dev_warn(&adapter->dev, "timeout waiting for bus ready\n");
- return -ETIMEDOUT;
+ return i2c_recover_bus(adapter);
}
}
@@ -990,6 +994,79 @@ out:
#define OMAP_I2C_SCHEME_0 0
#define OMAP_I2C_SCHEME_1 1
+static int omap_i2c_get_scl(struct i2c_adapter *adapter)
+{
+ struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter);
+ u32 reg;
+
+ reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG);
+
+ return reg & OMAP_I2C_SYSTEST_SCL_I_FUNC;
+}
+
+static int omap_i2c_get_sda(struct i2c_adapter *adapter)
+{
+ struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter);
+ u32 reg;
+
+ reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG);
+
+ return reg & OMAP_I2C_SYSTEST_SDA_I_FUNC;
+}
+
+static void omap_i2c_set_scl(struct i2c_adapter *adapter, int val)
+{
+ struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter);
+ u32 reg;
+
+ reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG);
+ if (val)
+ reg |= OMAP_I2C_SYSTEST_SCL_O;
+ else
+ reg &= ~OMAP_I2C_SYSTEST_SCL_O;
+ omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg);
+}
+
+static void omap_i2c_prepare_recovery(struct i2c_adapter *adapter)
+{
+ struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter);
+ u32 reg;
+
+ reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG);
+ /* enable test mode */
+ reg |= OMAP_I2C_SYSTEST_ST_EN;
+ /* select SDA/SCL IO mode */
+ reg |= 3 << OMAP_I2C_SYSTEST_TMODE_SHIFT;
+ /* set SCL to high-impedance state (reset value is 0) */
+ reg |= OMAP_I2C_SYSTEST_SCL_O;
+ /* set SDA to high-impedance state (reset value is 0) */
+ reg |= OMAP_I2C_SYSTEST_SDA_O;
+ omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg);
+}
+
+static void omap_i2c_unprepare_recovery(struct i2c_adapter *adapter)
+{
+ struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter);
+ u32 reg;
+
+ reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG);
+ /* restore reset values */
+ reg &= ~OMAP_I2C_SYSTEST_ST_EN;
+ reg &= ~OMAP_I2C_SYSTEST_TMODE_MASK;
+ reg &= ~OMAP_I2C_SYSTEST_SCL_O;
+ reg &= ~OMAP_I2C_SYSTEST_SDA_O;
+ omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg);
+}
+
+static struct i2c_bus_recovery_info omap_i2c_bus_recovery_info = {
+ .get_scl = omap_i2c_get_scl,
+ .get_sda = omap_i2c_get_sda,
+ .set_scl = omap_i2c_set_scl,
+ .prepare_recovery = omap_i2c_prepare_recovery,
+ .unprepare_recovery = omap_i2c_unprepare_recovery,
+ .recover_bus = i2c_generic_scl_recovery,
+};
+
static int __init
i2c_omap_probe(struct device_d *pdev)
{
@@ -1101,6 +1178,7 @@ i2c_omap_probe(struct device_d *pdev)
i2c_omap->adapter.nr = pdev->id;
i2c_omap->adapter.dev.parent = pdev;
i2c_omap->adapter.dev.device_node = pdev->device_node;
+ i2c_omap->adapter.bus_recovery_info = &omap_i2c_bus_recovery_info;
/* i2c device drivers may be active on return from add_adapter() */
r = i2c_add_numbered_adapter(&i2c_omap->adapter);
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/6] i2c: algo-bit: fix debug code
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
` (2 preceding siblings ...)
2015-07-30 14:52 ` [PATCH v2 3/6] i2c-omap: add bus recovery support Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 5/6] i2c: algo-bit: check if the bus is busy Jan Luebbe
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
Replace jiffies from kernel code with get_time_ns. The flags variable
used in the readbytes debug output does not exist.
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/algos/i2c-algo-bit.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index dc43eb8..62040cc 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -106,9 +106,10 @@ static int sclhi(struct i2c_algo_bit_data *adap)
}
}
#ifdef DEBUG
- if (jiffies != start && i2c_debug >= 3)
- pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
- "high\n", jiffies - start);
+ if ((get_time_ns() - start) < 10000)
+ pr_debug("i2c-algo-bit: needed %u usecs for SCL to go "
+ "high\n", (unsigned int)(get_time_ns() - start) /
+ 1000);
#endif
done:
@@ -426,10 +427,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
count--;
bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",
- inval,
- (flags & I2C_M_NO_RD_ACK)
- ? "(no ack/nak)"
- : (count ? "A" : "NA"));
+ inval, count ? "A" : "NA");
inval = acknak(i2c_adap, count);
if (inval < 0)
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 5/6] i2c: algo-bit: check if the bus is busy
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
` (3 preceding siblings ...)
2015-07-30 14:52 ` [PATCH v2 4/6] i2c: algo-bit: fix debug code Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 6/6] i2c: gpio: add bus recovery support Jan Luebbe
2015-07-31 7:29 ` [PATCH v2 0/6] i2c: add bus recovery infrastructure Sascha Hauer
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
If we have a timeout while waiting, try to recover.
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/algos/i2c-algo-bit.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 62040cc..2563c0d 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -117,6 +117,31 @@ done:
return 0;
}
+static int wait_busy(struct i2c_algo_bit_data *adap)
+{
+ uint64_t start;
+
+ if (sclhi(adap) < 0)
+ return -ETIMEDOUT;
+
+ start = get_time_ns();
+ while (!getsda(adap)) {
+ if (is_timeout(start, adap->timeout_ms * MSECOND)) {
+ if (getsda(adap))
+ break;
+ return -ETIMEDOUT;
+ }
+ }
+#ifdef DEBUG
+ if ((get_time_ns() - start) < 10000)
+ pr_debug("i2c-algo-bit: needed %u usecs for SDA to go "
+ "high\n", (unsigned int)(get_time_ns() - start) /
+ 1000);
+#endif
+
+ udelay(adap->udelay);
+ return 0;
+}
/* --- other auxiliary functions -------------------------------------- */
static void i2c_start(struct i2c_algo_bit_data *adap)
@@ -512,6 +537,13 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
return ret;
}
+ if (wait_busy(adap) < 0) { /* timeout */
+ dev_warn(&i2c_adap->dev, "timeout waiting for bus ready\n");
+ ret = i2c_recover_bus(i2c_adap);
+ if (ret < 0)
+ return ret;
+ }
+
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
i2c_start(adap);
for (i = 0; i < num; i++) {
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 6/6] i2c: gpio: add bus recovery support
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
` (4 preceding siblings ...)
2015-07-30 14:52 ` [PATCH v2 5/6] i2c: algo-bit: check if the bus is busy Jan Luebbe
@ 2015-07-30 14:52 ` Jan Luebbe
2015-07-31 7:29 ` [PATCH v2 0/6] i2c: add bus recovery infrastructure Sascha Hauer
6 siblings, 0 replies; 9+ messages in thread
From: Jan Luebbe @ 2015-07-30 14:52 UTC (permalink / raw)
To: barebox
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
---
drivers/i2c/busses/i2c-gpio.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index b4a0ecd..9362ed1 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <driver.h>
+#include <malloc.h>
#include <i2c/i2c.h>
#include <i2c/i2c-algo-bit.h>
#include <i2c/i2c-gpio.h>
@@ -187,6 +188,13 @@ static int i2c_gpio_probe(struct device_d *dev)
adap->algo_data = bit_data;
adap->dev.parent = dev;
adap->dev.device_node = dev->device_node;
+ adap->bus_recovery_info = xzalloc(sizeof(*adap->bus_recovery_info));
+ adap->bus_recovery_info->scl_gpio = pdata->scl_pin;
+ adap->bus_recovery_info->sda_gpio = pdata->sda_pin;
+ adap->bus_recovery_info->get_sda = i2c_get_sda_gpio_value;
+ adap->bus_recovery_info->get_scl = i2c_get_scl_gpio_value;
+ adap->bus_recovery_info->set_scl = i2c_set_scl_gpio_value;
+ adap->bus_recovery_info->recover_bus = i2c_generic_scl_recovery;
adap->nr = dev->id;
ret = i2c_bit_add_numbered_bus(adap);
@@ -201,10 +209,12 @@ static int i2c_gpio_probe(struct device_d *dev)
return 0;
err_add_bus:
+ free(adap->bus_recovery_info);
gpio_free(pdata->scl_pin);
err_request_scl:
gpio_free(pdata->sda_pin);
err_request_sda:
+ free(priv);
return ret;
}
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/6] i2c: add bus recovery infrastructure
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
` (5 preceding siblings ...)
2015-07-30 14:52 ` [PATCH v2 6/6] i2c: gpio: add bus recovery support Jan Luebbe
@ 2015-07-31 7:29 ` Sascha Hauer
2015-08-03 9:20 ` Sascha Hauer
6 siblings, 1 reply; 9+ messages in thread
From: Sascha Hauer @ 2015-07-31 7:29 UTC (permalink / raw)
To: Jan Luebbe; +Cc: barebox
On Thu, Jul 30, 2015 at 04:52:05PM +0200, Jan Luebbe wrote:
> This series ports the kernel's i2c bus recovery support to barebox.
>
> Bus recovery is necessary when a slave device pulls the SDA line low because it
> is in a wrong state. The fix is to toggle the SCL line, which move the slaves
> into the idle state. Using the same structure and callbacks as the kernel makes
> it easy to port the per-driver code to barebox.
>
> Changes from v1:
> - Let the driver configure the function pointers to avoid linking in
> i2c_generic_gpio_recovery when it is not actually needed.
> - Add recovery support to i2c-gpio.
>
> Jan Luebbe (6):
> i2c: add bus recovery infrastructure
> i2c-omap: clear ARDY twice
> i2c-omap: add bus recovery support
> i2c: algo-bit: fix debug code
> i2c: algo-bit: check if the bus is busy
> i2c: gpio: add bus recovery support
Applied, thanks
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/6] i2c: add bus recovery infrastructure
2015-07-31 7:29 ` [PATCH v2 0/6] i2c: add bus recovery infrastructure Sascha Hauer
@ 2015-08-03 9:20 ` Sascha Hauer
0 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-08-03 9:20 UTC (permalink / raw)
To: Jan Luebbe; +Cc: barebox
On Fri, Jul 31, 2015 at 09:29:21AM +0200, Sascha Hauer wrote:
> On Thu, Jul 30, 2015 at 04:52:05PM +0200, Jan Luebbe wrote:
> > This series ports the kernel's i2c bus recovery support to barebox.
> >
> > Bus recovery is necessary when a slave device pulls the SDA line low because it
> > is in a wrong state. The fix is to toggle the SCL line, which move the slaves
> > into the idle state. Using the same structure and callbacks as the kernel makes
> > it easy to port the per-driver code to barebox.
> >
> > Changes from v1:
> > - Let the driver configure the function pointers to avoid linking in
> > i2c_generic_gpio_recovery when it is not actually needed.
> > - Add recovery support to i2c-gpio.
> >
> > Jan Luebbe (6):
> > i2c: add bus recovery infrastructure
> > i2c-omap: clear ARDY twice
> > i2c-omap: add bus recovery support
> > i2c: algo-bit: fix debug code
> > i2c: algo-bit: check if the bus is busy
> > i2c: gpio: add bus recovery support
>
> Applied, thanks
Unfortunately I had to drop this branch. It adds a dependency from the
I2C core to GPIO so compilation for example on PPC breaks with:
In file included from drivers/i2c/i2c.c:26:0:
include/gpio.h:4:22: fatal error: asm/gpio.h: No such file or directory
#include <asm/gpio.h>
We'll need either some #ifdefery in the I2C core or some static inline
wrappers in include/gpio.h for !CONFIG_GENERIC_GPIO.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-08-03 9:20 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-30 14:52 [PATCH v2 0/6] i2c: add bus recovery infrastructure Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 1/6] " Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 2/6] i2c-omap: clear ARDY twice Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 3/6] i2c-omap: add bus recovery support Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 4/6] i2c: algo-bit: fix debug code Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 5/6] i2c: algo-bit: check if the bus is busy Jan Luebbe
2015-07-30 14:52 ` [PATCH v2 6/6] i2c: gpio: add bus recovery support Jan Luebbe
2015-07-31 7:29 ` [PATCH v2 0/6] i2c: add bus recovery infrastructure Sascha Hauer
2015-08-03 9:20 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox