Skip to contentSkip to conversation

rework gpio pxa driver for pinctrl

PATCH Superseded Haojian Zhuang 6 participants 29 messages Jan 23, 2013 – Jan 31, 2013 1 message not in the archive

Subsystems (6)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

cover rework gpio pxa driver for pinctrl

Remove all cpu depend macro. Bind gpio pxa driver with pinctrl driver.

#1 lore raw

PATCH 1/10 gpio: pxa: set initcall level to module init

gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted.

---
 drivers/gpio/gpio-pxa.c |    7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/gpio/gpio-pxa.c +1 -6
index 8325f58..9cc108d 100644
@@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = {
 		.of_match_table = of_match_ptr(pxa_gpio_dt_ids),
 	},
 };
-
-static int __init pxa_gpio_init(void)
-{
-	return platform_driver_register(&pxa_gpio_driver);
-}
-postcore_initcall(pxa_gpio_init);
+module_platform_driver(pxa_gpio_driver);
 
 #ifdef CONFIG_PM
 static int pxa_gpio_suspend(void)
Signature · 1 line
1.7.10.4
#2 lore raw

PATCH 1/10 gpio: pxa: set initcall level to module init

Quoted 5 lines · Haojian Zhuang

gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted.

Applied to my devel branch.

Thanks!
Linus Walleij

maintainer
#3 lore raw

PATCH 1/10 gpio: pxa: set initcall level to module init

In reply to Haojian Zhuang
Quoted 3 lines · Haojian Zhuang

gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted.

Hi Haojian,

If you switch gpio to module level, and as some modules use gpios in their init path, isn't it possible that some modules will fail their init, as GPIO API won't provide the gpio_*_value() functions ?

Cheers.

--
Robert

#4 lore raw

PATCH 1/10 gpio: pxa: set initcall level to module init

Quoted 11 lines · Robert Jarzmik
Quoted 3 lines · Haojian Zhuang

gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted.

Hi Haojian,

If you switch gpio to module level, and as some modules use gpios in their init path, isn't it possible that some modules will fail their init, as GPIO API won't provide the gpio_*_value() functions ?

gpio_request() should return EPROBE_DEFER, then the driver is using gpio API fails and it should be retried after a while. At that time, gpio driver should be launched
properly.

Regards
Haojian

#5 lore raw

PATCH 1/10 gpio: pxa: set initcall level to module init

Quoted 8 lines · Haojian Zhuang
Quoted 7 lines · Robert Jarzmik
Quoted 3 lines · Haojian Zhuang

gpio & pinctrl driver are used together. The pinctrl driver is already launched before gpio driver in Makefile. So set gpio driver to module init level. Otherwise, the sequence will be inverted.

Hi Haojian,

Quoted 8 lines
Quoted 3 lines

If you switch gpio to module level, and as some modules use gpios in their init path, isn't it possible that some modules will fail their init, as GPIO API won't provide the gpio_*_value() functions ?

gpio_request() should return EPROBE_DEFER, then the driver is using gpio API fails and it should be retried after a while. At that time, gpio driver should be launched
properly.

Correct. However it is not uncommon for modules to have untested errorpaths, such as:

ret = gpio_request(12);
if (ret)
return -ENODEV;

So you will not know before you test.

Then it is often common to have memory leaks in the errorpath...

So Tested-by: tags are appreciated.

Yours,
Linus Walleij

#6 lore raw

PATCH 2/10 gpio: pxa: identify ed mask reg with platform data

In reply to Haojian Zhuang

Avoid to judge whether edge mask register exists by CPU. Use platform data to identify it instead. The gpio edge mask register exists in MMP series SoC.

---
 arch/arm/mach-mmp/aspenite.c      |    7 +++++++
 arch/arm/mach-mmp/avengers_lite.c |    7 +++++++
 arch/arm/mach-mmp/brownstone.c    |    7 +++++++
 arch/arm/mach-mmp/flint.c         |    7 +++++++
 arch/arm/mach-mmp/gplugd.c        |    7 +++++++
 arch/arm/mach-mmp/tavorevb.c      |    7 +++++++
 arch/arm/mach-mmp/teton_bga.c     |    7 +++++++
 arch/arm/mach-mmp/ttc_dkb.c       |    7 +++++++
 drivers/gpio/gpio-pxa.c           |   11 ++++++++++-
 include/linux/gpio-pxa.h          |    1 +
 10 files changed, 67 insertions(+), 1 deletion(-)
arch/arm/mach-mmp/aspenite.c +7 -0
index e5dba9c..ee1fb62 100644
@@ -9,6 +9,7 @@
  *  publishhed by the Free Software Foundation.
  */
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -110,6 +111,10 @@ static unsigned long common_pin_config[] __initdata = {
 	GPIO121_KP_MKIN4,
 };
 
+static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct smc91x_platdata smc91x_info = {
 	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
 };
@@ -248,6 +253,8 @@ static void __init common_init(void)
 	pxa168_add_nand(&aspenite_nand_info);
 	pxa168_add_fb(&aspenite_lcd_info);
 	pxa168_add_keypad(&aspenite_keypad_info);
+	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&pxa168_device_gpio);
 
 	/* off-chip devices */
arch/arm/mach-mmp/avengers_lite.c +7 -0
index 603542a..8b4b1ae 100644
@@ -12,6 +12,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/gpio-pxa.h>
 #include <linux/platform_device.h>
 
 #include <asm/mach-types.h>
@@ -32,12 +33,18 @@ static unsigned long avengers_lite_pin_config_V16F[] __initdata = {
 	GPIO89_UART2_RXD,
 };
 
+static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static void __init avengers_lite_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F));
 
 	/* on-chip devices */
 	pxa168_add_uart(2);
+	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&pxa168_device_gpio);
 }
 
arch/arm/mach-mmp/brownstone.c +7 -0
index 5cb769c..0454488 100644
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/gpio-pxa.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
@@ -104,6 +105,10 @@ static unsigned long brownstone_pin_config[] __initdata = {
 	GPIO89_GPIO,
 };
 
+static struct pxa_gpio_platform_data mmp2_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct regulator_consumer_supply max8649_supply[] = {
 	REGULATOR_SUPPLY("vcc_core", NULL),
 };
@@ -202,6 +207,8 @@ static void __init brownstone_init(void)
 	/* on-chip devices */
 	mmp2_add_uart(1);
 	mmp2_add_uart(3);
+	platform_device_add_data(&mmp2_device_gpio, &mmp2_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&mmp2_device_gpio);
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
 	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
arch/arm/mach-mmp/flint.c +7 -0
index 8059cc0..7ec873c 100644
@@ -16,6 +16,7 @@
 #include <linux/smc91x.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 #include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
@@ -77,6 +78,10 @@ static unsigned long flint_pin_config[] __initdata = {
 	GPIO160_ND_RDY1,
 };
 
+static struct pxa_gpio_platform_data mmp2_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct smc91x_platdata flint_smc91x_info = {
 	.flags  = SMC91X_USE_16BIT | SMC91X_NOWAIT,
 };
@@ -111,6 +116,8 @@ static void __init flint_init(void)
 	/* on-chip devices */
 	mmp2_add_uart(1);
 	mmp2_add_uart(2);
+	platform_device_add_data(&mmp2_device_gpio, &mmp2_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&mmp2_device_gpio);
 
 	/* off-chip devices */
arch/arm/mach-mmp/gplugd.c +7 -0
index 5c3d61e..d592041 100644
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -127,6 +128,10 @@ static unsigned long gplugd_pin_config[] __initdata = {
 	GPIO116_I2S_TXD
 };
 
