[PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup.

STALE5630d

18 messages, 5 authors, 2011-03-04 · open the first message on its own page

[PATCH 0/7] OMAP2+: UART: runtime conversion + cleanup.

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:11

Converting uart driver to adapt to pm runtime api's.
Changes involves:
================
1.) Cleaning up certain uart calls from sram_idle func but still 
    retaining the prepare_idle/resume_idle func calls because as
    of today uart module level wakeup doesn't seem to work. 
    We have informed the hardware folks about this and discussion
    is in progress. So until we have a workaround for this we have to
    depend on prepare/resume calls to cut uart clock and wakeup based
    on io-daisy chain mechanism using uart_rx padconf.
2.) Removed all types of uart clock handling code from serial.c
    file and now onwards serial.c file is used only for device registration 
    and to probe early uart and pass some uart board data which
    can be passed as pdata to driver. Also cleaned up direct padconf usage.
3.) Using hwmod_mux api enable wakeup capability for uart pad during
    hwmod_idle state i.e., when uart clocks are disabled we can enable
    io-pad wakeup capability for uart if mux_data is available for 
    given uart. Also during during resume from idle call to uart we need
    to enable clocks back conditionally and this can be done only when io-pad
    wakeup event bit is set for uart_rx pad. So we need a hwmod api
    which can probe the uart pad and let us know whether a uart wakeup
    happened. So omap_hmwod_pad_wakeup_status api is added to meet this 
    requirement.
3.) Adapted omap-serial driver to use runtime api's.
4.) Modify serial_init calls to accept certain dma based uart parameters
5.) Minor cleanups and rename uart_rx_dma api.

Patch series is based on LO Kernel omap_for_linus branch.
Commit-id: 7cab8713b1ed0dab08ad6458f92a40b7ff4be619
Dependency patches needed to test system wide suspend on omap_for_linus branch.
https://patchwork.kernel.org/patch/550551/
https://patchwork.kernel.org/patch/513481/
https://patchwork.kernel.org/patch/501211/

Testing updates:
----------------
3430SDP, ZOOM2: retention, off_mode, system_wide suspend is tested.
OMAP3630 - Zoom3: pm-retention checked, off mode for per domain checked.
	[uart3/uart4 in per domain on omap3630].
OMAP4430[Blaze]: Boot tested.
OMAP2420/2430SDP: Boot tested

Govindraj.R (5):
  OMAP2+ : hwmod_data: update uart hwmod data.
  OMAP2+: mux: Enable wakeup for wakeup enable requested pads.
  OMAP2+: UART: Remove certain uart calls from sram_idle.
  OMAP2+: UART: Remove uart clock handling code serial.c
  Serial: OMAP: add runtime pm support for omap-serial driver

Jon Hunter (2):
  OMAP: Serial: Allow UART parameters to be configured from board file
  Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each
    UART

 arch/arm/mach-omap2/board-2430sdp.c           |    3 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    4 +-
 arch/arm/mach-omap2/board-4430sdp.c           |    3 +-
 arch/arm/mach-omap2/board-am3517evm.c         |    3 +-
 arch/arm/mach-omap2/board-apollon.c           |    3 +-
 arch/arm/mach-omap2/board-cm-t35.c            |    3 +-
 arch/arm/mach-omap2/board-cm-t3517.c          |    3 +-
 arch/arm/mach-omap2/board-devkit8000.c        |    3 +-
 arch/arm/mach-omap2/board-generic.c           |    3 +-
 arch/arm/mach-omap2/board-h4.c                |    3 +-
 arch/arm/mach-omap2/board-igep0020.c          |    3 +-
 arch/arm/mach-omap2/board-igep0030.c          |    3 +-
 arch/arm/mach-omap2/board-ldp.c               |    3 +-
 arch/arm/mach-omap2/board-n8x0.c              |    9 +-
 arch/arm/mach-omap2/board-omap3beagle.c       |    3 +-
 arch/arm/mach-omap2/board-omap3evm.c          |    3 +-
 arch/arm/mach-omap2/board-omap3logic.c        |    3 +-
 arch/arm/mach-omap2/board-omap3pandora.c      |    3 +-
 arch/arm/mach-omap2/board-omap3stalker.c      |    3 +-
 arch/arm/mach-omap2/board-omap3touchbook.c    |    3 +-
 arch/arm/mach-omap2/board-omap4panda.c        |    3 +-
 arch/arm/mach-omap2/board-overo.c             |    3 +-
 arch/arm/mach-omap2/board-rm680.c             |    3 +-
 arch/arm/mach-omap2/board-rx51.c              |    3 +-
 arch/arm/mach-omap2/board-ti8168evm.c         |    2 +-
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    3 +-
 arch/arm/mach-omap2/mux.c                     |   23 +
 arch/arm/mach-omap2/mux.h                     |   13 +
 arch/arm/mach-omap2/omap_hwmod.c              |   13 +
 arch/arm/mach-omap2/omap_hwmod_2420_data.c    |    3 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c    |    3 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |    4 +
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c    |    4 +
 arch/arm/mach-omap2/pm24xx.c                  |   11 -
 arch/arm/mach-omap2/pm34xx.c                  |   16 -
 arch/arm/mach-omap2/serial.c                  |  845 +++++--------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |   37 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    1 +
 arch/arm/plat-omap/include/plat/serial.h      |   10 +-
 drivers/tty/serial/omap-serial.c              |  323 +++++++++-
 40 files changed, 601 insertions(+), 789 deletions(-)

[PATCH 1/7] OMAP2+ : hwmod_data: update uart hwmod data.

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:12

Add HWMOD_SWSUP_SIDLE flag to uart*_hwmod data. With addition of this flag the
hwmod framework will take care of updating sysc reg with no_idle mode while
enabling clocks and to force_idle mode while disabling clocks.

Signed-off-by: Govindraj.R <redacted>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |    3 +++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |    3 +++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    4 ++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    4 ++++
 4 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index f323c6b..48392f3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -434,6 +434,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
 
 static struct omap_hwmod omap2420_uart1_hwmod = {
 	.name		= "uart1",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
 	.sdma_reqs	= uart1_sdma_reqs,
@@ -471,6 +472,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
 
 static struct omap_hwmod omap2420_uart2_hwmod = {
 	.name		= "uart2",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
 	.sdma_reqs	= uart2_sdma_reqs,
@@ -508,6 +510,7 @@ static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
 
 static struct omap_hwmod omap2420_uart3_hwmod = {
 	.name		= "uart3",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
 	.sdma_reqs	= uart3_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index de0015d..ab58a20 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -490,6 +490,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
 
 static struct omap_hwmod omap2430_uart1_hwmod = {
 	.name		= "uart1",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
 	.sdma_reqs	= uart1_sdma_reqs,
@@ -527,6 +528,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
 
 static struct omap_hwmod omap2430_uart2_hwmod = {
 	.name		= "uart2",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
 	.sdma_reqs	= uart2_sdma_reqs,
@@ -564,6 +566,7 @@ static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
 
 static struct omap_hwmod omap2430_uart3_hwmod = {
 	.name		= "uart3",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
 	.sdma_reqs	= uart3_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index e9d0012..79c39d4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -626,6 +626,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.name		= "uart1",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
 	.sdma_reqs	= uart1_sdma_reqs,
@@ -663,6 +664,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.name		= "uart2",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
 	.sdma_reqs	= uart2_sdma_reqs,
@@ -700,6 +702,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.name		= "uart3",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
 	.sdma_reqs	= uart3_sdma_reqs,
@@ -737,6 +740,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart4_hwmod = {
 	.name		= "uart4",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= uart4_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
 	.sdma_reqs	= uart4_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 79a8601..13c2df1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4587,6 +4587,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
 
 static struct omap_hwmod omap44xx_uart1_hwmod = {
 	.name		= "uart1",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.class		= &omap44xx_uart_hwmod_class,
 	.mpu_irqs	= omap44xx_uart1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart1_irqs),
@@ -4639,6 +4640,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
 
 static struct omap_hwmod omap44xx_uart2_hwmod = {
 	.name		= "uart2",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.class		= &omap44xx_uart_hwmod_class,
 	.mpu_irqs	= omap44xx_uart2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart2_irqs),
@@ -4691,6 +4693,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
 
 static struct omap_hwmod omap44xx_uart3_hwmod = {
 	.name		= "uart3",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.class		= &omap44xx_uart_hwmod_class,
 	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
 	.mpu_irqs	= omap44xx_uart3_irqs,
@@ -4744,6 +4747,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
 
 static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.name		= "uart4",
+	.flags		= HWMOD_SWSUP_SIDLE,
 	.class		= &omap44xx_uart_hwmod_class,
 	.mpu_irqs	= omap44xx_uart4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart4_irqs),
-- 
1.7.1

[PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:13

For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
are wakeup capable) enable the IO-daisy wakeup capability.
During re-muxing avoid direct write with val as this can disturb if any
mux done at bootloader level so read the pad then write back.

Also add a api to fetch the wake-up status bit is set for given omap-hwmod
device using available mux info which is added during omap_hwmod_mux_init.
Wakeup status bit is needed for uart_resume_idle call from sram_idle path
based on wake-up event has occurred for given uart we can enable clocks back.

Signed-off-by: Rajendra Nayak <redacted>
Signed-off-by: Govindraj.R <redacted>
---
 arch/arm/mach-omap2/mux.c                    |   23 +++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h                    |   13 +++++++++++++
 arch/arm/mach-omap2/omap_hwmod.c             |   13 +++++++++++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 98148b6..5338b93 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -317,6 +317,24 @@ err1:
 	return NULL;
 }
 
+/* Gets the wakeup status of given pad from omap-hwmod */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+	int i;
+	unsigned int val = -EINVAL;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		val = omap_mux_read(pad->partition, pad->mux->reg_offset);
+	}
+
+	if (val > 0 && val & OMAP_WAKEUP_EVENT)
+		return 1;
+	else
+		return 0;
+}
+
 /* Assumes the calling function takes care of locking */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
@@ -342,6 +360,9 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 				break;
 			flags &= ~OMAP_DEVICE_PAD_ENABLED;
 			val = pad->idle;
+			if (flags & OMAP_DEVICE_PAD_WAKEUP)
+				val |= OMAP_WAKEUP_EN;
+
 			pr_debug("%s: Idling %s %x\n", __func__,
 					pad->name, val);
 			break;
@@ -358,6 +379,8 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 		};
 
 		if (val >= 0) {
+			val |= omap_mux_read(pad->partition,
+						pad->mux->reg_offset);
 			omap_mux_write(pad->partition, val,
 					pad->mux->reg_offset);
 			pad->flags = flags;
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index a4ab17a..84a8fc2 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -220,8 +220,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
  */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+
+/**
+ * omap_hwmod_mux_wakeup - omap hwmod check given pad had wakeup event
+ * @hmux:		Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux);
 #else
 
+static inline int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+	return 0;
+}
+
 static inline int omap_mux_init_gpio(int gpio, int val)
 {
 	return 0;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 9e89a58..893dae1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2239,3 +2239,16 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 
 	return ret;
 }
+
+/**
+ * omap_hwmod_pad_wakeup_status - get pad wakeup status if mux is available.
+ * @oh: struct omap_hwmod *
+ *
+ * Returns the wake_up status bit of available pad mux pin.
+ */
+int omap_hmwod_pad_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh->mux)
+		return omap_hwmod_mux_wakeup(oh->mux);
+	return -EINVAL;
+}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index fedd829..4100be0 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -588,6 +588,7 @@ int omap_hwmod_for_each_by_class(const char *classname,
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
+int omap_hmwod_pad_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
-- 
1.7.1

[PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads

From: Varadarajan, Charulatha <hidden>
Date: 2011-03-02 04:49:58

Govind,

Couple of minor comments.

On Mon, Feb 28, 2011 at 20:09, Govindraj.R [off-list ref] wrote:
For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
are wakeup capable) enable the IO-daisy wakeup capability.
During re-muxing avoid direct write with val as this can disturb if any
mux done at bootloader level so read the pad then write back.

Also add a api to fetch the wake-up status bit is set for given omap-hwmod
%s/a api/an API/
quoted hunk
device using available mux info which is added during omap_hwmod_mux_init.
Wakeup status bit is needed for uart_resume_idle call from sram_idle path
based on wake-up event has occurred for given uart we can enable clocks back.

Signed-off-by: Rajendra Nayak <redacted>
Signed-off-by: Govindraj.R <redacted>
---
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++
?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++++
?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? 13 +++++++++++++
?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +
?4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 98148b6..5338b93 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -317,6 +317,24 @@ err1:
? ? ? ?return NULL;
?}

+/* Gets the wakeup status of given pad from omap-hwmod */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? int i;
+ ? ? ? unsigned int val = -EINVAL;
+
+ ? ? ? for (i = 0; i < hmux->nr_pads; i++) {
+ ? ? ? ? ? ? ? struct omap_device_pad *pad = &hmux->pads[i];
+
+ ? ? ? ? ? ? ? val = omap_mux_read(pad->partition, pad->mux->reg_offset);
+ ? ? ? }
+
+ ? ? ? if (val > 0 && val & OMAP_WAKEUP_EVENT)
+ ? ? ? ? ? ? ? return 1;
+ ? ? ? else
No need of else here.
+ ? ? ? ? ? ? ? return 0;
+}
+
- V Charulatha

[PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads

From: Govindraj <hidden>
Date: 2011-03-02 10:40:10

On Wed, Mar 2, 2011 at 10:19 AM, Varadarajan, Charulatha [off-list ref] wrote:
Govind,

Couple of minor comments.

On Mon, Feb 28, 2011 at 20:09, Govindraj.R [off-list ref] wrote:
quoted
For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
are wakeup capable) enable the IO-daisy wakeup capability.
During re-muxing avoid direct write with val as this can disturb if any
mux done at bootloader level so read the pad then write back.

Also add a api to fetch the wake-up status bit is set for given omap-hwmod
%s/a api/an API/
quoted
device using available mux info which is added during omap_hwmod_mux_init.
Wakeup status bit is needed for uart_resume_idle call from sram_idle path
based on wake-up event has occurred for given uart we can enable clocks back.

Signed-off-by: Rajendra Nayak <redacted>
Signed-off-by: Govindraj.R <redacted>
---
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++
?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++++
?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? 13 +++++++++++++
?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +
?4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 98148b6..5338b93 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -317,6 +317,24 @@ err1:
? ? ? ?return NULL;
?}

