linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] omap: Board specific muxing using hwmod
@ 2010-12-03  0:45 Tony Lindgren
  2010-12-03  0:45 ` [PATCH 1/6] omap2+: Add omap_mux_get_by_name Tony Lindgren
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

Here are some patches to allow us to pass the board specific mux data
to the platform level device init code, and then allow hwmod state
changes to do the pin muxing.

Dynamic remuxing is also supported as needed, the last patch in this
series sets up the board-*.c data for n8x0 to do uart3 rx pin remuxing
for the idle modes.

Regards,

Tony

---

Tony Lindgren (6):
      omap2+: Add omap_mux_get_by_name
      omap2+: Add support for hwmod specific muxing of devices
      omap2+: Allow hwmod state changes to mux pads based on the state changes
      omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux
      omap2+: Use omap_device_board_data for platform level serial init
      omap2+: Initialize serial ports for wake-up events for n8x0


 arch/arm/mach-omap2/board-n8x0.c              |   66 ++++++++-
 arch/arm/mach-omap2/devices.c                 |    2 
 arch/arm/mach-omap2/gpio.c                    |    2 
 arch/arm/mach-omap2/mux.c                     |  188 ++++++++++++++++++++++---
 arch/arm/mach-omap2/mux.h                     |   39 +++++
 arch/arm/mach-omap2/omap_hwmod.c              |   14 +-
 arch/arm/mach-omap2/pm.c                      |    3 
 arch/arm/mach-omap2/serial.c                  |   29 +++-
 arch/arm/plat-omap/i2c.c                      |    4 -
 arch/arm/plat-omap/include/plat/omap_device.h |   19 ++-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |   32 ++++
 arch/arm/plat-omap/include/plat/serial.h      |    5 +
 arch/arm/plat-omap/omap_device.c              |   14 ++
 13 files changed, 366 insertions(+), 51 deletions(-)

-- 
Signature

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/6] omap2+: Add omap_mux_get_by_name
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-03  0:45 ` [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices Tony Lindgren
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

Do this by splitting _omap_mux_init_signal as it already has most
of the necessary features.

Based on an earlier patch by Dan Murphy <dmurphy@ti.com>.

Cc: Dan Murphy <dmurphy@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/mux.c |   73 ++++++++++++++++++++++++++++++---------------
 1 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 3d71d93..0fa3d74 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -151,12 +151,14 @@ int __init omap_mux_init_gpio(int gpio, int val)
 	return -ENODEV;
 }
 
-static int __init _omap_mux_init_signal(struct omap_mux_partition *partition,
-					const char *muxname, int val)
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
 {
+	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
 	const char *mode_name;
-	int found = 0, mode0_len = 0;
+	int found = 0, found_mode, mode0_len = 0;
 	struct list_head *muxmodes = &partition->muxmodes;
 
 	mode_name = strchr(muxname, '.');
@@ -168,40 +170,34 @@ static int __init _omap_mux_init_signal(struct omap_mux_partition *partition,
 	}
 
 	list_for_each_entry(e, muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		char *m0_entry = m->muxnames[0];
+		char *m0_entry;
 		int i;
 
+		mux = &e->mux;
+		m0_entry = mux->muxnames[0];
+
 		/* First check for full name in mode0.muxmode format */
 		if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
 			continue;
 
 		/* Then check for muxmode only */
 		for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
-			char *mode_cur = m->muxnames[i];
+			char *mode_cur = mux->muxnames[i];
 
 			if (!mode_cur)
 				continue;
 
 			if (!strcmp(mode_name, mode_cur)) {
-				u16 old_mode;
-				u16 mux_mode;
-
-				old_mode = omap_mux_read(partition,
-							 m->reg_offset);
-				mux_mode = val | i;
-				pr_debug("%s: Setting signal "
-					 "%s.%s 0x%04x -> 0x%04x\n", __func__,
-					 m0_entry, muxname, old_mode, mux_mode);
-				omap_mux_write(partition, mux_mode,
-					       m->reg_offset);
+				*found_mux = mux;
 				found++;
+				found_mode = i;
 			}
 		}
 	}
 
-	if (found == 1)
-		return 0;
+	if (found == 1) {
+		return found_mode;
+	}
 
 	if (found > 1) {
 		pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
@@ -209,24 +205,51 @@ static int __init _omap_mux_init_signal(struct omap_mux_partition *partition,
 		return -EINVAL;
 	}
 
-	pr_err("%s: Could not set signal %s\n", __func__, muxname);
+	pr_err("%s: Could not find signal %s\n", __func__, muxname);
 
 	return -ENODEV;
 }
 
-int __init omap_mux_init_signal(const char *muxname, int val)
+static int __init
+omap_mux_get_by_name(const char *muxname,
+			struct omap_mux_partition **found_partition,
+			struct omap_mux **found_mux)
 {
 	struct omap_mux_partition *partition;
-	int ret;
 
 	list_for_each_entry(partition, &mux_partitions, node) {
-		ret = _omap_mux_init_signal(partition, muxname, val);
-		if (!ret)
-			return ret;
+		struct omap_mux *mux = NULL;
+		int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);
+		if (mux_mode < 0)
+			continue;
+
+		*found_partition = partition;
+		*found_mux = mux;
+
+		return mux_mode;
 	}
 
 	return -ENODEV;
+}
 
