[PATCHv2 2/3] msm: gpiomux: decentralize and modularize gpiomux init.

Rohit Vaswani rvaswani at codeaurora.org
Mon Mar 7 13:35:52 EST 2011


From: Gregory Bean <gbean at codeaurora.org>

Reorganize gpiomux initialization as follows:
- remove the global static gpiomux configuration table;
- remove the universal initcall from gpiomux.c;
- add a public function, msm_gpiomux_init, which installs
  a provided gpiomux config table and runs the code
  previously run by the universal init;
- Add initcalls in each of the board-specific gpiomux files.

This decentralization of gpiomux init improves its flexibility
by allowing board-specific runtime code to select and/or
assemble the correct gpiomux-config table and send it to the
gpiomux framework for initialization. Rather than having a single
static array which must meet all needs.

Change-Id: Id34e7a5471c1f5d415d6524729e4652a0798f49a
Signed-off-by: Rohit Vaswani <rvaswani at codeaurora.org>
---
v2: Re-send

 arch/arm/mach-msm/board-msm7x27.c |   19 ++++++++++
 arch/arm/mach-msm/board-msm7x30.c |   49 ++++++++++++++++++--------
 arch/arm/mach-msm/board-msm8x60.c |   18 +++++++++-
 arch/arm/mach-msm/board-qsd8x50.c |   33 ++++++++++++++----
 arch/arm/mach-msm/gpiomux-v1.h    |    8 ----
 arch/arm/mach-msm/gpiomux-v2.h    |    2 -
 arch/arm/mach-msm/gpiomux.c       |   68 +++++++++++++++++++++++++++++-------
 arch/arm/mach-msm/gpiomux.h       |   28 ++++++++++-----
 8 files changed, 169 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 16d7580..10affe5 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -45,6 +45,8 @@
 #include "socinfo.h"
 #include "clock.h"
 
+struct msm_gpiomux_config msm7x27_gpiomux_configs[NR_GPIO_IRQS] __initdata = {};
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= 0x9C004300,
@@ -75,6 +77,21 @@ static struct platform_device *devices[] __initdata = {
 
 extern struct sys_timer msm_timer;
 
+static int __init gpiomux_init(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		printk(KERN_ERR "msm_gpiomux_init failed - %n", rc);
+		return rc;
+	}
+
+	msm_gpiomux_install(msm7x27_gpiomux_configs,
+			ARRAY_SIZE(msm7x27_gpiomux_configs));
+	return 0;
+}
+
 static void __init msm7x2x_init_irq(void)
 {
 	msm_init_irq();
@@ -85,6 +102,8 @@ static void __init msm7x2x_init(void)
 	if (socinfo_init() < 0)
 		BUG();
 
+	gpiomux_init();
+
 	if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) {
 		smc91x_resources[0].start = 0x98000300;
 		smc91x_resources[0].end = 0x980003ff;
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index dc9fac1..59b91de 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -39,6 +39,9 @@
 #include "gpiomux.h"
 #include "proc_comm.h"
 
+#define UART2_SUSPENDED (GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |\
+			GPIOMUX_FUNC_2 | GPIOMUX_VALID)
+
 extern struct sys_timer msm_timer;
 
 static int hsusb_phy_init_seq[] = {
@@ -53,25 +56,23 @@ static struct msm_otg_platform_data msm_otg_pdata = {
 	.otg_control		= OTG_PHY_CONTROL,
 };
 
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-	[49] = { /* UART2 RFR */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+struct msm_gpiomux_config msm7x30_uart2_configs[] __initdata = {
+	{
+		.gpio = 49, /* UART2 RFR */
+		.suspended = UART2_SUSPENDED,
 	},
-	[50] = { /* UART2 CTS */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	{
+		.gpio = 50, /* UART2 CTS */
+		.suspended = UART2_SUSPENDED,
 	},
-	[51] = { /* UART2 RX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	{
+		.gpio = 51, /* UART2 RX */
+		.suspended = UART2_SUSPENDED,
 	},
-	[52] = { /* UART2 TX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	{
+		.gpio = 52, /* UART2 TX */
+		.suspended = UART2_SUSPENDED,
 	},
-#endif
 };
 
 static struct platform_device *devices[] __initdata = {
@@ -84,6 +85,22 @@ static struct platform_device *devices[] __initdata = {
 	&msm_device_hsusb_host,
 };
 
+static int __init gpiomux_init(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		printk(KERN_ERR "msm_gpiomux_init failed - %d\n", rc);
+		return rc;
+	}
+
+	msm_gpiomux_install(msm7x30_uart2_configs,
+			ARRAY_SIZE(msm7x30_uart2_configs));
+	return 0;
+
+}
+
 static void __init msm7x30_init_irq(void)
 {
 	msm_init_irq();
@@ -95,6 +112,8 @@ static void __init msm7x30_init(void)
 	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
 	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
 
+	gpiomux_init();
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 6c0b868..de4d8d1 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -29,8 +29,23 @@
 #include <mach/msm_iomap.h>
 #include "gpiomux.h"
 
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};
+struct msm_gpiomux_config msm8x60_gpiomux_configs[NR_GPIO_IRQS] __initdata = {};
 
+static int __init gpiomux_init(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		printk(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
+		return rc;
+	}
+
+	msm_gpiomux_install(msm8x60_gpiomux_configs,
+			ARRAY_SIZE(msm8x60_gpiomux_configs));
+
+	return 0;
+}
 
 static void __init msm8x60_map_io(void)
 {
@@ -65,6 +80,7 @@ static void __init msm8x60_init_irq(void)
 
 static void __init msm8x60_init(void)
 {
+	gpiomux_init();
 }
 
 MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index b63b7c4..33ab1fe 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -38,16 +38,19 @@
 #include "devices.h"
 #include "gpiomux.h"
 
+#define UART3_SUSPENDED (GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |\
+			GPIOMUX_FUNC_1 | GPIOMUX_VALID)
+
 extern struct sys_timer msm_timer;
 
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-	[86] = { /* UART3 RX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+struct msm_gpiomux_config qsd8x50_uart3_configs[] __initdata = {
+	{
+		.gpio = 86, /* UART3 RX */
+		.suspended = UART3_SUSPENDED,
 	},
-	[87] = { /* UART3 TX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+	{
+		.gpio = 87, /* UART3 TX */
+		.suspended = UART3_SUSPENDED,
 	},
 };
 
@@ -169,6 +172,21 @@ static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
 	.gpio_data = &sdc1_gpio,
 };
 
+static int __init gpiomux_init(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		printk(KERN_ERR "msm_gpiomux_init failed - %d\n", rc);
+		return rc;
+	}
+
+	msm_gpiomux_install(qsd8x50_uart3_configs,
+			ARRAY_SIZE(qsd8x50_uart3_configs));
+	return 0;
+}
+
 static void __init qsd8x50_init_mmc(void)
 {
 	if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa())