+/* Gets the wakeup status of given pad from omap-hwmod */
+int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
+{
+ ? ? ? int i;
+ ? ? ? unsigned int val = -EINVAL;
+
+ ? ? ? for (i = 0; i < hmux->nr_pads; i++) {
+ ? ? ? ? ? ? ? struct omap_device_pad *pad = &hmux->pads[i];
+
+ ? ? ? ? ? ? ? val = omap_mux_read(pad->partition, pad->mux->reg_offset);
+ ? ? ? }
+
+ ? ? ? if (val > 0 && val & OMAP_WAKEUP_EVENT)
+ ? ? ? ? ? ? ? return 1;
+ ? ? ? else
No need of else here.
Yes correct.

I am resending this patch with some more modifications
to fix one more issue in the above loop.

--
Thanks,
Govindraj.R



<<SNIP>>

[PATCH 3/7] OMAP2+: UART: Remove certain uart calls from sram_idle

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:14

In preparation to UART runtime conversion. Remove certain uart specific calls
from sram_idle path in pm24xx/34xx files.
These func calls will no more be used with upcoming uart runtime design.

1.) Removing console lock holding :- Now can be handled with omap-serial file
    itself with appropraite console_enable/disable calls for clk_enable/disable
    cases.
2.) omap_uart_can_sleep :- not needed driver can decide based on inactivity.
3.) omap_uart_prepare_suspend :- omap-serial can take care with driver
    suspend/resume hooks.

Signed-off-by: Govindraj.R <redacted>
---
 arch/arm/mach-omap2/pm24xx.c             |   11 -----------
 arch/arm/mach-omap2/pm34xx.c             |   16 ----------------
 arch/arm/plat-omap/include/plat/serial.h |    4 ----
 3 files changed, 0 insertions(+), 31 deletions(-)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 97feb3a..5af9881 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -132,11 +132,6 @@ static void omap2_enter_full_retention(void)
 	if (omap_irq_pending())
 		goto no_sleep;
 
-	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
-		if (!console_trylock())
-			goto no_sleep;
-
 	omap_uart_prepare_idle(0);
 	omap_uart_prepare_idle(1);
 	omap_uart_prepare_idle(2);
@@ -150,9 +145,6 @@ static void omap2_enter_full_retention(void)
 	omap_uart_resume_idle(1);
 	omap_uart_resume_idle(0);
 
-	if (!is_suspending())
-		console_unlock();
-
 no_sleep:
 	if (omap2_pm_debug) {
 		unsigned long long tmp;
@@ -267,8 +259,6 @@ static int omap2_can_sleep(void)
 {
 	if (omap2_fclks_active())
 		return 0;
-	if (!omap_uart_can_sleep())
-		return 0;
 	if (osc_ck->usecount > 1)
 		return 0;
 	if (omap_dma_running())
@@ -319,7 +309,6 @@ static int omap2_pm_suspend(void)
 	mir1 = omap_readl(0x480fe0a4);
 	omap_writel(1 << 5, 0x480fe0ac);
 
-	omap_uart_prepare_suspend();
 	omap2_enter_full_retention();
 
 	omap_writel(mir1, 0x480fe0a4);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f864e4..850bb0a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -395,13 +395,6 @@ void omap_sram_idle(void)
 		omap3_enable_io_chain();
 	}
 
-	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
-		if (per_next_state < PWRDM_POWER_ON ||
-		    core_next_state < PWRDM_POWER_ON)
-			if (!console_trylock())
-				goto console_still_active;
-
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
@@ -481,10 +474,6 @@ void omap_sram_idle(void)
 		omap_uart_resume_idle(3);
 	}
 
-	if (!is_suspending())
-		console_unlock();
-
-console_still_active:
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
 	    (per_next_state < PWRDM_POWER_ON ||
@@ -503,8 +492,6 @@ int omap3_can_sleep(void)
 {
 	if (!sleep_while_idle)
 		return 0;
-	if (!omap_uart_can_sleep())
-		return 0;
 	return 1;
 }
 
@@ -547,7 +534,6 @@ static int omap3_pm_suspend(void)
 			goto restore;
 	}
 
-	omap_uart_prepare_suspend();
 	omap3_intc_suspend();
 
 	omap_sram_idle();
@@ -594,14 +580,12 @@ static int omap3_pm_begin(suspend_state_t state)
 {
 	disable_hlt();
 	suspend_state = state;
-	omap_uart_enable_irqs(0);
 	return 0;
 }
 
 static void omap3_pm_end(void)
 {
 	suspend_state = PM_SUSPEND_ON;
-	omap_uart_enable_irqs(1);
 	enable_hlt();
 	return;
 }
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 8061695..6339848 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -106,12 +106,8 @@ struct omap_board_data;
 
 extern void omap_serial_init(void);
 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);
 extern void omap_uart_prepare_idle(int num);
 extern void omap_uart_resume_idle(int num);
-extern void omap_uart_enable_irqs(int enable);
 #endif
 
 #endif
-- 
1.7.1

[PATCH 4/7] OMAP2+: UART: Remove uart clock handling code serial.c

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:15

Cleanup serial.c file in preparation to addition of runtime api's in omap-serial
file. Cleanup serial.c file and remove all clock handling mechanism as
this will be taken care with pm runtime apis in omap-serial.c file itself.

1.) remove omap-device enable and disable. We can can use get_sync/put_sync api's
2.) remove context save/restore can be done with runtime_resume callback for
    get_sync call. No need to save context as all reg details available in
    uart_port structure can be used for restore, so add missing regs in
    uart port struct.
3.) Add api to identify console uart.
4.) Erratum handling informed as flag to driver and func to handle erratum
    can be moved to omap-serial driver itself.

Signed-off-by: Govindraj.R <redacted>
---
 arch/arm/mach-omap2/serial.c                  |  749 ++-----------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |   21 +-
 2 files changed, 75 insertions(+), 695 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 47eef48..755f4aa 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,25 +19,18 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/serial_reg.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/serial_8250.h>
 #include <linux/pm_runtime.h>
-#include <linux/console.h>
 
-#ifdef CONFIG_SERIAL_OMAP
 #include <plat/omap-serial.h>
-#endif
-
 #include <plat/common.h>
 #include <plat/board.h>
 #include <plat/clock.h>
 #include <plat/dma.h>
-#include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
 #include "prm2xxx_3xxx.h"
@@ -47,65 +40,9 @@
 #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 */
-
-#define UART_ERRATA_FIFO_FULL_ABORT	(0x1 << 0)
-#define UART_ERRATA_i202_MDR1_ACCESS	(0x1 << 1)
-
-/*
- * NOTE: By default the serial timeout is disabled as it causes lost characters
- * over the serial ports. This means that the UART clocks will stay on until
- * disabled via sysfs. This also causes that any deeper omap sleep states are
- * blocked. 
- */
-#define DEFAULT_TIMEOUT 0
-
-#define MAX_UART_HWMOD_NAME_LEN		16
-
-struct omap_uart_state {
-	int num;
-	int can_sleep;
-	struct timer_list timer;
-	u32 timeout;
-
-	void __iomem *wk_st;
-	void __iomem *wk_en;
-	u32 wk_mask;
-	u32 padconf;
-	u32 dma_enabled;
-
-	struct clk *ick;
-	struct clk *fck;
-	int clocked;
-
-	int irq;
-	int regshift;
-	int irqflags;
-	void __iomem *membase;
-	resource_size_t mapbase;
-
-	struct list_head node;
-	struct omap_hwmod *oh;
-	struct platform_device *pdev;
-
-	u32 errata;
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
-	int context_valid;
+#define MAX_UART_HWMOD_NAME_LEN                16
 
-	/* Registers to be saved/restored for OFF-mode */
-	u16 dll;
-	u16 dlh;
-	u16 ier;
-	u16 sysc;
-	u16 scr;
-	u16 wer;
-	u16 mcr;
-#endif
-};
-
-static LIST_HEAD(uart_list);
-static u8 num_uarts;
+static int omap_uart_con_id __initdata = -1;
 
 static int uart_idle_hwmod(struct omap_device *od)
 {
@@ -129,396 +66,35 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
 	},
 };
 