+int __init omap_mux_init_signal(const char *muxname, int val)
+{
+	struct omap_mux_partition *partition = NULL;
+	struct omap_mux *mux = NULL;
+	u16 old_mode;
+	int mux_mode;
+
+	mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
+	if (mux_mode < 0)
+		return mux_mode;
+
+	old_mode = omap_mux_read(partition, mux->reg_offset);
+	mux_mode |= val;
+	pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
+			 __func__, muxname, old_mode, mux_mode);
+	omap_mux_write(partition, mux_mode, mux->reg_offset);
+
+	return 0;
 }
 
 #ifdef CONFIG_DEBUG_FS

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
  2010-12-03  0:45 ` [PATCH 1/6] omap2+: Add omap_mux_get_by_name Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-23  2:46   ` Tony Lindgren
  2010-12-03  0:45 ` [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes Tony Lindgren
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

This allows adding hwmod specific pads dynamically during the
platform device init.

Note that we don't currently have the hwmod specific signals
listed in the hwmod data, but struct omap_hwmod_mux_info will
make that possible if necessary.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/mux.c                    |   67 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h                    |   24 +++++++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |   32 ++++++++++++
 3 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 0fa3d74..4008814 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -35,6 +35,8 @@
 
 #include <asm/system.h>
 
+#include <plat/omap_hwmod.h>
+
 #include "control.h"
 #include "mux.h"
 
@@ -49,6 +51,8 @@ struct omap_mux_entry {
 static LIST_HEAD(mux_partitions);
 static DEFINE_MUTEX(muxmode_mutex);
 
+static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux);
+
 struct omap_mux_partition *omap_mux_get(const char *name)
 {
 	struct omap_mux_partition *partition;
@@ -252,6 +256,69 @@ int __init omap_mux_init_signal(const char *muxname, int val)
 	return 0;
 }
 
+struct omap_hwmod_mux_info * __init
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	struct omap_hwmod_mux_info *hmux;
+	int i;
+
+	if (!bpads || nr_pads < 1)
+		return NULL;
+
+	hmux = kzalloc(sizeof(struct omap_hwmod_mux_info), GFP_KERNEL);
+	if (!hmux)
+		goto err1;
+
+	hmux->nr_pads = nr_pads;
+
+	hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
+				nr_pads, GFP_KERNEL);
+	if (!hmux->pads)
+		goto err2;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_mux_partition *partition;
+		struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
+		struct omap_mux *mux;
+		int mux_mode;
+
+		mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
+		if (mux_mode < 0)
+			goto err3;
+		if (!pad->partition)
+			pad->partition = partition;
+		if (!pad->mux)
+			pad->mux = mux;
+
+		pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
+		if (!pad->name) {
+			int j;
+
+			for (j = i - 1; j >= 0; j--)
+				kfree(hmux->pads[j].name);
+			goto err3;
+		}
+		strcpy(pad->name, bpad->name);
+
+		pad->flags = bpad->flags;
+		pad->enable = bpad->enable;
+		pad->idle = bpad->idle;
+		pad->off = bpad->off;
+		pr_debug("%s: Initialized %s\n", __func__, pad->name);
+	}
+
+	return hmux;
+
+err3:
+	kfree(hmux->pads);
+err2:
+	kfree(hmux);
+err1:
+	pr_err("%s: Could not allocate device mux entry\n", __func__);
+
+	return NULL;
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS	10
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 79076d6..8c78bed 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -145,6 +145,30 @@ struct omap_board_mux {
 	u16	value;
 };
 
+#define OMAP_DEVICE_PAD_ENABLED		BIT(7)	/* Should not be needed in board-*.c files */
+#define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad, needs enable, idle and off */
+#define OMAP_DEVICE_PAD_WAKEUP		BIT(0)	/* Flag a pad as wake-up capable */
+
+/**
+ * struct omap_device_pad - device specific pad configuration
+ * @name:		signal name
+ * @flags:		pad specific runtime flags
+ * @enable:		runtime value for a pad
+ * @idle:		idle value for a pad
+ * @off:		off value for a pad, defaults to safe mode
+ * @partition:		mux partition
+ * @mux:		mux register
+ */
+struct omap_device_pad {
+	char				*name;
+	u8				flags;
+	u16				enable;
+	u16				idle;
+	u16				off;
+	struct omap_mux_partition	*partition;
+	struct omap_mux			*mux;
+};
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 7eaa8ed..7616007 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -78,6 +78,18 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 #define HWMOD_IDLEMODE_SMART		(1 << 2)
 
 /**
+ * struct omap_hwmod_mux_info - hwmod specific mux configuration
+ * @pads:              array of omap_device_pad entries
+ * @nr_pads:           number of omap_device_pad entries
+ *
+ * Note that this is currently built during init as needed.
+ */
+struct omap_hwmod_mux_info {
+	int				nr_pads;
+	struct omap_device_pad		*pads;
+};
+
+/**
  * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
  * @name: name of the IRQ channel (module local name)
  * @irq_ch: IRQ channel ID
@@ -469,6 +481,7 @@ struct omap_hwmod {
 	const char			*name;
 	struct omap_hwmod_class		*class;
 	struct omap_device		*od;
+	struct omap_hwmod_mux_info	*mux;
 	struct omap_hwmod_irq_info	*mpu_irqs;
 	struct omap_hwmod_dma_info	*sdma_reqs;
 	struct omap_hwmod_rst_info	*rst_lines;
@@ -504,6 +517,25 @@ struct omap_hwmod {
 };
 
 int omap_hwmod_init(struct omap_hwmod **ohs);
+
+/**
+ * omap_hwmod_mux_init - initialize hwmod specific mux data
+ * @bpads:		Board specific device signal names
+ * @nr_pads:		Number of signal names for the device
+ *
+ * Called only from omap_device_build, do not use.
+ */
+#ifdef CONFIG_OMAP_MUX
+extern struct omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
+#else
+static inline omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	return NULL;
+}
+#endif
+
 int omap_hwmod_register(struct omap_hwmod *oh);
 int omap_hwmod_unregister(struct omap_hwmod *oh);
 struct omap_hwmod *omap_hwmod_lookup(const char *name);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
  2010-12-03  0:45 ` [PATCH 1/6] omap2+: Add omap_mux_get_by_name Tony Lindgren
  2010-12-03  0:45 ` [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-23  2:48   ` Tony Lindgren
  2010-12-03  0:45 ` [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux Tony Lindgren
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

Allow hwmod state changes to mux pads based on the state changes.

By default, only enable and disable the pads. In some rare cases
dynamic remuxing for the idles states is needed, this can be done
by passing the enable, idle, and off pads from board-*.c file along
with OMAP_DEVICE_PAD_REMUX flag.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/mux.c        |   48 ++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h        |   15 ++++++++++++
 arch/arm/mach-omap2/omap_hwmod.c |   14 +++++++++--
 3 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 4008814..b1a593f 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -319,6 +319,54 @@ err1:
 	return NULL;
 }
 
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+	int i;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+		int flags, val = -EINVAL;
+
+		flags = pad->flags;
+
+		switch (state) {
+		case _HWMOD_STATE_ENABLED:
+			if (flags & OMAP_DEVICE_PAD_ENABLED)
+				break;
+			flags |= OMAP_DEVICE_PAD_ENABLED;
+			val = pad->enable;
+			pr_debug("%s: Enabling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_IDLE:
+			if (!(flags & OMAP_DEVICE_PAD_REMUX))
+				break;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			val = pad->idle;
+			pr_debug("%s: Idling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_DISABLED:
+		default:
+			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
+			if (flags & OMAP_DEVICE_PAD_REMUX)
+				val = pad->off;
+			else
+				val = OMAP_MUX_MODE7;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			pr_debug("%s: Disabling %s %x\n", __func__,
+					pad->name, val);
+		};
+
+		if (val >= 0) {
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+			pad->flags = flags;
+		}
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS	10
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 8c78bed..c4b4f27 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -185,6 +185,17 @@ int omap_mux_init_gpio(int gpio, int val);
  */
 int omap_mux_init_signal(const char *muxname, int val);
 
+struct omap_hwmod_mux_info;
+
+/**
+ * omap_hwmod_mux - omap hwmod specific pin muxing
+ * @hmux:		Pads for a hwmod
+ * @state:		Desired _HWMOD_STATE
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+
 #else
 
 static inline int omap_mux_init_gpio(int gpio, int val)
@@ -196,6 +207,10 @@ static inline int omap_mux_init_signal(char *muxname, int val)
 	return 0;
 }
 
+}
+
+static inline void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
 #endif
 
 /**
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 5a30658..cd787a2 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -116,7 +116,6 @@
  * - Open Core Protocol Specification 2.2
  *
  * To do:
- * - pin mux handling
  * - handle IO mapping
  * - bus throughput & module latency measurement code
  *
@@ -146,6 +145,7 @@
 
 #include "cm.h"
 #include "prm.h"
+#include "mux.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
 #define MAX_MODULE_SOFTRESET_WAIT	10000
@@ -1197,7 +1197,9 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 	     oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
 		_deassert_hardreset(oh, oh->rst_lines[0].name);
 
-	/* XXX mux balls */
+	/* Mux pins for device runtime if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
 	_enable_clocks(oh);
@@ -1245,6 +1247,10 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
 	_del_initiator_dep(oh, mpu_oh);
 	_disable_clocks(oh);
 
+	/* Mux pins for device idle if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+
 	oh->_state = _HWMOD_STATE_IDLE;
 
 	return 0;
@@ -1288,7 +1294,9 @@ static int _shutdown(struct omap_hwmod *oh)
 	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
-	/* XXX mux any associated balls to safe mode */
+	/* Mux pins to safe mode or use populated off mode values */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
 
 	oh->_state = _HWMOD_STATE_DISABLED;
 

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
                   ` (2 preceding siblings ...)
  2010-12-03  0:45 ` [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-23  2:49   ` Tony Lindgren
  2010-12-03  0:45 ` [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init Tony Lindgren
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

This way board specific pads can be initialized automatically.
Note that this does not currently handle the multiple hwmod case.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/devices.c                 |    2 +-
 arch/arm/mach-omap2/gpio.c                    |    2 +-
 arch/arm/mach-omap2/pm.c                      |    3 ++-
 arch/arm/mach-omap2/serial.c                  |    4 ++--
 arch/arm/plat-omap/i2c.c                      |    4 ++--
 arch/arm/plat-omap/include/plat/omap_device.h |   19 +++++++++++++++++--
 arch/arm/plat-omap/omap_device.c              |   14 ++++++++++++--
 7 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5a0c148..389337c 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -1059,7 +1059,7 @@ static int __init omap_init_wdt(void)
 		return -EINVAL;
 	}
 
-	od = omap_device_build(dev_name, id, oh, NULL, 0,
+	od = omap_device_build(dev_name, id, oh, NULL, NULL, 0,
 				omap_wdt_latency,
 				ARRAY_SIZE(omap_wdt_latency), 0);
 	WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n",
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 413de18..488b769 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -75,7 +75,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		return -EINVAL;
 	}
 
-	od = omap_device_build(name, id - 1, oh, pdata,
+	od = omap_device_build(name, id - 1, oh, NULL, pdata,
 				sizeof(*pdata),	omap_gpio_latency,
 				ARRAY_SIZE(omap_gpio_latency),
 				false);
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 59ca03b..574b004 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -64,7 +64,8 @@ static int _init_omap_device(char *name, struct device **new_dev)
 		 __func__, name))
 		return -ENODEV;
 
-	od = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+	od = omap_device_build(oh->name, 0, oh, NULL, NULL, 0,
+			       pm_lats, 0, false);
 	if (WARN(IS_ERR(od), "%s: could not build omap_device for %s\n",
 		 __func__, name))
 		return -ENODEV;
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 9dc077e..905626e 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -797,8 +797,8 @@ void __init omap_serial_init_port(int port)
 	if (WARN_ON(!oh))
 		return;
 
-	od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
+	od = omap_device_build(name, uart->num, oh, NULL,
+			       pdata, pdata_size, omap_uart_latency,
 			       ARRAY_SIZE(omap_uart_latency), false);
 	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index a5bff9c..8275e41 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -154,8 +154,8 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	 */
 	if (cpu_is_omap34xx())
 		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	od = omap_device_build(name, bus_id, oh, pdata,
-			sizeof(struct omap_i2c_bus_platform_data),
+	od = omap_device_build(name, bus_id, oh, NULL,
+			pdata, sizeof(struct omap_i2c_bus_platform_data),
 			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
 	WARN(IS_ERR(od), "Could not build omap_device for %s\n", name);
 
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 28e2d1a..9d179d7 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -45,6 +45,20 @@ extern struct device omap_device_parent;
 #define OMAP_DEVICE_STATE_SHUTDOWN	3
 
 /**
+ * struct omap_device_board_data - board specific device data
+ * @id: instance id
+ * @flags: additional flags for platform init code
+ * @pads: array of device specific pads
+ * @pads_cnt: ARRAY_SIZE() of pads
+ */
+struct omap_device_board_data {
+	int			id;
+	u32			flags;
+	struct omap_device_pad	*pads;
+	int			pads_cnt;
+};
+
+/**
  * struct omap_device - omap_device wrapper for platform_devices
  * @pdev: platform_device
  * @hwmods: (one .. many per omap_device)
@@ -87,8 +101,9 @@ int omap_device_count_resources(struct omap_device *od);
 int omap_device_fill_resources(struct omap_device *od, struct resource *res);
 
 struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
+				      struct omap_hwmod *oh,
+				      struct omap_device_board_data *bdata,
+				      void *pdata, int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt, int is_early_device);
 
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index abe933c..a9a57ba 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -338,6 +338,7 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
  * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @bdata: board specific device data
  * @pdata: platform_data ptr to associate with the platform_device
  * @pdata_len: amount of memory pointed to by @pdata
  * @pm_lats: pointer to a omap_device_pm_latency array for this device
@@ -351,8 +352,9 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
  * passes along the return value of omap_device_build_ss().
  */
 struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
+				      struct omap_hwmod *oh,
+				      struct omap_device_board_data *bdata,
+				      void *pdata, int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt, int is_early_device)
 {
@@ -361,6 +363,14 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
 	if (!oh)
 		return ERR_PTR(-EINVAL);
 
+	if (bdata && bdata->pads && bdata->pads_cnt) {
+		struct omap_hwmod_mux_info *hmux;
+
+		hmux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
+		if (hmux)
+			oh->mux = hmux;
+	}
+
 	return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
 				    pdata_len, pm_lats, pm_lats_cnt,
 				    is_early_device);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
                   ` (3 preceding siblings ...)
  2010-12-03  0:45 ` [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-23  2:51   ` Tony Lindgren
  2010-12-03  0:45 ` [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0 Tony Lindgren
  2010-12-21 17:04 ` [PATCH 0/6] omap: Board specific muxing using hwmod Paul Walmsley
  6 siblings, 1 reply; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

