diff mbox

[6/8] pinctrl: COH901XXX: probe the driver from pinmux

Message ID 1321904926-32443-1-git-send-email-linus.walleij@stericsson.com
State Accepted, archived
Headers show

Commit Message

Linus Walleij Nov. 21, 2011, 7:48 p.m. UTC
From: Linus Walleij <linus.walleij@linaro.org>

The U300 pinmux and GPIO drivers are siblings and cannot really
live without each other. Unlike most other platforms they are not
one combined pin control and GPIO block, but two separate yet
interdependent units. Thus we need to tie them close together so
that the pin controller can cross-call to the GPIO driver when
it needs to e.g. bias pins and such things that only the GPIO
driver can do.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-u300/core.c           |    8 ++++++++
 drivers/pinctrl/pinctrl-coh901xxx.c |   28 +++++-----------------------
 drivers/pinctrl/pinctrl-coh901xxx.h |    3 +++
 drivers/pinctrl/pinmux-u300.c       |   18 +++++++++++++++++-
 4 files changed, 33 insertions(+), 24 deletions(-)
 create mode 100644 drivers/pinctrl/pinctrl-coh901xxx.h
diff mbox

Patch

diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index ac0791e..f399862 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1602,6 +1602,14 @@  static struct platform_device pinmux_device = {
 	.id = -1,
 	.num_resources = ARRAY_SIZE(pinmux_resources),
 	.resource = pinmux_resources,
+	.dev = {
+		/*
+		 * Pass in the GPIO platform device as platform data so that
+		 * the pinmux device can probe the GPIO device, a bit tricky
+		 * but works nicely!
+		 */
+		.platform_data = &gpio_device,
+	},
 };
 
 /* Pinmux settings */
diff --git a/drivers/pinctrl/pinctrl-coh901xxx.c b/drivers/pinctrl/pinctrl-coh901xxx.c
index 69fb707..7f51fb8 100644
--- a/drivers/pinctrl/pinctrl-coh901xxx.c
+++ b/drivers/pinctrl/pinctrl-coh901xxx.c
@@ -24,6 +24,7 @@ 
 #include <linux/slab.h>
 #include <linux/pinctrl/pinmux.h>
 #include <mach/gpio-u300.h>
+#include "pinctrl-coh901xxx.h"
 
 /*
  * Bias modes for U300 GPIOs
@@ -710,7 +711,8 @@  static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
 	}
 }
 
-static int __init u300_gpio_probe(struct platform_device *pdev)
+int __init u300_gpio_probe(struct platform_device *pdev,
+			   struct gpio_chip **chip)
 {
 	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
 	struct u300_gpio *gpio;
@@ -862,6 +864,7 @@  static int __init u300_gpio_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, gpio);
+	*chip = &gpio->chip;
 
 	return 0;
 
@@ -883,7 +886,7 @@  err_no_clk:
 	return err;
 }
 
-static int __exit u300_gpio_remove(struct platform_device *pdev)
+int __exit u300_gpio_remove(struct platform_device *pdev)
 {
 	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
 	struct u300_gpio *gpio = platform_get_drvdata(pdev);
@@ -912,27 +915,6 @@  static int __exit u300_gpio_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct platform_driver u300_gpio_driver = {
-	.driver		= {
-		.name	= "u300-gpio",
-	},
-	.remove		= __exit_p(u300_gpio_remove),
-};
-
-
-static int __init u300_gpio_init(void)
-{
-	return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
-}
-
-static void __exit u300_gpio_exit(void)
-{
-	platform_driver_unregister(&u300_gpio_driver);
-}
-
-arch_initcall(u300_gpio_init);
-module_exit(u300_gpio_exit);
-
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-coh901xxx.h b/drivers/pinctrl/pinctrl-coh901xxx.h
new file mode 100644
index 0000000..20390ec
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-coh901xxx.h
@@ -0,0 +1,3 @@ 
+int u300_gpio_probe(struct platform_device *pdev,
+		    struct gpio_chip **chip);
+int u300_gpio_remove(struct platform_device *pdev);
diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c
index 7e89b36..1232857 100644
--- a/drivers/pinctrl/pinmux-u300.c
+++ b/drivers/pinctrl/pinmux-u300.c
@@ -19,6 +19,7 @@ 
 #include <linux/err.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include "pinctrl-coh901xxx.h"
 
 /*
  * Register definitions for the U300 Padmux control registers in the
@@ -663,6 +664,7 @@  struct u300_pmx {
 	u32 phybase;
 	u32 physize;
 	void __iomem *virtbase;
+	struct platform_device *gpio_pdev;
 };
 
 /**
@@ -1056,6 +1058,7 @@  static struct pinctrl_desc u300_pmx_desc = {
 
 static int __init u300_pmx_probe(struct platform_device *pdev)
 {
+	struct gpio_chip *chip;
 	struct u300_pmx *upmx;
 	struct resource *res;
 	int ret;
@@ -1066,6 +1069,7 @@  static int __init u300_pmx_probe(struct platform_device *pdev)
 	if (!upmx)
 		return -ENOMEM;
 
+	upmx->gpio_pdev = dev_get_platdata(&pdev->dev);
 	upmx->dev = &pdev->dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1095,9 +1099,18 @@  static int __init u300_pmx_probe(struct platform_device *pdev)
 		goto out_no_pmx;
 	}
 
+	/* Now probe the sibling GPIO driver */
+	ret = u300_gpio_probe(upmx->gpio_pdev, &chip);
+	if (ret) {
+		dev_err(&pdev->dev, "could not probe sibling GPIO device\n");
+		goto out_no_gpio;
+	}
+
 	/* We will handle a range of GPIO pins */
-	for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
+	for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
+		u300_gpio_ranges[i].gc = chip;
 		pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
+	}
 
 	platform_set_drvdata(pdev, upmx);
 
@@ -1105,6 +1118,8 @@  static int __init u300_pmx_probe(struct platform_device *pdev)
 
 	return 0;
 
+out_no_gpio:
+	pinctrl_unregister(upmx->pctl);
 out_no_pmx:
 	iounmap(upmx->virtbase);
 out_no_remap:
@@ -1123,6 +1138,7 @@  static int __exit u300_pmx_remove(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
 		pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
+	u300_gpio_remove(upmx->gpio_pdev);
 	pinctrl_unregister(upmx->pctl);
 	iounmap(upmx->virtbase);
 	release_mem_region(upmx->phybase, upmx->physize);