-static inline unsigned int __serial_read_reg(struct uart_port *up,
-					     int offset)
-{
-	offset <<= up->regshift;
-	return (unsigned int)__raw_readb(up->membase + offset);
-}
-
-static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
-					   int offset)
-{
-	offset <<= uart->regshift;
-	return (unsigned int)__raw_readb(uart->membase + offset);
-}
-
-static inline void __serial_write_reg(struct uart_port *up, int offset,
-		int value)
-{
-	offset <<= up->regshift;
-	__raw_writeb(value, up->membase + offset);
-}
-
-static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
-				    int value)
-{
-	offset <<= uart->regshift;
-	__raw_writeb(value, uart->membase + offset);
-}
-
-/*
- * Internal UARTs need to be initialized for the 8250 autoconfig to work
- * properly. Note that the TX watermark initialization may not be needed
- * once the 8250.c watermark handling code is merged.
- */
-
-static inline void __init omap_uart_reset(struct omap_uart_state *uart)
-{
-	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-	serial_write_reg(uart, UART_OMAP_SCR, 0x08);
-	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
-}
-
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
-
-/*
- * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
- * The access to uart register after MDR1 Access
- * causes UART to corrupt data.
- *
- * Need a delay =
- * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
- * give 10 times as much
- */
-static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
-		u8 fcr_val)
-{
-	u8 timeout = 255;
-
-	serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
-	udelay(2);
-	serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
-			UART_FCR_CLEAR_RCVR);
-	/*
-	 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
-	 * TX_FIFO_E bit is 1.
-	 */
-	while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
-				(UART_LSR_THRE | UART_LSR_DR))) {
-		timeout--;
-		if (!timeout) {
-			/* Should *never* happen. we warn and carry on */
-			dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
-			serial_read_reg(uart, UART_LSR));
-			break;
-		}
-		udelay(1);
-	}
-}
-
-static void omap_uart_save_context(struct omap_uart_state *uart)
-{
-	u16 lcr = 0;
-
-	if (!enable_off_mode)
-		return;
-
-	lcr = serial_read_reg(uart, UART_LCR);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	uart->dll = serial_read_reg(uart, UART_DLL);
-	uart->dlh = serial_read_reg(uart, UART_DLM);
-	serial_write_reg(uart, UART_LCR, lcr);
-	uart->ier = serial_read_reg(uart, UART_IER);
-	uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
-	uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
-	uart->wer = serial_read_reg(uart, UART_OMAP_WER);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
-	uart->mcr = serial_read_reg(uart, UART_MCR);
-	serial_write_reg(uart, UART_LCR, lcr);
-
-	uart->context_valid = 1;
-}
-
-static void omap_uart_restore_context(struct omap_uart_state *uart)
-{
-	u16 efr = 0;
-
-	if (!enable_off_mode)
-		return;
-
-	if (!uart->context_valid)
-		return;
-
-	uart->context_valid = 0;
-
-	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
-	else
-		serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	efr = serial_read_reg(uart, UART_EFR);
-	serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
-	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(uart, UART_IER, 0x0);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	serial_write_reg(uart, UART_DLL, uart->dll);
-	serial_write_reg(uart, UART_DLM, uart->dlh);
-	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(uart, UART_IER, uart->ier);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
-	serial_write_reg(uart, UART_MCR, uart->mcr);
-	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
-	serial_write_reg(uart, UART_EFR, efr);
-	serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
-	serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
-	serial_write_reg(uart, UART_OMAP_WER, uart->wer);
-	serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
-
-	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
-	else
-		/* UART 16x mode */
-		serial_write_reg(uart, UART_OMAP_MDR1,
-				UART_OMAP_MDR1_16X_MODE);
-}
-#else
-static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
-static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
-#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-
-static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
-{
-	if (uart->clocked)
-		return;
-
-	omap_device_enable(uart->pdev);
-	uart->clocked = 1;
-	omap_uart_restore_context(uart);
-}
-
-#ifdef CONFIG_PM
-
-static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
-{
-	if (!uart->clocked)
-		return;
-
-	omap_uart_save_context(uart);
-	uart->clocked = 0;
-	omap_device_idle(uart->pdev);
-}
-
-static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
-{
-	/* Set wake-enable bit */
-	if (uart->wk_en && uart->wk_mask) {
-		u32 v = __raw_readl(uart->wk_en);
-		v |= uart->wk_mask;
-		__raw_writel(v, uart->wk_en);
-	}
-
-	/* Ensure IOPAD wake-enables are set */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v |= OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
-}
-
-static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
-{
-	/* Clear wake-enable bit */
-	if (uart->wk_en && uart->wk_mask) {
-		u32 v = __raw_readl(uart->wk_en);
-		v &= ~uart->wk_mask;
-		__raw_writel(v, uart->wk_en);
-	}
-
-	/* Ensure IOPAD wake-enables are cleared */
-	if (cpu_is_omap34xx() && uart->padconf) {
-		u16 v = omap_ctrl_readw(uart->padconf);
-		v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
-		omap_ctrl_writew(v, uart->padconf);
-	}
-}
-
-static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
-					       int enable)
-{
-	u8 idlemode;
-
-	if (enable) {
-		/**
-		 * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
-		 * in Smartidle Mode When Configured for DMA Operations.
-		 */
-		if (uart->dma_enabled)
-			idlemode = HWMOD_IDLEMODE_FORCE;
-		else
-			idlemode = HWMOD_IDLEMODE_SMART;
-	} else {
-		idlemode = HWMOD_IDLEMODE_NO;
-	}
-
-	omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
-}
-
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
-	omap_uart_enable_clocks(uart);
-
-	omap_uart_smart_idle_enable(uart, 0);
-	uart->can_sleep = 0;
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
-	else
-		del_timer(&uart->timer);
-}
-
-static void omap_uart_allow_sleep(struct omap_uart_state *uart)
-{
-	if (device_may_wakeup(&uart->pdev->dev))
-		omap_uart_enable_wakeup(uart);
-	else
-		omap_uart_disable_wakeup(uart);
-
-	if (!uart->clocked)
-		return;
-
-	omap_uart_smart_idle_enable(uart, 1);
-	uart->can_sleep = 1;
-	del_timer(&uart->timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+				unsigned short num)
 {
-	struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-	omap_uart_allow_sleep(uart);
-}
-
-void omap_uart_prepare_idle(int num)
-{
-	struct omap_uart_state *uart;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		if (num == uart->num && uart->can_sleep) {
-			omap_uart_disable_clocks(uart);
-			return;
-		}
-	}
-}
-
-void omap_uart_resume_idle(int num)
-{
-	struct omap_uart_state *uart;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		if (num == uart->num && uart->can_sleep) {
-			omap_uart_enable_clocks(uart);
-
-			/* Check for IO pad wakeup */
-			if (cpu_is_omap34xx() && uart->padconf) {
-				u16 p = omap_ctrl_readw(uart->padconf);
-
-				if (p & OMAP3_PADCONF_WAKEUPEVENT0)
-					omap_uart_block_sleep(uart);
-			}
-
-			/* Check for normal UART wakeup */
-			if (__raw_readl(uart->wk_st) & uart->wk_mask)
-				omap_uart_block_sleep(uart);
-			return;
-		}
-	}
-}
-
-void omap_uart_prepare_suspend(void)
-{
-	struct omap_uart_state *uart;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		omap_uart_allow_sleep(uart);
-	}
-}
-
-int omap_uart_can_sleep(void)
-{
-	struct omap_uart_state *uart;
-	int can_sleep = 1;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		if (!uart->clocked)
-			continue;
-
-		if (!uart->can_sleep) {
-			can_sleep = 0;
-			continue;
-		}
-
-		/* This UART can now safely sleep. */
-		omap_uart_allow_sleep(uart);
-	}
-
-	return can_sleep;
-}
-
-/**
- * omap_uart_interrupt()
- *
- * This handler is used only to detect that *any* UART interrupt has
- * occurred.  It does _nothing_ to handle the interrupt.  Rather,
- * any UART interrupt will trigger the inactivity timer so the
- * UART will not idle or sleep for its timeout period.
- *
- **/
-/* static int first_interrupt; */
-static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
-{
-	struct omap_uart_state *uart = dev_id;
-
-	omap_uart_block_sleep(uart);
-
-	return IRQ_NONE;
-}
-
-static void omap_uart_idle_init(struct omap_uart_state *uart)
-{
-	int ret;
-
-	uart->can_sleep = 0;
-	uart->timeout = DEFAULT_TIMEOUT;
-	setup_timer(&uart->timer, omap_uart_idle_timer,
-		    (unsigned long) uart);
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
-	omap_uart_smart_idle_enable(uart, 0);
-
-	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
-		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+	if (cpu_is_omap34xx()) {
+		u32 mod = num > 1 ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
-		u32 padconf = 0;
 
-		/* XXX These PRM accesses do not belong here */
 		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP3430_ST_UART1_MASK;
-			padconf = 0x182;
 			break;
 		case 1:
 			wk_mask = OMAP3430_ST_UART2_MASK;
-			padconf = 0x17a;
 			break;
 		case 2:
 			wk_mask = OMAP3430_ST_UART3_MASK;
-			padconf = 0x19e;
 			break;
 		case 3:
 			wk_mask = OMAP3630_ST_UART4_MASK;
-			padconf = 0x0d2;
 			break;
 		}
 		uart->wk_mask = wk_mask;
-		uart->padconf = padconf;
 	} else if (cpu_is_omap24xx()) {
 		u32 wk_mask = 0;
 		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-		switch (uart->num) {
+		switch (num) {
 		case 0:
 			wk_mask = OMAP24XX_ST_UART1_MASK;
 			break;
@@ -543,155 +119,44 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		uart->wk_en = NULL;
 		uart->wk_st = NULL;
 		uart->wk_mask = 0;
-		uart->padconf = 0;
-	}
-
-	uart->irqflags |= IRQF_SHARED;
-	ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
-				   IRQF_SHARED, "serial idle", (void *)uart);
-	WARN_ON(ret);
-}
-
-void omap_uart_enable_irqs(int enable)
-{
-	int ret;
-	struct omap_uart_state *uart;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		if (enable) {
-			pm_runtime_put_sync(&uart->pdev->dev);
-			ret = request_threaded_irq(uart->irq, NULL,
-						   omap_uart_interrupt,
-						   IRQF_SHARED,
-						   "serial idle",
-						   (void *)uart);
-		} else {
-			pm_runtime_get_noresume(&uart->pdev->dev);
-			free_irq(uart->irq, (void *)uart);
-		}
 	}
 }
 
-static ssize_t sleep_timeout_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
+char *cmdline_find_option(char *str)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *odev = to_omap_device(pdev);
-	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
+	extern char *saved_command_line;
 
-	return sprintf(buf, "%u\n", uart->timeout / HZ);
+	return strstr(saved_command_line, str);
 }
 
-static ssize_t sleep_timeout_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t n)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *odev = to_omap_device(pdev);
-	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
-	unsigned int value;
-
-	if (sscanf(buf, "%u", &value) != 1) {
-		dev_err(dev, "sleep_timeout_store: Invalid value\n");
-		return -EINVAL;
-	}
-
-	uart->timeout = value * HZ;
-	if (uart->timeout)
-		mod_timer(&uart->timer, jiffies + uart->timeout);
-	else
-		/* A zero value means disable timeout feature */
-		omap_uart_block_sleep(uart);
-
-	return n;
-}
-
-static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
-		sleep_timeout_store);
-#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
-#else
-static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
-	/* Needed to enable UART clocks when built without CONFIG_PM */
-	omap_uart_enable_clocks(uart);
-}
-#define DEV_CREATE_FILE(dev, attr)
-#endif /* CONFIG_PM */
-
-#ifndef CONFIG_SERIAL_OMAP
-/*
- * Override the default 8250 read handler: mem_serial_in()
- * Empty RX fifo read causes an abort on omap3630 and omap4
- * This function makes sure that an empty rx fifo is not read on these silicons
- * (OMAP1/2/3430 are not affected)
- */
-static unsigned int serial_in_override(struct uart_port *up, int offset)
-{
-	if (UART_RX == offset) {
-		unsigned int lsr;
-		lsr = __serial_read_reg(up, UART_LSR);
-		if (!(lsr & UART_LSR_DR))
-			return -EPERM;
-	}
-
-	return __serial_read_reg(up, offset);
-}
-
-static void serial_out_override(struct uart_port *up, int offset, int value)
-{
-	unsigned int status, tmout = 10000;
+	struct omap_hwmod *oh;
+	char oh_name[MAX_UART_HWMOD_NAME_LEN];
 
-	status = __serial_read_reg(up, UART_LSR);
-	while (!(status & UART_LSR_THRE)) {
-		/* Wait up to 10ms for the character(s) to be sent. */
-		if (--tmout == 0)
-			break;
-		udelay(1);
-		status = __serial_read_reg(up, UART_LSR);
-	}
-	__serial_write_reg(up, offset, value);
+	snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+	oh = omap_hwmod_lookup(oh_name);
+	WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+					oh_name);
+	return oh;
 }
-#endif
 
 static int __init omap_serial_early_init(void)
 {
 	int i = 0;
+	char omap_tty_name[MAX_UART_HWMOD_NAME_LEN];
+	struct omap_hwmod *oh;
 
-	do {
-		char oh_name[MAX_UART_HWMOD_NAME_LEN];
-		struct omap_hwmod *oh;
-		struct omap_uart_state *uart;
-
-		snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
-			 "uart%d", i + 1);
-		oh = omap_hwmod_lookup(oh_name);
-		if (!oh)
-			break;
-
-		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
-		if (WARN_ON(!uart))
-			return -ENODEV;
-
-		uart->oh = oh;
-		uart->num = i++;
-		list_add_tail(&uart->node, &uart_list);
-		num_uarts++;
-
-		/*
-		 * NOTE: omap_hwmod_init() has not yet been called,
-		 *       so no hwmod functions will work yet.
-		 */
-
-		/*
-		 * During UART early init, device need to be probed
-		 * to determine SoC specific init before omap_device
-		 * is ready.  Therefore, don't allow idle here
-		 */
-		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
-	} while (1);
-
+	for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+		snprintf(omap_tty_name, MAX_UART_HWMOD_NAME_LEN,
+			"%s%d", OMAP_SERIAL_NAME, i);
+		if (cmdline_find_option(omap_tty_name)) {
+			omap_uart_con_id = i;
+			oh = omap_uart_hwmod_lookup(i);
+			oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+			return 0;
+		}
+	}
 	return 0;
 }
 core_initcall(omap_serial_early_init);
@@ -709,149 +174,50 @@ core_initcall(omap_serial_early_init);
  */
 void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
-	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
 	struct omap_device *od;
-	void *pdata = NULL;
-	u32 pdata_size = 0;
-	char *name;
-#ifndef CONFIG_SERIAL_OMAP
-	struct plat_serial8250_port ports[2] = {
-		{},
-		{.flags = 0},
-	};
-	struct plat_serial8250_port *p = &ports[0];
-#else
-	struct omap_uart_port_info omap_up;
-#endif
+	struct omap_uart_port_info *pdata;
+	char *name = DRIVER_NAME;
 
 	if (WARN_ON(!bdata))
 		return;
 	if (WARN_ON(bdata->id < 0))
 		return;
-	if (WARN_ON(bdata->id >= num_uarts))
+	if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))
 		return;
 