This is needed to pass board specific data such as pads used.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/serial.c             |   27 ++++++++++++++++++---------
 arch/arm/plat-omap/include/plat/serial.h |    5 ++++-
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 905626e..45c3ee3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -698,16 +698,16 @@ void __init omap_serial_early_init(void)
 
 /**
  * omap_serial_init_port() - initialize single serial port
- * @port: serial port number (0-3)
+ * @bdata: port specific board data pointer
  *
- * This function initialies serial driver for given @port only.
+ * This function initialies serial driver for given port only.
  * Platforms can call this function instead of omap_serial_init()
  * if they don't plan to use all available UARTs as serial ports.
  *
  * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
  * use only one of the two.
  */
-void __init omap_serial_init_port(int port)
+void __init omap_serial_init_port(struct omap_device_board_data *bdata)
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
@@ -725,13 +725,15 @@ void __init omap_serial_init_port(int port)
 	struct omap_uart_port_info omap_up;
 #endif
 
-	if (WARN_ON(port < 0))
+	if (WARN_ON(!bdata))
 		return;
-	if (WARN_ON(port >= num_uarts))
+	if (WARN_ON(bdata->id < 0))
+		return;
+	if (WARN_ON(bdata->id >= num_uarts))
 		return;
 
 	list_for_each_entry(uart, &uart_list, node)
-		if (port == uart->num)
+		if (bdata->id == uart->num)
 			break;
 
 	oh = uart->oh;
@@ -797,7 +799,7 @@ void __init omap_serial_init_port(int port)
 	if (WARN_ON(!oh))
 		return;
 
-	od = omap_device_build(name, uart->num, oh, NULL,
+	od = omap_device_build(name, uart->num, oh, bdata,
 			       pdata, pdata_size, omap_uart_latency,
 			       ARRAY_SIZE(omap_uart_latency), false);
 	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
@@ -860,7 +862,14 @@ void __init omap_serial_init_port(int port)
 void __init omap_serial_init(void)
 {
 	struct omap_uart_state *uart;
+	struct omap_device_board_data bdata;
 
-	list_for_each_entry(uart, &uart_list, node)
-		omap_serial_init_port(uart->num);
+	list_for_each_entry(uart, &uart_list, node) {
+		bdata.id = uart->num;
+		bdata.flags = 0;
+		bdata.pads = NULL;
+		bdata.pads_cnt = 0;
+		omap_serial_init_port(&bdata);
+
+	}
 }
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 19145f5..dfa6346 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -93,9 +93,12 @@
 			})
 
 #ifndef __ASSEMBLER__
+
+struct omap_device_board_data;
+
 extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
