[RESEND,2/2] gpio: gpio-vf610: add imx7ulp support
diff mbox

Message ID 1500990438-3894-3-git-send-email-aisheng.dong@nxp.com
State New
Headers show

Commit Message

Aisheng Dong July 25, 2017, 1:47 p.m. UTC
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>
---
 drivers/gpio/gpio-vf610.c | 49 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

Comments

Linus Walleij Aug. 1, 2017, 12:03 p.m. UTC | #1
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
Aisheng Dong Aug. 1, 2017, 1:48 p.m. UTC | #2
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

Patch
diff mbox

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))