Skip to contentSkip to conversation

OMAP2+: UART: runtime conversion + cleanup.

PATCH New Govindraj.R 7 participants 25 messages Feb 28, 2011 – Mar 9, 2011

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover OMAP2+: UART: runtime conversion + cleanup.

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(-)
#1 lore raw

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

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.

---
 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(-)
arch/arm/mach-omap2/omap_hwmod_2420_data.c +3 -0
index f323c6b..48392f3 100644
@@ -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,
arch/arm/mach-omap2/omap_hwmod_2430_data.c +3 -0
index de0015d..ab58a20 100644
@@ -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,
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +4 -0
index e9d0012..79c39d4 100644
@@ -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,
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +4 -0
index 79a8601..13c2df1 100644
@@ -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),
Signature · 1 line
1.7.1
#2 lore raw

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

In reply to Govindraj.R

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.

---
 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(-)
arch/arm/mach-omap2/mux.c +23 -0
index 98148b6..5338b93 100644
@@ -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;
arch/arm/mach-omap2/mux.h +13 -0
index a4ab17a..84a8fc2 100644
@@ -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;
arch/arm/mach-omap2/omap_hwmod.c +13 -0
index 9e89a58..893dae1 100644
@@ -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;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index fedd829..4100be0 100644
@@ -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
Signature · 1 line
1.7.1
#3 lore raw

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

Govind,

Couple of minor comments.

Quoted 6 lines · Govindraj.R

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 26 lines

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.

---

?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(-)

arch/arm/mach-omap2/mux.c +5 -0
index 98148b6..5338b93 100644
@@ -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;

arch/arm/mach-omap2/mux.c err1: · line 334

Quoted 10 lines
arch/arm/mach-omap2/mux.c +10 -0
+
+ ? ? ? 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.

arch/arm/mach-omap2/mux.c err1: · line 331

Quoted 3 lines
arch/arm/mach-omap2/mux.c +3 -0
+ ? ? ? ? ? ? ? return 0;
+}
+

- V Charulatha

#4 lore raw

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

Quoted 44 lines · Charulatha

Govind,

Couple of minor comments.

Quoted 6 lines · Govindraj.R

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 30 lines

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.

---

?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(-)

arch/arm/mach-omap2/mux.c +9 -0
index 98148b6..5338b93 100644
@@ -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];
+
Quoted 8 lines

arch/arm/mach-omap2/mux.c err1: · line 334

Quoted 6 lines
arch/arm/mach-omap2/mux.c +6 -0
+ ? ? ? ? ? ? ? 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>>

#5 lore raw

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

In reply to Govindraj.R

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.

---
 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(-)
arch/arm/mach-omap2/pm24xx.c +0 -11
index 97feb3a..5af9881 100644
@@ -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);
arch/arm/mach-omap2/pm34xx.c +0 -16
index 2f864e4..850bb0a 100644
@@ -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;
 }
arch/arm/plat-omap/include/plat/serial.h +0 -4
index 8061695..6339848 100644
@@ -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
Signature · 1 line
1.7.1
#6 lore raw

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

In reply to Govindraj.R

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.

---
 arch/arm/mach-omap2/serial.c                  |  749 ++-----------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |   21 +-
 2 files changed, 75 insertions(+), 695 deletions(-)
arch/arm/mach-omap2/serial.c +57 -692
index 47eef48..755f4aa 100644
@@ -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);
-
 	}
 }
arch/arm/plat-omap/include/plat/omap-serial.h +18 -3
index 2682043..f9bc7ef 100644
@@ -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__ */
Signature · 1 line
1.7.1
#7 lore raw

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

In reply to Govindraj.R

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.

---
 drivers/tty/serial/omap-serial.c |  304 +++++++++++++++++++++++++++++++++++---
 1 files changed, 283 insertions(+), 21 deletions(-)
drivers/tty/serial/omap-serial.c +283 -21
index d40924a..bc877b9 100644
@@ -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,
 	},
 };
 
Signature · 1 line
1.7.1
#8 lore raw

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

Quoted 8 lines · Govindraj.R

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.

At least the errata handling should be in a separate patch as it's not related to runtime PM.

Also, please be sure to test building this driver as a module. Because of direct access to hwmod in this patch, it will currently build as a module.

Quoted 51 lines
---
 drivers/tty/serial/omap-serial.c |  304 +++++++++++++++++++++++++++++++++++---
 1 files changed, 283 insertions(+), 21 deletions(-)
drivers/tty/serial/omap-serial.c +20 -0
index d40924a..bc877b9 100644
@@ -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);
+}
+

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 122

Quoted 10 lines
drivers/tty/serial/omap-serial.c +10 -0
+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);
+	}
+}

This function should not be needed.

The timer should be replaced by the auto-suspend feature of runtime PM.

Instead of calling omap_port_disable() callers should call pm_runtime_put_autosuspend(), and the console_stop() should be part of the ->runtime_suspend() callback.

Also, why do you check for pm_runtime_suspended()? Just call it for every time and we get runtime PM use-counting and statistics for free and the ->runtime_suspend() callback will be called when the usecount goes to zero.

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 130

Quoted 7 lines
drivers/tty/serial/omap-serial.c +7 -0
+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);
+}

This will not be needed if using the autosuspend feature.

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 143

Quoted 12 lines
drivers/tty/serial/omap-serial.c +12 -0
+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);
+}