-extern void omap_serial_init_port(int port);
+extern void omap_serial_init_port(struct omap_device_board_data *bdata);
 extern int omap_uart_can_sleep(void);
 extern void omap_uart_check_wakeup(void);
 extern void omap_uart_prepare_suspend(void);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
                   ` (4 preceding siblings ...)
  2010-12-03  0:45 ` [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init Tony Lindgren
@ 2010-12-03  0:45 ` Tony Lindgren
  2010-12-14  3:17   ` Kevin Hilman
  2010-12-23  2:53   ` Tony Lindgren
  2010-12-21 17:04 ` [PATCH 0/6] omap: Board specific muxing using hwmod Paul Walmsley
  6 siblings, 2 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-03  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

Use omap_serial_init_port so we can let the serial code handle the
remuxing of the RX pads.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-n8x0.c |   66 ++++++++++++++++++++++++++++++++++++--
 1 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index d022301..e3429b4 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -29,6 +29,7 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
+#include <plat/omap_device.h>
 #include <plat/menelaus.h>
 #include <mach/irqs.h>
 #include <plat/mcspi.h>
@@ -754,8 +755,68 @@ static struct omap_board_mux board_mux[] __initdata = {
 	OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial0_pads[] __initdata = {
+	{ .name	= "uart1_rx.uart1_rx", .enable	= OMAP_MUX_MODE0 },
+	{ .name	= "uart1_tx.uart1_tx", .enable	= OMAP_MUX_MODE0 },
+};
+
+static struct omap_device_pad n800_serial1_pads[] __initdata = {
+	{ .name	= "uart2_rx.uart2_rx", .enable	= OMAP_MUX_MODE7, },
+	{
+		.name	= "uart2_tx.uart2_tx",
+		.enable	= OMAP_PULL_ENA | OMAP_MUX_MODE7,
+	},
+};
+
+static struct omap_device_pad n810_serial1_pads[] __initdata = {
+	{ .name	= "uart2_rx.uart2_rx", .enable	= OMAP_MUX_MODE0, },
+	{ .name	= "uart2_tx.uart2_tx", .enable	= OMAP_MUX_MODE0, },
+};
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	{
+		.name	= "uart3_rx_irrx.uart3_rx_irrx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+		.idle	= OMAP_MUX_MODE3	/* Mux as GPIO for idle */
+	},
+	{ .name	= "uart3_tx_irtx.uart3_tx_irtx", .enable = OMAP_MUX_MODE0, },
+};
+
+static struct omap_device_board_data serial0_data = {
+	.id		= 0,
+	.pads		= serial0_pads,
+	.pads_cnt	= ARRAY_SIZE(serial0_pads),
+};
+
+static struct omap_device_board_data serial1_data = {
+	.id		= 1,
+};
+
+static struct omap_device_board_data serial2_data = {
+	.id		= 2,
+	.pads		= serial2_pads,
+	.pads_cnt	= ARRAY_SIZE(serial2_pads),
+};
+
+static inline void board_serial_init(int is_n800)
+{
+	if (is_n800) {
+		serial1_data.pads = n800_serial1_pads;
+		serial1_data.pads_cnt = ARRAY_SIZE(n800_serial1_pads);
+	} else {
+		serial1_data.pads = n810_serial1_pads;
+		serial1_data.pads_cnt = ARRAY_SIZE(n810_serial1_pads);
+	}
+	omap_serial_init_port(&serial0_data);
+	omap_serial_init_port(&serial1_data);
+	omap_serial_init_port(&serial2_data);
+}
 #else
-#define board_mux	NULL
+static inline void board_serial_init(void)
+	omap_serial_init();
+}
 #endif
 
 static void __init n8x0_init_machine(void)
@@ -772,8 +833,7 @@ static void __init n8x0_init_machine(void)
 	if (machine_is_nokia_n810())
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
-
-	omap_serial_init();
+	board_serial_init(machine_is_nokia_n800());
 	n8x0_onenand_init();
 	n8x0_mmc_init();
 	n8x0_usb_init();

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0
  2010-12-03  0:45 ` [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0 Tony Lindgren
@ 2010-12-14  3:17   ` Kevin Hilman
  2010-12-18 17:53     ` Tony Lindgren
  2010-12-23  2:53   ` Tony Lindgren
  1 sibling, 1 reply; 16+ messages in thread
From: Kevin Hilman @ 2010-12-14  3:17 UTC (permalink / raw)
  To: linux-arm-kernel

Tony Lindgren <tony@atomide.com> writes:

> Use omap_serial_init_port so we can let the serial code handle the
> remuxing of the RX pads.
>
> Signed-off-by: Tony Lindgren <tony@atomide.com>

Does this work for UART wakeups on n810?  I don't see any 'idle' value
for the pads, so I'm guessing it wont work without those, right?  Or am
I missing something here.

Kevin