-	list_for_each_entry(uart, &uart_list, node)
-		if (bdata->id == uart->num)
-			break;
-
-	oh = uart->oh;
-	uart->dma_enabled = 0;
-#ifndef CONFIG_SERIAL_OMAP
-	name = "serial8250";
-
-	/*
-	 * !! 8250 driver does not use standard IORESOURCE* It
-	 * has it's own custom pdata that can be taken from
-	 * the hwmod resource data.  But, this needs to be
-	 * done after the build.
-	 *
-	 * ?? does it have to be done before the register ??
-	 * YES, because platform_device_data_add() copies
-	 * pdata, it does not use a pointer.
-	 */
-	p->flags = UPF_BOOT_AUTOCONF;
-	p->iotype = UPIO_MEM;
-	p->regshift = 2;
-	p->uartclk = OMAP24XX_BASE_BAUD * 16;
-	p->irq = oh->mpu_irqs[0].irq;
-	p->mapbase = oh->slaves[0]->addr->pa_start;
-	p->membase = omap_hwmod_get_mpu_rt_va(oh);
-	p->irqflags = IRQF_SHARED;
-	p->private_data = uart;
-
-	/*
-	 * omap44xx, ti816x: Never read empty UART fifo
-	 * omap3xxx: Never read empty UART fifo on UARTs
-	 * with IP rev >=0x52
-	 */
-	uart->regshift = p->regshift;
-	uart->membase = p->membase;
-	if (cpu_is_omap44xx() || cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-	else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
-			>= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
-		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
+	oh = omap_uart_hwmod_lookup(bdata->id);
+	if (!oh)
+		return;
 
-	if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
-		p->serial_in = serial_in_override;
-		p->serial_out = serial_out_override;
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Memory allocation for UART pdata failed\n");
+		return;
 	}
 
-	pdata = &ports[0];
-	pdata_size = 2 * sizeof(struct plat_serial8250_port);
-#else
-
-	name = DRIVER_NAME;
+	/* Enable the MDR1 errata for OMAP3 */
+	if (cpu_is_omap34xx())
+		pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 
-	omap_up.dma_enabled = uart->dma_enabled;
-	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
-	omap_up.mapbase = oh->slaves[0]->addr->pa_start;
-	omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
-	omap_up.irqflags = IRQF_SHARED;
-	omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	omap_uart_idle_init(pdata, bdata->id);
 
-	pdata = &omap_up;
-	pdata_size = sizeof(struct omap_uart_port_info);
-#endif
+	pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+	pdata->flags = UPF_BOOT_AUTOCONF;
+	if (bdata->id == omap_uart_con_id)
+		pdata->console_uart = true;
 
-	if (WARN_ON(!oh))
-		return;
-
-	od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
+	od = omap_device_build(name, bdata->id, oh, pdata,
+				sizeof(*pdata), 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);
 
 	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;
-	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = &od->pdev;
-
-	oh->dev_attr = uart;
-
-	console_lock(); /* in case the earlycon is on the UART */
-
-	/*
-	 * Because of early UART probing, UART did not get idled
-	 * on init.  Now that omap_device is ready, ensure full idle
-	 * before doing omap_device_enable().
-	 */
-	omap_hwmod_idle(uart->oh);
-
-	omap_device_enable(uart->pdev);
-	omap_uart_idle_init(uart);
-	omap_uart_reset(uart);
-	omap_hwmod_enable_wakeup(uart->oh);
-	omap_device_idle(uart->pdev);
-
-	/*
-	 * Need to block sleep long enough for interrupt driven
-	 * driver to start.  Console driver is in polling mode
-	 * so device needs to be kept enabled while polling driver
-	 * is in use.
-	 */
-	if (uart->timeout)
-		uart->timeout = (30 * HZ);
-	omap_uart_block_sleep(uart);
-	uart->timeout = DEFAULT_TIMEOUT;
-
-	console_unlock();
-
-	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask)) {
+	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
+	    (pdata->wk_en && pdata->wk_mask)) {
 		device_init_wakeup(&od->pdev.dev, true);
-		DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
 	}
-
-	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx() && !cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 }
 
 /**
@@ -863,15 +229,14 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  */
 void __init omap_serial_init(void)
 {
-	struct omap_uart_state *uart;
 	struct omap_board_data bdata;
+	u8 i;
 
-	list_for_each_entry(uart, &uart_list, node) {
-		bdata.id = uart->num;
+	for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+		bdata.id = i;
 		bdata.flags = 0;
 		bdata.pads = NULL;
 		bdata.pads_cnt = 0;
 		omap_serial_init_port(&bdata);
-
 	}
 }
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..f9bc7ef 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -56,13 +56,18 @@
 
 #define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
 
+#define UART_ERRATA_i202_MDR1_ACCESS	BIT(0)
+
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
-	void __iomem		*membase;	/* ioremap cookie or NULL */
-	resource_size_t		mapbase;	/* resource base */
-	unsigned long		irqflags;	/* request_irq flags */
 	upf_t			flags;		/* UPF_* flags */
+	unsigned int		errata;
+	unsigned int		console_uart;
+
+	void __iomem *wk_st;
+	void __iomem *wk_en;
+	u32 wk_mask;
 };
 
 struct uart_omap_dma {
@@ -100,6 +105,9 @@ struct uart_omap_port {
 	unsigned char		mcr;
 	unsigned char		fcr;
 	unsigned char		efr;
+	unsigned char		dll;
+	unsigned char		dlh;
+	unsigned char		mdr1;
 
 	int			use_dma;
 	/*
@@ -111,6 +119,13 @@ struct uart_omap_port {
 	unsigned char		msr_saved_flags;
 	char			name[20];
 	unsigned long		port_activity;
+	struct timer_list	inactivity_timer;
+	unsigned int		errata;
+	int			can_sleep;
+
+	void __iomem *wk_st;
+	void __iomem *wk_en;
+	u32 wk_mask;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
-- 
1.7.1

[PATCH 5/7] Serial: OMAP: add runtime pm support for omap-serial driver

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:16

Adapts omap-serial driver to use pm_runtime api's.

1.) Populate reg values to uart port which can be used for context restore.
2.) Moved Erratum handling func to driver from serial.c
3.) adding port_enable/disable func to enable/disable given uart port.
4.) using prepare/resume api's to cut and enable back uart func_clks.
5.) using timer to set flag to cut uart clocks based on this flag in
    sram_idle path.

Signed-off-by: Govindraj.R <redacted>
---
 drivers/tty/serial/omap-serial.c |  304 +++++++++++++++++++++++++++++++++++---
 1 files changed, 283 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d40924a..bc877b9 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -33,10 +33,21 @@
 #include <linux/clk.h>
 #include <linux/serial_core.h>
 #include <linux/irq.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/dma.h>
 #include <plat/dmtimer.h>
 #include <plat/omap-serial.h>
+#include <plat/serial.h>
+#include <plat/omap_device.h>
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+#define omap_uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
+#else
+#define omap_uart_console(port)	NULL
+#endif
+
+#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
 
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
@@ -44,6 +55,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
 static void serial_omap_rx_timeout(unsigned long uart_no);
 static int serial_omap_start_rxdma(struct uart_omap_port *up);
+static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
 
 static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
 {
@@ -90,6 +102,73 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
 	return port->uartclk/(baud * divisor);
 }
 
+static void omap_uart_smart_idle(struct uart_omap_port *up)
+{
+	struct platform_device *pdev = up->pdev;
+	struct omap_device *od = container_of(pdev, struct omap_device, pdev);
+
+	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
+}
+
+static void serial_omap_port_disable(struct uart_omap_port *up)
+{
+	if (!pm_runtime_suspended(&up->pdev->dev)) {
+		del_timer(&up->inactivity_timer);
+		if (omap_uart_console(&up->port))
+			console_stop(up->port.cons);
+
+		pm_runtime_put_sync(&up->pdev->dev);
+	}
+}
+
+static void serial_omap_inactivity_timer(unsigned long uart_no)
+{
+	struct uart_omap_port *up = ui[uart_no];
+
+	up->can_sleep = 1;
+	omap_uart_smart_idle(up);
+}
+
+static void serial_omap_port_enable(struct uart_omap_port *up)
+{
+	if (pm_runtime_suspended(&up->pdev->dev)) {
+		if (omap_uart_console(&up->port))
+			console_start(up->port.cons);
+
+		pm_runtime_get_sync(&up->pdev->dev);
+	}
+
+	up->can_sleep = 0;
+	mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
+}
+
+void omap_uart_prepare_idle(int num)
+{
+	struct uart_omap_port *up = ui[num];
+
+	if (up && up->can_sleep)
+		serial_omap_port_disable(up);
+}
+
+void omap_uart_resume_idle(int num)
+{
+	struct uart_omap_port *up = ui[num];
+	struct omap_device *od;
+	struct platform_device *pdev;
+
+	if (!up)
+		return;
+
+	pdev = up->pdev;
+	od = container_of(pdev, struct omap_device, pdev);
+
+	if (omap_hmwod_pad_wakeup_status(od->hwmods[0]) == true)
+		serial_omap_port_enable(up);
+
+	if (up->wk_st && (__raw_readl(up->wk_st) & up->wk_mask))
+		serial_omap_port_enable(up);
+}
+
 static void serial_omap_stop_rxdma(struct uart_omap_port *up)
 {
 	if (up->uart_dma.rx_dma_used) {
@@ -105,6 +184,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
 
+	serial_omap_port_enable(up);
 	dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
 	up->ier |= UART_IER_MSI;
 	serial_out(up, UART_IER, up->ier);
@@ -114,6 +194,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
 
+	serial_omap_port_enable(up);
 	if (up->use_dma &&
 		up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
 		/*
@@ -137,6 +218,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
 
+	serial_omap_port_enable(up);
 	if (up->use_dma)
 		serial_omap_stop_rxdma(up);
 	up->ier &= ~UART_IER_RLSI;
@@ -258,6 +340,7 @@ static void serial_omap_start_tx(struct uart_port *port)
 	unsigned int start;
 	int ret = 0;
 
+	serial_omap_port_enable(up);
 	if (!up->use_dma) {
 		serial_omap_enable_ier_thri(up);
 		return;
@@ -351,6 +434,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	unsigned int iir, lsr;
 	unsigned long flags;
 
+	serial_omap_port_enable(up);
 	iir = serial_in(up, UART_IIR);
 	if (iir & UART_IIR_NO_INT)
 		return IRQ_NONE;
@@ -385,6 +469,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
 	unsigned long flags = 0;
 	unsigned int ret = 0;
 
+	serial_omap_port_enable(up);
 	dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
 	spin_lock_irqsave(&up->port.lock, flags);
 	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
@@ -399,6 +484,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
 	unsigned char status;
 	unsigned int ret = 0;
 
+	serial_omap_port_enable(up);
 	status = check_modem_status(up);
 	dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
 
@@ -419,6 +505,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	unsigned char mcr = 0;
 
 	dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+	serial_omap_port_enable(up);
 	if (mctrl & TIOCM_RTS)
 		mcr |= UART_MCR_RTS;
 	if (mctrl & TIOCM_DTR)
@@ -440,6 +527,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
 	unsigned long flags = 0;
 
 	dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+	serial_omap_port_enable(up);
 	spin_lock_irqsave(&up->port.lock, flags);
 	if (break_state == -1)
 		up->lcr |= UART_LCR_SBC;
@@ -465,6 +553,7 @@ static int serial_omap_startup(struct uart_port *port)
 
 	dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
 
+	serial_omap_port_enable(up);
 	/*
 	 * Clear the FIFO buffers and disable them.
 	 * (they will be reenabled in set_termios())
@@ -530,6 +619,8 @@ static void serial_omap_shutdown(struct uart_port *port)
 	unsigned long flags = 0;
 
 	dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+
+	serial_omap_port_enable(up);
 	/*
 	 * Disable interrupts from this port
 	 */
@@ -668,6 +759,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
 	quot = serial_omap_get_divisor(port, baud);
 
+	up->dll = quot & 0xff;
+	up->dlh = quot >> 8;
+	up->mdr1 = UART_OMAP_MDR1_DISABLE;
+
 	up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
 			UART_FCR_ENABLE_FIFO;
 	if (up->use_dma)
@@ -677,6 +772,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * Ok, we're now changing the port state. Do it with
 	 * interrupts disabled.
 	 */
+	serial_omap_port_enable(up);
 	spin_lock_irqsave(&up->port.lock, flags);
 
 	/*
@@ -755,8 +851,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_MCR, up->mcr);
 
 	/* Protocol, Baud Rate, and Interrupt Settings */
+	if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_uart_mdr1_errataset(up);
+	else
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
-	serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	up->efr = serial_in(up, UART_EFR);
@@ -766,8 +865,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_IER, 0);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
-	serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
-	serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+	serial_out(up, UART_DLL, up->dll);	/* LS of divisor */
+	serial_out(up, UART_DLM, up->dlh);	/* MS of divisor */
 
 	serial_out(up, UART_LCR, 0);
 	serial_out(up, UART_IER, up->ier);
@@ -777,9 +876,14 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_LCR, cval);
 
 	if (baud > 230400 && baud != 3000000)