Similarily to the disable side, callers of this function should call pm_runtime_get_sync() and the console_start() should be in the ->runtime_resume method.

Again, no need to check pm_runtime_suspended() since the runtime PM core does usecounting already.

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 150

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+void omap_uart_prepare_idle(int num)
+{
+	struct uart_omap_port *up = ui[num];
+
+	if (up && up->can_sleep)
+		serial_omap_port_disable(up);

pm_runtime_put_autosuspend()

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 163

Quoted 13 lines
drivers/tty/serial/omap-serial.c +13 -0
+}
+
+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);
	od = to_omap_device(pdev);

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 170

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+	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);
+}

c.f. comments from PATCH 2/7

Also, direct hwmod access and PRCM accesses do not belong in drivers.

Until it is understood why wakeups are not working, these hacks should stay in mach-omap2/serial.c

drivers/tty/serial/omap-serial.c static void serial_omap_enable_ms(struct uart_port *port) · line 187

Quoted 8 lines
drivers/tty/serial/omap-serial.c +1 -0
 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);

pm_runtime_put_autosuspend()

similarily for all calls to omap_port_enable()

Quoted 154 lines
drivers/tty/serial/omap-serial.c +31 -5
 	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);

drivers/tty/serial/omap-serial.c serial_omap_pm(struct uart_port *port, unsigned int state, · line 937

Quoted 5 lines
drivers/tty/serial/omap-serial.c +2 -0
@@ -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);

FYI... this change doesn't apply when basing on the commit you mentioned in PATCH 0/7.

Quoted 120 lines
drivers/tty/serial/omap-serial.c +32 -12
 }
 
 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;

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1427

Quoted 9 lines
drivers/tty/serial/omap-serial.c +6 -0
@@ -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);

The changelog should describe why the IRQ-safe mode is needed.

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1431

Quoted 3 lines
drivers/tty/serial/omap-serial.c +3 -0
+	if (omap_up_info->console_uart) {
+		od = container_of(pdev, struct omap_device, pdev);
+		omap_hwmod_idle(od->hwmods[0]);

This was only in mach-omap2/serial.c because the early UART probing was accessing registers. With this driver becoming runtime PM aware, this hack should not be needed, and the

	oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;

should be removed from mach-omap2/serial.c

Quoted 108 lines
drivers/tty/serial/omap-serial.c +82 -1
+		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);
+	}
+}

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1552

Quoted 10 lines
drivers/tty/serial/omap-serial.c +10 -0
+
+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);
+	}
+}

Again, driver should not be doing direct PRCM accesses here.

For now, how about leaving these also in mach-omap2/serial.c and calling them via pdata function pointers:

if (pdata->enable_wakeup)

      pdata->enable_wakeup()
Quoted 35 lines
drivers/tty/serial/omap-serial.c +34 -0
+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 = {

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1595

Quoted 10 lines
drivers/tty/serial/omap-serial.c +1 -3
 	.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,
 	},
 };

Kevin

#9 lore raw

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

Quoted 11 lines · Kevin Hilman
Quoted 8 lines · Govindraj.R

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.

Quoted 3 lines

At least the errata handling should be in a separate patch as it's not related to runtime PM.

ok. will move to separate patch

Quoted 3 lines

Also, please be sure to test building this driver as a module. ?Because of direct access to hwmod in this patch, it will currently build as a module.

yes will check this out. I can check this only
on zoom board I think as most of other boards
seem to use omap-uart as console uart.

Quoted 64 lines
Quoted 51 lines

---
?drivers/tty/serial/omap-serial.c | ?304 +++++++++++++++++++++++++++++++++++--- ?1 files changed, 283 insertions(+), 21 deletions(-)

drivers/tty/serial/omap-serial.c +0 -0
index d40924a..bc877b9 100644
@@ -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>

drivers/tty/serial/omap-serial.c +10 -0
+#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];

drivers/tty/serial/omap-serial.c +9 -0
@@ -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);
+}
+

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 122

Quoted 10 lines
drivers/tty/serial/omap-serial.c +10 -0
+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);
+ ? ? }
+}

This function should not be needed.

Quoted 1 line

The timer should be replaced by the auto-suspend feature of runtime PM.

If I use autosuspend based on timer runtime framework will disable clocks based on autosuspend timeout.

But if I cut clocks outside sram idle path module level wakeup will not work. if I cut func clocks outside prepare for idle wake_up is a problem. So I am going with existing model where we are cutting clocks in prepare idle and enabling the clock back in resume_idle based on wakeup event as any other combination doesn't seem to work.

[As stated in other thread to reproduce the issue with module level wakeup]

Even with existing framework if I try to experiment by cutting clocks after uart timeout in allow_sleep func, module level wakeup doesn't seem to happen.

Quoted 10 lines

Instead of calling omap_port_disable() callers should call pm_runtime_put_autosuspend(), and the console_stop() should be part of the ->runtime_suspend() callback.

Also, why do you check for pm_runtime_suspended()? ?Just call it for every time and we get runtime PM use-counting and statistics for free and the ->runtime_suspend() callback will be called when the usecount goes to zero.

Yes correct, but I can't balance the put_sync and get_sync as said above. I can call put_sync only once in prepare_idle to cut clocks. But having put_sync outside prepare_idle, if clocks are cut module level wakeup doesn't seem to happen.