> ---
>  arch/arm/mach-omap2/board-n8x0.c |   66 ++++++++++++++++++++++++++++++++++++--
>  1 files changed, 63 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
> index d022301..e3429b4 100644
> --- a/arch/arm/mach-omap2/board-n8x0.c
> +++ b/arch/arm/mach-omap2/board-n8x0.c
> @@ -29,6 +29,7 @@
>  
>  #include <plat/board.h>
>  #include <plat/common.h>
> +#include <plat/omap_device.h>
>  #include <plat/menelaus.h>
>  #include <mach/irqs.h>
>  #include <plat/mcspi.h>
> @@ -754,8 +755,68 @@ static struct omap_board_mux board_mux[] __initdata = {
>  	OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
>  	{ .reg_offset = OMAP_MUX_TERMINATOR },
>  };
> +
> +static struct omap_device_pad serial0_pads[] __initdata = {
> +	{ .name	= "uart1_rx.uart1_rx", .enable	= OMAP_MUX_MODE0 },
> +	{ .name	= "uart1_tx.uart1_tx", .enable	= OMAP_MUX_MODE0 },
> +};
> +
> +static struct omap_device_pad n800_serial1_pads[] __initdata = {
> +	{ .name	= "uart2_rx.uart2_rx", .enable	= OMAP_MUX_MODE7, },
> +	{
> +		.name	= "uart2_tx.uart2_tx",
> +		.enable	= OMAP_PULL_ENA | OMAP_MUX_MODE7,
> +	},
> +};
> +
> +static struct omap_device_pad n810_serial1_pads[] __initdata = {
> +	{ .name	= "uart2_rx.uart2_rx", .enable	= OMAP_MUX_MODE0, },
> +	{ .name	= "uart2_tx.uart2_tx", .enable	= OMAP_MUX_MODE0, },
> +};
> +
> +static struct omap_device_pad serial2_pads[] __initdata = {
> +	{
> +		.name	= "uart3_rx_irrx.uart3_rx_irrx",
> +		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
> +		.enable	= OMAP_MUX_MODE0,
> +		.idle	= OMAP_MUX_MODE3	/* Mux as GPIO for idle */
> +	},
> +	{ .name	= "uart3_tx_irtx.uart3_tx_irtx", .enable = OMAP_MUX_MODE0, },
> +};
> +
> +static struct omap_device_board_data serial0_data = {
> +	.id		= 0,
> +	.pads		= serial0_pads,
> +	.pads_cnt	= ARRAY_SIZE(serial0_pads),
> +};
> +
> +static struct omap_device_board_data serial1_data = {
> +	.id		= 1,
> +};
> +
> +static struct omap_device_board_data serial2_data = {
> +	.id		= 2,
> +	.pads		= serial2_pads,
> +	.pads_cnt	= ARRAY_SIZE(serial2_pads),
> +};
> +
> +static inline void board_serial_init(int is_n800)
> +{
> +	if (is_n800) {
> +		serial1_data.pads = n800_serial1_pads;
> +		serial1_data.pads_cnt = ARRAY_SIZE(n800_serial1_pads);
> +	} else {
> +		serial1_data.pads = n810_serial1_pads;
> +		serial1_data.pads_cnt = ARRAY_SIZE(n810_serial1_pads);
> +	}
> +	omap_serial_init_port(&serial0_data);
> +	omap_serial_init_port(&serial1_data);
> +	omap_serial_init_port(&serial2_data);
> +}
>  #else
> -#define board_mux	NULL
> +static inline void board_serial_init(void)
> +	omap_serial_init();
> +}
>  #endif
>  
>  static void __init n8x0_init_machine(void)
> @@ -772,8 +833,7 @@ static void __init n8x0_init_machine(void)
>  	if (machine_is_nokia_n810())
>  		i2c_register_board_info(2, n810_i2c_board_info_2,
>  					ARRAY_SIZE(n810_i2c_board_info_2));
> -
> -	omap_serial_init();
> +	board_serial_init(machine_is_nokia_n800());
>  	n8x0_onenand_init();
>  	n8x0_mmc_init();
>  	n8x0_usb_init();
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0
  2010-12-14  3:17   ` Kevin Hilman
@ 2010-12-18 17:53     ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-18 17:53 UTC (permalink / raw)
  To: linux-arm-kernel

* Kevin Hilman <khilman@deeprootsystems.com> [101213 19:17]:
> Tony Lindgren <tony@atomide.com> writes:
> 
> > Use omap_serial_init_port so we can let the serial code handle the
> > remuxing of the RX pads.
> >
> > Signed-off-by: Tony Lindgren <tony@atomide.com>
> 
> Does this work for UART wakeups on n810?  I don't see any 'idle' value
> for the pads, so I'm guessing it wont work without those, right?  Or am
> I missing something here.

Well this is still missing the gpio_request parts that are needed
for the serial port to wake. I have not added that as it currently
means we also get a gpio interrupt for every rx.

I'll do more patches to deal with the gpio parts later on.

The idle values are only needed for rx pins:

+static struct omap_device_pad serial2_pads[] __initdata = {
+       {
+               .name   = "uart3_rx_irrx.uart3_rx_irrx",
+               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+               .enable = OMAP_MUX_MODE0,
+               .idle   = OMAP_MUX_MODE3        /* Mux as GPIO for idle */
+       },
+       { .name = "uart3_tx_irtx.uart3_tx_irtx", .enable = OMAP_MUX_MODE0, },
+};

For the others, nothing is done dynamically.

Regards,

Tony

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 0/6] omap: Board specific muxing using hwmod
  2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
                   ` (5 preceding siblings ...)
  2010-12-03  0:45 ` [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0 Tony Lindgren
@ 2010-12-21 17:04 ` Paul Walmsley
  2010-12-23  3:07   ` Tony Lindgren
  6 siblings, 1 reply; 16+ messages in thread
From: Paul Walmsley @ 2010-12-21 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, 2 Dec 2010, Tony Lindgren wrote:

> Here are some patches to allow us to pass the board specific mux data
> to the platform level device init code, and then allow hwmod state
> changes to do the pin muxing.
> 
> Dynamic remuxing is also supported as needed, the last patch in this
> series sets up the board-*.c data for n8x0 to do uart3 rx pin remuxing
> for the idle modes.

Tony and I have been discussing these patches recently.  Here are some of 
the topics from that conversation, to share with the lists.  Tony, I hope 
I've summarized our discussions accurately; please correct anything you 
feel I've misstated below.  For those new to OMAP mux/padconf discussions, 
there is a short glossary at the bottom of this message that might be 
useful.

- Tony mentioned that the patch set had several purposes.  One purpose is 
to provide a mechanism for dynamic padconf reprogramming based on the 
state of a hwmod, such as in patch 6.  But another important purpose is to 
try to figure out a way to move common padconf programming out of the 
board files wherever it's possible and into the subarch-to-driver 
integration code in arch/arm/*omap*.

- In the past, I had suggested that the hwmod data should contain a list 
of signals for each hwmod.  (For example, uart2_hwmod would have 
"uart2_tx", "uart2_rts", "uart2_cts", and "uart2_rx" associated with it in 
the hwmod data.)  The hwmod code would indicate to the mux code when the 
signals associated with a hwmod became "enabled," "idle," or "shutdown," 
as the hwmod's state changed.  But looking at the code, and trying a 
sample implementation of this, I suspect this approach, while conceptually 
clean, may be too heavyweight for dynamic padconf reprogramming between 
the enable and idle states, as in patch 6.  In that patch, there's only 
one pad that needs to be reprogrammed when the hwmod goes idle, or is 
re-enabled.  No current need to iterate over all of the hwmod's signals.  
So, for the current use-case, we agreed that enable/idle dynamic padconf 
reprogramming could be done only for the specific pads that needed to 
change; and could be triggered by the hwmod's state, rather than the state 
of the hwmod's individual signals.  If at some point in the future it 
makes sense to add the signals to the hwmod data, we can always do it 
then.

- We also discussed where to store the dynamically-created padconf 
reprogramming data.  We agreed that we should probably defer storing the 
data in the omap_device layer.  The struct omap_device_board_data and 
struct omap_device_pad don't have any pointers or other references to or 
from struct omap_device.  We discussed that it might make more sense to 
store that data in the mux layer or in the hwmod data.  For the current 
scope of these patches, we agreed that it probably makes sense to 
associate that dynamically-created data to the struct hwmod.

- We also discussed that it might make sense to defer adding a bdata the 
omap_device_build() interface for this merge window, until we had a better 
sense of the use cases and how the board data relates to the 
platform_data.  We agreed that, in general, we should try to move as much 
of the common padconf details as possible out of the individual board 
files.

...

Based on the discussion and review, I had a few specific comments on the 
patches:

- It looks like patch 6 can use static mux directives for all but one of 
its dynamic padconf reprogramming entries (uart3_rx_irrx).  In terms of 
enable/idle padconf reprogramming, it might be worth trying to minimize 
the number of these, since many IP blocks can switch frequently between 
idled and enabled states.

- It seems like it might be problematic to program CONTROL_PADCONF 
registers based on the enabled/idled/shutdown state of a single hwmod.  
This is because the CONTROL_PADCONF settings affect multiple hwmods.  For 
example, the correct setting of ETK_D1 pad on OMAP3 can depend on the 
state of several different hwmods: ETK, McSPI3, HSUSB, GPIO1.  If dynamic 
padconf reprogramming directives for the same pad(s) (e.g., ETK_D1) are 
associated with more than one of these hwmods, then the final padconf 
setting could be unpredictable: basically, the last hwmod to change state 
will be the one that determines the setting of the padconf register.  
Ultimately, it may be necessary to make dynamic padconf reprogramming 
directives conditional on the states of all of the hwmods that are 
associated with a pad.  For example, something like this:

omap_mux_add_dynamic_remux(etk_hwmod,    HWMOD_STATE_NOT_ENABLED,
	                   mcspi3_hwmod, HWMOD_STATE_ENABLED,
                           hsusb1_hwmod, HWMOD_STATE_NOT_ENABLED,
                           gpio1_hwmod,  HWMOD_STATE_DONT_CARE,
                           "etk_d1", OMAP_MUX_MODE1)

meaning that pad "etk_d1" would only be programmed to mode 1 (mcspi3_somi)
when:

(etk_hwmod_state != HWMOD_STATE_ENABLED) &&
(mcspi3_hwmod_state == HWMOD_STATE_ENABLED) &&
(hsusb1_hwmod == HWMOD_STATE_NOT_ENABLED)

This may not be necessary to implement right away, since the use cases are 
not clear; and code to implement this will need some careful engineering 
to keep it from becoming too heavyweight.  If it does become necessary, it 
seems that this type of data would then be best stored in some higher 
layer than the struct hwmod.

...

We also discussed one other general comment about the mux layer - not 
related to these patches.  Since some signals can appear on multiple pads, 
at some point in the future, maybe in the future it might be useful to 
allow board files to specify their pad configurations in terms of (package 
ID, ball ID) -> (signal ID) -- so, for example, (CUS, AC11) -> (gpio_81).  
The idea being that the board designer, using a PCB design tool, might 
someday be able to export a list of padconf settings out of their EDA 
tools that we could use in the board files.  Looking at the OMAP3530 IBIS 
model at 

   http://focus.ti.com/lit/mo/symlink/omap3530-25_cus__ibis_model.ibs

it includes both the ball ID (which it calls the "pin") and the pad/mode 0 
name (which it calls the "signal name").

It still makes sense to me for padconf constraints associated with 
subarch-to-driver integration code -- such as usb-musb.c or usb-ehci.c - 
to refer to signals (since that's what is meaningful for those IP blocks) 
and let the mux code figure out what pads those signals appear on for that 
board's configuration.  That way, that code can stay board 
file-independent...


Just some thoughts, more comments welcome.


- Paul


An informal glossary for the usage of padconf-related terms in this 
E-mail:


signal: an on-chip input or output signal, exported by an on-chip IP block 
        such as UART2 or I2C1.  These signals can be routed to the
        OMAP IO multiplexing device controlled by the CONTROL_PADCONF
        registers.  Some examples of signals: "uart3_rx_irrx", "cam_d6".
        Some signals can appear on multiple pads, e.g., on 
        OMAP3, "uart1_rx" be muxed to the dss_data7 pad or the uart1_rx 
        pad.

pad: the area on the OMAP silicon die that may be connected to a ball or a 
     pin on the exterior OMAP package.  Each pad is controlled by a
     16-bit wide CONTROL_PADCONF register.  These 16-bit registers can be 
     named by their "mode 0 name", which is unique for a silicon
     design.

ball: an electrical connection point on the plastic OMAP package, 
      connecting to the printed circuit board or to a POPped chip, on 
      OMAPs in ball-grid array (BGA) packages.  Balls are identified
      with codes such as "AC23" or "Y22", documented in the chip data 
      manual.  Also called "pin"

mode 0 name: used in the context of pads and CONTROL_PADCONF registers, 
             the mode 0 name is the name of the signal that is connected 
             to that pad when the CONTROL_PADCONF register associated with 
             that pad is set to mux mode 0.

package: an enclosure for OMAP silicon, that contains small wires that 
         connect pads on the silicon to balls or other connection points
         on the exterior of the package.  One type of OMAP, e.g. 
         OMAP3430 ES3.1, might be available in several different packages 
         with different ball spacing, POP vs. non-POP, etc.  TI identifies 
         their OMAP packages with three letter codes, e.g., "CBC", "CUS", 
         "ZAC".

driver code: code in drivers/*

subarch-to-driver code: code in arch/arm/*omap* that creates an 
                        omap_device

padconf: pad configuration details that are programmed into the 
         CONTROL_PADCONF registers - these details include
         the mux mode, pull settings, off-mode pad configuration, etc.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices
  2010-12-03  0:45 ` [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices Tony Lindgren
@ 2010-12-23  2:46   ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  2:46 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 16:35]:
> This allows adding hwmod specific pads dynamically during the
> platform device init.
> 
> Note that we don't currently have the hwmod specific signals
> listed in the hwmod data, but struct omap_hwmod_mux_info will
> make that possible if necessary.

