Message ID | DB6PR07MB3509F48523F601D4F6429D069DBA2@DB6PR07MB3509.eurprd07.prod.outlook.com |
---|---|
State | Superseded |
Delegated to: | Andi Shyti |
Headers | show |
Series | pca954x: Reset if channel select fails | expand |
Hi Wojciech, On Fri, Aug 09, 2024 at 08:17:52AM GMT, Wojciech Siudy (Nokia) wrote: > From da1630ee3ed664df8fbd74c4063ab130c4e98c5d Mon Sep 17 00:00:00 2001 > From: Wojciech Siudy <wojciech.siudy@nokia.com> Nice to see patches from Nokia :-) > Date: Fri, 9 Aug 2024 09:59:27 +0200 > Subject: [PATCH] pca954x: Reset if channel select fails please remove the mail header from the commit log. If you want your name to appear without the "... (Nokia)" part you can simply add: From: Wojciech Siudy <wojciech.siudy@nokia.com> > Channel selection that has timed out is a symptom of mux'es I2C > subsystem failure. Without sending reset pulse the POR of entire > system would be needed to restore the communication. > > Signed-off-by: siudy <wojciech.siudy@nokia.com> siudy? ... > @@ -329,6 +345,12 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) > ret = pca954x_reg_write(muxc->parent, client, regval); > data->last_chan = ret < 0 ? 0 : regval; > } > + if (ret == -ETIMEDOUT && (data->reset_cont || data->reset_gpio)) { > + dev_warn(&client->dev, "channel select failed, resetting...\n"); > + pca954x_reset_assert(data); > + udelay(10); Why 10? Andi
Hi Andi, > Nice to see patches from Nokia :-) I am glad to hear that :-) > please remove the mail header from the commit log. OK. > Why 10? Well, the datasheet mentions minimal hold time as 4 ns, so 10 us seems to be exaggeration, however when we get under 1 us must keep in mind potential paths capacity and lack of synchronization between mux and CPU clock, so let's stay with 1 us that I will post in next version of the patch. Regards, Wojciech
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 6f8401825..0034e663b 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -316,6 +316,22 @@ static u8 pca954x_regval(struct pca954x *data, u8 chan) return 1 << chan; } +static void pca954x_reset_deassert(struct pca954x *data) +{ + if (data->reset_cont) + reset_control_deassert(data->reset_cont); + else + gpiod_set_value_cansleep(data->reset_gpio, 0); +} + +static void pca954x_reset_assert(struct pca954x *data) +{ + if (data->reset_cont) + reset_control_assert(data->reset_cont); + else + gpiod_set_value_cansleep(data->reset_gpio, 1); +} + static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) { struct pca954x *data = i2c_mux_priv(muxc); @@ -329,6 +345,12 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) ret = pca954x_reg_write(muxc->parent, client, regval); data->last_chan = ret < 0 ? 0 : regval; } + if (ret == -ETIMEDOUT && (data->reset_cont || data->reset_gpio)) { + dev_warn(&client->dev, "channel select failed, resetting...\n"); + pca954x_reset_assert(data); + udelay(10); + pca954x_reset_deassert(data); + } return ret; } @@ -543,14 +565,6 @@ static int pca954x_get_reset(struct device *dev, struct pca954x *data) return 0; } -static void pca954x_reset_deassert(struct pca954x *data) -{ - if (data->reset_cont) - reset_control_deassert(data->reset_cont); - else - gpiod_set_value_cansleep(data->reset_gpio, 0); -} - /* * I2C init/probing/exit functions */