Quoted 9 lines

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 130

Quoted 7 lines
drivers/tty/serial/omap-serial.c +7 -0
+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);
+}

This will not be needed if using the autosuspend feature.

Using autosuspend, module level wakeup will not happen since autosuspend cuts clocks outside prepare_idle based on autosuspend timeout.

Quoted 17 lines

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 141

Quoted 13 lines
drivers/tty/serial/omap-serial.c +12 -0
+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);
+}

Similarily to the disable side, callers of this function should call pm_runtime_get_sync() and the console_start() should be in the ->runtime_resume method.

Agree, will move console_start/console_stop func to runtime sync callbacks.

Quoted 4 lines

Again, no need to check pm_runtime_suspended() since the runtime PM core does usecounting already.

Agree, but balancing put_sync is an issue currently for uart with get_sync as we can use put_sync just once in prepare_idle.

Quoted 34 lines

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud)

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+void omap_uart_prepare_idle(int num)
+{
+ ? ? struct uart_omap_port *up = ui[num];
+
+ ? ? if (up && up->can_sleep)
+ ? ? ? ? ? ? serial_omap_port_disable(up);

? ? ? ? ? ? ? ?pm_runtime_put_autosuspend()

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 160

Quoted 13 lines
drivers/tty/serial/omap-serial.c +13 -0
+}
+
+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);

? ? ? ?od = to_omap_device(pdev);

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 166

Quoted 6 lines
drivers/tty/serial/omap-serial.c +6 -0
+ ? ? 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);
+}

c.f. comments from PATCH 2/7

Quoted 5 lines

Also, direct hwmod access and PRCM accesses do not belong in drivers.

Until it is understood why wakeups are not working, these hacks should stay in mach-omap2/serial.c

Ok. I will add callbacks to handle wk_mask and wk_st
will retain these funcs in serial.c but new format of this func can use uart_port id based on which i can select wk_st and wk_mask values and then read/write into these.

Quoted 160 lines

drivers/tty/serial/omap-serial.c static void serial_omap_enable_ms(struct uart_port *port) · line 187

Quoted 8 lines
drivers/tty/serial/omap-serial.c +1 -0
 ?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);

? ? ? ?pm_runtime_put_autosuspend()

similarily for all calls to omap_port_enable()

Quoted 147 lines
drivers/tty/serial/omap-serial.c +1 -0
 ? ? ? 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) { ? ? ? ? ? ? ? /*

drivers/tty/serial/omap-serial.c +8 -0
@@ -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())

drivers/tty/serial/omap-serial.c +2 -0
@@ -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
? ? ? ?*/

drivers/tty/serial/omap-serial.c +4 -0
@@ -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)

drivers/tty/serial/omap-serial.c +0 -0
@@ -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);

? ? ? /*

drivers/tty/serial/omap-serial.c +0 -0
@@ -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);

drivers/tty/serial/omap-serial.c +8 -3
@@ -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 */

drivers/tty/serial/omap-serial.c +0 -0
@@ -818,6 +922,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
 ? ? ? unsigned char efr;
 
Quoted 16 lines

drivers/tty/serial/omap-serial.c serial_omap_pm(struct uart_port *port, unsigned int state, · line 937

Quoted 12 lines
drivers/tty/serial/omap-serial.c +4 -0
 ? ? ? 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);

FYI... this change doesn't apply when basing on the commit you mentioned in PATCH 0/7.

this patch series will apply on top the
dependency patches specified in cover letter.

Specially needs
https://patchwork.kernel.org/patch/501211/
without which it will fail here.

Quoted 117 lines
Quoted 117 lines
drivers/tty/serial/omap-serial.c +5 -1
 ?}
 
 ?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;

drivers/tty/serial/omap-serial.c +27 -10
@@ -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;
 
Quoted 14 lines

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1427

Quoted 12 lines
drivers/tty/serial/omap-serial.c +6 -0
 ? ? ? 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);

The changelog should describe why the IRQ-safe mode is needed.

yes will add.
we need to use get_sync in irq_context hence needed.

Quoted 5 lines

drivers/tty/serial/omap-serial.c static int serial_omap_probe(struct platform_device *pdev) · line 1430

Quoted 4 lines
drivers/tty/serial/omap-serial.c +3 -0
+ ? ? if (omap_up_info->console_uart) {
+ ? ? ? ? ? ? od = container_of(pdev, struct omap_device, pdev);
+ ? ? ? ? ? ? omap_hwmod_idle(od->hwmods[0]);
Quoted 7 lines

This was only in mach-omap2/serial.c because the early UART probing was accessing registers. ?With this driver becoming runtime PM aware, this hack should not be needed, and the

? ? ? ?oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;

should be removed from mach-omap2/serial.c

Yes. Since any omap-uart can be used as
console uart and the console uart can be used
for earlyprintk's.

For earlyprintk's the early console driver will use printch from debug macro to print through uart during which hwmod is getting initialized

--> _setup

    --> _idle
     ---> _disable_clocks

at this point of time while printch is happening and hwmod disables uart clocks I dont have uart-console driver available which can enable clocks back.

So I have to use those flags when earlyprintk is enabled. I have added some more changes into omap_serial_early_init which uses these flags only when earlyprintk config is defined and earlyprintk word is used in bootarg, snip below.

<<Function SNIP>>
==================================
static int __init omap_serial_early_init(void)
{

#ifdef CONFIG_EARLY_PRINTK
        int i = 0;
        char omap_tty_name[MAX_UART_HWMOD_NAME_LEN];
        struct omap_hwmod *oh;

        if (!cmdline_find_option("earlyprintk"))
                return 0;

        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;
                }
        }