-		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
+		up->mdr1 = UART_OMAP_MDR1_13X_MODE;
+	else
+		up->mdr1 = UART_OMAP_MDR1_16X_MODE;
+
+	if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_uart_mdr1_errataset(up);
 	else
-		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
 	/* Hardware Flow Control Configuration */
 
@@ -818,6 +922,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
 	unsigned char efr;
 
 	dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+
+	serial_omap_port_enable(up);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -827,6 +933,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_EFR, efr);
 	serial_out(up, UART_LCR, 0);
+	if (state)
+		serial_omap_port_disable(up);
 }
 
 static void serial_omap_release_port(struct uart_port *port)
@@ -904,6 +1012,8 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
 static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	serial_omap_port_enable(up);
 	wait_for_xmitr(up);
 	serial_out(up, UART_TX, ch);
 }
@@ -911,8 +1021,10 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
 static int serial_omap_poll_get_char(struct uart_port *port)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
-	unsigned int status = serial_in(up, UART_LSR);
+	unsigned int status;
 
+	serial_omap_port_enable(up);
+	status = serial_in(up, UART_LSR);
 	if (!(status & UART_LSR_DR))
 		return NO_POLL_CHAR;
 
@@ -922,7 +1034,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
 #endif /* CONFIG_CONSOLE_POLL */
 
 #ifdef CONFIG_SERIAL_OMAP_CONSOLE
-
 static struct uart_omap_port *serial_omap_console_ports[4];
 
 static struct uart_driver serial_omap_reg;
@@ -931,6 +1042,7 @@ static void serial_omap_console_putchar(struct uart_port *port, int ch)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
 
+	serial_omap_port_enable(up);
 	wait_for_xmitr(up);
 	serial_out(up, UART_TX, ch);
 }
@@ -944,6 +1056,7 @@ serial_omap_console_write(struct console *co, const char *s,
 	unsigned int ier;
 	int locked = 1;
 
+	serial_omap_port_enable(up);
 	local_irq_save(flags);
 	if (up->port.sysrq)
 		locked = 0;
@@ -1058,22 +1171,25 @@ static struct uart_driver serial_omap_reg = {
 	.cons		= OMAP_CONSOLE,
 };
 
-static int
-serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+static int serial_omap_suspend(struct device *dev)
 {
-	struct uart_omap_port *up = platform_get_drvdata(pdev);
+	struct uart_omap_port *up = dev_get_drvdata(dev);
 
-	if (up)
+	if (up) {
 		uart_suspend_port(&serial_omap_reg, &up->port);
+		serial_omap_port_disable(up);
+	}
+
 	return 0;
 }
 
-static int serial_omap_resume(struct platform_device *dev)
+static int serial_omap_resume(struct device *dev)
 {
-	struct uart_omap_port *up = platform_get_drvdata(dev);
+	struct uart_omap_port *up = dev_get_drvdata(dev);
 
 	if (up)
 		uart_resume_port(&serial_omap_reg, &up->port);
+
 	return 0;
 }
 
@@ -1221,9 +1337,10 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
 
 static int serial_omap_probe(struct platform_device *pdev)
 {
-	struct uart_omap_port	*up;
+	struct uart_omap_port	*up = NULL;
 	struct resource		*mem, *irq, *dma_tx, *dma_rx;
 	struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+	struct omap_device *od;
 	int ret = -ENOSPC;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1273,12 +1390,23 @@ static int serial_omap_probe(struct platform_device *pdev)
 	up->port.ops = &serial_omap_pops;
 	up->port.line = pdev->id;
 
-	up->port.membase = omap_up_info->membase;
-	up->port.mapbase = omap_up_info->mapbase;
+	up->port.mapbase = mem->start;
+	up->port.membase = ioremap(mem->start, mem->end - mem->start);
+
+	if (!up->port.membase) {
+		dev_err(&pdev->dev, "can't ioremap UART\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
 	up->port.flags = omap_up_info->flags;
-	up->port.irqflags = omap_up_info->irqflags;
 	up->port.uartclk = omap_up_info->uartclk;
 	up->uart_dma.uart_base = mem->start;
+	up->errata = omap_up_info->errata;
+
+	up->wk_st = omap_up_info->wk_st;
+	up->wk_en = omap_up_info->wk_en;
+	up->wk_mask = omap_up_info->wk_mask;
 
 	if (omap_up_info->dma_enabled) {
 		up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1291,19 +1419,35 @@ static int serial_omap_probe(struct platform_device *pdev)
 		up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
 		up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 	}
+	init_timer(&(up->inactivity_timer));
+	up->inactivity_timer.function = serial_omap_inactivity_timer;
+	up->inactivity_timer.data = up->pdev->id;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_irq_safe(&pdev->dev);
+
+	if (omap_up_info->console_uart) {
+		od = container_of(pdev, struct omap_device, pdev);
+		omap_hwmod_idle(od->hwmods[0]);
+		serial_omap_port_enable(up);
+	}
 
 	ui[pdev->id] = up;
 	serial_omap_add_console_port(up);
 
 	ret = uart_add_one_port(&serial_omap_reg, &up->port);
 	if (ret != 0)
-		goto do_release_region;
+		goto err1;
 
+	dev_set_drvdata(&pdev->dev, up);
 	platform_set_drvdata(pdev, up);
+
 	return 0;
 err:
 	dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
 				pdev->id, __func__, ret);
+err1:
+	kfree(up);
 do_release_region:
 	release_mem_region(mem->start, (mem->end - mem->start) + 1);
 	return ret;
@@ -1315,20 +1459,138 @@ static int serial_omap_remove(struct platform_device *dev)
 
 	platform_set_drvdata(dev, NULL);
 	if (up) {
+		pm_runtime_disable(&up->pdev->dev);
 		uart_remove_one_port(&serial_omap_reg, &up->port);
 		kfree(up);
 	}
 	return 0;
 }
 
+/*
+ * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
+ * The access to uart register after MDR1 Access
+ * causes UART to corrupt data.
+ *
+ * Need a delay =
+ * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+ * give 10 times as much
+ */
+static void omap_uart_mdr1_errataset(struct uart_omap_port *up)
+{
+	u8 timeout = 255;
+
+	serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	udelay(2);
+	serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
+			UART_FCR_CLEAR_RCVR);
+	/*
+	 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+	 * TX_FIFO_E bit is 1.
+	 */
+	while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
+				(UART_LSR_THRE | UART_LSR_DR))) {
+		timeout--;
+		if (!timeout) {
+			/* Should *never* happen. we warn and carry on */
+			dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+			serial_in(up, UART_LSR));
+			break;
+		}
+		udelay(1);
+	}
+}
+
+static void omap_uart_restore_context(struct uart_omap_port *up)
+{
+	u16 efr = 0;
+
+	if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_uart_mdr1_errataset(up);
+	else
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+	efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, UART_EFR_ECB);
+	serial_out(up, UART_LCR, 0x0); /* Operational mode */
+	serial_out(up, UART_IER, 0x0);
+	serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+	serial_out(up, UART_DLL, up->dll);
+	serial_out(up, UART_DLM, up->dlh);
+	serial_out(up, UART_LCR, 0x0); /* Operational mode */
+	serial_out(up, UART_IER, up->ier);
+	serial_out(up, UART_FCR, up->fcr);
+	serial_out(up, UART_LCR, 0x80);
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+	serial_out(up, UART_EFR, efr);
+	serial_out(up, UART_LCR, UART_LCR_WLEN8);
+	if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_uart_mdr1_errataset(up);
+	else
+		/* UART 16x mode */
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
+}
+
+static void omap_uart_enable_wakeup(struct uart_omap_port *up)
+{
+	/* Set wake-enable bit */
+	if (up->wk_en && up->wk_mask) {
+		u32 v = __raw_readl(up->wk_en);
+		v |= up->wk_mask;
+		__raw_writel(v, up->wk_en);
+	}
+}
+
+static void omap_uart_disable_wakeup(struct uart_omap_port *up)
+{
+	/* Clear wake-enable bit */
+	if (up->wk_en && up->wk_mask) {
+		u32 v = __raw_readl(up->wk_en);
+		v &= ~up->wk_mask;
+		__raw_writel(v, up->wk_en);
+	}
+}
+
+static int omap_serial_runtime_suspend(struct device *dev)
+{
+	struct uart_omap_port *up = dev_get_drvdata(dev);
+
+	if (!up)
+		goto done;
+
+	if (device_may_wakeup(&up->pdev->dev))
+		omap_uart_enable_wakeup(up);
+	else
+		omap_uart_disable_wakeup(up);
+done:
+	return 0;
+}
+
+static int omap_serial_runtime_resume(struct device *dev)
+{
+	struct uart_omap_port *up = dev_get_drvdata(dev);
+
+	if (!up)
+		goto done;
+
+	omap_uart_restore_context(up);
+done:
+	return 0;
+}
+
+static const struct dev_pm_ops omap_serial_dev_pm_ops = {
+	.suspend = serial_omap_suspend,
+	.resume	= serial_omap_resume,
+	.runtime_suspend = omap_serial_runtime_suspend,
+	.runtime_resume = omap_serial_runtime_resume,
+};
+
 static struct platform_driver serial_omap_driver = {
 	.probe          = serial_omap_probe,
 	.remove         = serial_omap_remove,
-
-	.suspend	= serial_omap_suspend,
-	.resume		= serial_omap_resume,
 	.driver		= {
 		.name	= DRIVER_NAME,
+		.pm = &omap_serial_dev_pm_ops,
 	},
 };
 
-- 
1.7.1

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:17

From: Jon Hunter <redacted>

The following UART parameters are defined within the UART driver:

1). Whether the UART uses DMA (dma_enabled), by default set to 0
2). The size of dma buffer (set to 4096 bytes)
3). The time after which the dma should stop if no more data is received.
4). The idle timeout (DEFAULT_TIMEOUT) that sets the can_sleep flag after
    uart inactivity.
5). Add default serial pads to board data if no pad info is available from
    board file to avoid breaking uart wakeup capability from rx pad.

Different UARTs may be used for different purpose such as the console,
for interfacing bluetooth chip, for interfacing to a modem chip, etc.
Therefore, it is necessary to be able to customize the above settings
for a given board on a per UART basis.

This change allows these parameters to be configured from the board file
and allows the parameters to be configured for each UART independently.

If a board does not define its own custom parameters for the UARTs, then
use the default parameters in the structure "omap_serial_default_info".
The default parameters are defined to be the same as the current settings
in the UART driver to avoid breaking the UART for any board. By default,
make all boards use the default UART parameters.

Signed-off-by: Govindraj.R <redacted>
Signed-off-by: Deepak K <redacted>
Signed-off-by: Jon Hunter <redacted>
---
 arch/arm/mach-omap2/board-2430sdp.c           |    3 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    4 +-
 arch/arm/mach-omap2/board-4430sdp.c           |    3 +-
 arch/arm/mach-omap2/board-am3517evm.c         |    3 +-
 arch/arm/mach-omap2/board-apollon.c           |    3 +-
 arch/arm/mach-omap2/board-cm-t35.c            |    3 +-
 arch/arm/mach-omap2/board-cm-t3517.c          |    3 +-
 arch/arm/mach-omap2/board-devkit8000.c        |    3 +-
 arch/arm/mach-omap2/board-generic.c           |    3 +-
 arch/arm/mach-omap2/board-h4.c                |    3 +-
 arch/arm/mach-omap2/board-igep0020.c          |    3 +-
 arch/arm/mach-omap2/board-igep0030.c          |    3 +-
 arch/arm/mach-omap2/board-ldp.c               |    3 +-
 arch/arm/mach-omap2/board-n8x0.c              |    9 +-
 arch/arm/mach-omap2/board-omap3beagle.c       |    3 +-
 arch/arm/mach-omap2/board-omap3evm.c          |    3 +-
 arch/arm/mach-omap2/board-omap3logic.c        |    3 +-
 arch/arm/mach-omap2/board-omap3pandora.c      |    3 +-
 arch/arm/mach-omap2/board-omap3stalker.c      |    3 +-
 arch/arm/mach-omap2/board-omap3touchbook.c    |    3 +-
 arch/arm/mach-omap2/board-omap4panda.c        |    3 +-
 arch/arm/mach-omap2/board-overo.c             |    3 +-
 arch/arm/mach-omap2/board-rm680.c             |    3 +-
 arch/arm/mach-omap2/board-rx51.c              |    3 +-
 arch/arm/mach-omap2/board-ti8168evm.c         |    2 +-
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    3 +-
 arch/arm/mach-omap2/serial.c                  |  108 +++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/omap-serial.h |   14 +++-
 arch/arm/plat-omap/include/plat/serial.h      |    6 +-
 drivers/tty/serial/omap-serial.c              |   10 +-
 30 files changed, 177 insertions(+), 45 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index cc42d47..0cfa3c7 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -38,6 +38,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <plat/gpmc-smc91x.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -249,7 +250,7 @@ static void __init omap_2430sdp_init(void)
 	omap2430_i2c_init();
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 	omap2_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 8950ecc..7d7df08 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -39,8 +39,8 @@
 #include <plat/gpmc.h>
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
-
 #include <plat/gpmc-smc91x.h>
