Skip to content

Commit 7b211c7

Browse files
robimarkowsakernel
authored andcommitted
Revert "i2c: pxa: move to generic GPIO recovery"
This reverts commit 0b01392. Conversion of PXA to generic I2C recovery, makes the I2C bus completely lock up if recovery pinctrl is present in the DT and I2C recovery is enabled. So, until the generic I2C recovery can also work with PXA lets revert to have working I2C and I2C recovery again. Signed-off-by: Robert Marko <robert.marko@sartura.hr> Cc: stable@vger.kernel.org # 5.11+ Acked-by: Andi Shyti <andi.shyti@kernel.org> Acked-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent b85ea95 commit 7b211c7

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

drivers/i2c/busses/i2c-pxa.c

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ struct pxa_i2c {
265265
u32 hs_mask;
266266

267267
struct i2c_bus_recovery_info recovery;
268+
struct pinctrl *pinctrl;
269+
struct pinctrl_state *pinctrl_default;
270+
struct pinctrl_state *pinctrl_recovery;
268271
};
269272

270273
#define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -1299,12 +1302,13 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)
12991302
*/
13001303
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
13011304
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
1305+
1306+
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
13021307
}
13031308

13041309
static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
13051310
{
13061311
struct pxa_i2c *i2c = adap->algo_data;
1307-
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
13081312
u32 isr;
13091313

13101314
/*
@@ -1318,7 +1322,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
13181322
i2c_pxa_do_reset(i2c);
13191323
}
13201324

1321-
WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));
1325+
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
13221326

13231327
dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
13241328
readl(_IBMR(i2c)), readl(_ISR(i2c)));
@@ -1340,20 +1344,76 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
13401344
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
13411345
return 0;
13421346

1343-
bri->pinctrl = devm_pinctrl_get(dev);
1344-
if (PTR_ERR(bri->pinctrl) == -ENODEV) {
1345-
bri->pinctrl = NULL;
1347+
i2c->pinctrl = devm_pinctrl_get(dev);
1348+
if (PTR_ERR(i2c->pinctrl) == -ENODEV)
1349+
i2c->pinctrl = NULL;
1350+
if (IS_ERR(i2c->pinctrl))
1351+
return PTR_ERR(i2c->pinctrl);
1352+
1353+
if (!i2c->pinctrl)
1354+
return 0;
1355+
1356+
i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
1357+
PINCTRL_STATE_DEFAULT);
1358+
i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
1359+
1360+
if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
1361+
dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
1362+
PTR_ERR(i2c->pinctrl_default),
1363+
PTR_ERR(i2c->pinctrl_recovery));
1364+
return 0;
1365+
}
1366+
1367+
/*
1368+
* Claiming GPIOs can influence the pinmux state, and may glitch the
1369+
* I2C bus. Do this carefully.
1370+
*/
1371+
bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
1372+
if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
1373+
return -EPROBE_DEFER;
1374+
if (IS_ERR(bri->scl_gpiod)) {
1375+
dev_info(dev, "missing scl gpio recovery information: %pe\n",
1376+
bri->scl_gpiod);
1377+
return 0;
1378+
}
1379+
1380+
/*
1381+
* We have SCL. Pull SCL low and wait a bit so that SDA glitches
1382+
* have no effect.
1383+
*/
1384+
gpiod_direction_output(bri->scl_gpiod, 0);
1385+
udelay(10);
1386+
bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
1387+
1388+
/* Wait a bit in case of a SDA glitch, and then release SCL. */
1389+
udelay(10);
1390+
gpiod_direction_output(bri->scl_gpiod, 1);
1391+
1392+
if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
1393+
return -EPROBE_DEFER;
1394+
1395+
if (IS_ERR(bri->sda_gpiod)) {
1396+
dev_info(dev, "missing sda gpio recovery information: %pe\n",
1397+
bri->sda_gpiod);
13461398
return 0;
13471399
}
1348-
if (IS_ERR(bri->pinctrl))
1349-
return PTR_ERR(bri->pinctrl);
13501400

13511401
bri->prepare_recovery = i2c_pxa_prepare_recovery;
13521402
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
1403+
bri->recover_bus = i2c_generic_scl_recovery;
13531404

13541405
i2c->adap.bus_recovery_info = bri;
13551406

1356-
return 0;
1407+
/*
1408+
* Claiming GPIOs can change the pinmux state, which confuses the
1409+
* pinctrl since pinctrl's idea of the current setting is unaffected
1410+
* by the pinmux change caused by claiming the GPIO. Work around that
1411+
* by switching pinctrl to the GPIO state here. We do it this way to
1412+
* avoid glitching the I2C bus.
1413+
*/
1414+
pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
1415+
1416+
return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
13571417
}
13581418

13591419
static int i2c_pxa_probe(struct platform_device *dev)

0 commit comments

Comments
 (0)