#endif
        return 0;
}

core_initcall(omap_serial_early_init);

=========================================

Quoted 122 lines
Quoted 109 lines
drivers/tty/serial/omap-serial.c +5 -1
+ ? ? ? ? ? ? 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;

drivers/tty/serial/omap-serial.c +75 -0
@@ -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);
+ ? ? }
+}

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1552

Quoted 10 lines
drivers/tty/serial/omap-serial.c +10 -0
+
+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);
+ ? ? }
+}

Again, driver should not be doing direct PRCM accesses here.

Quoted 6 lines

For now, how about leaving these also in mach-omap2/serial.c and calling them via pdata function pointers:

?if (pdata->enable_wakeup)
? ? ?pdata->enable_wakeup()

Agree will move these func's and use func. pointer.

--
Thanks,
Govindraj.R

Quoted 52 lines
Quoted 35 lines
drivers/tty/serial/omap-serial.c +34 -0
+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 = {

drivers/tty/serial/omap-serial.c static int serial_omap_remove(struct platform_device *dev) · line 1594

Quoted 10 lines
drivers/tty/serial/omap-serial.c +1 -3
 ? ? ? .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,
 ? ? ? },
 ?};

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#10 lore raw

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

Govindraj <[email protected]> writes:

[...]

Quoted 11 lines
Quoted 3 lines

This function should not be needed.

The timer should be replaced by the auto-suspend feature of runtime PM.

If I use autosuspend based on timer runtime framework will disable clocks based on autosuspend timeout.

But if I cut clocks outside sram idle path module level wakeup will not work.
if I cut func clocks outside prepare for idle wake_up is a problem.

As I mentioned in the other thread, module wakeups are not the problem, rather the module generating the interrupt is the problem. So cutting clocks outside prepare_for_idle path is not the problem. It's the re-enabling of the clocks that is important.

Quoted 37 lines

So I am going with existing model where we are cutting clocks in prepare idle and enabling the clock back in resume_idle based on wakeup event as any other combination doesn't seem to work.

[As stated in other thread to reproduce the issue
with module level wakeup]

Even with existing framework if I try to experiment by cutting clocks after uart timeout in allow_sleep func, module level wakeup doesn't seem to happen.

Quoted 10 lines

Instead of calling omap_port_disable() callers should call pm_runtime_put_autosuspend(), and the console_stop() should be part of the ->runtime_suspend() callback.

Also, why do you check for pm_runtime_suspended()? ?Just call it for every time and we get runtime PM use-counting and statistics for free and the ->runtime_suspend() callback will be called when the usecount goes to zero.

Yes correct, but I can't balance the put_sync and get_sync as said above. I can call put_sync only once in prepare_idle to cut clocks. But having put_sync outside prepare_idle, if clocks are cut module level wakeup doesn't seem to happen.

Quoted 9 lines

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 130

Quoted 7 lines
drivers/tty/serial/omap-serial.c +7 -0
+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);
+}

This will not be needed if using the autosuspend feature.

Quoted 3 lines

Using autosuspend, module level wakeup will not happen since autosuspend cuts clocks outside prepare_idle based on autosuspend timeout.

OK, I get the point. You mentioned module level wakeups about 10 times in this message. ;)

However, rather than continue to hack around this problem we need to understand the root cause. Thanks to Paul, I think I undersand the root cause as explained in the other thread, and I think there's a relatively easy way to make them work.

So here's an experiment to try with autosuspend. I suspect this will work, just hack it up to prove the concept. If it works, we can make something more generic. Here are a few alternatives to try. I may experiment with some of them tomorrow as well, but please let me know what you try:

Using autosuspend, clocks will get cut independently of the idle path. Then, use the PRCM ISR detection of UART module wakeups to call the UART's interrupt handler. The interrupt handler will pm_runtime_get(), enable the clocks, and then take care of the interrupt. Done.

Alternatively, you could test it on current code by simply removing the resume_from_idle call from the idle path and calling it instead from the PRCM ISR when UART module wakeups are detected.

Another option to experiment with: use PRCM ISR to trigger a SW interrupt of the UART IRQ (cf. MPU_INTC.INTCPS_ISR_SETn registers.) This may be the cleanest approach, and not require calling into the driver, but I'm not sure if the normal interrupt clearing process will also clear the SW interrupt.

The best longer-term solution is will be to use the chained PRCM interrupt handler[1] (not yet finished.) Using that, drivers could directly register for their individual module wakeup interrupts.

Kevin

[1] http://marc.info/?l=linux-omap&m=129258489308837&w=2

maintainer
#11 lore raw

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

Hi Govindraj,

what also would be good to find out is why the UART is apparently sending asynchronous wakeups even when the driver doesn't set SCR_REG.RX_CTS_WU_EN. This seems contrary to the expectation that 34xx TRM vZH section 17.4.4.1.4.1 "Wake-up Interrupt" sets. Could you please clarify under which circumstances the RX_CTS_WU_EN bit is used? I suppose that, given that it's also mentioned under section 17.4.5.1.1 "Module Power Savings", it might only be used when SLEEP_MODE is enabled.