+#include <plat/omap-serial.h>
 
 #include "board-flash.h"
 #include "mux.h"
@@ -798,7 +798,7 @@ static void __init omap_3430sdp_init(void)
 	spi_register_board_info(sdp3430_spi_board_info,
 				ARRAY_SIZE(sdp3430_spi_board_info));
 	ads7846_dev_init();
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 1a943be..9687aec 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -643,7 +644,7 @@ static void __init omap_4430sdp_init(void)
 	omap4_i2c_init();
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 
 	usb_musb_init(&musb_board_data);
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 634fe65..bbc79a4 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "control.h"
@@ -487,7 +488,7 @@ static void __init am3517_evm_init(void)
 
 	am3517_evm_i2c_init();
 	omap_display_init(&am3517_evm_dss_data);
-	omap_serial_init();
+	omap_serial_init(NULL);
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 4ef4aad..e021cdb 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,6 +39,7 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "control.h"
@@ -342,7 +343,7 @@ static void __init omap_apollon_init(void)
 	 * if not needed.
 	 */
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
 
 static void __init omap_apollon_map_io(void)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 7311824..8ecde7e 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -48,6 +48,7 @@
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
 #include <plat/mcspi.h>
+#include <plat/omap-serial.h>
 
 #include <mach/hardware.h>
 
@@ -788,7 +789,7 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init cm_t35_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	cm_t35_init_i2c();
 	cm_t35_init_nand();
 	cm_t35_init_ads7846();
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 38bef6d..a1c0d87 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -43,6 +43,7 @@
 #include <plat/usb.h>
 #include <plat/nand.h>
 #include <plat/gpmc.h>
+#include <plat/omap-serial.h>
 
 #include <mach/am35xx.h>
 
@@ -292,7 +293,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init cm_t3517_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
 	cm_t3517_init_rtc();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 54abdd0..28fac56 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -47,6 +47,7 @@
 #include <plat/usb.h>
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -784,7 +785,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init devkit8000_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
-	omap_serial_init();
+	omap_serial_init(NULL);
 
 	omap_dm9000_init();
 
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 682da92..450128b 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -29,6 +29,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <plat/omap-serial.h>
 
 static struct omap_board_config_kernel generic_config[] = {
 };
@@ -43,7 +44,7 @@ static void __init omap_generic_init_early(void)
 
 static void __init omap_generic_init(void)
 {
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
 
 static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index f6a3872..6481bab 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -39,6 +39,7 @@
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "control.h"
@@ -370,7 +371,7 @@ static void __init omap_h4_init(void)
 
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
 
 static void __init omap_h4_map_io(void)
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 54e6318..9223b9b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -34,6 +34,7 @@
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
 #include <plat/onenand.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -686,7 +687,7 @@ static void __init igep2_init(void)
 	igep2_i2c_init();
 	platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
 	omap_display_init(&igep2_dss_data);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	usb_ehci_init(&ehci_pdata);
 
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index d75028e..c593a5c 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -31,6 +31,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <plat/onenand.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -432,7 +433,7 @@ static void __init igep3_init(void)
 	/* Register I2C busses and drivers */
 	igep3_i2c_init();
 	platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	usb_ehci_init(&ehci_pdata);
 
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index a3fae56..ff93da7 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -40,6 +40,7 @@
 #include <plat/common.h>
 #include <plat/gpmc.h>
 #include <mach/board-zoom.h>
+#include <plat/omap-serial.h>
 
 #include <asm/delay.h>
 #include <plat/usb.h>
@@ -430,7 +431,7 @@ static void __init omap_ldp_init(void)
 	spi_register_board_info(ldp_spi_board_info,
 				ARRAY_SIZE(ldp_spi_board_info));
 	ads7846_dev_init();
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index b36cbd2..7347256 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -33,6 +33,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 
@@ -662,22 +663,22 @@ static inline void board_serial_init(void)
 	bdata.pads_cnt = 0;
 
 	bdata.id = 0;
-	omap_serial_init_port(&bdata);
+	omap_serial_init_port(&bdata, NULL);
 
 	bdata.id = 1;
-	omap_serial_init_port(&bdata);
+	omap_serial_init_port(&bdata, NULL);
 
 	bdata.id = 2;
 	bdata.pads = serial2_pads;
 	bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
-	omap_serial_init_port(&bdata);
+	omap_serial_init_port(&bdata, NULL);
 }
 
 #else
 
 static inline void board_serial_init(void)
 {
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
 
 #endif
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index a1faea3..e6c0299 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -45,6 +45,7 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -613,7 +614,7 @@ static void __init omap3_beagle_init(void)
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_display_init(&beagle_dss_data);
-	omap_serial_init();
+	omap_serial_init(NULL);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	gpio_request(170, "DVI_nPD");
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 5364147..0b793f1 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -46,6 +46,7 @@
 #include <plat/mcspi.h>
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -831,7 +832,7 @@ static void __init omap3_evm_init(void)
 	spi_register_board_info(omap3evm_spi_board_info,
 				ARRAY_SIZE(omap3evm_spi_board_info));
 
-	omap_serial_init();
+	omap_serial_init(NULL);
 
 	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
 	usb_nop_xceiv_register();
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index b726943..0b5ba52 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -44,6 +44,7 @@
 #include <plat/gpmc-smsc911x.h>
 #include <plat/gpmc.h>
 #include <plat/sdrc.h>
+#include <plat/omap-serial.h>
 
 #define OMAP3LOGIC_SMSC911X_CS			1
 
@@ -212,7 +213,7 @@ static void __init omap3logic_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3torpedo_fix_pbias_voltage();
 	omap3logic_i2c_init();
-	omap_serial_init();
+	omap_serial_init(NULL);
 	board_mmc_init();
 	board_smsc911x_init();
 
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 17ef547..6f84247 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -48,6 +48,7 @@
 #include <plat/usb.h>
 #include <plat/display.h>
 #include <plat/nand.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -703,7 +704,7 @@ static void __init omap3pandora_init(void)
 	platform_add_devices(omap3pandora_devices,
 			ARRAY_SIZE(omap3pandora_devices));
 	omap_display_init(&pandora_dss_data);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap3pandora_ads7846_init();
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 07006c3..629bdce 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -41,6 +41,7 @@
 #include <plat/usb.h>
 #include <plat/display.h>
 #include <plat/panel-generic-dpi.h>
+#include <plat/omap-serial.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -639,7 +640,7 @@ static void __init omap3_stalker_init(void)
 	spi_register_board_info(omap3stalker_spi_board_info,
 				ARRAY_SIZE(omap3stalker_spi_board_info));
 
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	usb_ehci_init(&ehci_pdata);
 	ads7846_dev_init();
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 6a60f79..c6bf289 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -48,6 +48,7 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -519,7 +520,7 @@ static void __init omap3_touchbook_init(void)
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	gpio_request(176, "DVI_nPD");
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 3dd241b..2245ed1 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -39,6 +39,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include <plat/omap-serial.h>
 #include "timer-gp.h"
 
 #include "hsmmc.h"
@@ -470,7 +471,7 @@ static void __init omap4_panda_init(void)
 	omap4_panda_i2c_init();
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	platform_device_register(&omap_vwlan_device);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
 	usb_musb_init(&musb_board_data);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index a33ec0e..960a3ea 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -46,6 +46,7 @@
 #include <mach/hardware.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -450,7 +451,7 @@ static void __init overo_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	overo_i2c_init();
 	platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
-	omap_serial_init();
+	omap_serial_init(NULL);
 	overo_flash_init();
 	usb_musb_init(&musb_board_data);
 	usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index bdebcb7..bd4b7ad 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -27,6 +27,7 @@
 #include <plat/gpmc.h>
 #include <plat/common.h>
 #include <plat/onenand.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -162,7 +163,7 @@ static struct omap_musb_board_data rm680_musb_data = {
 static void __init rm680_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&rm680_musb_data);
 	rm680_peripherals_init();
 }
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 3cf72fe..08619e9 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -29,6 +29,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <plat/usb.h>
+#include <plat/omap-serial.h>
 
 #include "mux.h"
 #include "pm.h"
@@ -127,7 +128,7 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init rx51_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_serial_init();
+	omap_serial_init(NULL);
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
 
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index f2b0971..c4f83ed 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -42,7 +42,7 @@ static void __init ti8168_evm_init_irq(void)
 
 static void __init ti8168_evm_init(void)
 {
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
 
 static void __init ti8168_evm_map_io(void)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index e0e040f..82ca121 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -26,6 +26,7 @@
 
 #include <plat/common.h>
 #include <plat/usb.h>
+#include <plat/omap-serial.h>
 
 #include <mach/board-zoom.h>
 
@@ -394,5 +395,5 @@ void __init zoom_peripherals_init(void)
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
-	omap_serial_init();
+	omap_serial_init(NULL);
 }
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
 
 static int omap_uart_con_id __initdata = -1;
 
+static struct omap_uart_port_info omap_serial_default_info[] = {
+	{
+		.dma_enabled	= 0,
+		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+		.idle_timeout	= DEFAULT_IDLE_TIMEOUT,
+	},
+};
+
 static int uart_idle_hwmod(struct omap_device *od)
 {
 	omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
 	},
 };
 
