diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 117f367636b8..9696d6ec46c0 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1007,11 +1007,24 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap) pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default); } -static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, +/* + * We switch SCL and SDA to their GPIO function and do some bitbanging + * for bus recovery. These alternative pinmux settings can be + * described in the device tree by a separate pinctrl state "gpio". If + * this is missing this is not a big problem, the only implication is + * that we can't do bus recovery. + */ +static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, struct platform_device *pdev) { struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo; + i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!i2c_imx->pinctrl || IS_ERR(i2c_imx->pinctrl)) { + dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n"); + return PTR_ERR(i2c_imx->pinctrl); + } + i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl, PINCTRL_STATE_DEFAULT); i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl, @@ -1021,12 +1034,15 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node, "scl-gpios", 0, NULL); - if (!gpio_is_valid(rinfo->sda_gpio) || - !gpio_is_valid(rinfo->scl_gpio) || - IS_ERR(i2c_imx->pinctrl_pins_default) || - IS_ERR(i2c_imx->pinctrl_pins_gpio)) { + if (rinfo->sda_gpio == -EPROBE_DEFER || + rinfo->scl_gpio == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (!gpio_is_valid(rinfo->sda_gpio) || + !gpio_is_valid(rinfo->scl_gpio) || + IS_ERR(i2c_imx->pinctrl_pins_default) || + IS_ERR(i2c_imx->pinctrl_pins_gpio)) { dev_dbg(&pdev->dev, "recovery information incomplete\n"); - return; + return 0; } dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", @@ -1036,6 +1052,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; rinfo->recover_bus = i2c_generic_gpio_recovery; i2c_imx->adapter.bus_recovery_info = rinfo; + + return 0; } static u32 i2c_imx_func(struct i2c_adapter *adapter) @@ -1139,7 +1157,11 @@ static int i2c_imx_probe(struct platform_device *pdev) i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); - i2c_imx_init_recovery_info(i2c_imx, pdev); + /* Init optional bus recovery function */ + ret = i2c_imx_init_recovery_info(i2c_imx, pdev); + /* Give it another chance if pinctrl used is not ready yet */ + if (ret == -EPROBE_DEFER) + goto clk_disable; /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); |