- Paul

#12 lore raw

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

Quoted 11 lines · Paul Walmsley

Hi Govindraj,

what also would be good to find out is why the UART is apparently sending asynchronous wakeups even when the driver doesn't set SCR_REG.RX_CTS_WU_EN. ?This seems contrary to the expectation that 34xx TRM vZH section 17.4.4.1.4.1 "Wake-up Interrupt" sets. ?Could you please clarify under which circumstances the RX_CTS_WU_EN bit is used? ?I suppose that, given that it's also mentioned under section 17.4.5.1.1 "Module Power Savings", it might only be used when SLEEP_MODE is enabled.

AFAIK, sleep_mode is used only for uart internal power saving options if fifo's are empty which inturn can stop uart internal baud clock. To enable back uart baud clock and start uart internal activity it will depend on RX_CTS_WU_EN from scr to restart uart_baud_clock.

For system level powers saving like cutting uart_fclks wakeup will depend on WER reg for wakeup event or io-pad wakeup depending on power state.
Since I am cutting fclks directly I am depending on WER reg wakeup events.

--
Thanks,
Govindraj.R

Quoted 3 lines

- Paul

#13 lore raw

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

In reply to Kevin Hilman
Quoted 76 lines · Kevin Hilman

Govindraj <[email protected]> writes:

[...]

Quoted 11 lines
Quoted 3 lines

This function should not be needed.

The timer should be replaced by the auto-suspend feature of runtime PM.

If I use autosuspend based on timer runtime framework will disable clocks based on autosuspend timeout.

But if I cut clocks outside sram idle path module level wakeup will not work.
if I cut func clocks outside prepare for idle wake_up is a problem.

As I mentioned in the other thread, module wakeups are not the problem, rather the module generating the interrupt is the problem. ?So cutting clocks outside prepare_for_idle path is not the problem. ?It's the re-enabling of the clocks that is important.

Quoted 37 lines

So I am going with existing model where we are cutting clocks in prepare idle and enabling the clock back in resume_idle based on wakeup event as any other combination doesn't seem to work.

[As stated in other thread to reproduce the issue
with module level wakeup]

Even with existing framework if I try to experiment by cutting clocks after uart timeout in allow_sleep func, module level wakeup doesn't seem to happen.

Quoted 10 lines

Instead of calling omap_port_disable() callers should call pm_runtime_put_autosuspend(), and the console_stop() should be part of the ->runtime_suspend() callback.

Also, why do you check for pm_runtime_suspended()? ?Just call it for every time and we get runtime PM use-counting and statistics for free and the ->runtime_suspend() callback will be called when the usecount goes to zero.

Yes correct, but I can't balance the put_sync and get_sync as said above. I can call put_sync only once in prepare_idle to cut clocks. But having put_sync outside prepare_idle, if clocks are cut module level wakeup doesn't seem to happen.

Quoted 9 lines

drivers/tty/serial/omap-serial.c serial_omap_get_divisor(struct uart_port *port, unsigned int baud) · line 130

Quoted 7 lines
drivers/tty/serial/omap-serial.c +7 -0
+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);
+}

This will not be needed if using the autosuspend feature.

Quoted 3 lines

Using autosuspend, module level wakeup will not happen since autosuspend cuts clocks outside prepare_idle based on autosuspend timeout.

OK, I get the point. ?You mentioned module level wakeups about 10 times in this message. ?;)

However, rather than continue to hack around this problem we need to understand the root cause. ?Thanks to Paul, I think I undersand the root cause as explained in the other thread, and I think there's a relatively easy way to make them work.

So here's an experiment to try with autosuspend. ?I suspect this will work, just hack it up to prove the concept. ?If it works, we can make something more generic. ?Here are a few alternatives to try. ?I may experiment with some of them tomorrow as well, but please let me know what you try:

Quoted 8 lines

Using autosuspend, clocks will get cut independently of the idle path. Then, use the PRCM ISR detection of UART module wakeups to call the UART's interrupt handler. ?The interrupt handler will pm_runtime_get(), enable the clocks, and then take care of the interrupt. ?Done.

Alternatively, you could test it on current code by simply removing the resume_from_idle call from the idle path and calling it instead from the PRCM ISR when UART module wakeups are detected.

I remember doing similar experiment didn't seem to help,

Quoted 6 lines

Another option to experiment with: use PRCM ISR to trigger a SW interrupt of the UART IRQ (cf. MPU_INTC.INTCPS_ISR_SETn registers.) This may be the cleanest approach, and not require calling into the driver, but I'm not sure if the normal interrupt clearing process will also clear the SW interrupt.

need to check this.

Quoted 4 lines

The best longer-term solution is will be to use the chained PRCM interrupt handler[1] (not yet finished.) ?Using that, drivers could directly register for their individual module wakeup interrupts.

Agree.

Quoted 6 lines

Kevin

[1] http://marc.info/?l=linux-omap&m=129258489308837&w=2

#14 lore raw

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

Govindraj <[email protected]> writes:

[...]

Quoted 12 lines
Quoted 12 lines

So here's an experiment to try with autosuspend. ?I suspect this will work, just hack it up to prove the concept. ?If it works, we can make something more generic. ?Here are a few alternatives to try. ?I may experiment with some of them tomorrow as well, but please let me know what you try:

