Add a new init_recovery() callback to struct 'i2c_bus_recovery_info' and modify the i2c_init_recovery() function to call that if specified instead of the generic i2c_gpio_init_recovery() function.
This allows controller drivers to skip calling the generic code by implementing a dummy callback function, or alternatively to run a fine tuned custom implementation.
This is needed for the 'i2c-pxa' driver in order to be able to fix a long standing bug for which the fix will be implemented in a followup patch.
Cc: stable@vger.kernel.org # 6.3+ Signed-off-by: Imre Kaloz kaloz@openwrt.org Reviewed-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Gabor Juhos j4g8y7@gmail.com --- Changes in v2: - add 'Reviewed-by' tag from Linus Walleij - rebase on tip of i2c/for-current --- drivers/i2c/i2c-core-base.c | 8 +++++++- include/linux/i2c.h | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index ecca8c006b020379fb53293b20ab09ba25314609..e38be81dbcc17dd15947a189fd3b89def8529d1e 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -427,12 +427,18 @@ static int i2c_init_recovery(struct i2c_adapter *adap) struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; bool is_error_level = true; char *err_str; + int ret;
if (!bri) return 0;
- if (i2c_gpio_init_recovery(adap) == -EPROBE_DEFER) + if (bri->init_recovery) { + ret = bri->init_recovery(adap); + if (ret) + return ret; + } else if (i2c_gpio_init_recovery(adap) == -EPROBE_DEFER) { return -EPROBE_DEFER; + }
if (!bri->recover_bus) { err_str = "no suitable method provided"; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 20fd41b51d5c85ee1665395c07345faafd8e2fca..4cefdd4c730fc9dc4655f6581f3dea64435d7124 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -636,6 +636,9 @@ struct i2c_timings { * for generic GPIO recovery. * @get_bus_free: Returns the bus free state as seen from the IP core in case it * has a more complex internal logic than just reading SDA. Optional. + * @init_recovery: If specified, it will be called instead of the generic GPIO + * recovery initialization code. Platform may use a dummy callback to skip + * calling the generic code, or it may use a custom implementation. * @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 @@ -660,6 +663,7 @@ struct i2c_bus_recovery_info { void (*set_sda)(struct i2c_adapter *adap, int val); int (*get_bus_free)(struct i2c_adapter *adap);
+ int (*init_recovery)(struct i2c_adapter *adap); void (*prepare_recovery)(struct i2c_adapter *adap); void (*unprepare_recovery)(struct i2c_adapter *adap);