+static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct i2c_board_info gplugd_i2c_board_info[] = {
 	{
 		.type = "isl1208",
@@ -185,6 +190,8 @@ static void __init gplugd_init(void)
 	pxa168_add_uart(3);
 	pxa168_add_ssp(1);
 	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&pxa168_device_gpio);
 
 	pxa168_add_eth(&gplugd_eth_platform_data);
arch/arm/mach-mmp/tavorevb.c +7 -0
index b28f908..a855e69 100644
@@ -8,6 +8,7 @@
  *  publishhed by the Free Software Foundation.
  */
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -60,6 +61,10 @@ static unsigned long tavorevb_pin_config[] __initdata = {
 	DF_RDY0_DF_RDY0,
 };
 
+static struct pxa_gpio_platform_data ttc_dkb_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct smc91x_platdata tavorevb_smc91x_info = {
 	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
 };
@@ -93,6 +98,8 @@ static void __init tavorevb_init(void)
 
 	/* on-chip devices */
 	pxa910_add_uart(1);
+	platform_device_add_data(&pxa910_device_gpio, &ttc_dkb_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&pxa910_device_gpio);
 
 	/* off-chip devices */
arch/arm/mach-mmp/teton_bga.c +7 -0
index dd30ea7..9f64f37 100644
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 #include <linux/input.h>
 #include <linux/platform_data/keypad-pxa27x.h>
 #include <linux/i2c.h>
@@ -49,6 +50,10 @@ static unsigned long teton_bga_pin_config[] __initdata = {
 	GPIO78_GPIO,
 };
 
+static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static unsigned int teton_bga_matrix_key_map[] = {
 	KEY(0, 6, KEY_ESC),
 	KEY(0, 7, KEY_ENTER),
@@ -79,6 +84,8 @@ static void __init teton_bga_init(void)
 	pxa168_add_uart(1);
 	pxa168_add_keypad(&teton_bga_keypad_info);
 	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info));
+	platform_device_add_data(&pxa168_device_gpio, &pxa168_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_device_register(&pxa168_device_gpio);
 }
 
arch/arm/mach-mmp/ttc_dkb.c +7 -0
index ce55fd8..74081cd 100644
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/platform_data/mv_usb.h>
 
@@ -73,6 +74,10 @@ static unsigned long ttc_dkb_pin_config[] __initdata = {
 	DF_RDY0_DF_RDY0,
 };
 
+static struct pxa_gpio_platform_data ttc_dkb_gpio_pdata = {
+	.ed_mask	= 1,
+};
+
 static struct mtd_partition ttc_dkb_onenand_partitions[] = {
 	{
 		.name		= "bootloader",
@@ -196,6 +201,8 @@ static void __init ttc_dkb_init(void)
 
 	/* off-chip devices */
 	pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
+	platform_device_add_data(&pxa910_device_gpio, &ttc_dkb_gpio_pdata,
+				 sizeof(struct pxa_gpio_platform_data));
 	platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
 
 #ifdef CONFIG_USB_MV_UDC
drivers/gpio/gpio-pxa.c +10 -1
index 9cc108d..8e66c6b 100644
@@ -493,6 +493,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
 	int ret, nr_banks, nr_gpios;
+	struct pxa_gpio_platform_data *pdata;
 	struct device_node *prev, *next, *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
@@ -501,6 +502,14 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Failed to find gpio controller\n");
 		return -EFAULT;
 	}
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	ret = of_find_property(np, "marvell,gpio-ed-mask", NULL);
+	if (ret)
+		pdata->ed_mask = 1;
+	/* set the platform data */
+	pdev->dev.platform_data = pdata;
 	gpio_type = (int)of_id->data;
 
 	next = of_get_next_child(np, NULL);
@@ -604,7 +613,7 @@ static int pxa_gpio_probe(struct platform_device *pdev)
 		writel_relaxed(0, c->regbase + GRER_OFFSET);
 		writel_relaxed(~0,c->regbase + GEDR_OFFSET);
 		/* unmask GPIO edge detect for AP side */
-		if (gpio_is_mmp_type(gpio_type))
+		if (info->ed_mask)
 			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
 	}
 
include/linux/gpio-pxa.h +1 -0
index d755b28..d88d6e3 100644
@@ -14,6 +14,7 @@ extern int pxa_last_gpio;
 extern int pxa_irq_to_gpio(int irq);
 
 struct pxa_gpio_platform_data {
+	unsigned ed_mask;	/* not 0 means ed_mask reg is available */
 	int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
 };
 
Signature · 1 line
1.7.10.4
#7 lore raw

PATCH 2/10 gpio: pxa: identify ed mask reg with platform data

Quoted 5 lines · Haojian Zhuang

Avoid to judge whether edge mask register exists by CPU. Use platform data to identify it instead. The gpio edge mask register exists in MMP series SoC.

ARM SoC folks: do you approve (ACK) this patch so I can apply it to my GPIO tree?

It looks allright to me, I just want to know so that there are no huge changes around this code in the ARM SoC tree that will cause trouble.

Yours,
Linus Walleij

#8 lore raw

PATCH 2/10 gpio: pxa: identify ed mask reg with platform data

Quoted 7 lines · Linus Walleij
Quoted 4 lines · Haojian Zhuang

Avoid to judge whether edge mask register exists by CPU. Use platform data to identify it instead. The gpio edge mask register exists in MMP series SoC.

Quoted 8 lines
Quoted 1 line

ARM SoC folks: do you approve (ACK) this patch so I can apply it to my GPIO tree?

It looks allright to me, I just want to know so that there are no huge changes around this code in the ARM SoC tree that will cause trouble.

Actually this goes for the whole series.

It touches a lot of code in arch/arm/*

Haoijan, do you prefer if ACK it so you can take it up through ARM SoC?

I'm OK to take it all through my GPIO tree as well if the ARM people ACK them.

Yours,
Linus Walleij

maintainer
#9 lore raw

PATCH 2/10 gpio: pxa: identify ed mask reg with platform data

Quoted 20 lines · Linus Walleij
Quoted 7 lines · Linus Walleij
Quoted 4 lines · Haojian Zhuang

Avoid to judge whether edge mask register exists by CPU. Use platform data to identify it instead. The gpio edge mask register exists in MMP series SoC.

Quoted 8 lines
Quoted 1 line

ARM SoC folks: do you approve (ACK) this patch so I can apply it to my GPIO tree?

It looks allright to me, I just want to know so that there are no huge changes around this code in the ARM SoC tree that will cause trouble.

Actually this goes for the whole series.

Quoted 8 lines

It touches a lot of code in arch/arm/*

Haoijan, do you prefer if ACK it so you can take it up through ARM SoC?

I'm OK to take it all through my GPIO tree as well if the ARM people ACK them.

I'm fine to merge into gpio git tree.

#10 lore raw

PATCH 2/10 gpio: pxa: identify ed mask reg with platform data

In reply to Linus Walleij
Quoted 20 lines · Linus Walleij
Quoted 7 lines · Linus Walleij
Quoted 4 lines · Haojian Zhuang

Avoid to judge whether edge mask register exists by CPU. Use platform data to identify it instead. The gpio edge mask register exists in MMP series SoC.

Quoted 8 lines
Quoted 1 line

ARM SoC folks: do you approve (ACK) this patch so I can apply it to my GPIO tree?

It looks allright to me, I just want to know so that there are no huge changes around this code in the ARM SoC tree that will cause trouble.

Actually this goes for the whole series.

Quoted 7 lines

It touches a lot of code in arch/arm/*

Haoijan, do you prefer if ACK it so you can take it up through ARM SoC?

I'm OK to take it all through my GPIO tree as well if the ARM people ACK them.

The series is:

Just in case, feel free to apply these to a topic branch that we can pull in as a shared one in case of (excessive) conflicts. I haven't seen any sign of any yet though.

-Olof

#11 lore raw

PATCH 3/10 gpio: pxa: avoid to use global irq base

In reply to Haojian Zhuang

Avoid to use global irq_base in gpio-pxa driver. Define irq_base in each pxa_gpio_chip instead. Then we can avoid to use macro PXA_GPIO_TO_IRQ() & MMP_GPIO_TO_IRQ().

---
 arch/arm/mach-pxa/pxa25x.c |    2 +-
 arch/arm/mach-pxa/pxa27x.c |    2 +-
 drivers/gpio/gpio-pxa.c    |  142 ++++++++++++++++++++++----------------------
 include/linux/gpio-pxa.h   |    4 +-
 4 files changed, 77 insertions(+), 73 deletions(-)
arch/arm/mach-pxa/pxa25x.c +1 -1
index 3f5171e..f4c293a 100644
@@ -289,7 +289,7 @@ static inline void pxa25x_init_pm(void) {}
 
 static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = pxa_irq_to_gpio(d->irq);
+	int gpio = pxa_irq_to_gpio(d);
 	uint32_t mask = 0;
 
 	if (gpio >= 0 && gpio < 85)
arch/arm/mach-pxa/pxa27x.c +1 -1
index 8047ee0..257d936 100644
@@ -356,7 +356,7 @@ static inline void pxa27x_init_pm(void) {}
  */
 static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = pxa_irq_to_gpio(d->irq);