Using autosuspend, clocks will get cut independently of the idle path. Then, use the PRCM ISR detection of UART module wakeups to call the UART's interrupt handler. ?The interrupt handler will pm_runtime_get(), enable the clocks, and then take care of the interrupt. ?Done.

Quoted 6 lines
Quoted 3 lines

Alternatively, you could test it on current code by simply removing the resume_from_idle call from the idle path and calling it instead from the PRCM ISR when UART module wakeups are detected.

I remember doing similar experiment didn't seem to help,

To show it's possible, I did really hacky proof of concept, hard-coded to UART3 console for n900/beagle, but at least it shows that this approach can work, and the module-level wakeups are working and can be used as the trigger for UART wakeup instead of resume_from_idle. Of course, it still has problems with using serial after non-UART wakeups, but once omap-serial is using runtime PM, that will no longer be an issue.

My hacky branch is called pm-wip/uart-wkup and is in my pm git tree[1] (based at the pm-core branch)

To test module-level wakeups (instead of IO-ring) I again forced CORE to stay on during suspend, and tested wakeup from suspend on 3430/n900:

echo 3 > /debug/pm_debug/core_pwrdm/suspend
echo mem > /sys/power/state

Kevin

[1] git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git

#15 lore raw

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

In reply to Govindraj.R

From: Jon Hunter <[email protected]>

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.

---
 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(-)
arch/arm/mach-omap2/board-2430sdp.c +2 -1
index cc42d47..0cfa3c7 100644
@@ -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);
 
arch/arm/mach-omap2/board-3430sdp.c +2 -2
index 8950ecc..7d7df08 100644
@@ -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);
arch/arm/mach-omap2/board-4430sdp.c +2 -1
index 1a943be..9687aec 100644
@@ -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);
arch/arm/mach-omap2/board-am3517evm.c +2 -1
index 634fe65..bbc79a4 100644
@@ -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);
arch/arm/mach-omap2/board-apollon.c +2 -1
index 4ef4aad..e021cdb 100644
@@ -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)
arch/arm/mach-omap2/board-cm-t35.c +2 -1
index 7311824..8ecde7e 100644
@@ -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();
arch/arm/mach-omap2/board-cm-t3517.c +2 -1
index 38bef6d..a1c0d87 100644
@@ -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();
arch/arm/mach-omap2/board-devkit8000.c +2 -1
index 54abdd0..28fac56 100644
@@ -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();
 
arch/arm/mach-omap2/board-generic.c +2 -1
index 682da92..450128b 100644
@@ -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)
arch/arm/mach-omap2/board-h4.c +2 -1
index f6a3872..6481bab 100644
@@ -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)
arch/arm/mach-omap2/board-igep0020.c +2 -1
index 54e6318..9223b9b 100644
@@ -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);
 
arch/arm/mach-omap2/board-igep0030.c +2 -1
index d75028e..c593a5c 100644
@@ -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);
 
arch/arm/mach-omap2/board-ldp.c +2 -1
index a3fae56..ff93da7 100644
@@ -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);
arch/arm/mach-omap2/board-n8x0.c +5 -4
index b36cbd2..7347256 100644
@@ -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
arch/arm/mach-omap2/board-omap3beagle.c +2 -1
index a1faea3..e6c0299 100644
@@ -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");
arch/arm/mach-omap2/board-omap3evm.c +2 -1
index 5364147..0b793f1 100644
@@ -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();
arch/arm/mach-omap2/board-omap3logic.c +2 -1
index b726943..0b5ba52 100644
@@ -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();
 
arch/arm/mach-omap2/board-omap3pandora.c +2 -1
index 17ef547..6f84247 100644
@@ -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();
arch/arm/mach-omap2/board-omap3stalker.c +2 -1
index 07006c3..629bdce 100644
@@ -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();
arch/arm/mach-omap2/board-omap3touchbook.c +2 -1
index 6a60f79..c6bf289 100644
@@ -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");
arch/arm/mach-omap2/board-omap4panda.c +2 -1
index 3dd241b..2245ed1 100644
@@ -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);
arch/arm/mach-omap2/board-overo.c +2 -1
index a33ec0e..960a3ea 100644
@@ -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);
arch/arm/mach-omap2/board-rm680.c +2 -1
index bdebcb7..bd4b7ad 100644
@@ -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();
 }
arch/arm/mach-omap2/board-rx51.c +2 -1
index 3cf72fe..08619e9 100644
@@ -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();
 
arch/arm/mach-omap2/board-ti8168evm.c +1 -1
index f2b0971..c4f83ed 100644
@@ -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)
arch/arm/mach-omap2/board-zoom-peripherals.c +2 -1
index e0e040f..82ca121 100644
@@ -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);
 }
arch/arm/mach-omap2/serial.c +103 -5

161 lines not on this page · raw message

arch/arm/plat-omap/include/plat/omap-serial.h +11 -3
index f9bc7ef..4f12d6c 100644
@@ -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;
 
arch/arm/plat-omap/include/plat/serial.h +4 -2
index 6339848..2ed24b3 100644
@@ -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
drivers/tty/serial/omap-serial.c +5 -5
index bc877b9..008645c 100644
@@ -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);
Signature · 1 line
1.7.1
#16 lore raw

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

