Message ID | 1500990438-3894-3-git-send-email-aisheng.dong@nxp.com |
---|---|
State | New |
Headers | show |
On Tue, Jul 25, 2017 at 3:47 PM, Dong Aisheng <aisheng.dong@nxp.com> wrote: > The Rapid General-Purpose Input and Output with 2 Ports (RGPIO2P) > on MX7ULP is similar to GPIO on Vibrid. But unlike Vibrid, the > RGPIO2P has an extra Port Data Direction Register (PDDR) used > to configure the individual port pins for input or output. > > We introduce a FSL_GPIO_HAVE_PDDR with fsl_gpio_soc_data data > to distinguish this differences. And we support getting the output > status by checking the GPIO direction in PDDR. > > Cc: Linus Walleij <linus.walleij@linaro.org> > Cc: Alexandre Courbot <gnurou@gmail.com> > Cc: Shawn Guo <shawnguo@kernel.org> > Cc: Fugang Duan <fugang.duan@nxp.com> > Cc: Peter Chen <peter.chen@nxp.com> > Acked-by: Stefan Agner <stefan@agner.ch> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> This is mostly OK but I want a change. > +struct fsl_gpio_soc_data { > + u32 flags; > +}; Why introduce complex things like bitwise flags. That looks like premature optimization and trying to outsmart the compiler, don't do that. Add a bool have_paddr; simply, and use that in the code. Apart from that it is fine. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBMaW51cyBXYWxsZWlqIFttYWls dG86bGludXMud2FsbGVpakBsaW5hcm8ub3JnXQ0KPiBTZW50OiBUdWVzZGF5LCBBdWd1c3QgMDEs IDIwMTcgODowNCBQTQ0KPiBUbzogQS5zLiBEb25nDQo+IENjOiBsaW51eC1ncGlvQHZnZXIua2Vy bmVsLm9yZzsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOw0KPiBTaGF3biBH dW87IFN0ZWZhbiBBZ25lcjsgSmFja3kgQmFpOyBBbmR5IER1YW47IFBldGVyIENoZW47IERvbmcg QWlzaGVuZzsNCj4gU2FzY2hhIEhhdWVyOyBBbGV4YW5kcmUgQ291cmJvdA0KPiBTdWJqZWN0OiBS ZTogW1BBVENIIFJFU0VORCAyLzJdIGdwaW86IGdwaW8tdmY2MTA6IGFkZCBpbXg3dWxwIHN1cHBv cnQNCj4gDQo+IE9uIFR1ZSwgSnVsIDI1LCAyMDE3IGF0IDM6NDcgUE0sIERvbmcgQWlzaGVuZyA8 YWlzaGVuZy5kb25nQG54cC5jb20+IHdyb3RlOg0KPiANCj4gPiBUaGUgUmFwaWQgR2VuZXJhbC1Q dXJwb3NlIElucHV0IGFuZCBPdXRwdXQgd2l0aCAyIFBvcnRzIChSR1BJTzJQKSBvbg0KPiA+IE1Y N1VMUCBpcyBzaW1pbGFyIHRvIEdQSU8gb24gVmlicmlkLiBCdXQgdW5saWtlIFZpYnJpZCwgdGhl IFJHUElPMlANCj4gPiBoYXMgYW4gZXh0cmEgUG9ydCBEYXRhIERpcmVjdGlvbiBSZWdpc3RlciAo UEREUikgdXNlZCB0byBjb25maWd1cmUgdGhlDQo+ID4gaW5kaXZpZHVhbCBwb3J0IHBpbnMgZm9y IGlucHV0IG9yIG91dHB1dC4NCj4gPg0KPiA+IFdlIGludHJvZHVjZSBhIEZTTF9HUElPX0hBVkVf UEREUiB3aXRoIGZzbF9ncGlvX3NvY19kYXRhIGRhdGEgdG8NCj4gPiBkaXN0aW5ndWlzaCB0aGlz IGRpZmZlcmVuY2VzLiBBbmQgd2Ugc3VwcG9ydCBnZXR0aW5nIHRoZSBvdXRwdXQgc3RhdHVzDQo+ ID4gYnkgY2hlY2tpbmcgdGhlIEdQSU8gZGlyZWN0aW9uIGluIFBERFIuDQo+ID4NCj4gPiBDYzog TGludXMgV2FsbGVpaiA8bGludXMud2FsbGVpakBsaW5hcm8ub3JnPg0KPiA+IENjOiBBbGV4YW5k cmUgQ291cmJvdCA8Z251cm91QGdtYWlsLmNvbT4NCj4gPiBDYzogU2hhd24gR3VvIDxzaGF3bmd1 b0BrZXJuZWwub3JnPg0KPiA+IENjOiBGdWdhbmcgRHVhbiA8ZnVnYW5nLmR1YW5AbnhwLmNvbT4N Cj4gPiBDYzogUGV0ZXIgQ2hlbiA8cGV0ZXIuY2hlbkBueHAuY29tPg0KPiA+IEFja2VkLWJ5OiBT dGVmYW4gQWduZXIgPHN0ZWZhbkBhZ25lci5jaD4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBEb25nIEFp c2hlbmcgPGFpc2hlbmcuZG9uZ0BueHAuY29tPg0KPiANCj4gVGhpcyBpcyBtb3N0bHkgT0sgYnV0 IEkgd2FudCBhIGNoYW5nZS4NCj4gDQo+ID4gK3N0cnVjdCBmc2xfZ3Bpb19zb2NfZGF0YSB7DQo+ ID4gKyAgICAgICB1MzIgZmxhZ3M7DQo+ID4gK307DQo+IA0KPiBXaHkgaW50cm9kdWNlIGNvbXBs ZXggdGhpbmdzIGxpa2UgYml0d2lzZSBmbGFncy4gVGhhdCBsb29rcyBsaWtlIHByZW1hdHVyZQ0K PiBvcHRpbWl6YXRpb24gYW5kIHRyeWluZyB0byBvdXRzbWFydCB0aGUgY29tcGlsZXIsIGRvbid0 IGRvIHRoYXQuDQo+IA0KDQpJdCdzIGZvciBjb252ZW5pZW50bHkgYWRkaW5nIG5ldyBmbGFncyBp biB0aGUgZnV0dXJlLg0KQnV0IGl0J3MgdHJ1ZSB0aGF0IGl0IG1heSBiZSBwcmVtYXR1cmUgb3B0 aW1pemF0aW9uLg0KDQo+IEFkZCBhIGJvb2wgaGF2ZV9wYWRkcjsNCj4gDQo+IHNpbXBseSwgYW5k IHVzZSB0aGF0IGluIHRoZSBjb2RlLg0KPiANCg0KV2lsbCBkbyBpdC4NClRoYW5rcyBmb3IgdGhl IGFkdmljZS4NCg0KUmVnYXJkcw0KRG9uZyBBaXNoZW5nDQoNCj4gQXBhcnQgZnJvbSB0aGF0IGl0 IGlzIGZpbmUuDQo+IA0KPiBZb3VycywNCj4gTGludXMgV2FsbGVpag0K -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 521fbe3..a439d27 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -30,10 +30,15 @@ #define VF610_GPIO_PER_PORT 32 +struct fsl_gpio_soc_data { + u32 flags; +}; + struct vf610_gpio_port { struct gpio_chip gc; void __iomem *base; void __iomem *gpio_base; + const struct fsl_gpio_soc_data *sdata; u8 irqc[VF610_GPIO_PER_PORT]; int irq; }; @@ -43,6 +48,7 @@ struct vf610_gpio_port { #define GPIO_PCOR 0x08 #define GPIO_PTOR 0x0c #define GPIO_PDIR 0x10 +#define GPIO_PDDR 0x14 #define PORT_PCR(n) ((n) * 0x4) #define PORT_PCR_IRQC_OFFSET 16 @@ -59,10 +65,18 @@ struct vf610_gpio_port { #define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_LOGIC_ONE 0xc +/* SoC has a Port Data Direction Register (PDDR) */ +#define FSL_GPIO_HAVE_PDDR BIT(0) + static struct irq_chip vf610_gpio_irq_chip; +static const struct fsl_gpio_soc_data imx_data = { + .flags = FSL_GPIO_HAVE_PDDR, +}; + static const struct of_device_id vf610_gpio_dt_ids[] = { - { .compatible = "fsl,vf610-gpio" }, + { .compatible = "fsl,vf610-gpio", .data = NULL, }, + { .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, }, { /* sentinel */ } }; @@ -79,8 +93,18 @@ static inline u32 vf610_gpio_readl(void __iomem *reg) static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct vf610_gpio_port *port = gpiochip_get_data(gc); - - return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio)); + unsigned long mask = BIT(gpio); + void __iomem *addr; + + if (port->sdata && port->sdata->flags & FSL_GPIO_HAVE_PDDR) { + mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR); + addr = mask ? port->gpio_base + GPIO_PDOR : + port->gpio_base + GPIO_PDIR; + return !!(vf610_gpio_readl(addr) & BIT(gpio)); + } else { + return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) + & BIT(gpio)); + } } static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) @@ -96,12 +120,28 @@ static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { + struct vf610_gpio_port *port = gpiochip_get_data(chip); + unsigned long mask = BIT(gpio); + u32 val; + + if (port->sdata && port->sdata->flags & FSL_GPIO_HAVE_PDDR) { + val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); + val &= ~mask; + vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); + } + return pinctrl_gpio_direction_input(chip->base + gpio); } static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { + struct vf610_gpio_port *port = gpiochip_get_data(chip); + unsigned long mask = BIT(gpio); + + if (port->sdata && port->sdata->flags & FSL_GPIO_HAVE_PDDR) + vf610_gpio_writel(mask, port->gpio_base + GPIO_PDDR); + vf610_gpio_set(chip, gpio, value); return pinctrl_gpio_direction_output(chip->base + gpio); @@ -216,6 +256,8 @@ static struct irq_chip vf610_gpio_irq_chip = { static int vf610_gpio_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = of_match_device(vf610_gpio_dt_ids, + &pdev->dev); struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct vf610_gpio_port *port; @@ -227,6 +269,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; + port->sdata = of_id->data; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->base = devm_ioremap_resource(dev, iores); if (IS_ERR(port->base))