+	int gpio = pxa_irq_to_gpio(d);
 	uint32_t mask;
 
 	if (gpio >= 0 && gpio < 128)
drivers/gpio/gpio-pxa.c +72 -70

238 lines not on this page · raw message

include/linux/gpio-pxa.h +3 -1
index d88d6e3..bdee118 100644
@@ -1,6 +1,8 @@
 #ifndef __GPIO_PXA_H
 #define __GPIO_PXA_H
 
+#include <linux/irq.h>
+
 #define GPIO_bit(x)	(1 << ((x) & 0x1f))
 
 #define gpio_to_bank(gpio)	((gpio) >> 5)
@@ -11,7 +13,7 @@
  */
 extern int pxa_last_gpio;
 
-extern int pxa_irq_to_gpio(int irq);
+extern int pxa_irq_to_gpio(struct irq_data *d);
 
 struct pxa_gpio_platform_data {
 	unsigned ed_mask;	/* not 0 means ed_mask reg is available */
Signature · 1 line
1.7.10.4
#12 lore raw

PATCH 3/10 gpio: pxa: avoid to use global irq base

Quoted 11 lines · Haojian Zhuang

Avoid to use global irq_base in gpio-pxa driver. Define irq_base in each pxa_gpio_chip instead. Then we can avoid to use macro PXA_GPIO_TO_IRQ() & MMP_GPIO_TO_IRQ().

---
 arch/arm/mach-pxa/pxa25x.c |    2 +-
 arch/arm/mach-pxa/pxa27x.c |    2 +-
 drivers/gpio/gpio-pxa.c    |  142 ++++++++++++++++++++++----------------------
 include/linux/gpio-pxa.h   |    4 +-
 4 files changed, 77 insertions(+), 73 deletions(-)

[...]

Quoted 4 lines
drivers/gpio/gpio-pxa.c +0 -0
index 8e66c6b..da6e7fd 100644

[...]

drivers/gpio/gpio-pxa.c static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, · line 458

Quoted 9 lines
drivers/gpio/gpio-pxa.c +1 -1
@@ -485,7 +452,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-const struct irq_domain_ops pxa_irq_domain_ops = {
+static const struct irq_domain_ops pxa_irq_domain_ops = {
 	.map	= pxa_irq_domain_map,
 	.xlate	= irq_domain_xlate_twocell,
 };

You should also move this out of CONFIG_OF as I don't think it is a dependency, and also otherwise you get the below...

Quoted 51 lines
drivers/gpio/gpio-pxa.c +32 -8
@@ -529,14 +496,6 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
 	nr_gpios = nr_banks << 5;
 	pxa_last_gpio = nr_gpios - 1;
 
-	irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
-	if (irq_base < 0) {
-		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
-		goto err;
-	}
-	domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
-				       &pxa_irq_domain_ops, NULL);
-	pxa_gpio_of_node = np;
 	return 0;
 err:
 	iounmap(gpio_reg_base);
@@ -546,6 +505,56 @@ err:
 #define pxa_gpio_probe_dt(pdev)		(-1)
 #endif
 
+static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
+			      int (*set_wake)(unsigned int, unsigned int))
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = devm_kzalloc(&pdev->dev, nbanks * sizeof(*chips), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = gpio_reg_base + BANK_OFF(i);
+		chips[i].set_wake = set_wake;
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+		c->to_irq = pxa_gpio_to_irq;
+#ifdef CONFIG_OF_GPIO
+		c->of_node = pxa_gpio_of_node;
+		c->of_xlate = pxa_gpio_of_xlate;
+		c->of_gpio_n_cells = 2;
+#endif

drivers/gpio/gpio-pxa.c err: · line 549

Quoted 10 lines
drivers/gpio/gpio-pxa.c +10 -0
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+
+		chips[i].irq_base = irq_alloc_descs(-1, 0, c->ngpio, 0);
+		if (chips[i].irq_base < 0)
+			return -EINVAL;
+		if (!irq_domain_add_legacy(pdev->dev.of_node, c->ngpio,
+					   chips[i].irq_base, 0,
+					   &pxa_irq_domain_ops, &chips[i]))

if !CONFIG_OF, you get:
drivers/gpio/gpio-pxa.c:479: error: 'pxa_irq_domain_ops' undeclared (first use in this function)

Also, for !CONFIG_IRQ_DOMAIN, you get:
drivers/gpio/gpio-pxa.c: In function 'pxa_init_gpio_chip':
drivers/gpio/gpio-pxa.c:477: error: implicit declaration of function 'irq_domain_add_legacy'

Should we select IRQ_DOMAIN for PXA?
Will it work for other drivers?

Quoted 11 lines
drivers/gpio/gpio-pxa.c +8 -0
+			return -ENODEV;
+
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
 static int pxa_gpio_probe(struct platform_device *pdev)
 {
 	struct pxa_gpio_chip *c;

[...]

Signature · 2 lines
Regards,
Igor.
#13 lore raw

PATCH 3/10 gpio: pxa: avoid to use global irq base

Quoted 100 lines · Igor Grinberg
Quoted 11 lines · Haojian Zhuang

Avoid to use global irq_base in gpio-pxa driver. Define irq_base in each pxa_gpio_chip instead. Then we can avoid to use macro PXA_GPIO_TO_IRQ() & MMP_GPIO_TO_IRQ().

---
 arch/arm/mach-pxa/pxa25x.c |    2 +-
 arch/arm/mach-pxa/pxa27x.c |    2 +-
 drivers/gpio/gpio-pxa.c    |  142 ++++++++++++++++++++++----------------------
 include/linux/gpio-pxa.h   |    4 +-
 4 files changed, 77 insertions(+), 73 deletions(-)

[...]

Quoted 4 lines
drivers/gpio/gpio-pxa.c +0 -0
index 8e66c6b..da6e7fd 100644

[...]

drivers/gpio/gpio-pxa.c static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, · line 458

Quoted 9 lines
drivers/gpio/gpio-pxa.c +1 -1
@@ -485,7 +452,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
      return 0;
 }
 
-const struct irq_domain_ops pxa_irq_domain_ops = {
+static const struct irq_domain_ops pxa_irq_domain_ops = {
      .map    = pxa_irq_domain_map,
      .xlate  = irq_domain_xlate_twocell,
 };

You should also move this out of CONFIG_OF as I don't think it is a dependency, and also otherwise you get the below...

Quoted 51 lines
drivers/gpio/gpio-pxa.c +32 -8
@@ -529,14 +496,6 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
      nr_gpios = nr_banks << 5;
      pxa_last_gpio = nr_gpios - 1;
 
-     irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
-     if (irq_base < 0) {
-             dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
-             goto err;
-     }
-     domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
-                                    &pxa_irq_domain_ops, NULL);
-     pxa_gpio_of_node = np;
      return 0;
 err:
      iounmap(gpio_reg_base);
@@ -546,6 +505,56 @@ err:
 #define pxa_gpio_probe_dt(pdev)              (-1)
 #endif
 
+static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
+                           int (*set_wake)(unsigned int, unsigned int))
+{
+     int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+     struct pxa_gpio_chip *chips;
+
+     chips = devm_kzalloc(&pdev->dev, nbanks * sizeof(*chips), GFP_KERNEL);
+     if (chips == NULL) {
+             pr_err("%s: failed to allocate GPIO chips\n", __func__);
+             return -ENOMEM;
+     }
+
+     for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+             struct gpio_chip *c = &chips[i].chip;
+
+             sprintf(chips[i].label, "gpio-%d", i);
+             chips[i].regbase = gpio_reg_base + BANK_OFF(i);
+             chips[i].set_wake = set_wake;
+
+             c->base  = gpio;
+             c->label = chips[i].label;
+
+             c->direction_input  = pxa_gpio_direction_input;
+             c->direction_output = pxa_gpio_direction_output;
+             c->get = pxa_gpio_get;
+             c->set = pxa_gpio_set;
+             c->to_irq = pxa_gpio_to_irq;
+#ifdef CONFIG_OF_GPIO
+             c->of_node = pxa_gpio_of_node;
+             c->of_xlate = pxa_gpio_of_xlate;
+             c->of_gpio_n_cells = 2;
+#endif

drivers/gpio/gpio-pxa.c err: · line 549

Quoted 10 lines
drivers/gpio/gpio-pxa.c +10 -0
+
+             /* number of GPIOs on last bank may be less than 32 */
+             c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+
+             chips[i].irq_base = irq_alloc_descs(-1, 0, c->ngpio, 0);
+             if (chips[i].irq_base < 0)
+                     return -EINVAL;
+             if (!irq_domain_add_legacy(pdev->dev.of_node, c->ngpio,
+                                        chips[i].irq_base, 0,
+                                        &pxa_irq_domain_ops, &chips[i]))

if !CONFIG_OF, you get:
drivers/gpio/gpio-pxa.c:479: error: 'pxa_irq_domain_ops' undeclared (first use in this function)

Quoted 7 lines

Also, for !CONFIG_IRQ_DOMAIN, you get:
drivers/gpio/gpio-pxa.c: In function 'pxa_init_gpio_chip':
drivers/gpio/gpio-pxa.c:477: error: implicit declaration of function 'irq_domain_add_legacy'

Should we select IRQ_DOMAIN for PXA?
Will it work for other drivers?

We could use IRQ_DOMAIN. After all these patches are applied, there's no CONFIG_IRQ_DOMAIN in pxa-gpio.c.
I tested the gpio driver on pxa910 (arch/mmp) w/wo CONFIG_OF. It works.

Thanks for your test. I'm sorry that I didn't do enough build test on pxa. I'll fix all these issues.

Quoted 18 lines

drivers/gpio/gpio-pxa.c err: · line 560

Quoted 11 lines
drivers/gpio/gpio-pxa.c +8 -0
+                     return -ENODEV;
+
+             gpiochip_add(c);
+     }
+     pxa_gpio_chips = chips;
+     return 0;
+}
+
 static int pxa_gpio_probe(struct platform_device *pdev)
 {
      struct pxa_gpio_chip *c;

[...]

--
Regards,
Igor.

#14 lore raw

PATCH 4/10 gpio: pxa: use platform data for gpio inverted

In reply to Haojian Zhuang

Avoid to judge whether gpio is inverted by identifying cpu in gpio driver. Move this into platform data of gpio driver.

---
 arch/arm/mach-pxa/pxa25x.c |    3 +++
 drivers/gpio/gpio-pxa.c    |   41 ++++++++++++++++++++++++++---------------
 include/linux/gpio-pxa.h   |    1 +
 3 files changed, 30 insertions(+), 15 deletions(-)
arch/arm/mach-pxa/pxa25x.c +3 -0
index f4c293a..8d77090 100644
@@ -340,6 +340,9 @@ void __init pxa25x_map_io(void)
 }
 
 static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
