On 4 October 2012 13:30, Uwe Kleine-König
<[email protected]> wrote:
Hi Uwe,
Please see if following fixup looks fine to you:
fixup! i2c/adapter: Add bus recovery infrastructure
---
drivers/i2c/i2c-core.c | 33 ++++++++++++++-------------------
include/linux/i2c.h | 22 ++++++++++++----------
2 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index bdc249a..393d5f7 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -107,24 +107,14 @@ static int i2c_device_uevent(struct device *dev,
struct kobj_uevent_env *env)
#endif /* CONFIG_HOTPLUG */
/* i2c bus recovery routines */
-static inline void set_scl_value(struct i2c_adapter *adap, int val)
+static void set_scl_gpio_value(struct i2c_adapter *adap, int val)
{
- struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
-
- if (bri->is_gpio_recovery)
- gpio_set_value(bri->scl_gpio, val);
- else
- bri->set_scl(adap, val);
+ gpio_set_value(adap->bus_recovery_info->scl_gpio, val);
}
-static inline int get_sda_value(struct i2c_adapter *adap)
+static int get_sda_gpio_value(struct i2c_adapter *adap)
{
- struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
-
- if (bri->is_gpio_recovery)
- return gpio_get_value(bri->sda_gpio);
- else
- return bri->get_sda(adap);
+ return gpio_get_value(adap->bus_recovery_info->sda_gpio);
}
static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap)
@@ -152,8 +142,7 @@ static int i2c_get_gpios_for_recovery(struct
i2c_adapter *adap)
ret = bri->get_gpio(bri->sda_gpio);
if (unlikely(ret ||
- gpio_request_one(bri->sda_gpio, bri->sda_gpio_flags,
- "i2c-sda"))) {
+ gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda"))) {
/* work without sda polling */
dev_warn(dev, "can't get sda: %d. Skip sda polling\n",
bri->sda_gpio);
@@ -190,7 +179,7 @@ static int i2c_recover_bus(struct i2c_adapter *adap)
{
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
unsigned long delay = 1000000;
- int i, ret, val = 1;
+ int i, ret, val = 0;
if (bri->is_gpio_recovery) {
ret = i2c_get_gpios_for_recovery(adap);
@@ -201,12 +190,12 @@ static int i2c_recover_bus(struct i2c_adapter *adap)
delay = DIV_ROUND_UP(delay, bri->clock_rate_khz * 2);
for (i = 0; i < bri->clock_cnt * 2; i++, val = !val) {
- set_scl_value(adap, val);
+ bri->set_scl(adap, val);
ndelay(delay);
/* break if sda got high, check only when scl line is high */
if (!bri->skip_sda_polling && val)
- if (unlikely(get_sda_value(adap)))
+ if (unlikely(bri->get_sda(adap)))
break;
}
@@ -1030,6 +1019,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
bri->recover_bus = i2c_recover_bus;
if (bri->is_gpio_recovery) {
+ if (!bri->scl_gpio_flags)
+ bri->scl_gpio_flags = GPIOF_OPEN_DRAIN |
+ GPIOF_OUT_INIT_HIGH;
+
+ bri->set_scl = set_scl_gpio_value;
+ bri->get_sda = get_sda_gpio_value;
dev_info(&adap->dev,
"registered for gpio bus recovery\n");
} else if (bri->set_scl) {
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index c43e5c4..dd470a1 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -382,10 +382,10 @@ struct i2c_algorithm {
* scl type recovery.
* @clock_cnt: count of max clocks to be generated. Required for both gpio and
* scl type recovery.
- * @set_scl: controller specific scl configuration routine. Only required if
- * is_gpio_recovery == false
- * @get_sda: controller specific sda read routine. Only required if
- * is_gpio_recovery == false and skip_sda_polling == false.
+ * @set_scl: controller specific routine, if is_gpio_recovery == false.
+ * set_scl_gpio_value otherwise
+ * @get_sda: controller specific routine, if is_gpio_recovery == false.
+ * get_sda_gpio_value otherwise
* @get_gpio: called before recover_bus() to get padmux configured
for scl line.
* as gpio. Only required if is_gpio_recovery == true. Return 0 on success.
* @put_gpio: called after recover_bus() to get padmux configured for scl line
@@ -394,10 +394,9 @@ struct i2c_algorithm {
* true.
* @sda_gpio: gpio number of the sda line. Only required if is_gpio_recovery ==
* true and skip_sda_polling == false.
- * @scl_gpio_flags: flag for gpio_request_one of scl_gpio. 0 implies
- * GPIOF_OUT_INIT_LOW.
- * @sda_gpio_flags: flag for gpio_request_one of sda_gpio. 0 implies
- * GPIOF_OUT_INIT_LOW.
+ * @scl_gpio_flags: flag for gpio_request_one of scl_gpio. If passed as 0,
+ * (GPIOF_OPEN_DRAIN | GPIOF_OUT_INIT_HIGH) is used instead.
+ * These is no need of sda_gpio_flags, as we always read it in input mode.
*/
struct i2c_bus_recovery_info {
int (*recover_bus)(struct i2c_adapter *);
@@ -406,7 +405,11 @@ struct i2c_bus_recovery_info {
u32 clock_rate_khz;
u8 clock_cnt;
- /* scl/sda recovery */
+ /*
+ * Fn pointers for recovery, will point either to:
+ * - set_scl_gpio_value and get_sda_gpio_value for gpio recovery
+ * - Controller specific routines, otherwise
+ */
void (*set_scl)(struct i2c_adapter *, int val);
int (*get_sda)(struct i2c_adapter *);
@@ -416,7 +419,6 @@ struct i2c_bus_recovery_info {
unsigned scl_gpio;
unsigned sda_gpio;
unsigned long scl_gpio_flags;
- unsigned long sda_gpio_flags;
};
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html