Message ID | 20210406113306.2633595-1-xiaoning.wang@nxp.com |
---|---|
Headers | show |
Series | i2c: imx-lpi2c: New features and bug fixes | expand |
On Tue, Apr 06, 2021 at 07:33:03PM +0800, Clark Wang wrote: > Add i2c bus dma mode configuration example. > > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> > --- > V2 changes: > - New patch added in V2 > --- > .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml > index 0a4b28827dcc..3868fec0cf27 100644 > --- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml > +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml > @@ -51,6 +51,16 @@ properties: > sda-gpios: > maxItems: 1 > > + dmas: > + minItems: 2 > + maxItems: 2 > + > + dma-names: > + minItems: 2 > + maxItems: 2 > + items: > + enum: [ "tx", "rx" ] Please define the order: items: - const: tx - const: rx > + > required: > - compatible > - reg > @@ -75,4 +85,6 @@ examples: > pinctrl-1 = <&pinctrl_i2c_recovery>; > scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; > sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; > + dmas = <&edma1 0 16>, <&edma1 0 15>; > + dma-names = "tx","rx"; > }; > -- > 2.25.1 >
On Tue, Apr 06, 2021 at 07:32:53PM +0800, Clark Wang wrote: > The lpi2c driver has add the missing ipg clock. > So add the ipg clock here for all lpi2c nodes. > > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> Historically, we use 'arm64: dts: ...' as subject prefix for arm64 DTS patch, and 'ARM: dts: ...' for arm. Shawn > --- > V2 changes: > - New patch added in V2 > --- > .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 24 ++++++++++++------- > 1 file changed, 16 insertions(+), 8 deletions(-) > > diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > index 960a802b8b6e..b5ed12a06538 100644 > --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > @@ -111,8 +111,10 @@ uart3_lpcg: clock-controller@5a490000 { > i2c0: i2c@5a800000 { > reg = <0x5a800000 0x4000>; > interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>, > + <&i2c0_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_0 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_0>; > @@ -122,8 +124,10 @@ i2c0: i2c@5a800000 { > i2c1: i2c@5a810000 { > reg = <0x5a810000 0x4000>; > interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>, > + <&i2c1_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_1 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_1>; > @@ -133,8 +137,10 @@ i2c1: i2c@5a810000 { > i2c2: i2c@5a820000 { > reg = <0x5a820000 0x4000>; > interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>, > + <&i2c2_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_2 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_2>; > @@ -144,8 +150,10 @@ i2c2: i2c@5a820000 { > i2c3: i2c@5a830000 { > reg = <0x5a830000 0x4000>; > interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>, > + <&i2c3_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_3 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_3>; > -- > 2.25.1 >
> From: Clark Wang <xiaoning.wang@nxp.com> > Sent: Tuesday, April 6, 2021 7:33 PM > > The lpi2c driver has add the missing ipg clock. Pls drop this line as binding is not decided by driver > So add the ipg clock here for all lpi2c nodes. Per clock? Maybe better refined as add the missing per clock .... > > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> > --- > V2 changes: > - New patch added in V2 > --- > arch/arm/boot/dts/imx7ulp.dtsi | 10 ++++++---- > 1 file changed, 6 insertions(+), 4 deletions(-) > > diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi > index b7ea37ad4e55..eb0d4b8f624d 100644 > --- a/arch/arm/boot/dts/imx7ulp.dtsi > +++ b/arch/arm/boot/dts/imx7ulp.dtsi > @@ -328,8 +328,9 @@ lpi2c6: i2c@40a40000 { > compatible = "fsl,imx7ulp-lpi2c"; > reg = <0x40a40000 0x10000>; > interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>; > - clock-names = "ipg"; > + clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>, > + <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>; > + clock-names = "per", "ipg"; > assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>; > assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>; > assigned-clock-rates = <48000000>; > @@ -340,8 +341,9 @@ lpi2c7: i2c@40a50000 { > compatible = "fsl,imx7ulp-lpi2c"; > reg = <0x40a50000 0x10000>; > interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>; > - clock-names = "ipg"; > + clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>, > + <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>; > + clock-names = "per", "ipg"; > assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>; > assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>; > assigned-clock-rates = <48000000>; > -- > 2.25.1
> From: Clark Wang <xiaoning.wang@nxp.com> > Sent: Tuesday, April 6, 2021 7:33 PM > > The lpi2c driver has add the missing ipg clock. > So add the ipg clock here for all lpi2c nodes. > > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> > --- > V2 changes: > - New patch added in V2 > --- > .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 24 ++++++++++++------- > 1 file changed, 16 insertions(+), 8 deletions(-) > > diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > index 960a802b8b6e..b5ed12a06538 100644 > --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi > @@ -111,8 +111,10 @@ uart3_lpcg: clock-controller@5a490000 { > i2c0: i2c@5a800000 { > reg = <0x5a800000 0x4000>; > interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; Added by mistake? > + clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>, > + <&i2c0_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_0 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_0>; @@ -122,8 +124,10 @@ > i2c0: i2c@5a800000 { > i2c1: i2c@5a810000 { > reg = <0x5a810000 0x4000>; > interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; Ditto > + clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>, > + <&i2c1_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_1 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_1>; @@ -133,8 +137,10 @@ > i2c1: i2c@5a810000 { > i2c2: i2c@5a820000 { > reg = <0x5a820000 0x4000>; > interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>, > + <&i2c2_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_2 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_2>; @@ -144,8 +150,10 @@ > i2c2: i2c@5a820000 { > i2c3: i2c@5a830000 { > reg = <0x5a830000 0x4000>; > interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>; > - clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>; > - clock-names = "per"; > + interrupt-parent = <&gic>; > + clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>, > + <&i2c3_lpcg IMX_LPCG_CLK_4>; > + clock-names = "per", "ipg"; > assigned-clocks = <&clk IMX_SC_R_I2C_3 IMX_SC_PM_CLK_PER>; > assigned-clock-rates = <24000000>; > power-domains = <&pd IMX_SC_R_I2C_3>; > -- > 2.25.1
> From: Clark Wang <xiaoning.wang@nxp.com> > Sent: Tuesday, April 6, 2021 7:33 PM > > Manage irq resource request/release in runtime pm to save irq domain's > power. > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > Signed-off-by: Fugang Duan <fugang.duan@nxp.com> > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> > Reviewed-by: Frank Li <Frank.Li@nxp.com> Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com> Regards Aisheng > --- > V2 changes: > - Change to use request_irq/free_irq. > --- > drivers/i2c/busses/i2c-imx-lpi2c.c | 30 ++++++++++++++++++------------ > 1 file changed, 18 insertions(+), 12 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c > b/drivers/i2c/busses/i2c-imx-lpi2c.c > index 89b7b0795f51..333209ba81c1 100644 > --- a/drivers/i2c/busses/i2c-imx-lpi2c.c > +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c > @@ -94,6 +94,7 @@ enum lpi2c_imx_pincfg { > > struct lpi2c_imx_struct { > struct i2c_adapter adapter; > + int irq; > struct clk *clk_per; > struct clk *clk_ipg; > void __iomem *base; > @@ -571,7 +572,7 @@ static int lpi2c_imx_probe(struct platform_device > *pdev) { > struct lpi2c_imx_struct *lpi2c_imx; > unsigned int temp; > - int irq, ret; > + int ret; > > lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL); > if (!lpi2c_imx) > @@ -581,9 +582,9 @@ static int lpi2c_imx_probe(struct platform_device > *pdev) > if (IS_ERR(lpi2c_imx->base)) > return PTR_ERR(lpi2c_imx->base); > > - irq = platform_get_irq(pdev, 0); > - if (irq < 0) > - return irq; > + lpi2c_imx->irq = platform_get_irq(pdev, 0); > + if (lpi2c_imx->irq < 0) > + return lpi2c_imx->irq; > > lpi2c_imx->adapter.owner = THIS_MODULE; > lpi2c_imx->adapter.algo = &lpi2c_imx_algo; > @@ -609,13 +610,6 @@ static int lpi2c_imx_probe(struct platform_device > *pdev) > if (ret) > lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ; > > - ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0, > - pdev->name, lpi2c_imx); > - if (ret) { > - dev_err(&pdev->dev, "can't claim irq %d\n", irq); > - return ret; > - } > - > i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx); > platform_set_drvdata(pdev, lpi2c_imx); > > @@ -668,6 +662,7 @@ static int __maybe_unused > lpi2c_runtime_suspend(struct device *dev) { > struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); > > + free_irq(lpi2c_imx->irq, lpi2c_imx); > lpi2c_imx_clocks_unprepare(lpi2c_imx); > pinctrl_pm_select_sleep_state(dev); > > @@ -677,10 +672,21 @@ static int __maybe_unused > lpi2c_runtime_suspend(struct device *dev) static int __maybe_unused > lpi2c_runtime_resume(struct device *dev) { > struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); > + int ret = 0; > > pinctrl_pm_select_default_state(dev); > + ret = lpi2c_imx_clocks_prepare(lpi2c_imx); > + if (ret) > + return ret; > > - return lpi2c_imx_clocks_prepare(lpi2c_imx); > + ret = request_irq(lpi2c_imx->irq, lpi2c_imx_isr, 0, > + dev_name(dev), lpi2c_imx); > + if (ret) { > + dev_err(dev, "can't claim irq %d\n", lpi2c_imx->irq); > + return ret; > + } > + > + return ret; > } > > static const struct dev_pm_ops lpi2c_pm_ops = { > -- > 2.25.1
> From: Clark Wang <xiaoning.wang@nxp.com> > Sent: Tuesday, April 6, 2021 7:33 PM > > Add bus recovery feature for LPI2C. > Need add gpio pinctrl, scl-gpios and sda-gpios configuration in dts. > > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> > --- > V2 changes: > - No change. Add dt-bindings in the next patch. Dt binding patch should be sent before driver change > --- > drivers/i2c/busses/i2c-imx-lpi2c.c | 83 ++++++++++++++++++++++++++++++ > 1 file changed, 83 insertions(+) > > diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c > b/drivers/i2c/busses/i2c-imx-lpi2c.c > index 77ceb743b282..77dd6ee5a4a8 100644 > --- a/drivers/i2c/busses/i2c-imx-lpi2c.c > +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c > @@ -18,6 +18,7 @@ > #include <linux/module.h> > #include <linux/of.h> > #include <linux/of_device.h> > +#include <linux/of_gpio.h> > #include <linux/pinctrl/consumer.h> > #include <linux/platform_device.h> > #include <linux/pm_runtime.h> > @@ -108,6 +109,11 @@ struct lpi2c_imx_struct { > unsigned int txfifosize; > unsigned int rxfifosize; > enum lpi2c_imx_mode mode; > + > + struct i2c_bus_recovery_info rinfo; > + struct pinctrl *pinctrl; > + struct pinctrl_state *pinctrl_pins_default; > + struct pinctrl_state *pinctrl_pins_gpio; > }; > > static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, @@ -135,6 > +141,8 @@ static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx) > > if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { > dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n"); > + if (lpi2c_imx->adapter.bus_recovery_info) > + i2c_recover_bus(&lpi2c_imx->adapter); > return -ETIMEDOUT; > } > schedule(); > @@ -192,6 +200,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct > *lpi2c_imx) > > if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { > dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n"); > + if (lpi2c_imx->adapter.bus_recovery_info) > + i2c_recover_bus(&lpi2c_imx->adapter); > break; > } > schedule(); > @@ -329,6 +339,8 @@ static int lpi2c_imx_txfifo_empty(struct > lpi2c_imx_struct *lpi2c_imx) > > if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { > dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n"); > + if (lpi2c_imx->adapter.bus_recovery_info) > + i2c_recover_bus(&lpi2c_imx->adapter); > return -ETIMEDOUT; > } > schedule(); > @@ -528,6 +540,71 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) > return IRQ_HANDLED; > } > > +static void lpi2c_imx_prepare_recovery(struct i2c_adapter *adap) { > + struct lpi2c_imx_struct *lpi2c_imx; > + > + lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter); > + > + pinctrl_select_state(lpi2c_imx->pinctrl, > +lpi2c_imx->pinctrl_pins_gpio); } > + > +static void lpi2c_imx_unprepare_recovery(struct i2c_adapter *adap) { > + struct lpi2c_imx_struct *lpi2c_imx; > + > + lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter); > + > + pinctrl_select_state(lpi2c_imx->pinctrl, > +lpi2c_imx->pinctrl_pins_default); } > + > +/* > + * 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 lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx, > + struct platform_device *pdev) > +{ > + struct i2c_bus_recovery_info *rinfo = &lpi2c_imx->rinfo; > + > + lpi2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev); > + if (!lpi2c_imx->pinctrl || IS_ERR(lpi2c_imx->pinctrl)) { > + dev_info(&pdev->dev, "can't get pinctrl, bus recovery not > supported\n"); > + return PTR_ERR(lpi2c_imx->pinctrl); > + } > + > + lpi2c_imx->pinctrl_pins_default = pinctrl_lookup_state(lpi2c_imx->pinctrl, > + PINCTRL_STATE_DEFAULT); > + lpi2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(lpi2c_imx->pinctrl, > + "gpio"); > + rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN); > + rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", > +GPIOD_OUT_HIGH_OPEN_DRAIN); > + > + if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER || > + PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) { > + return -EPROBE_DEFER; > + } else if (IS_ERR(rinfo->sda_gpiod) || > + IS_ERR(rinfo->scl_gpiod) || > + IS_ERR(lpi2c_imx->pinctrl_pins_default) || > + IS_ERR(lpi2c_imx->pinctrl_pins_gpio)) { > + dev_dbg(&pdev->dev, "recovery information incomplete\n"); > + return 0; > + } > + > + dev_info(&pdev->dev, "using scl%s for recovery\n", > + rinfo->sda_gpiod ? ",sda" : ""); > + > + rinfo->prepare_recovery = lpi2c_imx_prepare_recovery; > + rinfo->unprepare_recovery = lpi2c_imx_unprepare_recovery; > + rinfo->recover_bus = i2c_generic_scl_recovery; > + lpi2c_imx->adapter.bus_recovery_info = rinfo; > + > + return 0; > +} > + > static u32 lpi2c_imx_func(struct i2c_adapter *adapter) { > return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -632,6 +709,12 > @@ static int lpi2c_imx_probe(struct platform_device *pdev) > lpi2c_imx->txfifosize = 1 << (temp & 0x0f); > lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f); > > + /* Init optional bus recovery function */ > + ret = lpi2c_imx_init_recovery_info(lpi2c_imx, pdev); > + /* Give it another chance if pinctrl used is not ready yet */ > + if (ret == -EPROBE_DEFER) > + goto rpm_disable; > + > ret = i2c_add_adapter(&lpi2c_imx->adapter); > if (ret) > goto rpm_disable; > -- > 2.25.1