+#ifdef CONFIG_CPU_PXA26x
+	.inverted = 1,
+#endif
 	.gpio_set_wake = gpio_set_wake,
 };
 
drivers/gpio/gpio-pxa.c +26 -15

124 lines not on this page · raw message

include/linux/gpio-pxa.h +1 -0
index bdee118..c8d07be5 100644
@@ -17,6 +17,7 @@ extern int pxa_irq_to_gpio(struct irq_data *d);
 
 struct pxa_gpio_platform_data {
 	unsigned ed_mask;	/* not 0 means ed_mask reg is available */
+	unsigned inverted;	/* only valid for PXA26x */
 	int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
 };
 
Signature · 1 line
1.7.10.4
#15 lore raw

PATCH 4/10 gpio: pxa: use platform data for gpio inverted

Quoted 4 lines · Haojian Zhuang

Avoid to judge whether gpio is inverted by identifying cpu in gpio driver. Move this into platform data of gpio driver.

(...)

drivers/gpio/gpio-pxa.c struct pxa_gpio_chip { · line 75

Quoted 7 lines

+++ b/drivers/gpio/gpio-pxa.c

drivers/gpio/gpio-pxa.c +1 -0
@@ -71,6 +71,7 @@ struct pxa_gpio_chip {
        struct gpio_chip chip;
        void __iomem    *regbase;
        unsigned int    irq_base;
+       unsigned int    inverted;
        char label[10];

I would use bool for this.

(No big deal, but if you want to nitpick..)

Yours,
Linus Walleij

#16 lore raw

PATCH 5/10 gpio: pxa: remove gpio_type

In reply to Haojian Zhuang

Since gpio_type is used to check whether gafr register is valid. So move it into platform data.

---
 arch/arm/mach-pxa/pxa25x.c |    1 +
 arch/arm/mach-pxa/pxa27x.c |    1 +
 drivers/gpio/gpio-pxa.c    |   43 ++++++-------------------------------------
 include/linux/gpio-pxa.h   |    1 +
 4 files changed, 9 insertions(+), 37 deletions(-)
arch/arm/mach-pxa/pxa25x.c +1 -0
index 8d77090..90415a6 100644
@@ -343,6 +343,7 @@ static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
 #ifdef CONFIG_CPU_PXA26x
 	.inverted = 1,
 #endif
+	.gafr = 1,
 	.gpio_set_wake = gpio_set_wake,
 };
 
arch/arm/mach-pxa/pxa27x.c +1 -0
index 257d936..91ac5d9 100644
@@ -422,6 +422,7 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
 }
 
 static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
+	.gafr = 1,
 	.gpio_set_wake = gpio_set_wake,
 };
 
drivers/gpio/gpio-pxa.c +6 -37

118 lines not on this page · raw message

include/linux/gpio-pxa.h +1 -0
index c8d07be5..5a9e003 100644
@@ -17,6 +17,7 @@ extern int pxa_irq_to_gpio(struct irq_data *d);
 
 struct pxa_gpio_platform_data {
 	unsigned ed_mask;	/* not 0 means ed_mask reg is available */
+	unsigned gafr;		/* only valid for PXA25x/PXA26x/PXA27x */
 	unsigned inverted;	/* only valid for PXA26x */
 	int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
 };
Signature · 1 line
1.7.10.4
#17 lore raw

PATCH 5/10 gpio: pxa: remove gpio_type

Quoted 4 lines · Haojian Zhuang

Since gpio_type is used to check whether gafr register is valid. So move it into platform data.

(...)