Hi,

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 21 lines
arch/arm/mach-omap2/serial.c +9 -0
index 755f4aa..530e9e3 100644
@@ -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 20 lines
arch/arm/mach-omap2/serial.c +16 -0
 = {
 	},
 };
 
+#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,
+	},
+};

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency omap_uart_latency[] = {

Quoted 10 lines
arch/arm/mach-omap2/serial.c +10 -0
+
+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

=

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency omap_uart_latency[] = {

Quoted 9 lines
arch/arm/mach-omap2/serial.c +8 -0
 {
+	{
+		.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 =

{

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency omap_uart_latency[] = { · line 117

Quoted 6 lines
arch/arm/mach-omap2/serial.c +6 -0
+	{
+		.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

Quoted 5 lines
arch/arm/mach-omap2/serial.c +0 -1
--

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

#17 lore raw

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

Quoted 64 lines · Sricharan R

Hi,

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 21 lines
arch/arm/mach-omap2/serial.c +9 -0
index 755f4aa..530e9e3 100644
@@ -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 20 lines
arch/arm/mach-omap2/serial.c +16 -0
 = {
 ? ? ? },
 };
 
+#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,
+ ? ? ?},
+};

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 104

Quoted 10 lines
arch/arm/mach-omap2/serial.c +10 -0
+
+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

=

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 113

Quoted 9 lines
arch/arm/mach-omap2/serial.c +8 -0
 {
+ ? ? ?{
+ ? ? ? ? ? ? ?.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 7 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 119

Quoted 6 lines
arch/arm/mach-omap2/serial.c +6 -0
+ ? ? ?{
+ ? ? ? ? ? ? ?.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.

Quoted 3 lines

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

#18 lore raw

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

Hi,

Quoted 5 lines

-----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 8 lines

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

Quoted 2 lines · Sricharan R

Hi,

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/arm/mach-omap2/serial.c

Quoted 25 lines
Quoted 25 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 20 lines

index 755f4aa..530e9e3 100644

arch/arm/mach-omap2/serial.c +9 -0
@@ -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 4 lines
arch/arm/mach-omap2/serial.c +0 -0
 = {
 ? ? ? },
 };
 
Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 83

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+#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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 91

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 99

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 104

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]

__initdata

Quoted 5 lines
Quoted 5 lines

=

Quoted 4 lines
arch/arm/mach-omap2/serial.c +3 -0
 {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 113

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata

=

Quoted 4 lines
Quoted 4 lines

{

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 12 lines
Quoted 4 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 119

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ? ? ? ? ?.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 1 line

Prior to this change uart wakeup is based on rx_pad and we were

populating

Quoted 9 lines

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.

Quoted 9 lines

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 1 line

Is it consistent that across all socs that only UART3 would have

UART/IRDA

Quoted 1 line

functions capability so that serial2 pads can always be called

"rx_irxx"

Quoted 4 lines
Quoted 1 line

?.

Yes from OMAP2420 to OMAP4430 uart3 can used as irda.

Ok.

Quoted 3 lines

--
Thanks,
Govindraj.R

#19 lore raw

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

Quoted 113 lines · Sricharan R

Hi,

Quoted 5 lines

-----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 8 lines

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

Quoted 2 lines · Sricharan R

Hi,

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/arm/mach-omap2/serial.c

Quoted 25 lines
Quoted 25 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 20 lines

index 755f4aa..530e9e3 100644

arch/arm/mach-omap2/serial.c +9 -0
@@ -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 4 lines
arch/arm/mach-omap2/serial.c +0 -0
 = {
 ? ? ? },
 };
 
Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 83

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+#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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 91

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 99

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 104

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]

__initdata

Quoted 5 lines
Quoted 5 lines

=

Quoted 4 lines
arch/arm/mach-omap2/serial.c +3 -0
 {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 113

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[] __initdata

=

Quoted 4 lines
Quoted 4 lines

{

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 12 lines
Quoted 4 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 119

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ? ? ? ? ?.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 1 line

Prior to this change uart wakeup is based on rx_pad and we were

populating

Quoted 9 lines

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.

Quoted 3 lines

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.

Quoted 2 lines

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 11 lines

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 19 lines
Quoted 9 lines

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 1 line

Is it consistent that across all socs that only UART3 would have

UART/IRDA

Quoted 1 line

functions capability so that serial2 pads can always be called

"rx_irxx"

Quoted 4 lines
Quoted 1 line

?.

Yes from OMAP2420 to OMAP4430 uart3 can used as irda.

Ok.

Quoted 3 lines

--
Thanks,
Govindraj.R

maintainer
#20 lore raw

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

Quoted 8 lines · Govindraj
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

+ ? ? ? ? ? ? ?.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

#21 lore raw

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

Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Govindraj
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

+static struct omap_device_pad default_serial1_pads[] __initdata = {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

Quoted 9 lines
Quoted 3 lines
Quoted 3 lines

OMAP_DEVICE_PAD_WAKEUP,

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

+ ? ? ? ? ? ? ?.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

Quoted 2 lines

Tony

#22 lore raw

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

In reply to Govindraj

Hi,

Quoted 5 lines

-----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 19 lines

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

Quoted 13 lines · Sricharan R

Hi,

Quoted 5 lines

-----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 6 lines

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 <[email protected]>

Quoted 63 lines · wrote:
Quoted 63 lines
Quoted 2 lines
Quoted 2 lines

Hi,

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/arm/mach-omap2/serial.c

Quoted 25 lines
Quoted 25 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 20 lines

index 755f4aa..530e9e3 100644

arch/arm/mach-omap2/serial.c +9 -0
@@ -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 4 lines
arch/arm/mach-omap2/serial.c +0 -0
 = {
 ? ? ? },
 };
 
Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 83

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+#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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 91

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 99

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 104

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]

__initdata

Quoted 5 lines
Quoted 5 lines

=

Quoted 4 lines
arch/arm/mach-omap2/serial.c +3 -0
 {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
Quoted 6 lines
Quoted 6 lines

OMAP_DEVICE_PAD_WAKEUP,

Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 113

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[]

__initdata

Quoted 31 lines
Quoted 31 lines

=

Quoted 4 lines
Quoted 4 lines

{

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 12 lines
Quoted 4 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 119

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ? ? ? ? ?.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 1 line

Prior to this change uart wakeup is based on rx_pad and we were

populating

Quoted 9 lines

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.

Quoted 1 line
Quoted 1 line

Now, in this change only the RX pin is configured. So if some board

uses

Quoted 9 lines
Quoted 2 lines

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 27 lines

init_port func.

Quoted 2 lines

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 11 lines

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.

Quoted 6 lines

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 7 lines

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 6 lines

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.

Quoted 24 lines

--
Thanks,
Govindraj.R

Quoted 19 lines
Quoted 9 lines

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 1 line

Is it consistent that across all socs that only UART3 would have

UART/IRDA

Quoted 1 line

functions capability so that serial2 pads can always be called

"rx_irxx"

Quoted 4 lines
Quoted 1 line

?.

Yes from OMAP2420 to OMAP4430 uart3 can used as irda.

Ok.

Quoted 3 lines

--
Thanks,
Govindraj.R

#23 lore raw

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

Quoted 199 lines · Sricharan R

Hi,

Quoted 5 lines

-----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 19 lines

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

Quoted 13 lines · Sricharan R

Hi,

Quoted 5 lines

-----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 6 lines

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 <[email protected]>

Quoted 63 lines · wrote:
Quoted 63 lines
Quoted 2 lines
Quoted 2 lines

Hi,

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/arm/mach-omap2/serial.c

Quoted 25 lines
Quoted 25 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency

Quoted 20 lines

index 755f4aa..530e9e3 100644

arch/arm/mach-omap2/serial.c +9 -0
@@ -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 4 lines
arch/arm/mach-omap2/serial.c +0 -0
 = {
 ? ? ? },
 };
 
Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 83

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+#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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 91

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 8 lines
Quoted 8 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 99

Quoted 8 lines
arch/arm/mach-omap2/serial.c +8 -0
+ ? ? ? ? ? ? ?.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 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 104

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap36xx_serial3_pads[]

__initdata

Quoted 5 lines
Quoted 5 lines

=

Quoted 4 lines
arch/arm/mach-omap2/serial.c +3 -0
 {
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
Quoted 6 lines
Quoted 6 lines

OMAP_DEVICE_PAD_WAKEUP,

Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 113

Quoted 5 lines
arch/arm/mach-omap2/serial.c +5 -0
+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
+ ? ? ?},
+};
+
+static struct omap_device_pad default_omap4_serial3_pads[]

__initdata

Quoted 31 lines
Quoted 31 lines

=

Quoted 4 lines
Quoted 4 lines

{

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ?{
+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |

OMAP_DEVICE_PAD_WAKEUP,

Quoted 12 lines
Quoted 4 lines

arch/arm/mach-omap2/serial.c static struct omap_device_pm_latency · line 119

Quoted 3 lines
arch/arm/mach-omap2/serial.c +3 -0
+ ? ? ? ? ? ? ?.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 1 line

Prior to this change uart wakeup is based on rx_pad and we were

populating

Quoted 9 lines

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.

Quoted 1 line
Quoted 1 line

Now, in this change only the RX pin is configured. So if some board

uses

Quoted 9 lines
Quoted 2 lines

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 27 lines

init_port func.

Quoted 2 lines

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 11 lines

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.

Quoted 6 lines

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 7 lines

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 6 lines

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.

Quoted 3 lines

? ? ?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 27 lines
Quoted 26 lines

--
Thanks,
Govindraj.R

Quoted 19 lines
Quoted 9 lines

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 1 line

Is it consistent that across all socs that only UART3 would have

UART/IRDA

Quoted 1 line

functions capability so that serial2 pads can always be called

"rx_irxx"

Quoted 4 lines
Quoted 1 line

?.

Yes from OMAP2420 to OMAP4430 uart3 can used as irda.

Ok.

Quoted 3 lines

--
Thanks,
Govindraj.R

#24 lore raw

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

In reply to Govindraj.R

From: Jon Hunter <[email protected]>

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.

---
 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(-)
arch/arm/mach-omap2/serial.c +2 -0
index 530e9e3..ff52442 100644
@@ -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)
arch/arm/plat-omap/include/plat/omap-serial.h +4 -2
index 4f12d6c..e338f4e 100644
@@ -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;
 };
 
drivers/tty/serial/omap-serial.c +8 -7
index 008645c..5c3d2fc 100644
@@ -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;
Signature · 1 line
1.7.1