|
@@ -984,11 +984,24 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
|
|
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
|
|
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 platform_device *pdev)
|
|
{
|
|
{
|
|
struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
|
|
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,
|
|
i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
|
|
PINCTRL_STATE_DEFAULT);
|
|
PINCTRL_STATE_DEFAULT);
|
|
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
|
|
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
|
|
@@ -1001,7 +1014,7 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
|
|
IS_ERR(i2c_imx->pinctrl_pins_default) ||
|
|
IS_ERR(i2c_imx->pinctrl_pins_default) ||
|
|
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
|
|
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
|
|
dev_dbg(&pdev->dev, "recovery information incomplete\n");
|
|
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",
|
|
dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
|
|
@@ -1011,6 +1024,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
|
|
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
|
|
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
|
|
rinfo->recover_bus = i2c_generic_gpio_recovery;
|
|
rinfo->recover_bus = i2c_generic_gpio_recovery;
|
|
i2c_imx->adapter.bus_recovery_info = rinfo;
|
|
i2c_imx->adapter.bus_recovery_info = rinfo;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static u32 i2c_imx_func(struct i2c_adapter *adapter)
|
|
static u32 i2c_imx_func(struct i2c_adapter *adapter)
|
|
@@ -1081,12 +1096,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
|
|
- if (IS_ERR(i2c_imx->pinctrl)) {
|
|
|
|
- ret = PTR_ERR(i2c_imx->pinctrl);
|
|
|
|
- goto clk_disable;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/* Request IRQ */
|
|
/* Request IRQ */
|
|
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
|
|
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
|
|
pdev->name, i2c_imx);
|
|
pdev->name, i2c_imx);
|
|
@@ -1125,7 +1134,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|
i2c_imx, IMX_I2C_I2CR);
|
|
i2c_imx, IMX_I2C_I2CR);
|
|
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
|
|
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 rpm_disable;
|
|
|
|
|
|
/* Add I2C adapter */
|
|
/* Add I2C adapter */
|
|
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
|
|
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
|