drivers/gpio/gpio-pxa.c struct pxa_gpio_chip { · line 76

Quoted 7 lines

+++ b/drivers/gpio/gpio-pxa.c

drivers/gpio/gpio-pxa.c +1 -0
@@ -72,6 +72,7 @@ struct pxa_gpio_chip {
        void __iomem    *regbase;
        unsigned int    irq_base;
        unsigned int    inverted;
+       unsigned int    gafr;
        char label[10];

Also looks like some kind of a bool.

Yours,
Linus Walleij

#18 lore raw

PATCH 5/10 gpio: pxa: remove gpio_type

Quoted 10 lines · Linus Walleij
Quoted 4 lines · Haojian Zhuang

Since gpio_type is used to check whether gafr register is valid. So move it into platform data.

(...)

Quoted 9 lines

drivers/gpio/gpio-pxa.c struct pxa_gpio_chip { · line 76

Quoted 7 lines

+++ b/drivers/gpio/gpio-pxa.c

drivers/gpio/gpio-pxa.c +1 -0
@@ -72,6 +72,7 @@ struct pxa_gpio_chip {
        void __iomem    *regbase;
        unsigned int    irq_base;
        unsigned int    inverted;
+       unsigned int    gafr;
        char label[10];

Also looks like some kind of a bool.

Actually, no... GAFR is the PXA Alternate Function register name, so unsigned int (or u32) is good.

Signature · 2 lines
Regards,
Igor.
#19 lore raw

PATCH 5/10 gpio: pxa: remove gpio_type

Quoted 21 lines · Igor Grinberg
Quoted 10 lines · Linus Walleij
Quoted 4 lines · Haojian Zhuang

Since gpio_type is used to check whether gafr register is valid. So move it into platform data.

(...)

Quoted 9 lines

drivers/gpio/gpio-pxa.c struct pxa_gpio_chip { · line 76

Quoted 7 lines

+++ b/drivers/gpio/gpio-pxa.c

drivers/gpio/gpio-pxa.c +1 -0
@@ -72,6 +72,7 @@ struct pxa_gpio_chip {
        void __iomem    *regbase;
        unsigned int    irq_base;
        unsigned int    inverted;
+       unsigned int    gafr;
        char label[10];

Also looks like some kind of a bool.

Quoted 2 lines

Actually, no... GAFR is the PXA Alternate Function register name, so unsigned int (or u32) is good.

Alternate funtion register?

Thanks for telling!

So this is about muxing and should thus be in the pinctrl framework?

Or is there some criss-cross with pinctrl already that I'm not aware of?

Yours,
Linus Walleij

#20 lore raw

PATCH 6/10 gpio: pxa: define nr gpios in platform data

In reply to Haojian Zhuang

Avoid to define gpio numbers in gpio driver. Define it in platform data instead.

---
 arch/arm/mach-mmp/aspenite.c      |    1 +
 arch/arm/mach-mmp/avengers_lite.c |    1 +
 arch/arm/mach-mmp/brownstone.c    |    1 +
 arch/arm/mach-mmp/flint.c         |    1 +
 arch/arm/mach-mmp/gplugd.c        |    1 +
 arch/arm/mach-mmp/tavorevb.c      |    1 +
 arch/arm/mach-mmp/teton_bga.c     |    1 +
 arch/arm/mach-mmp/ttc_dkb.c       |    1 +
 arch/arm/mach-pxa/pxa25x.c        |    3 +++
 arch/arm/mach-pxa/pxa27x.c        |    1 +
 arch/arm/mach-pxa/pxa3xx.c        |   15 +++++++++++-
 drivers/gpio/gpio-pxa.c           |   48 +++++++------------------------------
 include/linux/gpio-pxa.h          |    1 +
 13 files changed, 35 insertions(+), 41 deletions(-)
arch/arm/mach-mmp/aspenite.c +1 -0
index ee1fb62..f5aea07 100644
@@ -112,6 +112,7 @@ static unsigned long common_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/avengers_lite.c +1 -0
index 8b4b1ae..2f93f8f 100644
@@ -34,6 +34,7 @@ static unsigned long avengers_lite_pin_config_V16F[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/brownstone.c +1 -0
index 0454488..7f07cc5 100644
@@ -106,6 +106,7 @@ static unsigned long brownstone_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data mmp2_gpio_pdata = {
+	.nr_gpios	= 192,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/flint.c +1 -0
index 7ec873c..bf37d97 100644
@@ -79,6 +79,7 @@ static unsigned long flint_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data mmp2_gpio_pdata = {
+	.nr_gpios	= 192,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/gplugd.c +1 -0
index d592041..47808e1 100644
@@ -129,6 +129,7 @@ static unsigned long gplugd_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/tavorevb.c +1 -0
index a855e69..dd4a22b 100644
@@ -62,6 +62,7 @@ static unsigned long tavorevb_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data ttc_dkb_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/teton_bga.c +1 -0
index 9f64f37..b3e7bf9 100644
@@ -51,6 +51,7 @@ static unsigned long teton_bga_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data pxa168_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-mmp/ttc_dkb.c +1 -0
index 74081cd..597268c 100644
@@ -75,6 +75,7 @@ static unsigned long ttc_dkb_pin_config[] __initdata = {
 };
 
 static struct pxa_gpio_platform_data ttc_dkb_gpio_pdata = {
+	.nr_gpios	= 128,
 	.ed_mask	= 1,
 };
 
arch/arm/mach-pxa/pxa25x.c +3 -0
index 90415a6..eb82ece 100644
@@ -342,6 +342,9 @@ void __init pxa25x_map_io(void)
 static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
 #ifdef CONFIG_CPU_PXA26x
 	.inverted = 1,
+	.nr_gpios = 90,
+#else
+	.nr_gpios = 85,
 #endif
 	.gafr = 1,
 	.gpio_set_wake = gpio_set_wake,
arch/arm/mach-pxa/pxa27x.c +1 -0
index 91ac5d9..8e6b164 100644
@@ -423,6 +423,7 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
 
 static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
 	.gafr = 1,
+	.nr_gpios = 121,
 	.gpio_set_wake = gpio_set_wake,
 };
 
arch/arm/mach-pxa/pxa3xx.c +14 -1
index 656a1bb..a0cc797 100644
@@ -435,6 +435,10 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)
 	pxa_register_device(&pxa3xx_device_i2c_power, info);
 }
 
+static struct pxa_gpio_platform_data pxa3xx_gpio_info __initdata = {
+	.nr_gpios = 128,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&pxa_device_gpio,
 	&pxa27x_device_udc,
@@ -482,8 +486,17 @@ static int __init pxa3xx_init(void)
 		register_syscore_ops(&pxa3xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
-		if (!of_have_populated_dt())
+		if (!of_have_populated_dt()) {
+			if (cpu_is_pxa93x())
+				pxa3xx_gpio_info.nr_gpios = 192;
+			ret = platform_device_add_data(&pxa_device_gpio,
+					&pxa3xx_gpio_info,
+					sizeof(struct pxa_gpio_platform_data);
+			if (ret < 0)
+				break;
+
 			ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+		}
 	}
 
 	return ret;
drivers/gpio/gpio-pxa.c +8 -40

85 lines not on this page · raw message

include/linux/gpio-pxa.h +1 -0
index 5a9e003..cf17f4c 100644
@@ -19,6 +19,7 @@ struct pxa_gpio_platform_data {
 	unsigned ed_mask;	/* not 0 means ed_mask reg is available */
 	unsigned gafr;		/* only valid for PXA25x/PXA26x/PXA27x */
 	unsigned inverted;	/* only valid for PXA26x */
+	unsigned nr_gpios;
 	int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
 };
 
Signature · 1 line
1.7.10.4
#21 lore raw

PATCH 6/10 gpio: pxa: define nr gpios in platform data

Quoted 19 lines · Haojian Zhuang

Avoid to define gpio numbers in gpio driver. Define it in platform data instead.

---
 arch/arm/mach-mmp/aspenite.c      |    1 +
 arch/arm/mach-mmp/avengers_lite.c |    1 +
 arch/arm/mach-mmp/brownstone.c    |    1 +
 arch/arm/mach-mmp/flint.c         |    1 +
 arch/arm/mach-mmp/gplugd.c        |    1 +
 arch/arm/mach-mmp/tavorevb.c      |    1 +
 arch/arm/mach-mmp/teton_bga.c     |    1 +
 arch/arm/mach-mmp/ttc_dkb.c       |    1 +
 arch/arm/mach-pxa/pxa25x.c        |    3 +++
 arch/arm/mach-pxa/pxa27x.c        |    1 +
 arch/arm/mach-pxa/pxa3xx.c        |   15 +++++++++++-
 drivers/gpio/gpio-pxa.c           |   48 +++++++------------------------------
 include/linux/gpio-pxa.h          |    1 +
 13 files changed, 35 insertions(+), 41 deletions(-)

[...]

arch/arm/mach-pxa/pxa3xx.c void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) · line 440

Quoted 11 lines
arch/arm/mach-pxa/pxa3xx.c +3 -0
index 656a1bb..a0cc797 100644
@@ -435,6 +435,10 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)
 	pxa_register_device(&pxa3xx_device_i2c_power, info);
 }
 
+static struct pxa_gpio_platform_data pxa3xx_gpio_info __initdata = {
+	.nr_gpios = 128,
+};

This misses the:
#include <linux/gpio-pxa.h>

Quoted 5 lines
arch/arm/mach-pxa/pxa3xx.c +1 -0
+
 static struct platform_device *devices[] __initdata = {
 	&pxa_device_gpio,
 	&pxa27x_device_udc,

arch/arm/mach-pxa/pxa3xx.c static int __init pxa3xx_init(void) · line 494

Quoted 10 lines
arch/arm/mach-pxa/pxa3xx.c +6 -1
@@ -482,8 +486,17 @@ static int __init pxa3xx_init(void)
 		register_syscore_ops(&pxa3xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
-		if (!of_have_populated_dt())
+		if (!of_have_populated_dt()) {
+			if (cpu_is_pxa93x())
+				pxa3xx_gpio_info.nr_gpios = 192;
+			ret = platform_device_add_data(&pxa_device_gpio,
+					&pxa3xx_gpio_info,
+					sizeof(struct pxa_gpio_platform_data);

Closing parenthesis is missing...

Quoted 8 lines
arch/arm/mach-pxa/pxa3xx.c +4 -0
+			if (ret < 0)
+				break;
+
 			ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+		}
 	}
 
 	return ret;

[...]

Signature · 2 lines
Regards,
Igor.
#22 lore raw

PATCH 7/10 gpio: pxa: clean code for compatible name

In reply to Haojian Zhuang

Use compatible variable name in gpio pxa driver.

---
 drivers/gpio/gpio-pxa.c |  194 ++++++++++++++++++++++++-----------------------
 1 file changed, 98 insertions(+), 96 deletions(-)
drivers/gpio/gpio-pxa.c +98 -96
index 67be225..5870944 100644
@@ -95,9 +95,9 @@ static void __iomem *gpio_reg_base;
 #define for_each_gpio_chip(i, c)			\
 	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
 
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+static inline void __iomem *gpio_chip_base(struct gpio_chip *gc)
 {
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+	return container_of(gc, struct pxa_gpio_chip, chip)->regbase;
 }
 
 static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
@@ -210,14 +210,14 @@ static int pxa_gpio_direction_output(struct gpio_chip *gc,
 	return 0;
 }
 
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int pxa_gpio_get(struct gpio_chip *gc, unsigned offset)
 {
-	return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+	return readl_relaxed(gpio_chip_base(gc) + GPLR_OFFSET) & (1 << offset);
 }
 
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void pxa_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
-	writel_relaxed(1 << offset, gpio_chip_base(chip) +
+	writel_relaxed(1 << offset, gpio_chip_base(gc) +
 				(value ? GPSR_OFFSET : GPCR_OFFSET));
 }
 
@@ -242,57 +242,58 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
 /* Update only those GRERx and GFERx edge detection register bits if those
  * bits are set in c->irq_mask
  */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
+static inline void update_edge_detect(struct pxa_gpio_chip *chip)
 {
 	uint32_t grer, gfer;
 
-	grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	writel_relaxed(grer, c->regbase + GRER_OFFSET);
-	writel_relaxed(gfer, c->regbase + GFER_OFFSET);
+	grer = readl_relaxed(chip->regbase + GRER_OFFSET) & ~chip->irq_mask;
+	gfer = readl_relaxed(chip->regbase + GFER_OFFSET) & ~chip->irq_mask;
+	grer |= chip->irq_edge_rise & chip->irq_mask;
+	gfer |= chip->irq_edge_fall & chip->irq_mask;
+	writel_relaxed(grer, chip->regbase + GRER_OFFSET);
+	writel_relaxed(gfer, chip->regbase + GFER_OFFSET);
 }
 
 static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
-	struct pxa_gpio_chip *c;
+	struct pxa_gpio_chip *chip;
 	int gpio = pxa_irq_to_gpio(d);
 	unsigned long gpdr, mask = GPIO_bit(gpio);
 
-	c = gpio_to_pxachip(gpio);
+	chip = gpio_to_pxachip(gpio);
 
 	if (type == IRQ_TYPE_PROBE) {
 		/* Don't mess with enabled GPIOs using preconfigured edges or
 		 * GPIOs set to alternate function or to output during probe
 		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+		if ((chip->irq_edge_rise | chip->irq_edge_fall)
+			& GPIO_bit(gpio))
 			return 0;
 
-		if (__gpio_is_occupied(c, gpio))
+		if (__gpio_is_occupied(chip, gpio))
 			return 0;
 
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 	}
 
-	gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
+	gpdr = readl_relaxed(chip->regbase + GPDR_OFFSET);
 
-	if (__gpio_is_inverted(c, gpio))
-		writel_relaxed(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip, gpio))
+		writel_relaxed(gpdr | mask,  chip->regbase + GPDR_OFFSET);
 	else
-		writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+		writel_relaxed(gpdr & ~mask, chip->regbase + GPDR_OFFSET);
 
 	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
+		chip->irq_edge_rise |= mask;
 	else
-		c->irq_edge_rise &= ~mask;
+		chip->irq_edge_rise &= ~mask;
 
 	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
+		chip->irq_edge_fall |= mask;
 	else
-		c->irq_edge_fall &= ~mask;
+		chip->irq_edge_fall &= ~mask;
 
-	update_edge_detect(c);
+	update_edge_detect(chip);
 
 	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
 		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
@@ -302,21 +303,21 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
 
 static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
 {
-	struct pxa_gpio_chip *c;
+	struct pxa_gpio_chip *chip;
 	int loop, gpio, gpio_base, n;
 	unsigned long gedr;
-	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_chip *ic = irq_desc_get_chip(desc);
 
-	chained_irq_enter(chip, desc);
+	chained_irq_enter(ic, desc);
 
 	do {
 		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
+		for_each_gpio_chip(gpio, chip) {
+			gpio_base = chip->chip.base;
 
-			gedr = readl_relaxed(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			writel_relaxed(gedr, c->regbase + GEDR_OFFSET);
+			gedr = readl_relaxed(chip->regbase + GEDR_OFFSET);
+			gedr = gedr & chip->irq_mask;
+			writel_relaxed(gedr, chip->regbase + GEDR_OFFSET);
 
 			for_each_set_bit(n, &gedr, BITS_PER_LONG) {
 				loop = 1;
@@ -326,38 +327,38 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
 		}
 	} while (loop);
 
-	chained_irq_exit(chip, desc);
+	chained_irq_exit(ic, desc);
 }
 
 static void pxa_ack_muxed_gpio(struct irq_data *d)
 {
 	int gpio = pxa_irq_to_gpio(d);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	struct pxa_gpio_chip *chip = gpio_to_pxachip(gpio);
 
-	writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+	writel_relaxed(GPIO_bit(gpio), chip->regbase + GEDR_OFFSET);
 }
 
 static void pxa_mask_muxed_gpio(struct irq_data *d)
 {
 	int gpio = pxa_irq_to_gpio(d);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	struct pxa_gpio_chip *chip = gpio_to_pxachip(gpio);
 	uint32_t grer, gfer;
 
-	c->irq_mask &= ~GPIO_bit(gpio);
+	chip->irq_mask &= ~GPIO_bit(gpio);
 
-	grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	writel_relaxed(grer, c->regbase + GRER_OFFSET);
-	writel_relaxed(gfer, c->regbase + GFER_OFFSET);
+	grer = readl_relaxed(chip->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = readl_relaxed(chip->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	writel_relaxed(grer, chip->regbase + GRER_OFFSET);
+	writel_relaxed(gfer, chip->regbase + GFER_OFFSET);
 }
 
 static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
 {
 	int gpio = pxa_irq_to_gpio(d);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	struct pxa_gpio_chip *chip = gpio_to_pxachip(gpio);
 
-	if (c->set_wake)
-		return c->set_wake(gpio, on);
+	if (chip->set_wake)
+		return chip->set_wake(gpio, on);
 	else
 		return 0;
 }
@@ -365,10 +366,10 @@ static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
 static void pxa_unmask_muxed_gpio(struct irq_data *d)
 {
 	int gpio = pxa_irq_to_gpio(d);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	struct pxa_gpio_chip *chip = gpio_to_pxachip(gpio);
 
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
+	chip->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(chip);
 }
 
 static struct irq_chip pxa_muxed_gpio_chip = {
@@ -468,38 +469,37 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 	}
 
 	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
+		struct gpio_chip *gc = &chips[i].chip;
 
 		sprintf(chips[i].label, "gpio-%d", i);
 		chips[i].regbase = gpio_reg_base + BANK_OFF(i);
 		chips[i].set_wake = set_wake;
 
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-		c->to_irq = pxa_gpio_to_irq;
-#ifdef CONFIG_OF_GPIO
-		c->of_node = pxa_gpio_of_node;
-		c->of_xlate = pxa_gpio_of_xlate;
-		c->of_gpio_n_cells = 2;
-#endif
-
 		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gc->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
 
-		chips[i].irq_base = irq_alloc_descs(-1, 0, c->ngpio, 0);
+		chips[i].irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
 		if (chips[i].irq_base < 0)
 			return -EINVAL;
-		if (!irq_domain_add_legacy(pdev->dev.of_node, c->ngpio,
+		if (!irq_domain_add_legacy(pdev->dev.of_node, gc->ngpio,
 					   chips[i].irq_base, 0,
 					   &pxa_irq_domain_ops, &chips[i]))
 			return -ENODEV;
 
-		gpiochip_add(c);
+		gc->base  = gpio;
+		gc->label = chips[i].label;
+
+		gc->direction_input  = pxa_gpio_direction_input;
+		gc->direction_output = pxa_gpio_direction_output;
+		gc->get = pxa_gpio_get;
+		gc->set = pxa_gpio_set;
+		gc->to_irq = pxa_gpio_to_irq;
+#ifdef CONFIG_OF_GPIO
+		gc->of_node = pxa_gpio_of_node;
+		gc->of_xlate = pxa_gpio_of_xlate;
+		gc->of_gpio_n_cells = 2;
+#endif
+		gpiochip_add(gc);
 	}
 	pxa_gpio_chips = chips;
 	return 0;
@@ -507,10 +507,10 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 
 static int pxa_gpio_probe(struct platform_device *pdev)
 {
-	struct pxa_gpio_chip *c;
+	struct pxa_gpio_chip *chip;
 	struct resource *res;
 	struct clk *clk;
-	struct pxa_gpio_platform_data *info;
+	struct pxa_gpio_platform_data *pdata;
 	int gpio, irq, ret, use_of = 0;
 	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
 
@@ -549,22 +549,24 @@ static int pxa_gpio_probe(struct platform_device *pdev)
 	}
 
 	/* Initialize GPIO chips */
-	info = dev_get_platdata(&pdev->dev);
-	pxa_last_gpio = info->nr_gpios - 1;
-	pxa_init_gpio_chip(pdev, pxa_last_gpio,
-			   info ? info->gpio_set_wake : NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	pxa_last_gpio = pdata->nr_gpios - 1;
+	ret = pxa_init_gpio_chip(pdev, pxa_last_gpio,
+				 pdata ? pdata->gpio_set_wake : NULL);
+	if (ret < 0)
+		return ret;
 
 	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		writel_relaxed(0, c->regbase + GFER_OFFSET);
-		writel_relaxed(0, c->regbase + GRER_OFFSET);
-		writel_relaxed(~0,c->regbase + GEDR_OFFSET);
+	for_each_gpio_chip(gpio, chip) {
+		writel_relaxed(0, chip->regbase + GFER_OFFSET);
+		writel_relaxed(0, chip->regbase + GRER_OFFSET);
+		writel_relaxed(~0,chip->regbase + GEDR_OFFSET);
 		/* unmask GPIO edge detect for AP side */
-		if (info->ed_mask)
-			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
+		if (pdata->ed_mask)
+			writel_relaxed(~0, chip->regbase + ED_MASK_OFFSET);
 		/* update for gpio inverted & gafr */
-		c->inverted = info->inverted;
-		c->gafr = info->gafr;
+		chip->inverted = pdata->inverted;
+		chip->gafr = pdata->gafr;
 	}
 
 	if (!use_of) {
@@ -606,34 +608,34 @@ module_platform_driver(pxa_gpio_driver);
 #ifdef CONFIG_PM
 static int pxa_gpio_suspend(void)
 {
-	struct pxa_gpio_chip *c;
+	struct pxa_gpio_chip *chip;
 	int gpio;
 
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
-		c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET);
-		c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET);
+	for_each_gpio_chip(gpio, chip) {
+		chip->saved_gplr = readl_relaxed(chip->regbase + GPLR_OFFSET);
+		chip->saved_gpdr = readl_relaxed(chip->regbase + GPDR_OFFSET);
+		chip->saved_grer = readl_relaxed(chip->regbase + GRER_OFFSET);
+		chip->saved_gfer = readl_relaxed(chip->regbase + GFER_OFFSET);
 
 		/* Clear GPIO transition detect bits */
-		writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET);
+		writel_relaxed(~0, chip->regbase + GEDR_OFFSET);
 	}
 	return 0;
 }
 
 static void pxa_gpio_resume(void)
 {
-	struct pxa_gpio_chip *c;
+	struct pxa_gpio_chip *chip;
 	int gpio;
 
-	for_each_gpio_chip(gpio, c) {
+	for_each_gpio_chip(gpio, chip) {
 		/* restore level with set/clear */
-		writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+		writel_relaxed( chip->saved_gplr, chip->regbase + GPSR_OFFSET);
+		writel_relaxed(~chip->saved_gplr, chip->regbase + GPCR_OFFSET);
 
-		writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET);
-		writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET);
-		writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+		writel_relaxed(chip->saved_grer, chip->regbase + GRER_OFFSET);
+		writel_relaxed(chip->saved_gfer, chip->regbase + GFER_OFFSET);
+		writel_relaxed(chip->saved_gpdr, chip->regbase + GPDR_OFFSET);
 	}
 }
 #else
Signature · 1 line
1.7.10.4
#23 lore raw

PATCH 8/10 gpio: pxa: remove arch related macro

In reply to Haojian Zhuang

Remove macro CONFIG_ARCH_PXA.

---
 drivers/gpio/gpio-pxa.c |   30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/gpio/gpio-pxa.c +15 -15
index 5870944..21cf8fd 100644
@@ -570,21 +570,21 @@ static int pxa_gpio_probe(struct platform_device *pdev)
 	}
 
 	if (!use_of) {
-#ifdef CONFIG_ARCH_PXA
-		irq = gpio_to_irq(0);
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-		irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
-		irq = gpio_to_irq(1);
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-		irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
-
-		for (irq  = gpio_to_irq(gpio_offset);
+		if (irq0 > 0) {
+			irq = gpio_to_irq(0);
+			irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+						 handle_edge_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+			irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
+		}
+		if (irq1 > 0) {
+			irq = gpio_to_irq(1);
+			irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+						 handle_edge_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+			irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
+		}
+		for (irq = gpio_to_irq(gpio_offset);
 			irq <= gpio_to_irq(pxa_last_gpio); irq++) {
 			irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
 						 handle_edge_irq);
Signature · 1 line
1.7.10.4
#24 lore raw

PATCH 9/10 gpio: pxa: move gpio properties into child node

In reply to Haojian Zhuang

Move gpio properties into child node. So pinctrl driver could binds to each gpio chip with gpio range.

---
 drivers/gpio/gpio-pxa.c |   33 ++++++++-------------------------
 1 file changed, 8 insertions(+), 25 deletions(-)
drivers/gpio/gpio-pxa.c +8 -25
index 21cf8fd..528f742 100644
@@ -63,10 +63,6 @@
 
 int pxa_last_gpio;
 
-#ifdef CONFIG_OF
-static struct device_node *pxa_gpio_of_node;
-#endif
-
 struct pxa_gpio_chip {
 	struct gpio_chip chip;
 	void __iomem	*regbase;
@@ -404,9 +400,9 @@ static const struct irq_domain_ops pxa_irq_domain_ops = {
 
 static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
-	int ret, nr_banks;
+	int ret;
 	struct pxa_gpio_platform_data *pdata;
-	struct device_node *prev, *next, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
 
@@ -432,25 +428,7 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
 	/* set the platform data */
 	pdev->dev.platform_data = pdata;
 
-	next = of_get_next_child(np, NULL);
-	prev = next;
-	if (!next) {
-		dev_err(&pdev->dev, "Failed to find child gpio node\n");
-		ret = -EINVAL;
-		goto err;
-	}
-	for (nr_banks = 1; ; nr_banks++) {
-		next = of_get_next_child(np, prev);
-		if (!next)
-			break;
-		prev = next;
-	}
-	of_node_put(prev);
-
 	return 0;
-err:
-	iounmap(gpio_reg_base);
-	return ret;
 }
 #else
 #define pxa_gpio_probe_dt(pdev)		(-1)
@@ -460,6 +438,7 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 			      int (*set_wake)(unsigned int, unsigned int))
 {
 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct device_node *next, *np = pdev->dev.of_node;
 	struct pxa_gpio_chip *chips;
 
 	chips = devm_kzalloc(&pdev->dev, nbanks * sizeof(*chips), GFP_KERNEL);
@@ -468,6 +447,7 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 		return -ENOMEM;
 	}
 
+	next = of_get_next_child(np, NULL);
 	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
 		struct gpio_chip *gc = &chips[i].chip;
 
@@ -495,7 +475,10 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 		gc->set = pxa_gpio_set;
 		gc->to_irq = pxa_gpio_to_irq;
 #ifdef CONFIG_OF_GPIO
-		gc->of_node = pxa_gpio_of_node;
+		gc->of_node = next;
+		next = of_get_next_child(np, next);
+		of_node_put(gc->of_node);
+
 		gc->of_xlate = pxa_gpio_of_xlate;
 		gc->of_gpio_n_cells = 2;
 #endif
Signature · 1 line
1.7.10.4
#25 lore raw

PATCH 9/10 gpio: pxa: move gpio properties into child node

Quoted 62 lines · Haojian Zhuang

Move gpio properties into child node. So pinctrl driver could binds to each gpio chip with gpio range.

---
 drivers/gpio/gpio-pxa.c |   33 ++++++++-------------------------
 1 file changed, 8 insertions(+), 25 deletions(-)
drivers/gpio/gpio-pxa.c +2 -24
index 21cf8fd..528f742 100644
@@ -63,10 +63,6 @@
 
 int pxa_last_gpio;
 
-#ifdef CONFIG_OF
-static struct device_node *pxa_gpio_of_node;
-#endif
-
 struct pxa_gpio_chip {
 	struct gpio_chip chip;
 	void __iomem	*regbase;
@@ -404,9 +400,9 @@ static const struct irq_domain_ops pxa_irq_domain_ops = {
 
 static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
-	int ret, nr_banks;
+	int ret;
 	struct pxa_gpio_platform_data *pdata;
-	struct device_node *prev, *next, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
 
@@ -432,25 +428,7 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
 	/* set the platform data */
 	pdev->dev.platform_data = pdata;
 
-	next = of_get_next_child(np, NULL);
-	prev = next;
-	if (!next) {
-		dev_err(&pdev->dev, "Failed to find child gpio node\n");
-		ret = -EINVAL;
-		goto err;
-	}
-	for (nr_banks = 1; ; nr_banks++) {
-		next = of_get_next_child(np, prev);
-		if (!next)
-			break;
-		prev = next;
-	}
-	of_node_put(prev);
-
 	return 0;
-err:
-	iounmap(gpio_reg_base);
-	return ret;
 }
 #else
 #define pxa_gpio_probe_dt(pdev)		(-1)

drivers/gpio/gpio-pxa.c static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end, · line 441

Quoted 4 lines
drivers/gpio/gpio-pxa.c +1 -0
@@ -460,6 +438,7 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 			      int (*set_wake)(unsigned int, unsigned int))
 {
 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct device_node *next, *np = pdev->dev.of_node;

The above introduces:
drivers/gpio/gpio-pxa.c:453: warning: unused variable 'np' drivers/gpio/gpio-pxa.c:453: warning: unused variable 'next'

for the !CONFIG_OF case (after the below is fixed).

drivers/gpio/gpio-pxa.c static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end, · line 450

Quoted 8 lines
drivers/gpio/gpio-pxa.c +1 -0
 	struct pxa_gpio_chip *chips;
 
 	chips = devm_kzalloc(&pdev->dev, nbanks * sizeof(*chips), GFP_KERNEL);
@@ -468,6 +447,7 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 		return -ENOMEM;
 	}
 
+	next = of_get_next_child(np, NULL);

This does not compile for the !CONFIG_OF case, so at least,
you should #ifdef the above line or probably the better solution would be to stub out the of_get_next_child() in the OF code (probably include/linux/of.h).

Quoted 16 lines
drivers/gpio/gpio-pxa.c +4 -1
 	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
 		struct gpio_chip *gc = &chips[i].chip;
 
@@ -495,7 +475,10 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 		gc->set = pxa_gpio_set;
 		gc->to_irq = pxa_gpio_to_irq;
 #ifdef CONFIG_OF_GPIO
-		gc->of_node = pxa_gpio_of_node;
+		gc->of_node = next;
+		next = of_get_next_child(np, next);
+		of_node_put(gc->of_node);
+
 		gc->of_xlate = pxa_gpio_of_xlate;
 		gc->of_gpio_n_cells = 2;
 #endif
Signature · 2 lines
Regards,
Igor.
#26 lore raw

PATCH 10/10 gpio: pxa: bind to pinctrl by request

In reply to Haojian Zhuang

While gpio pins is requested, request the pin of pinctrl driver first.

---
 drivers/gpio/gpio-pxa.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
drivers/gpio/gpio-pxa.c +13 -0
index 528f742..d64ec8c 100644
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
@@ -159,6 +160,17 @@ int pxa_irq_to_gpio(struct irq_data *d)
 	return gpio;
 }
 
+static int pxa_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = gc->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
 static int pxa_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 {
 	struct pxa_gpio_chip *chip = NULL;
@@ -469,6 +481,7 @@ static int pxa_init_gpio_chip(struct platform_device *pdev, int gpio_end,
 		gc->base  = gpio;
 		gc->label = chips[i].label;
 
+		gc->request = pxa_gpio_request;
 		gc->direction_input  = pxa_gpio_direction_input;
 		gc->direction_output = pxa_gpio_direction_output;
 		gc->get = pxa_gpio_get;
Signature · 1 line
1.7.10.4
#27 lore raw

cover rework gpio pxa driver for pinctrl

In reply to Haojian Zhuang
Quoted 1 line · Haojian Zhuang

Remove all cpu depend macro. Bind gpio pxa driver with pinctrl driver.

Please route this patch series by Mika so he can test it on his funny hardware too.

Can we have this based on top of Mika's patches of these work out fine on the PXA?

Yours,
Linus Walleij

A message that is not in the archive (sent off-list or not yet received): [email protected]

#29 lore raw

cover rework gpio pxa driver for pinctrl

Quoted 9 lines · Mika Westerberg
Quoted 7 lines · Linus Walleij
Quoted 1 line · Haojian Zhuang

Remove all cpu depend macro. Bind gpio pxa driver with pinctrl driver.

Please route this patch series by Mika so he can test it on his funny hardware too.

Quoted 6 lines

The hardware we have is Intel Lynxpoint (a PCH chipset for Haswell which has x86 core). The only PXA based IP block it has is the SPI controller as far as I know. For GPIOs we have Intel own GPIO block, which is different than the PXA one (at least I think so, adding Mathias just in case).

Not sure how it helps if I test this series on Lynxpoint :-)

Heheh sorry Mika there is too much PXA stuff happening right now :-)

I admit I confused the GPIO for the SPI. I'll just go and apply Haoijan's patches.

Yours,
Linus Walleij