@@ -202,6 +220,7 @@ static void __init qsd8x50_init(void)
 	msm_device_otg.dev.platform_data = &msm_otg_pdata;
 	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
 	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
+	gpiomux_init();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	qsd8x50_init_mmc();
 }
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
index 71d86fe..96ad5fa 100644
--- a/arch/arm/mach-msm/gpiomux-v1.h
+++ b/arch/arm/mach-msm/gpiomux-v1.h
@@ -17,14 +17,6 @@
 #ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
 #define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
 
-#if defined(CONFIG_ARCH_MSM7X30)
-#define GPIOMUX_NGPIOS 182
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define GPIOMUX_NGPIOS 165
-#else
-#define GPIOMUX_NGPIOS 133
-#endif
-
 typedef u32 gpiomux_config_t;
 
 enum {
diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h
index 3bf10e7..a7dec1ea 100644
--- a/arch/arm/mach-msm/gpiomux-v2.h
+++ b/arch/arm/mach-msm/gpiomux-v2.h
@@ -17,8 +17,6 @@
 #ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
 #define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
 
-#define GPIOMUX_NGPIOS 173
-
 typedef u16 gpiomux_config_t;
 
 enum {
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 53af21a..9ef9864 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -15,20 +15,31 @@
  * 02110-1301, USA.
  */
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include "gpiomux.h"
 
+struct msm_gpiomux_rec {
+	gpiomux_config_t active;
+	gpiomux_config_t suspended;
+	int              ref;
+};
 static DEFINE_SPINLOCK(gpiomux_lock);
+static struct msm_gpiomux_rec *msm_gpiomux_recs;
+static unsigned msm_gpiomux_ngpio;
 
 int msm_gpiomux_write(unsigned gpio,
 		      gpiomux_config_t active,
 		      gpiomux_config_t suspended)
 {
-	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
 	unsigned long irq_flags;
 	gpiomux_config_t setting;
 
-	if (gpio >= GPIOMUX_NGPIOS)
+	if (!msm_gpiomux_recs)
+		return -EFAULT;
+
+	if (gpio >= msm_gpiomux_ngpio)
 		return -EINVAL;
 
 	spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -50,10 +61,13 @@ EXPORT_SYMBOL(msm_gpiomux_write);
 
 int msm_gpiomux_get(unsigned gpio)
 {
-	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
 	unsigned long irq_flags;
 
-	if (gpio >= GPIOMUX_NGPIOS)
+	if (!msm_gpiomux_recs)
+		return -EFAULT;
+
+	if (gpio >= msm_gpiomux_ngpio)
 		return -EINVAL;
 
 	spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -66,10 +80,13 @@ EXPORT_SYMBOL(msm_gpiomux_get);
 
 int msm_gpiomux_put(unsigned gpio)
 {
-	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
 	unsigned long irq_flags;
 
-	if (gpio >= GPIOMUX_NGPIOS)
+	if (!msm_gpiomux_recs)
+		return -EFAULT;
+
+	if (gpio >= msm_gpiomux_ngpio)
 		return -EINVAL;
 
 	spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -81,16 +98,39 @@ int msm_gpiomux_put(unsigned gpio)
 }
 EXPORT_SYMBOL(msm_gpiomux_put);
 
-static int __init gpiomux_init(void)
+int msm_gpiomux_init(size_t ngpio)
+{
+	if (!ngpio)
+		return -EINVAL;
+
+	if (msm_gpiomux_recs)
+		return -EPERM;
+
+	msm_gpiomux_recs = kzalloc(sizeof(struct msm_gpiomux_rec) * ngpio,
+				   GFP_KERNEL);
+	if (!msm_gpiomux_recs)
+		return -ENOMEM;
+
+	msm_gpiomux_ngpio = ngpio;
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_init);
+
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs)
 {
 	unsigned n;
+	int rc;
+
+	if (!msm_gpiomux_recs)
+		return;
 
-	for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
-		msm_gpiomux_configs[n].ref = 0;
-		if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
-			continue;
-		__msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+	for (n = 0; n < nconfigs; ++n) {
+		rc = msm_gpiomux_write(configs[n].gpio,
+				       configs[n].active,
+				       configs[n].suspended);
+		if (rc)
+			pr_err("%s: write failure: %d\n", __func__, rc);
 	}
-	return 0;
 }
-postcore_initcall(gpiomux_init);
+EXPORT_SYMBOL(msm_gpiomux_install);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
index b178d9c..38bf511 100644
--- a/arch/arm/mach-msm/gpiomux.h
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -37,17 +37,16 @@
  * Available settings differ by target; see the gpiomux header
  * specific to your target arch for available configurations.
  *
+ * @gpio: The index number of the gpio being described.
  * @active: The configuration to be installed when the line is
  * active, or its reference count is > 0.
  * @suspended: The configuration to be installed when the line
  * is suspended, or its reference count is 0.
- * @ref: The reference count of the line.  For internal use of
- * the gpiomux framework only.
  */
 struct msm_gpiomux_config {
+	unsigned         gpio;
 	gpiomux_config_t active;
 	gpiomux_config_t suspended;
-	unsigned         ref;
 };
 
 /**
@@ -63,13 +62,16 @@ enum {
 
 #ifdef CONFIG_MSM_GPIOMUX
 
-/* Each architecture must provide its own instance of this table.
- * To avoid having gpiomux manage any given gpio, one or both of
- * the entries can avoid setting GPIOMUX_VALID - the absence
- * of that flag will prevent the configuration from being applied
- * during state transitions.
+/* Before using gpiomux, initialize the subsystem by telling it how many
+ * gpios are going to be managed.  Calling any other gpiomux functions before
+ * msm_gpiomux_init is unsupported.
  */
-extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
+int msm_gpiomux_init(size_t ngpio);
+
+/* Install a block of gpiomux configurations in gpiomux.  This is functionally
+ * identical to calling msm_gpiomux_write many times.
+ */
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs);
 
 /* Increment a gpio's reference count, possibly activating the line. */
 int __must_check msm_gpiomux_get(unsigned gpio);
@@ -94,6 +96,14 @@ int msm_gpiomux_write(unsigned gpio,
  */
 void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
 #else
+static inline int msm_gpiomux_init(size_t ngpio)
+{
+	return -ENOSYS;
+}
+
+static inline void
+msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs) {}
+
 static inline int __must_check msm_gpiomux_get(unsigned gpio)
 {
 	return -ENOSYS;
-- 
Sent by an employee of the Qualcomm Innovation Center,Inc
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.




More information about the linux-arm-kernel mailing list