Message ID | 20230918-vf610-gpio-v3-4-ada82a17adc5@nxp.com |
---|---|
State | New |
Headers | show |
Series | [v3,1/6] dt-bindings: gpio: vf610: update gpio-ranges | expand |
Hi Peng, please see my notes below. On 23-09-18, Peng Fan (OSS) wrote: > From: Peng Fan <peng.fan@nxp.com> > > i.MX8ULP GPIO supports similar feature as i.MX7ULP GPIO, but i.MX8ULP is > not compatible with i.MX7ULP per binding doc. i.MX8ULP only has one > register base, not two base. > > Add a new of_device_id entry for i.MX8ULP. But to make the driver could > also support old bindings, check the compatible string first, before > check the device data. > > Signed-off-by: Peng Fan <peng.fan@nxp.com> > --- > drivers/gpio/gpio-vf610.c | 55 +++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 49 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c > index dbc7ba0ee72c..ef2455093708 100644 > --- a/drivers/gpio/gpio-vf610.c > +++ b/drivers/gpio/gpio-vf610.c > @@ -25,6 +25,7 @@ > struct fsl_gpio_soc_data { > /* SoCs has a Port Data Direction Register (PDDR) */ > bool have_paddr; > + bool is_imx8ulp; I would invert the logic: bool have_dual_base; > }; > > struct vf610_gpio_port { > @@ -60,13 +61,22 @@ struct vf610_gpio_port { > #define PORT_INT_EITHER_EDGE 0xb > #define PORT_INT_LOGIC_ONE 0xc > > +#define IMX8ULP_GPIO_BASE_OFF 0x40 > +#define IMX8ULP_BASE_OFF 0x80 > + static const struct fsl_gpio_soc_data vf610_data = { .have_dual_base = true, }; static const struct fsl_gpio_soc_data imx_data = { .have_paddr = true, .have_dual_base = true, }; static const struct fsl_gpio_soc_data imx8ulp_data = { .have_paddr = true, }; This also introduces .data pointer for the vf610 case and we could drop the 'port->sdata' guard from the 'if (port->sdata && port->sdata->paddr)' pattern. This of course would be an additional patch. > + > static const struct of_device_id vf610_gpio_dt_ids[] = { > { .compatible = "fsl,vf610-gpio", .data = NULL, }, > { .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, }, > + { .compatible = "fsl,imx8ulp-gpio", .data = &imx8ulp_data, }, > { /* sentinel */ } > }; > > @@ -255,6 +265,42 @@ static void vf610_gpio_disable_clk(void *data) > clk_disable_unprepare(data); > } > > +static int vf610_gpio_map_base(struct platform_device *pdev, struct vf610_gpio_port *port) > +{ > + struct device *dev = &pdev->dev; > + bool dual_base; > + > + /* support old compatible strings */ > + if (device_is_compatible(dev, "fsl,imx7ulp-gpio") && > + (device_is_compatible(dev, "fsl,imx93-gpio") || > + (device_is_compatible(dev, "fsl,imx8ulp-gpio")))) { > + dual_base = true; Move this part into probe() (see below) and drop the rest. > + } else if (port->sdata && port->sdata->is_imx8ulp) { > + dual_base = false; > + } else { > + dual_base = true; > + }; > + > + if (dual_base) { if (port->sdata-have_dual_base) { > + port->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(port->base)) > + return PTR_ERR(port->base); > + > + port->gpio_base = devm_platform_ioremap_resource(pdev, 1); > + if (IS_ERR(port->gpio_base)) > + return PTR_ERR(port->gpio_base); > + } else { > + port->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(port->base)) > + return PTR_ERR(port->base); > + > + port->gpio_base = port->base + IMX8ULP_GPIO_BASE_OFF; > + port->base = port->base + IMX8ULP_BASE_OFF; > + } > + > + return 0; > +} > + > static int vf610_gpio_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > @@ -269,13 +315,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) > return -ENOMEM; > > port->sdata = of_device_get_match_data(dev); /* Handle old device-tree bindings */ if (device_is_compatible(dev, "fsl,imx7ulp-gpio") && (device_is_compatible(dev, "fsl,imx93-gpio") || (device_is_compatible(dev, "fsl,imx8ulp-gpio")))) port->sdata->have_dual_base = true; > - port->base = devm_platform_ioremap_resource(pdev, 0); > - if (IS_ERR(port->base)) > - return PTR_ERR(port->base); > > - port->gpio_base = devm_platform_ioremap_resource(pdev, 1); > - if (IS_ERR(port->gpio_base)) > - return PTR_ERR(port->gpio_base); > + ret = vf610_gpio_map_base(pdev, port); > + if (ret) > + return ret; > > port->irq = platform_get_irq(pdev, 0); > if (port->irq < 0) Regards, Marco
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index dbc7ba0ee72c..ef2455093708 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -25,6 +25,7 @@ struct fsl_gpio_soc_data { /* SoCs has a Port Data Direction Register (PDDR) */ bool have_paddr; + bool is_imx8ulp; }; struct vf610_gpio_port { @@ -60,13 +61,22 @@ struct vf610_gpio_port { #define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_LOGIC_ONE 0xc +#define IMX8ULP_GPIO_BASE_OFF 0x40 +#define IMX8ULP_BASE_OFF 0x80 + static const struct fsl_gpio_soc_data imx_data = { .have_paddr = true, }; +static const struct fsl_gpio_soc_data imx8ulp_data = { + .have_paddr = true, + .is_imx8ulp = true, +}; + static const struct of_device_id vf610_gpio_dt_ids[] = { { .compatible = "fsl,vf610-gpio", .data = NULL, }, { .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, }, + { .compatible = "fsl,imx8ulp-gpio", .data = &imx8ulp_data, }, { /* sentinel */ } }; @@ -255,6 +265,42 @@ static void vf610_gpio_disable_clk(void *data) clk_disable_unprepare(data); } +static int vf610_gpio_map_base(struct platform_device *pdev, struct vf610_gpio_port *port) +{ + struct device *dev = &pdev->dev; + bool dual_base; + + /* support old compatible strings */ + if (device_is_compatible(dev, "fsl,imx7ulp-gpio") && + (device_is_compatible(dev, "fsl,imx93-gpio") || + (device_is_compatible(dev, "fsl,imx8ulp-gpio")))) { + dual_base = true; + } else if (port->sdata && port->sdata->is_imx8ulp) { + dual_base = false; + } else { + dual_base = true; + }; + + if (dual_base) { + port->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(port->base)) + return PTR_ERR(port->base); + + port->gpio_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(port->gpio_base)) + return PTR_ERR(port->gpio_base); + } else { + port->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(port->base)) + return PTR_ERR(port->base); + + port->gpio_base = port->base + IMX8ULP_GPIO_BASE_OFF; + port->base = port->base + IMX8ULP_BASE_OFF; + } + + return 0; +} + static int vf610_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -269,13 +315,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) return -ENOMEM; port->sdata = of_device_get_match_data(dev); - port->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(port->base)) - return PTR_ERR(port->base); - port->gpio_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(port->gpio_base)) - return PTR_ERR(port->gpio_base); + ret = vf610_gpio_map_base(pdev, port); + if (ret) + return ret; port->irq = platform_get_irq(pdev, 0); if (port->irq < 0)