+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+	{
+		.name	= "uart1_rx.uart1_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+	{
+		.name	= "uart2_rx.uart2_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+	{
+		.name	= "uart3_rx_irrx.uart3_rx_irrx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata = {
+	{
+		.name	= "gpmc_wait3.uart4_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE2,
+	},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata = {
+	{
+		.name	= "uart4_rx.uart4_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+#else
+static struct omap_device_pad default_serial0_pads[] __initdata = {};
+static struct omap_device_pad default_serial1_pads[] __initdata = {};
+static struct omap_device_pad default_serial2_pads[] __initdata = {};
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata = {};
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata = {};
+#endif
+
 static void omap_uart_idle_init(struct omap_uart_port_info *uart,
 				unsigned short num)
 {
@@ -164,6 +221,7 @@ core_initcall(omap_serial_early_init);
 /**
  * omap_serial_init_port() - initialize single serial port
  * @bdata: port specific board data pointer
+ * @info: platform specific data pointer
  *
  * This function initialies serial driver for given port only.
  * Platforms can call this function instead of omap_serial_init()
@@ -172,7 +230,8 @@ core_initcall(omap_serial_early_init);
  * 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(struct omap_board_data *bdata)
+void __init omap_serial_init_port(struct omap_board_data *bdata,
+			struct omap_uart_port_info *info)
 {
 	struct omap_hwmod *oh;
 	struct omap_device *od;
@@ -190,6 +249,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	if (!oh)
 		return;
 
+	if (info == NULL)
+		info = omap_serial_default_info;
+
 	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		pr_err("Memory allocation for UART pdata failed\n");
@@ -204,6 +266,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
 	pdata->flags = UPF_BOOT_AUTOCONF;
+	pdata->dma_enabled = info->dma_enabled;
+	pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+	pdata->dma_rx_timeout = info->dma_rx_timeout;
+	pdata->idle_timeout = info->idle_timeout;
 	if (bdata->id == omap_uart_con_id)
 		pdata->console_uart = true;
 
@@ -222,21 +288,53 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 /**
  * omap_serial_init() - initialize all supported serial ports
+ * @info: platform specific data pointer
  *
  * Initializes all available UARTs as serial ports. Platforms
  * can call this function when they want to have default behaviour
  * for serial ports (e.g initialize them all as serial ports).
  */
-void __init omap_serial_init(void)
+void __init omap_serial_init(struct omap_uart_port_info *info)
 {
 	struct omap_board_data bdata;
 	u8 i;
 
+	if (info == NULL)
+		info = omap_serial_default_info;
+
 	for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
 		bdata.id = i;
 		bdata.flags = 0;
-		bdata.pads = NULL;
-		bdata.pads_cnt = 0;
-		omap_serial_init_port(&bdata);
+		switch (i) {
+		case 0:
+			bdata.pads = default_serial0_pads;
+			bdata.pads_cnt = ARRAY_SIZE(default_serial0_pads);
+			break;
+		case 1:
+			bdata.pads = default_serial1_pads;
+			bdata.pads_cnt = ARRAY_SIZE(default_serial1_pads);
+			break;
+		case 2:
+			bdata.pads = default_serial2_pads;
+			bdata.pads_cnt = ARRAY_SIZE(default_serial2_pads);
+			break;
+		case 3:
+			if (cpu_is_omap44xx()) {
+				bdata.pads = default_omap4_serial3_pads;
+				bdata.pads_cnt =
+					ARRAY_SIZE(default_omap4_serial3_pads);
+			} else {
+				bdata.pads = default_omap36xx_serial3_pads;
+				bdata.pads_cnt =
+					ARRAY_SIZE(default_omap36xx_serial3_pads);
+			}
+			break;
+		default:
+			bdata.pads = NULL;
+			bdata.pads_cnt = 0;
+			break;
+		}
+
+		omap_serial_init_port(&bdata, info);
 	}
 }
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index f9bc7ef..4f12d6c 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -51,7 +51,11 @@
 
 #define OMAP_UART_DMA_CH_FREE	-1
 
-#define RX_TIMEOUT		(3 * HZ)
+#define RX_TIMEOUT		(3 * HZ)	/* RX DMA timeout (jiffies) */
+#define DEFAULT_RXDMA_TIMEOUT	1		/* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_BUFSIZE	4096		/* RX DMA buffer size */
+#define DEFAULT_IDLE_TIMEOUT	(5 * HZ)	/* UART idle timeout (secs) */
+
 #define OMAP_MAX_HSUART_PORTS	4
 
 #define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
@@ -64,6 +68,9 @@ struct omap_uart_port_info {
 	upf_t			flags;		/* UPF_* flags */
 	unsigned int		errata;
 	unsigned int		console_uart;
+	unsigned int		dma_rx_buf_size;/* DMA Rx Buffer Size */
+	unsigned int		dma_rx_timeout;	/* DMA RX timeout */
+	unsigned int		idle_timeout;	/* OMAP UART idle timeout */
 
 	void __iomem *wk_st;
 	void __iomem *wk_en;
@@ -91,8 +98,8 @@ struct uart_omap_dma {
 	spinlock_t		rx_lock;
 	/* timer to poll activity on rx dma */
 	struct timer_list	rx_timer;
-	int			rx_buf_size;
-	int			rx_timeout;
+	unsigned int		rx_buf_size;
+	unsigned int		rx_timeout;
 };
 
 struct uart_omap_port {
@@ -120,6 +127,7 @@ struct uart_omap_port {
 	char			name[20];
 	unsigned long		port_activity;
 	struct timer_list	inactivity_timer;
+	unsigned int		idle_timeout;
 	unsigned int		errata;
 	int			can_sleep;
 
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 6339848..2ed24b3 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -103,9 +103,11 @@
 #ifndef __ASSEMBLER__
 
 struct omap_board_data;
+struct omap_uart_port_info;
 
-extern void omap_serial_init(void);
-extern void omap_serial_init_port(struct omap_board_data *bdata);
+extern void omap_serial_init(struct omap_uart_port_info *platform_data);
+extern void omap_serial_init_port(struct omap_board_data *bdata,
+		struct omap_uart_port_info *platform_data);
 extern void omap_uart_prepare_idle(int num);
 extern void omap_uart_resume_idle(int num);
 #endif
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index bc877b9..008645c 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -47,8 +47,6 @@
 #define omap_uart_console(port)	NULL
 #endif
 
-#define OMAP_UART_CLK_PUT_DELAY (5 * HZ)
-
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
 /* Forward declaration of functions */
@@ -139,7 +137,7 @@ static void serial_omap_port_enable(struct uart_omap_port *up)
 	}
 
 	up->can_sleep = 0;
-	mod_timer(&up->inactivity_timer, jiffies + OMAP_UART_CLK_PUT_DELAY);
+	mod_timer(&up->inactivity_timer, jiffies + up->idle_timeout);
 }
 
 void omap_uart_prepare_idle(int num)
@@ -1412,16 +1410,18 @@ static int serial_omap_probe(struct platform_device *pdev)
 		up->uart_dma.uart_dma_tx = dma_tx->start;
 		up->uart_dma.uart_dma_rx = dma_rx->start;
 		up->use_dma = 1;
-		up->uart_dma.rx_buf_size = 4096;
-		up->uart_dma.rx_timeout = 2;
+		up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
+		up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
 		spin_lock_init(&(up->uart_dma.tx_lock));
 		spin_lock_init(&(up->uart_dma.rx_lock));
 		up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
 		up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
 	}
+
 	init_timer(&(up->inactivity_timer));
 	up->inactivity_timer.function = serial_omap_inactivity_timer;
 	up->inactivity_timer.data = up->pdev->id;
+	up->idle_timeout = omap_up_info->idle_timeout;
 
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_irq_safe(&pdev->dev);
-- 
1.7.1

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Sricharan R <hidden>
Date: 2011-03-01 19:16:19

Hi,
quoted hunk
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+	{
+		.dma_enabled	= 0,
+		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+		.idle_timeout	= DEFAULT_IDLE_TIMEOUT,
+	},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
	omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
= {
	},
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+	{
+		.name	= "uart1_rx.uart1_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+	{
+		.name	= "uart2_rx.uart2_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+	{
+		.name	= "uart3_rx_irrx.uart3_rx_irrx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata
=
{
+	{
+		.name	= "gpmc_wait3.uart4_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE2,
+	},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata =
{
+	{
+		.name	= "uart4_rx.uart4_rx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+	},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx pins?
Is it consistent that across all socs that only UART3 would have UART/IRDA
functions capability so that serial2 pads can always be called "rx_irxx"
?.

Thanks,
 sricharan
--
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

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Govindraj <hidden>
Date: 2011-03-02 07:40:58

On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R [off-list ref] wrote:
Hi,
quoted
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
+ ? ? ?},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
? ? ? omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
quoted
= {
? ? ? },
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[] __initdata
=
quoted
{
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata =
{
quoted
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx pins?
The intention here is to enable wakeup capabilities for uart rx pad.

AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.

Prior to this change uart wakeup is based on rx_pad and we were populating
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.

So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current omap_serial_init.

Is it consistent that across all socs that only UART3 would have UART/IRDA
functions capability so that serial2 pads can always be called "rx_irxx"
?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.

--
Thanks,
Govindraj.R

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Sricharan R <hidden>
Date: 2011-03-02 08:19:41

Hi,
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 1:11 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R [off-list ref] wrote:
quoted
Hi,
quoted
diff --git a/arch/arm/mach-omap2/serial.c
b/arch/arm/mach-omap2/serial.c
quoted
quoted
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
+ ? ? ?},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
? ? ? omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
quoted
= {
? ? ? },
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]
__initdata
quoted
=
quoted
{
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata
=
quoted
{
quoted
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx
pins?

The intention here is to enable wakeup capabilities for uart rx pad.

AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.
Yes. The idea is to be independent of the bootloaders for mux settings.
Prior to this change uart wakeup is based on rx_pad and we were
populating
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.
Now, in this change only the RX pin is configured. So if some board uses
omap_serial_init then only the RX is going to be configured.
How will they configure the rest of the pins?
They cannot call omap_serial_init_port after this just to configure the
rest of the mux pins( cts, rts, tx).

So data which is passed from omap_serial_init should have the
configuration
for all the pins, and this default data should be consistent across
atleast
some boards, so that they can use this. This will reduce the data
duplication across board files.

If this is not true, then all the pads can be configured from the board
files itself using omap_serial_init_port and you can set the required
RX wakeup capability there as well.
So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current
omap_serial_init.

quoted
Is it consistent that across all socs that only UART3 would have
UART/IRDA
quoted
functions capability so that serial2 pads can always be called
"rx_irxx"
quoted
?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
Ok.
--
Thanks,
Govindraj.R

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Govindraj <hidden>
Date: 2011-03-02 10:07:11

On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R [off-list ref] wrote:
Hi,
quoted
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 1:11 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
quoted
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R [off-list ref] wrote:
quoted
Hi,
quoted
diff --git a/arch/arm/mach-omap2/serial.c
b/arch/arm/mach-omap2/serial.c
quoted
quoted
quoted
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
+ ? ? ?},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
? ? ? omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
quoted
= {
? ? ? },
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]
__initdata
quoted
quoted
=
quoted
{
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata
=
quoted
quoted
{
quoted
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx
pins?

The intention here is to enable wakeup capabilities for uart rx pad.

AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.
Yes. The idea is to be independent of the bootloaders for mux settings.
quoted
Prior to this change uart wakeup is based on rx_pad and we were
populating
quoted
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.
Now, in this change only the RX pin is configured. So if some board uses
omap_serial_init then only the RX is going to be configured.
How will they configure the rest of the pins?

They should call omap_serial_init_port to configure each individual uart with
mux_info filled and not use omap_serial_init.

If any board is not dependent for mux from u-boot then they use above said
init_port func.

They cannot call omap_serial_init_port after this just to configure the
rest of the mux pins( cts, rts, tx).
No. You need to use either omap_serial_init_port or omap_serial_init
you cannot call both apis from board file please refer to both func
documentation.

Also please note i am not configuring all uart pins for pullups and pull downs
with this patch series and its not related to this patch series.
I am only enabling wakeup-enable pin for rx as it was done before.
So data which is passed from omap_serial_init should have the
configuration
for all the pins, and this default data should be consistent across
atleast
some boards, so that they can use this. This will reduce the data
duplication across board files.

If this is not true, then all the pads can be configured from the board
files itself using omap_serial_init_port and you can set the required
RX wakeup capability there as well.
Yes that be done but currently but that is not in my intention here
with my patch
I just want to retain rx wakeup by default to avoid breaking support
for any board.

Adding pin mux for each individual pin is a separate activity where I also
need access to various boards So I am leaving that to developers who
want to configure
for the corresponding boards using init_port api.

Removing mux from u-boot level and adding it to board file is beyond
the scope of this
patch series and is a separate topic of discussion, as current patch series
assumes that uarts are muxed from u-boot level and needs to only enable wakeup
capability for rx-pin.

Hope this clarifies.

--
Thanks,
Govindraj.R

quoted
So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current
omap_serial_init.

quoted
Is it consistent that across all socs that only UART3 would have
UART/IRDA
quoted
functions capability so that serial2 pads can always be called
"rx_irxx"
quoted
quoted
?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
Ok.
quoted
--
Thanks,
Govindraj.R

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: tony@atomide.com (Tony Lindgren)
Date: 2011-03-02 18:24:02

* Govindraj [off-list ref] [110302 02:05]:
quoted
quoted
quoted
quoted
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
...

AFAIK you should only need the OMAP_DEVICE_PAD_REMUX option for
omap24xx. And if you use that option, you also need the .idle
value.

Tony

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Govindraj <hidden>
Date: 2011-03-03 12:14:38

On Wed, Mar 2, 2011 at 11:54 PM, Tony Lindgren [off-list ref] wrote:
* Govindraj [off-list ref] [110302 02:05]:
quoted
quoted
quoted
quoted
quoted
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
...

AFAIK you should only need the OMAP_DEVICE_PAD_REMUX option for
omap24xx. And if you use that option, you also need the .idle
value.
Yes correct. I should avoid enabling rx-pad wakeup for omap24xx and
populate rx pad wakeup only for 3xxx onwards as done prior to this patch.

Will correct this in next version.

--
Thanks,
Govindraj.R


Tony

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Sricharan R <hidden>
Date: 2011-03-03 05:08:12

Hi,
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 3:37 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R [off-list ref] wrote:
quoted
Hi,
quoted
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 1:11 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
quoted
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R [off-list ref]
wrote:
quoted
quoted
quoted
Hi,
quoted
diff --git a/arch/arm/mach-omap2/serial.c
b/arch/arm/mach-omap2/serial.c
quoted
quoted
quoted
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
+ ? ? ?},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
? ? ? omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
quoted
= {
? ? ? },
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]
__initdata
quoted
quoted
=
quoted
{
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[]
__initdata
quoted
=
quoted
quoted
{
quoted
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx
pins?

The intention here is to enable wakeup capabilities for uart rx pad.

AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.
Yes. The idea is to be independent of the bootloaders for mux settings.
quoted
Prior to this change uart wakeup is based on rx_pad and we were
populating
quoted
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.
Now, in this change only the RX pin is configured. So if some board
uses
quoted
omap_serial_init then only the RX is going to be configured.
How will they configure the rest of the pins?

They should call omap_serial_init_port to configure each individual uart
with
mux_info filled and not use omap_serial_init.

If any board is not dependent for mux from u-boot then they use above
said
init_port func.

quoted
They cannot call omap_serial_init_port after this just to configure the
rest of the mux pins( cts, rts, tx).
No. You need to use either omap_serial_init_port or omap_serial_init
you cannot call both apis from board file please refer to both func
documentation.

Also please note i am not configuring all uart pins for pullups and pull
downs
with this patch series and its not related to this patch series.
I am only enabling wakeup-enable pin for rx as it was done before.
quoted
So data which is passed from omap_serial_init should have the
configuration
for all the pins, and this default data should be consistent across
atleast
some boards, so that they can use this. This will reduce the data
duplication across board files.

If this is not true, then all the pads can be configured from the board
files itself using omap_serial_init_port and you can set the required
RX wakeup capability there as well.
Yes that be done but currently but that is not in my intention here
with my patch
I just want to retain rx wakeup by default to avoid breaking support
for any board.

Adding pin mux for each individual pin is a separate activity where I
also
need access to various boards So I am leaving that to developers who
want to configure
for the corresponding boards using init_port api.

Removing mux from u-boot level and adding it to board file is beyond
the scope of this
patch series and is a separate topic of discussion, as current patch
series
assumes that uarts are muxed from u-boot level and needs to only enable
wakeup
capability for rx-pin.

Hope this clarifies.
It is true that this patch is not intending to configure the pads.

But my question is, after this patch say
   1) some board file calls omap_serial_port.
   2) As a result , all the uarts devices are build and only the Rx pad is
configured for each device.
   3) After this there will be no way of configuring the rest of the pads
??
      That should not happen. Also relying that the bootloaders are going
      to do the configuration is not correct.

      So if some board calls omap_serial_port then there should be default
values for all pads which a board can use, otherwise the board calls
omap_serial_init_port for each of the device.

--
Thanks,
Govindraj.R

quoted
quoted
So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current
omap_serial_init.

quoted
Is it consistent that across all socs that only UART3 would have
UART/IRDA
quoted
functions capability so that serial2 pads can always be called
"rx_irxx"
quoted
quoted
?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
Ok.
quoted
--
Thanks,
Govindraj.R

[PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file

From: Govindraj <hidden>
Date: 2011-03-04 06:25:45

On Thu, Mar 3, 2011 at 10:38 AM, Sricharan R [off-list ref] wrote:
Hi,
quoted
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 3:37 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
quoted
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R [off-list ref] wrote:
quoted
Hi,
quoted
-----Original Message-----
From: Govindraj [mailto:govindraj.ti at gmail.com]
Sent: Wednesday, March 02, 2011 1:11 PM
To: Sricharan R
Cc: Govindraj.R; linux-omap at vger.kernel.org;
linux-serial at vger.kernel.org;
quoted
linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
configured from board file

On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R [off-list ref]
wrote:
quoted
quoted
quoted
quoted
Hi,
quoted
diff --git a/arch/arm/mach-omap2/serial.c
b/arch/arm/mach-omap2/serial.c
quoted
quoted
quoted
index 755f4aa..530e9e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -44,6 +44,15 @@
static int omap_uart_con_id __initdata = -1;

+static struct omap_uart_port_info omap_serial_default_info[] = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
+ ? ? ?},
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
? ? ? omap_hwmod_idle(od->hwmods[0]);
@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
omap_uart_latency[]
quoted
= {
? ? ? },
};

+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_serial0_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_serial2_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]
__initdata
quoted
quoted
=
quoted
{
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[]
__initdata
quoted
quoted
=
quoted
quoted
{
quoted
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
OMAP_DEVICE_PAD_WAKEUP,
quoted
quoted
quoted
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
Here only the UART RX pins are muxed, so what about the cts, rts, tx
pins?

The intention here is to enable wakeup capabilities for uart rx pad.

AFAIK most of the boards are currently dependent on bootloader for
uart-muxing if any board is not dependent on bootloader then we
can use omap_serial_init_port along with board_mux_info from board.
Yes. The idea is to be independent of the bootloaders for mux settings.
quoted
Prior to this change uart wakeup is based on rx_pad and we were
populating
quoted
offset and using omap_ctrl api's to read/write which is cleaned up now.
Most of boards are dependent on uart-rx wakeup to avoid breaking any
board support we
are using omap_serial_init by filling default values, which provides
us with same
environment but with right approach towards handling mux data with a
handshake with
hwmod framework.
Now, in this change only the RX pin is configured. So if some board
uses
quoted
quoted
omap_serial_init then only the RX is going to be configured.
How will they configure the rest of the pins?

They should call omap_serial_init_port to configure each individual uart
with
mux_info filled and not use omap_serial_init.

If any board is not dependent for mux from u-boot then they use above
said
quoted
init_port func.

quoted
They cannot call omap_serial_init_port after this just to configure the
rest of the mux pins( cts, rts, tx).
No. You need to use either omap_serial_init_port or omap_serial_init
you cannot call both apis from board file please refer to both func
documentation.

Also please note i am not configuring all uart pins for pullups and pull
downs
with this patch series and its not related to this patch series.
I am only enabling wakeup-enable pin for rx as it was done before.
quoted
So data which is passed from omap_serial_init should have the
configuration
for all the pins, and this default data should be consistent across
atleast
some boards, so that they can use this. This will reduce the data
duplication across board files.

If this is not true, then all the pads can be configured from the board
files itself using omap_serial_init_port and you can set the required
RX wakeup capability there as well.
Yes that be done but currently but that is not in my intention here
with my patch
I just want to retain rx wakeup by default to avoid breaking support
for any board.

Adding pin mux for each individual pin is a separate activity where I
also
quoted
need access to various boards So I am leaving that to developers who
want to configure
for the corresponding boards using init_port api.

Removing mux from u-boot level and adding it to board file is beyond
the scope of this
patch series and is a separate topic of discussion, as current patch
series
quoted
assumes that uarts are muxed from u-boot level and needs to only enable
wakeup
capability for rx-pin.

Hope this clarifies.
It is true that this patch is not intending to configure the pads.

But my question is, after this patch say
? 1) some board file calls omap_serial_port.
? 2) As a result , all the uarts devices are build and only the Rx pad is
configured for each device.
? 3) After this there will be no way of configuring the rest of the pads
??
? ? ?That should not happen. Also relying that the bootloaders are going
? ? ?to do the configuration is not correct.

? ? ?So if some board calls omap_serial_port then there should be default
values for all pads which a board can use, otherwise the board calls
omap_serial_init_port for each of the device.
ok I will add default values for all pads and enable rx wakeup for rx pad.

Will incorporate in next version.

--
Thanks,
Govindraj.R


quoted
--
Thanks,
Govindraj.R

quoted
quoted
So if any board needs specific mux they can go ahead and add required
mux data in
board file and use map_serial_init_port instead of current
omap_serial_init.

quoted
Is it consistent that across all socs that only UART3 would have
UART/IRDA
quoted
functions capability so that serial2 pads can always be called
"rx_irxx"
quoted
quoted
?.
Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
Ok.
quoted
--
Thanks,
Govindraj.R

[PATCH 7/7] Serial: OMAP2+: Make the RX_TIMEOUT for DMA configurable for each UART

From: Govindraj.R <hidden>
Date: 2011-02-28 14:39:18

From: Jon Hunter <redacted>

When using DMA there are two timeouts defined. The first timeout,
rx_timeout, is really a polling rate in which software polls the
DMA status to see if the DMA has finished. This is necessary for
the RX side because we do not know how much data we will receive.
The secound timeout, RX_TIMEOUT, is a timeout after which the
DMA will be stopped if no more data is received. To make this
clearer, rename rx_timeout as rx_poll_rate and rename the
function serial_omap_rx_timeout() to serial_omap_rxdma_poll().

The OMAP-Serial driver defines an RX_TIMEOUT of 3 seconds that is
used to indicate when the DMA for UART can be stopped if no more
data is received. The value is a global definition that is applied
to all instances of the UART.

Each UART may be used for a different purpose and so the timeout
required may differ. Make this value configurable for each UART so
that this value can be optimised for power savings.

Signed-off-by: Govindraj.R <redacted>
Signed-off-by: Jon Hunter <redacted>
---
 arch/arm/mach-omap2/serial.c                  |    2 ++
 arch/arm/plat-omap/include/plat/omap-serial.h |    6 ++++--
 drivers/tty/serial/omap-serial.c              |   15 ++++++++-------
 3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 530e9e3..ff52442 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -48,6 +48,7 @@ static struct omap_uart_port_info omap_serial_default_info[] = {
 	{
 		.dma_enabled	= 0,
 		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
 		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
 		.idle_timeout	= DEFAULT_IDLE_TIMEOUT,
 	},
@@ -268,6 +269,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 	pdata->flags = UPF_BOOT_AUTOCONF;
 	pdata->dma_enabled = info->dma_enabled;
 	pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+	pdata->dma_rx_poll_rate = info->dma_rx_poll_rate;
 	pdata->dma_rx_timeout = info->dma_rx_timeout;
 	pdata->idle_timeout = info->idle_timeout;
 	if (bdata->id == omap_uart_con_id)
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 4f12d6c..e338f4e 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -51,8 +51,8 @@
 
 #define OMAP_UART_DMA_CH_FREE	-1
 
-#define RX_TIMEOUT		(3 * HZ)	/* RX DMA timeout (jiffies) */
-#define DEFAULT_RXDMA_TIMEOUT	1		/* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_TIMEOUT	(3 * HZ)	/* RX DMA timeout (jiffies) */
+#define DEFAULT_RXDMA_POLLRATE	1		/* RX DMA polling rate (us) */
 #define DEFAULT_RXDMA_BUFSIZE	4096		/* RX DMA buffer size */
 #define DEFAULT_IDLE_TIMEOUT	(5 * HZ)	/* UART idle timeout (secs) */
 
@@ -70,6 +70,7 @@ struct omap_uart_port_info {
 	unsigned int		console_uart;
 	unsigned int		dma_rx_buf_size;/* DMA Rx Buffer Size */
 	unsigned int		dma_rx_timeout;	/* DMA RX timeout */
+	unsigned int		dma_rx_poll_rate;	/* DMA RX timeout */
 	unsigned int		idle_timeout;	/* OMAP UART idle timeout */
 
 	void __iomem *wk_st;
@@ -99,6 +100,7 @@ struct uart_omap_dma {
 	/* timer to poll activity on rx dma */
 	struct timer_list	rx_timer;
 	unsigned int		rx_buf_size;
+	unsigned int		rx_poll_rate;
 	unsigned int		rx_timeout;
 };
 
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 008645c..5c3d2fc 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -51,7 +51,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
 /* Forward declaration of functions */
 static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rx_timeout(unsigned long uart_no);
+static void serial_omap_rxdma_poll(unsigned long uart_no);
 static int serial_omap_start_rxdma(struct uart_omap_port *up);
 static void omap_uart_mdr1_errataset(struct uart_omap_port *up);
 
@@ -589,7 +589,7 @@ static int serial_omap_startup(struct uart_port *port)
 			(dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
 			0);
 		init_timer(&(up->uart_dma.rx_timer));
-		up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+		up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
 		up->uart_dma.rx_timer.data = up->pdev->id;
 		/* Currently the buffer size is 4KB. Can increase it */
 		up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
@@ -1191,7 +1191,7 @@ static int serial_omap_resume(struct device *dev)
 	return 0;
 }
 
-static void serial_omap_rx_timeout(unsigned long uart_no)
+static void serial_omap_rxdma_poll(unsigned long uart_no)
 {
 	struct uart_omap_port *up = ui[uart_no];
 	unsigned int curr_dma_pos, curr_transmitted_size;
@@ -1201,9 +1201,9 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
 	if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
 			     (curr_dma_pos == 0)) {
 		if (jiffies_to_msecs(jiffies - up->port_activity) <
-							RX_TIMEOUT) {
+						up->uart_dma.rx_timeout) {
 			mod_timer(&up->uart_dma.rx_timer, jiffies +
-				usecs_to_jiffies(up->uart_dma.rx_timeout));
+				usecs_to_jiffies(up->uart_dma.rx_poll_rate));
 		} else {
 			serial_omap_stop_rxdma(up);
 			up->ier |= (UART_IER_RDI | UART_IER_RLSI);
@@ -1232,7 +1232,7 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
 		}
 	} else  {
 		mod_timer(&up->uart_dma.rx_timer, jiffies +
-			usecs_to_jiffies(up->uart_dma.rx_timeout));
+			usecs_to_jiffies(up->uart_dma.rx_poll_rate));
 	}
 	up->port_activity = jiffies;
 }
@@ -1270,7 +1270,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up)
 	/* FIXME: Cache maintenance needed here? */
 	omap_start_dma(up->uart_dma.rx_dma_channel);
 	mod_timer(&up->uart_dma.rx_timer, jiffies +
-				usecs_to_jiffies(up->uart_dma.rx_timeout));
+				usecs_to_jiffies(up->uart_dma.rx_poll_rate));
 	up->uart_dma.rx_dma_used = true;
 	return ret;
 }
@@ -1412,6 +1412,7 @@ static int serial_omap_probe(struct platform_device *pdev)
 		up->use_dma = 1;
 		up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
 		up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
+		up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
 		spin_lock_init(&(up->uart_dma.tx_lock));
 		spin_lock_init(&(up->uart_dma.rx_lock));
 		up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
-- 
1.7.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help