Here's this one rebased on top of recent patches from Paul.
Also moved the code around a bit with the omap_device_build
dependency removed.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Wed, 22 Dec 2010 18:42:35 -0800
Subject: [PATCH] omap2+: Add support for hwmod specific muxing of devices

This allows adding hwmod specific pads dynamically during the
platform device init.

Note that we don't currently have the hwmod specific signals
listed in the hwmod data, but struct omap_hwmod_mux_info will
make that possible if necessary.

Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 0fa3d74..27eb51a 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -35,6 +35,8 @@
 
 #include <asm/system.h>
 
+#include <plat/omap_hwmod.h>
+
 #include "control.h"
 #include "mux.h"
 
@@ -252,6 +254,69 @@ int __init omap_mux_init_signal(const char *muxname, int val)
 	return 0;
 }
 
+struct omap_hwmod_mux_info * __init
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	struct omap_hwmod_mux_info *hmux;
+	int i;
+
+	if (!bpads || nr_pads < 1)
+		return NULL;
+
+	hmux = kzalloc(sizeof(struct omap_hwmod_mux_info), GFP_KERNEL);
+	if (!hmux)
+		goto err1;
+
+	hmux->nr_pads = nr_pads;
+
+	hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
+				nr_pads, GFP_KERNEL);
+	if (!hmux->pads)
+		goto err2;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_mux_partition *partition;
+		struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
+		struct omap_mux *mux;
+		int mux_mode;
+
+		mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
+		if (mux_mode < 0)
+			goto err3;
+		if (!pad->partition)
+			pad->partition = partition;
+		if (!pad->mux)
+			pad->mux = mux;
+
+		pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
+		if (!pad->name) {
+			int j;
+
+			for (j = i - 1; j >= 0; j--)
+				kfree(hmux->pads[j].name);
+			goto err3;
+		}
+		strcpy(pad->name, bpad->name);
+
+		pad->flags = bpad->flags;
+		pad->enable = bpad->enable;
+		pad->idle = bpad->idle;
+		pad->off = bpad->off;
+		pr_debug("%s: Initialized %s\n", __func__, pad->name);
+	}
+
+	return hmux;
+
+err3:
+	kfree(hmux->pads);
+err2:
+	kfree(hmux);
+err1:
+	pr_err("%s: Could not allocate device mux entry\n", __func__);
+
+	return NULL;
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS	10
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index f5f7f49..9c48b9d 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -145,6 +145,32 @@ struct omap_board_mux {
 	u16	value;
 };
 
+#define OMAP_DEVICE_PAD_ENABLED		BIT(7)	/* Not needed for board-*.c */
+#define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad,
+						   needs enable, idle and off
+						   values */
+#define OMAP_DEVICE_PAD_WAKEUP		BIT(0)	/* Pad is wake-up capable */
+
+/**
+ * struct omap_device_pad - device specific pad configuration
+ * @name:		signal name
+ * @flags:		pad specific runtime flags
+ * @enable:		runtime value for a pad
+ * @idle:		idle value for a pad
+ * @off:		off value for a pad, defaults to safe mode
+ * @partition:		mux partition
+ * @mux:		mux register
+ */
+struct omap_device_pad {
+	char				*name;
+	u8				flags;
+	u16				enable;
+	u16				idle;
+	u16				off;
+	struct omap_mux_partition	*partition;
+	struct omap_mux			*mux;
+};
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
@@ -161,6 +187,14 @@ int omap_mux_init_gpio(int gpio, int val);
  */
 int omap_mux_init_signal(const char *muxname, int val);
 
+/**
+ * omap_hwmod_mux_init - initialize hwmod specific mux data
+ * @bpads:		Board specific device signal names
+ * @nr_pads:		Number of signal names for the device
+ */
+extern struct omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
+
 #else
 
 static inline int omap_mux_init_gpio(int gpio, int val)
@@ -172,6 +206,12 @@ static inline int omap_mux_init_signal(char *muxname, int val)
 	return 0;
 }
 
