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: Gabor Juhos j4g8y7@gmail.com Signed-off-by: Imre Kaloz kaloz@openwrt.org --- 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 7ad1ad5c8c3f56943b627254b1fdbf8f787afdb5..6b8b961b845caf6f28ea1a9a76d623ac73f5e0dd 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 2e4903b7f7bc11627f9cbc23a4d549dd48c4dcc7..1cff399822c817429e520572546a3d0b7f704723 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -638,6 +638,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 @@ -662,6 +665,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);