+static inline struct omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	return NULL;
+}
+
 static struct omap_board_mux *board_mux __initdata __maybe_unused;
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index b219a88..6864a99 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -81,6 +81,18 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 #define HWMOD_IDLEMODE_SMART_WKUP	(1 << 3)
 
 /**
+ * struct omap_hwmod_mux_info - hwmod specific mux configuration
+ * @pads:              array of omap_device_pad entries
+ * @nr_pads:           number of omap_device_pad entries
+ *
+ * Note that this is currently built during init as needed.
+ */
+struct omap_hwmod_mux_info {
+	int				nr_pads;
+	struct omap_device_pad		*pads;
+};
+
+/**
  * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
  * @name: name of the IRQ channel (module local name)
  * @irq_ch: IRQ channel ID
@@ -487,6 +499,7 @@ struct omap_hwmod {
 	const char			*name;
 	struct omap_hwmod_class		*class;
 	struct omap_device		*od;
+	struct omap_hwmod_mux_info	*mux;
 	struct omap_hwmod_irq_info	*mpu_irqs;
 	struct omap_hwmod_dma_info	*sdma_reqs;
 	struct omap_hwmod_rst_info	*rst_lines;

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes
  2010-12-03  0:45 ` [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes Tony Lindgren
@ 2010-12-23  2:48   ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  2:48 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 16:35]:
> Allow hwmod state changes to mux pads based on the state changes.
> 
> By default, only enable and disable the pads. In some rare cases
> dynamic remuxing for the idles states is needed, this can be done
> by passing the enable, idle, and off pads from board-*.c file along
> with OMAP_DEVICE_PAD_REMUX flag.

Here's this one updated mostly to build if CONFIG_OMAP_MUX is not
set.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Wed, 22 Dec 2010 18:42:35 -0800
Subject: [PATCH] omap2+: Allow hwmod state changes to mux pads based on the state changes

Allow hwmod state changes to mux pads based on the state changes.

By default, only enable and disable the pads. In some rare cases
dynamic remuxing for the idles states is needed, this can be done
by passing the enable, idle, and off pads from board-*.c file along
with OMAP_DEVICE_PAD_REMUX flag.

Thanks to Paul Walmsley <paul@booyaka.com> for the comments on the
hwmod related changes.

Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 27eb51a..17bd639 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -317,6 +317,54 @@ err1:
 	return NULL;
 }
 
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+	int i;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+		int flags, val = -EINVAL;
+
+		flags = pad->flags;
+
+		switch (state) {
+		case _HWMOD_STATE_ENABLED:
+			if (flags & OMAP_DEVICE_PAD_ENABLED)
+				break;
+			flags |= OMAP_DEVICE_PAD_ENABLED;
+			val = pad->enable;
+			pr_debug("%s: Enabling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_IDLE:
+			if (!(flags & OMAP_DEVICE_PAD_REMUX))
+				break;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			val = pad->idle;
+			pr_debug("%s: Idling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_DISABLED:
+		default:
+			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
+			if (flags & OMAP_DEVICE_PAD_REMUX)
+				val = pad->off;
+			else
+				val = OMAP_MUX_MODE7;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			pr_debug("%s: Disabling %s %x\n", __func__,
+					pad->name, val);
+		};
+
+		if (val >= 0) {
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+			pad->flags = flags;
+		}
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS	10
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 9c48b9d..c9ec50d 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -171,6 +171,8 @@ struct omap_device_pad {
 	struct omap_mux			*mux;
 };
 
+struct omap_hwmod_mux_info;
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
@@ -195,6 +197,15 @@ int omap_mux_init_signal(const char *muxname, int val);
 extern struct omap_hwmod_mux_info *
 omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
 
+/**
+ * omap_hwmod_mux - omap hwmod specific pin muxing
+ * @hmux:		Pads for a hwmod
+ * @state:		Desired _HWMOD_STATE
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+
 #else
 
 static inline int omap_mux_init_gpio(int gpio, int val)
@@ -212,6 +223,10 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
 	return NULL;
 }
 
+static inline void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+}
+
 static struct omap_board_mux *board_mux __initdata __maybe_unused;
 
 #endif
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 77a8be6..e282e35 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -116,7 +116,6 @@
  * - Open Core Protocol Specification 2.2
  *
  * To do:
- * - pin mux handling
  * - handle IO mapping
  * - bus throughput & module latency measurement code
  *
@@ -149,6 +148,7 @@
 #include "cm44xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
+#include "mux.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
 #define MAX_MODULE_SOFTRESET_WAIT	10000
@@ -1229,7 +1229,9 @@ static int _enable(struct omap_hwmod *oh)
 	     oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
 		_deassert_hardreset(oh, oh->rst_lines[0].name);
 
-	/* XXX mux balls */
+	/* Mux pins for device runtime if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
 	_enable_clocks(oh);
@@ -1276,6 +1278,10 @@ static int _idle(struct omap_hwmod *oh)
 	_del_initiator_dep(oh, mpu_oh);
 	_disable_clocks(oh);
 
+	/* Mux pins for device idle if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+
 	oh->_state = _HWMOD_STATE_IDLE;
 
 	return 0;
@@ -1334,7 +1340,9 @@ static int _shutdown(struct omap_hwmod *oh)
 	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
-	/* XXX mux any associated balls to safe mode */
+	/* Mux pins to safe mode or use populated off mode values */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
 
 	oh->_state = _HWMOD_STATE_DISABLED;
 

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux
  2010-12-03  0:45 ` [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux Tony Lindgren
@ 2010-12-23  2:49   ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  2:49 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 16:35]:
> This way board specific pads can be initialized automatically.
> Note that this does not currently handle the multiple hwmod case.

This one can now be dropped. As Paul pointed out the relationship
to omap_device needs more thinking. So let's populated the hwmod
mux info from each platform device init code for now.

Regards,

Tony

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init
  2010-12-03  0:45 ` [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init Tony Lindgren
@ 2010-12-23  2:51   ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  2:51 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 16:35]:
> This is needed to pass board specific data such as pads used.

Here's this one updated to not use omap_device_build.

Regards,

Tony


Author: Tony Lindgren <tony@atomide.com>
Date:   Wed Dec 22 18:42:35 2010 -0800

    omap2+: Add struct omap_board_data and use it for platform level serial init
    
    This is needed to pass board specific data such as pads used to the
    platform level driver init code.
    
    Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index c9ec50d..a4ab17a 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -87,6 +87,20 @@
 #define OMAP_MUX_GPIO_IN_MODE3		(1 << 1)
 
 /**
+ * struct omap_board_data - board specific device data
+ * @id: instance id
+ * @flags: additional flags for platform init code
+ * @pads: array of device specific pads
+ * @pads_cnt: ARRAY_SIZE() of pads
+ */
+struct omap_board_data {
+	int			id;
+	u32			flags;
+	struct omap_device_pad	*pads;
+	int			pads_cnt;
+};
+
+/**
  * struct mux_partition - contain partition related information
  * @name: name of the current partition
  * @flags: flags specific to this partition
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c8740ba..c645788 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -45,6 +45,7 @@
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
 #include "control.h"
+#include "mux.h"
 
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV	0x52
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
@@ -694,16 +695,16 @@ void __init omap_serial_early_init(void)
 
 /**
  * omap_serial_init_port() - initialize single serial port
- * @port: serial port number (0-3)
+ * @bdata: port specific board data pointer
  *
- * This function initialies serial driver for given @port only.
+ * This function initialies serial driver for given port only.
  * Platforms can call this function instead of omap_serial_init()
  * if they don't plan to use all available UARTs as serial ports.
  *
  * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
  * use only one of the two.
  */
-void __init omap_serial_init_port(int port)
+void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
@@ -721,13 +722,15 @@ void __init omap_serial_init_port(int port)
 	struct omap_uart_port_info omap_up;
 #endif
 
-	if (WARN_ON(port < 0))
+	if (WARN_ON(!bdata))
 		return;
-	if (WARN_ON(port >= num_uarts))
+	if (WARN_ON(bdata->id < 0))
+		return;
+	if (WARN_ON(bdata->id >= num_uarts))
 		return;
 
 	list_for_each_entry(uart, &uart_list, node)
-		if (port == uart->num)
+		if (bdata->id == uart->num)
 			break;
 
 	oh = uart->oh;
@@ -799,6 +802,8 @@ void __init omap_serial_init_port(int port)
 	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
+	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
+
 	uart->irq = oh->mpu_irqs[0].irq;
 	uart->regshift = 2;
 	uart->mapbase = oh->slaves[0]->addr->pa_start;
@@ -856,7 +861,14 @@ void __init omap_serial_init_port(int port)
 void __init omap_serial_init(void)
 {
 	struct omap_uart_state *uart;
+	struct omap_board_data bdata;
 
-	list_for_each_entry(uart, &uart_list, node)
-		omap_serial_init_port(uart->num);
+	list_for_each_entry(uart, &uart_list, node) {
+		bdata.id = uart->num;
+		bdata.flags = 0;
+		bdata.pads = NULL;
+		bdata.pads_cnt = 0;
+		omap_serial_init_port(&bdata);
+
+	}
 }
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 19145f5..cec5d56 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -93,9 +93,12 @@
 			})
 
 #ifndef __ASSEMBLER__
+
+struct omap_board_data;
+
 extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
-extern void omap_serial_init_port(int port);
+extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
 extern void omap_uart_check_wakeup(void);
 extern void omap_uart_prepare_suspend(void);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0
  2010-12-03  0:45 ` [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0 Tony Lindgren
  2010-12-14  3:17   ` Kevin Hilman
@ 2010-12-23  2:53   ` Tony Lindgren
  1 sibling, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  2:53 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 16:35]:
> Use omap_serial_init_port so we can let the serial code handle the
> remuxing of the RX pads.

And finally here's this one updated based on Paul's comments.
Let's not go through the list of all the static pins but
instead let's keep it shorter by only initializing the uart3
rx pin.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Wed, 22 Dec 2010 18:42:36 -0800
Subject: [PATCH] omap2+: Initialize serial port for dynamic remuxing for n8x0

Use omap_serial_init_port so we can let the serial code handle the
remuxing of the RX pads. Note that this patch alone is not enough
and additional GPIO related patches are needed.

Only initialize uart3_rx_irrx pin, the other uart pins can be
stay static.

Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 43af70e..147d900 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -645,6 +645,43 @@ static struct omap_board_mux board_mux[] __initdata = {
 	OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	{
+		.name	= "uart3_rx_irrx.uart3_rx_irrx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+		.idle	= OMAP_MUX_MODE3	/* Mux as GPIO for idle */
+	},
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+
+	bdata.flags = 0;
+	bdata.pads = NULL;
+	bdata.pads_cnt = 0;
+
+	bdata.id = 0;
+	omap_serial_init_port(&bdata);
+
+	bdata.id = 1;
+	omap_serial_init_port(&bdata);
+
+	bdata.id = 2;
+	bdata.pads = serial2_pads;
+	bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
+	omap_serial_init_port(&bdata);
+}
+
+#else
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
+
 #endif
 
 static void __init n8x0_init_machine(void)
@@ -659,8 +696,7 @@ static void __init n8x0_init_machine(void)
 	if (machine_is_nokia_n810())
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
-
-	omap_serial_init();
+	board_serial_init();
 	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 0/6] omap: Board specific muxing using hwmod
  2010-12-21 17:04 ` [PATCH 0/6] omap: Board specific muxing using hwmod Paul Walmsley
@ 2010-12-23  3:07   ` Tony Lindgren
  0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2010-12-23  3:07 UTC (permalink / raw)
  To: linux-arm-kernel

* Paul Walmsley <paul@pwsan.com> [101221 09:03]:
> Hi,
> 
> On Thu, 2 Dec 2010, Tony Lindgren wrote:
> 
> > Here are some patches to allow us to pass the board specific mux data
> > to the platform level device init code, and then allow hwmod state
> > changes to do the pin muxing.
> > 
> > Dynamic remuxing is also supported as needed, the last patch in this
> > series sets up the board-*.c data for n8x0 to do uart3 rx pin remuxing
> > for the idle modes.
> 
> Tony and I have been discussing these patches recently.  Here are some of 
> the topics from that conversation, to share with the lists.  Tony, I hope 
> I've summarized our discussions accurately; please correct anything you 
> feel I've misstated below.  For those new to OMAP mux/padconf discussions, 
> there is a short glossary at the bottom of this message that might be 
> useful.

Yeah, that's a good summary, adding few more comments below.
 
> - We also discussed that it might make sense to defer adding a bdata the 
> omap_device_build() interface for this merge window, until we had a better 
> sense of the use cases and how the board data relates to the 
> platform_data.  We agreed that, in general, we should try to move as much 
> of the common padconf details as possible out of the individual board 
> files.

I've now dropped the omap_device_build parts from the patches. For now,
we can populate the hwmod mux data from each platform init function.
 
> Based on the discussion and review, I had a few specific comments on the 
> patches:
> 
> - It looks like patch 6 can use static mux directives for all but one of 
> its dynamic padconf reprogramming entries (uart3_rx_irrx).  In terms of 
> enable/idle padconf reprogramming, it might be worth trying to minimize 
> the number of these, since many IP blocks can switch frequently between 
> idled and enabled states.

Good point, I've changed the n8x0 related patch to keep uart3 rx there
for now. In the long run we probably want to have a separate list for
dynamic pins. The other pins we should still enable during init and disable
when the driver is removed. But that can be added later.
 
> - It seems like it might be problematic to program CONTROL_PADCONF 
> registers based on the enabled/idled/shutdown state of a single hwmod.  
> This is because the CONTROL_PADCONF settings affect multiple hwmods.  For 
> example, the correct setting of ETK_D1 pad on OMAP3 can depend on the 
> state of several different hwmods: ETK, McSPI3, HSUSB, GPIO1.  If dynamic 
> padconf reprogramming directives for the same pad(s) (e.g., ETK_D1) are 
> associated with more than one of these hwmods, then the final padconf 
> setting could be unpredictable: basically, the last hwmod to change state 
> will be the one that determines the setting of the padconf register.  
> Ultimately, it may be necessary to make dynamic padconf reprogramming 
> directives conditional on the states of all of the hwmods that are 
> associated with a pad.  For example, something like this:
> 
> omap_mux_add_dynamic_remux(etk_hwmod,    HWMOD_STATE_NOT_ENABLED,
> 	                   mcspi3_hwmod, HWMOD_STATE_ENABLED,
>                            hsusb1_hwmod, HWMOD_STATE_NOT_ENABLED,
>                            gpio1_hwmod,  HWMOD_STATE_DONT_CARE,
>                            "etk_d1", OMAP_MUX_MODE1)
> 
> meaning that pad "etk_d1" would only be programmed to mode 1 (mcspi3_somi)
> when:
> 
> (etk_hwmod_state != HWMOD_STATE_ENABLED) &&
> (mcspi3_hwmod_state == HWMOD_STATE_ENABLED) &&
> (hsusb1_hwmod == HWMOD_STATE_NOT_ENABLED)
> 
> This may not be necessary to implement right away, since the use cases are 
> not clear; and code to implement this will need some careful engineering 
> to keep it from becoming too heavyweight.  If it does become necessary, it 
> seems that this type of data would then be best stored in some higher 
> layer than the struct hwmod.

Yes these kind of issues need to be dealt separately. Probably the best
place to deal with shared pins in each board-*.c file.
 
> We also discussed one other general comment about the mux layer - not 
> related to these patches.  Since some signals can appear on multiple pads, 
> at some point in the future, maybe in the future it might be useful to 
> allow board files to specify their pad configurations in terms of (package 
> ID, ball ID) -> (signal ID) -- so, for example, (CUS, AC11) -> (gpio_81).  
> The idea being that the board designer, using a PCB design tool, might 
> someday be able to export a list of padconf settings out of their EDA 
> tools that we could use in the board files.  Looking at the OMAP3530 IBIS 
> model at 
> 
>    http://focus.ti.com/lit/mo/symlink/omap3530-25_cus__ibis_model.ibs
> 
> it includes both the ball ID (which it calls the "pin") and the pad/mode 0 
> name (which it calls the "signal name").

That can be added easily, but depends on CONFIG_DEBUG_FS for the ball IDs
currently.

Regards,

Tony

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-12-23  3:07 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-03  0:45 [PATCH 0/6] omap: Board specific muxing using hwmod Tony Lindgren
2010-12-03  0:45 ` [PATCH 1/6] omap2+: Add omap_mux_get_by_name Tony Lindgren
2010-12-03  0:45 ` [PATCH 2/6] omap2+: Add support for hwmod specific muxing of devices Tony Lindgren
2010-12-23  2:46   ` Tony Lindgren
2010-12-03  0:45 ` [PATCH 3/6] omap2+: Allow hwmod state changes to mux pads based on the state changes Tony Lindgren
2010-12-23  2:48   ` Tony Lindgren
2010-12-03  0:45 ` [PATCH 4/6] omap2+: Add struct omap_device_board_data and allow omap_device_build initialize pads to mux Tony Lindgren
2010-12-23  2:49   ` Tony Lindgren
2010-12-03  0:45 ` [PATCH 5/6] omap2+: Use omap_device_board_data for platform level serial init Tony Lindgren
2010-12-23  2:51   ` Tony Lindgren
2010-12-03  0:45 ` [PATCH 6/6] omap2+: Initialize serial ports for wake-up events for n8x0 Tony Lindgren
2010-12-14  3:17   ` Kevin Hilman
2010-12-18 17:53     ` Tony Lindgren
2010-12-23  2:53   ` Tony Lindgren
2010-12-21 17:04 ` [PATCH 0/6] omap: Board specific muxing using hwmod Paul Walmsley
2010-12-23  3:07   ` Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).