Skip to contentSkip to conversation

OMAP2+: UART: Get context loss count to context restore

PATCH New Govindraj.R 3 participants 7 messages Nov 11, 2011 – Nov 16, 2011

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

PATCH v8 10/20 OMAP2+: UART: Get context loss count to context restore

Avoid unconditional context restore every time we gate uart clocks. Check whether context loss happened based on which we can context restore uart regs from uart_port structure.

---
 arch/arm/mach-omap2/serial.c                  |    2 ++
 arch/arm/plat-omap/include/plat/omap-serial.h |    3 +++
 drivers/tty/serial/omap-serial.c              |   20 ++++++++++++++++++--
 3 files changed, 23 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/serial.c +2 -0
index 06887d3..98e2666 100644
@@ -33,6 +33,7 @@
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
@@ -478,6 +479,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_up.dma_enabled = uart->dma_enabled;
 	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
 	omap_up.flags = UPF_BOOT_AUTOCONF;
+	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
 
 	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
arch/arm/plat-omap/include/plat/omap-serial.h +3 -0
index 5b913c7..348c9ea 100644
@@ -62,6 +62,8 @@ struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
 	upf_t			flags;		/* UPF_* flags */
+
+	int (*get_context_loss_count)(struct device *);
 };
 
 struct uart_omap_dma {
@@ -114,6 +116,7 @@ struct uart_omap_port {
 	unsigned char		msr_saved_flags;
 	char			name[20];
 	unsigned long		port_activity;
+	u32			context_loss_cnt;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +18 -2
index f5a5ed6..ea4c24a 100644
@@ -1440,15 +1440,31 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
 #ifdef CONFIG_PM_RUNTIME
 static int serial_omap_runtime_suspend(struct device *dev)
 {
+	struct uart_omap_port *up = dev_get_drvdata(dev);
+	struct omap_uart_port_info *pdata = dev->platform_data;
+
+	if (!up)
+		return -EINVAL;
+
+	if (pdata->get_context_loss_count)
+		up->context_loss_cnt = pdata->get_context_loss_count(dev);
+
 	return 0;
 }
 
 static int serial_omap_runtime_resume(struct device *dev)
 {
 	struct uart_omap_port *up = dev_get_drvdata(dev);
+	struct omap_uart_port_info *pdata = dev->platform_data;
 
-	if (up)
-		serial_omap_restore_context(up);
+	if (up) {
+		if (pdata->get_context_loss_count) {
+			u32 loss_cnt = pdata->get_context_loss_count(dev);
+
+			if (up->context_loss_cnt != loss_cnt)
+				serial_omap_restore_context(up);
+		}
+	}
 
 	return 0;
 }
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH v8 11/20 OMAP2+: UART: Move errata handling from serial.c to omap-serial

Move the errata handling mechanism from serial.c to omap-serial file and utilise the same func in driver file.

Errata i202, i291 are moved to be handled with omap-serial Moving the errata macro from serial.c file to driver header file as from on errata will be handled in driver file itself. Corrected errata id from chapter reference 2.15 to errata id i291.

Removed errata and dma_enabled fields from omap_uart_state struct as they are no more needed with errata handling done within omap-serial.

---
 arch/arm/mach-omap2/serial.c                  |   98 +++++++------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    6 ++
 drivers/tty/serial/omap-serial.c              |   66 ++++++++++++++++-
 3 files changed, 96 insertions(+), 74 deletions(-)
arch/arm/mach-omap2/serial.c +28 -70
index 98e2666..a52bd99 100644
@@ -42,8 +42,6 @@
 #include "control.h"
 #include "mux.h"
 
-#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
@@ -61,59 +59,17 @@ struct omap_uart_state {
 	void __iomem *wk_st;
 	void __iomem *wk_en;
 	u32 wk_mask;
-	u32 dma_enabled;
 
 	int clocked;
 
 	struct list_head node;
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
-
-	u32 errata;
 };
 
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-#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);
-	}
-}
-
-#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-
 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 {
 	if (uart->clocked)
@@ -156,27 +112,6 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
 	}
 }
 
-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);
@@ -267,7 +202,28 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 	}
 }
 
+/*
+ * Errata i291: [UART]:Cannot Acknowledge Idle Requests
+ * in Smartidle Mode When Configured for DMA Operations.
+ * WA: configure uart in force idle mode.
+ */
+static void omap_uart_set_noidle(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
+}
+
+static void omap_uart_set_forceidle(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+}
+
 #else
+static void omap_uart_set_noidle(struct platform_device *pdev) {}
+static void omap_uart_set_forceidle(struct platform_device *pdev) {}
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
 {
 	/* Needed to enable UART clocks when built without CONFIG_PM */
@@ -473,13 +429,19 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 			break;
 
 	oh = uart->oh;
-	uart->dma_enabled = 0;
 	name = DRIVER_NAME;
 
 	omap_up.dma_enabled = uart->dma_enabled;
 	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
 	omap_up.flags = UPF_BOOT_AUTOCONF;
 	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
+	omap_up.set_forceidle = omap_uart_set_forceidle;
+	omap_up.set_noidle = omap_uart_set_noidle;
+
+	/* Enable the MDR1 errata for OMAP2/3/4 */
+	if ((cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) &&
+						!cpu_is_ti816x())
+		omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;
 
 	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
@@ -519,10 +481,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
 		(pdata->wk_en && pdata->wk_mask))
 		device_init_wakeup(&pdev->dev, true);
-
-	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx() && !cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 }
 
 /**
arch/arm/plat-omap/include/plat/omap-serial.h +6 -0
index 348c9ea..fd3d2f7 100644
@@ -58,12 +58,17 @@
 
 #define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
 
+#define UART_ERRATA_i202_MDR1_ACCESS	(0x1 << 1)
+
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
 	upf_t			flags;		/* UPF_* flags */
+	u32			errata;
 
 	int (*get_context_loss_count)(struct device *);
+	void (*set_forceidle)(struct platform_device *);
+	void (*set_noidle)(struct platform_device *);
 };
 
 struct uart_omap_dma {
@@ -117,6 +122,7 @@ struct uart_omap_port {
 	char			name[20];
 	unsigned long		port_activity;
 	u32			context_loss_cnt;
+	u32			errata;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +62 -4

116 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#2 lore raw

PATCH v8 11/20 OMAP2+: UART: Move errata handling from serial.c to omap-serial

Hi Govindraj,

Quoted 18 lines · Govindraj.R

Move the errata handling mechanism from serial.c to omap-serial file and utilise the same func in driver file.

Errata i202, i291 are moved to be handled with omap-serial Moving the errata macro from serial.c file to driver header file as from on errata will be handled in driver file itself. Corrected errata id from chapter reference 2.15 to errata id i291.

Removed errata and dma_enabled fields from omap_uart_state struct as they are no more needed with errata handling done within omap-serial.

---
  arch/arm/mach-omap2/serial.c                  |   98 +++++++------------------
  arch/arm/plat-omap/include/plat/omap-serial.h |    6 ++
  drivers/tty/serial/omap-serial.c              |   66 ++++++++++++++++-
  3 files changed, 96 insertions(+), 74 deletions(-)

[snip]

Quoted 5 lines

+/*
+ * Errata i291: [UART]:Cannot Acknowledge Idle Requests
+ * in Smartidle Mode When Configured for DMA Operations.
+ * WA: configure uart in force idle mode.
+ */

Sorry, I should have checked this on the last version. However, this errata only appears to impact OMAP3 devices not OMAP1, OMAP2 or OMAP4. Can we add the devices impacted by this in the above comment? I believe it is just OMAP3430 and OMAP3630.

Quoted 28 lines
arch/arm/mach-omap2/serial.c +16 -1
+static void omap_uart_set_noidle(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
+}
+
+static void omap_uart_set_forceidle(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+}
+
  #else
+static void omap_uart_set_noidle(struct platform_device *pdev) {}
+static void omap_uart_set_forceidle(struct platform_device *pdev) {}
  static void omap_uart_block_sleep(struct omap_uart_state *uart)
  {
  	/* Needed to enable UART clocks when built without CONFIG_PM */
@@ -473,13 +429,19 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  			break;
 
  	oh = uart->oh;
-	uart->dma_enabled = 0;
  	name = DRIVER_NAME;
 
  	omap_up.dma_enabled = uart->dma_enabled;

arch/arm/mach-omap2/serial.c void __init omap_serial_init_port(struct omap_board_data *bdata) · line 444

Quoted 10 lines
arch/arm/mach-omap2/serial.c +7 -0
  	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
  	omap_up.flags = UPF_BOOT_AUTOCONF;
  	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
+	omap_up.set_forceidle = omap_uart_set_forceidle;
+	omap_up.set_noidle = omap_uart_set_noidle;
+
+	/* Enable the MDR1 errata for OMAP2/3/4 */
+	if ((cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())&&
+						!cpu_is_ti816x())
+		omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;

I am not sure that this will apply the errata for OMAP3630 devices. I think we need cpu_is_omap36xx() above too. Or you may wish to do !cpu_class_is_omap1 and !cpu_is_omap2420.

Quoted 150 lines
arch/arm/mach-omap2/serial.c +0 -4
  	pdata =&omap_up;
  	pdata_size = sizeof(struct omap_uart_port_info);
@@ -519,10 +481,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
  	if (((cpu_is_omap34xx() || cpu_is_omap44xx())&&  bdata->pads) ||
  		(pdata->wk_en&&  pdata->wk_mask))
  		device_init_wakeup(&pdev->dev, true);
-
-	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx()&&  !cpu_is_ti816x())
-		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
  }
 
  /**
arch/arm/plat-omap/include/plat/omap-serial.h +6 -0
index 348c9ea..fd3d2f7 100644
@@ -58,12 +58,17 @@
 
  #define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
 
+#define UART_ERRATA_i202_MDR1_ACCESS	(0x1<<  1)
+
  struct omap_uart_port_info {
  	bool			dma_enabled;	/* To specify DMA Mode */
  	unsigned int		uartclk;	/* UART clock rate */
  	upf_t			flags;		/* UPF_* flags */
+	u32			errata;
 
  	int (*get_context_loss_count)(struct device *);
+	void (*set_forceidle)(struct platform_device *);
+	void (*set_noidle)(struct platform_device *);
  };
 
  struct uart_omap_dma {
@@ -117,6 +122,7 @@ struct uart_omap_port {
  	char			name[20];
  	unsigned long		port_activity;
  	u32			context_loss_cnt;
+	u32			errata;
  };
 
  #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +54 -4
index ea4c24a..77f0829 100644
@@ -51,6 +51,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 serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
 
  static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
  {
@@ -808,7 +809,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
  	/* Protocol, Baud Rate, and Interrupt Settings */
 
-	serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	if (up->errata&  UART_ERRATA_i202_MDR1_ACCESS)
+		serial_omap_mdr1_errataset(up, up->mdr1);
+	else
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
+
  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
  	up->efr = serial_in(up, UART_EFR);
@@ -833,7 +838,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
  	else
  		up->mdr1 = UART_OMAP_MDR1_16X_MODE;
 
-	serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	if (up->errata&  UART_ERRATA_i202_MDR1_ACCESS)
+		serial_omap_mdr1_errataset(up, up->mdr1);
+	else
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
  	/* Hardware Flow Control Configuration */
 
@@ -1362,6 +1370,7 @@ static int serial_omap_probe(struct platform_device *pdev)
  	up->port.flags = omap_up_info->flags;
  	up->port.uartclk = omap_up_info->uartclk;
  	up->uart_dma.uart_base = mem->start;
+	up->errata = omap_up_info->errata;
 
  	if (omap_up_info->dma_enabled) {
  		up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1415,9 +1424,47 @@ static int serial_omap_remove(struct platform_device *dev)
  	return 0;
  }
 
+/*
+ * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
+ * 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 serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
+{
+	u8 timeout = 255;
+
+	serial_out(up, UART_OMAP_MDR1, 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 serial_omap_restore_context(struct uart_omap_port *up)
  {
-	serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+	if (up->errata&  UART_ERRATA_i202_MDR1_ACCESS)
+		serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+	else
+		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
  	serial_out(up, UART_EFR, UART_EFR_ECB);
  	serial_out(up, UART_LCR, 0x0); /* Operational mode */
@@ -1434,7 +1481,10 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
  	serial_out(up, UART_OMAP_SCR, up->scr);
  	serial_out(up, UART_EFR, up->efr);
  	serial_out(up, UART_LCR, up->lcr);
-	serial_out(up, UART_OMAP_MDR1, up->mdr1);
+	if (up->errata&  UART_ERRATA_i202_MDR1_ACCESS)
+		serial_omap_mdr1_errataset(up, up->mdr1);
+	else
+		serial_out(up, UART_OMAP_MDR1, up->mdr1);
  }
 
  #ifdef CONFIG_PM_RUNTIME

drivers/tty/serial/omap-serial.c static int serial_omap_runtime_suspend(struct device *dev) · line 1505

Quoted 7 lines
drivers/tty/serial/omap-serial.c +4 -0
@@ -1449,6 +1499,10 @@ static int serial_omap_runtime_suspend(struct device *dev)
  	if (pdata->get_context_loss_count)
  		up->context_loss_cnt = pdata->get_context_loss_count(dev);
 
+	/* Errata i291 */
+	if (up->use_dma&&  pdata->set_forceidle)
+		pdata->set_forceidle(up->pdev);
+

So it does appear that you are applying this to all devices. I think that this should only impact omap3.

drivers/tty/serial/omap-serial.c static int serial_omap_runtime_resume(struct device *dev) · line 1524

Quoted 11 lines
drivers/tty/serial/omap-serial.c +4 -0
  	return 0;
  }
 
@@ -1464,6 +1518,10 @@ static int serial_omap_runtime_resume(struct device *dev)
  			if (up->context_loss_cnt != loss_cnt)
  				serial_omap_restore_context(up);
  		}
+
+		/* Errata i291 */
+		if (up->use_dma&&  pdata->set_noidle)
+			pdata->set_noidle(up->pdev);

Same as above.

Cheers
Jon

#3 lore raw

PATCH v8 11/20 OMAP2+: UART: Move errata handling from serial.c to omap-serial

Quoted 1 line · Jon Hunter

Hi Govindraj,

[...]

Quoted 19 lines
Quoted 5 lines

? ? ? ?oh = uart->oh;
- ? ? ? uart->dma_enabled = 0;
? ? ? ?name = DRIVER_NAME;

Quoted 13 lines

? ? ? ?omap_up.dma_enabled = uart->dma_enabled;
? ? ? ?omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
? ? ? ?omap_up.flags = UPF_BOOT_AUTOCONF;
? ? ? ?omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
+ ? ? ? omap_up.set_forceidle = omap_uart_set_forceidle;
+ ? ? ? omap_up.set_noidle = omap_uart_set_noidle;
+
+ ? ? ? /* Enable the MDR1 errata for OMAP2/3/4 */
+ ? ? ? if ((cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())&&
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !cpu_is_ti816x())
+ ? ? ? ? ? ? ? omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;

Quoted 4 lines

I am not sure that this will apply the errata for OMAP3630 devices. I think we need cpu_is_omap36xx() above too. Or you may wish to do !cpu_class_is_omap1 and !cpu_is_omap2420.

Yes correct, I have updated this patch as here [1].

btw, omap-serial is applicable only for omap2+ so
I think cpu_class_is omap1 not applicable here
need to be handled in /mach-omap1/serial.c.

Quoted 14 lines
Quoted 14 lines

? ? ? ?pdata =&omap_up;
? ? ? ?pdata_size = sizeof(struct omap_uart_port_info);

(quoted diff) +0 -0
@@ -519,10 +481,6 @@ void __init omap_serial_init_port(struct
 omap_board_data *bdata)

? ? ? ?if (((cpu_is_omap34xx() || cpu_is_omap44xx())&& ?bdata->pads) || ? ? ? ? ? ? ? ?(pdata->wk_en&& ?pdata->wk_mask))
? ? ? ? ? ? ? ?device_init_wakeup(&pdev->dev, true);
-
- ? ? ? /* Enable the MDR1 errata for OMAP3 */
- ? ? ? if (cpu_is_omap34xx()&& ?!cpu_is_ti816x())
- ? ? ? ? ? ? ? uart->errata |= UART_ERRATA_i202_MDR1_ACCESS; ?}

?/**

[...]

Quoted 9 lines
Quoted 5 lines

+ ? ? ? /* Errata i291 */
+ ? ? ? if (up->use_dma&& ?pdata->set_forceidle)
+ ? ? ? ? ? ? ? pdata->set_forceidle(up->pdev);
+

So it does appear that you are applying this to all devices. I think that this should only impact omap3.

Yes correct, new one is has here [1].

--
Thanks,
Govindraj.R

[1]:

same is updated in here
(v8 uart runtime patches hosted in gitorious)
git://gitorious.org/runtime_3-0/runtime_3-0.git 3.2-rc1_uart_runtime.

Quoted 1 line

From e7ac07903a813f624c4a19d93131d40a09eb8f81 Mon Sep 17 00:00:00 2001

From: Govindraj.R <[email protected]>
Date: Mon, 7 Nov 2011 19:00:33 +0530
Subject: [PATCH v8 11/20] OMAP2+: UART: Move errata handling from serial.c to omap-serial

Move the errata handling mechanism from serial.c to omap-serial file and utilise the same func in driver file.

Errata i202, i291 are moved to be handled with omap-serial Moving the errata macro from serial.c file to driver header file as from on errata will be handled in driver file itself. Corrected errata id from chapter reference 2.15 to errata id i291.

Removed errata and dma_enabled fields from omap_uart_state struct as they are no more needed with errata handling done within omap-serial.

---
 arch/arm/mach-omap2/serial.c                  |  101 ++++++++-----------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    7 ++
 drivers/tty/serial/omap-serial.c              |   68 ++++++++++++++++-
 3 files changed, 102 insertions(+), 74 deletions(-)
arch/arm/mach-omap2/serial.c +0 -44
index 98e2666..9cbf230 100644
@@ -42,8 +42,6 @@
 #include "control.h"
 #include "mux.h"
 
-#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
@@ -61,59 +59,17 @@ struct omap_uart_state {
 	void __iomem *wk_st;
 	void __iomem *wk_en;
 	u32 wk_mask;
-	u32 dma_enabled;
 
 	int clocked;
 
 	struct list_head node;
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
-
-	u32 errata;
 };
 
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-#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);
-	}
-}
-
-#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-
 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 {
 	if (uart->clocked)
@@ -156,27 +112,6 @@ static void omap_uart_disable_wakeup(struct

omap_uart_state *uart)
}
}

-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);
@@ -267,7 +202,28 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
}
}

+/*
+ * Errata i291: [UART]:Cannot Acknowledge Idle Requests
+ * in Smartidle Mode When Configured for DMA Operations.
+ * WA: configure uart in force idle mode.
+ */
+static void omap_uart_set_noidle(struct platform_device *pdev) +{
+ struct omap_device *od = to_omap_device(pdev);
+
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
+}
+
+static void omap_uart_set_forceidle(struct platform_device *pdev) +{
+ struct omap_device *od = to_omap_device(pdev);
+
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+}
+
#else
+static void omap_uart_set_noidle(struct platform_device *pdev) {} +static void omap_uart_set_forceidle(struct platform_device *pdev) {}
static void omap_uart_block_sleep(struct omap_uart_state *uart) {
/* Needed to enable UART clocks when built without CONFIG_PM */
@@ -473,13 +429,22 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
break;

oh = uart->oh;
- uart->dma_enabled = 0;
name = DRIVER_NAME;

omap_up.dma_enabled = uart->dma_enabled;
omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
omap_up.flags = UPF_BOOT_AUTOCONF; omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
+ omap_up.set_forceidle = omap_uart_set_forceidle;
+ omap_up.set_noidle = omap_uart_set_noidle;
+
+ /* Enable the MDR1 Errata i202 for OMAP2430/3xxx/44xx */
+ if (!cpu_is_omap2420() && !cpu_is_ti816x())
+ omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;
+
+ /* Enable DMA Mode Force Idle Errata i291 for omap34xx/3630 */
+ if (cpu_is_omap34xx() || cpu_is_omap3630())
+ omap_up.errata |= UART_ERRATA_i291_DMA_FORCEIDLE;

pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info);
@@ -519,10 +484,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
(pdata->wk_en && pdata->wk_mask)) device_init_wakeup(&pdev->dev, true);
-
- /* Enable the MDR1 errata for OMAP3 */
- if (cpu_is_omap34xx() && !cpu_is_ti816x())
- uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
}

/**

(quoted diff) +0 -0

b/arch/arm/plat-omap/include/plat/omap-serial.h
index 348c9ea..842b429 100644

arch/arm/plat-omap/include/plat/omap-serial.h +7 -0
@@ -58,12 +58,18 @@
 
 #define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
 
+#define UART_ERRATA_i202_MDR1_ACCESS	BIT(0)
+#define UART_ERRATA_i291_DMA_FORCEIDLE	BIT(1)
+
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
 	upf_t			flags;		/* UPF_* flags */
+	u32			errata;
 
 	int (*get_context_loss_count)(struct device *);
+	void (*set_forceidle)(struct platform_device *);
+	void (*set_noidle)(struct platform_device *);
 };
 
 struct uart_omap_dma {
@@ -117,6 +123,7 @@ struct uart_omap_port {
 	char			name[20];
 	unsigned long		port_activity;
 	u32			context_loss_cnt;
+	u32			errata;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +1 -0
index ea4c24a..764ac77 100644
@@ -51,6 +51,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 serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
 
 static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
 {
@@ -808,7 +809,11 @@ serial_omap_set_termios(struct uart_port *port,

struct ktermios *termios,

/* Protocol, Baud Rate, and Interrupt Settings */

- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

up->efr = serial_in(up, UART_EFR);
@@ -833,7 +838,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
else
up->mdr1 = UART_OMAP_MDR1_16X_MODE;

- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);

/* Hardware Flow Control Configuration */

@@ -1362,6 +1370,7 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.flags = omap_up_info->flags;
up->port.uartclk = omap_up_info->uartclk; up->uart_dma.uart_base = mem->start;
+ up->errata = omap_up_info->errata;

if (omap_up_info->dma_enabled) {
up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1415,9 +1424,47 @@ static int serial_omap_remove(struct platform_device *dev)
return 0;
}

+/*
+ * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
+ * 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 serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) +{
+ u8 timeout = 255;
+
+ serial_out(up, UART_OMAP_MDR1, 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 serial_omap_restore_context(struct uart_omap_port *up) {
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+ else
+ serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, 0x0); /* Operational mode */
@@ -1434,7 +1481,10 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
serial_out(up, UART_OMAP_SCR, up->scr);
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, up->lcr);
- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
}

#ifdef CONFIG_PM_RUNTIME
@@ -1449,6 +1499,11 @@ static int serial_omap_runtime_suspend(struct device *dev)
if (pdata->get_context_loss_count)
up->context_loss_cnt = pdata->get_context_loss_count(dev);

+ /* Errata i291 */
+ if (up->use_dma && pdata->set_forceidle &&
+ (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
+ pdata->set_forceidle(up->pdev);
+
return 0;
}

@@ -1464,6 +1519,11 @@ static int serial_omap_runtime_resume(struct device *dev)
if (up->context_loss_cnt != loss_cnt)
serial_omap_restore_context(up);
}
+
+ /* Errata i291 */
+ if (up->use_dma && pdata->set_noidle &&
+ (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
+ pdata->set_noidle(up->pdev);
}

return 0;

Signature · 1 line
1.7.4.1
#4 lore raw

PATCH v8 11/20 OMAP2+: UART: Move errata handling from serial.c to omap-serial

Hi Govindraj,

Quoted 24 lines · Govindraj
Quoted 1 line · Jon Hunter

Hi Govindraj,

[...]

Quoted 19 lines
Quoted 18 lines
        oh = uart->oh;
-       uart->dma_enabled = 0;
        name = DRIVER_NAME;

        omap_up.dma_enabled = uart->dma_enabled;
        omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
        omap_up.flags = UPF_BOOT_AUTOCONF;
        omap_up.get_context_loss_count =

omap_pm_get_dev_context_loss_count;

(quoted diff) +5 -0
+       omap_up.set_forceidle = omap_uart_set_forceidle;
+       omap_up.set_noidle = omap_uart_set_noidle;
+
+       /* Enable the MDR1 errata for OMAP2/3/4 */
+       if ((cpu_is_omap2430() || cpu_is_omap34xx() ||

cpu_is_omap44xx())&&

(quoted diff) +2 -0
+                                               !cpu_is_ti816x())
+               omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;
Quoted 6 lines
Quoted 4 lines

I am not sure that this will apply the errata for OMAP3630 devices. I think we need cpu_is_omap36xx() above too. Or you may wish to do !cpu_class_is_omap1 and !cpu_is_omap2420.

Yes correct, I have updated this patch as here [1].

Thanks! Looks good.

Quoted 3 lines

btw, omap-serial is applicable only for omap2+ so
I think cpu_class_is omap1 not applicable here
need to be handled in /mach-omap1/serial.c.

Duh! I missed that. We are good then.

Cheers
Jon

#5 lore raw

PATCH v8 12/20 OMAP2+: UART: Add wakeup mechanism for omap-uarts

In reply to Govindraj.R
Quoted 1 line

From the runtime callbacks enable hwmod wakeups for uart which will

internally enable io-pad wakeups for uarts if they have rx-pad pins set as wakeup capabale.

Use the io-ring wakeup mechanism after uart clock gating and leave the PM_WKST set for uart to default reset values cleanup the code in serial.c which was handling PM_WKST reg. Irq_chaing(PRM_DRIVER) is used to wakeup uart after uart clocks are gated using pad wakeup mechanism.

---
 arch/arm/mach-omap2/serial.c                  |   96 +++---------------------
 arch/arm/plat-omap/include/plat/omap-serial.h |    2 +
 drivers/tty/serial/omap-serial.c              |   15 ++++
 3 files changed, 29 insertions(+), 84 deletions(-)
arch/arm/mach-omap2/serial.c +12 -84
index a52bd99..d1d8b88 100644
@@ -56,10 +56,6 @@ struct omap_uart_state {
 	int num;
 	int can_sleep;
 
-	void __iomem *wk_st;
-	void __iomem *wk_en;
-	u32 wk_mask;
-
 	int clocked;
 
 	struct list_head node;
@@ -92,26 +88,6 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
 	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);
-	}
-}
-
-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);
-	}
-}
-
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
 {
 	omap_uart_enable_clocks(uart);
@@ -141,65 +117,17 @@ int omap_uart_can_sleep(void)
 	return can_sleep;
 }
 
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
 {
-	int ret;
-
-	uart->can_sleep = 0;
-	omap_uart_smart_idle_enable(uart, 0);
+	struct omap_device *od = to_omap_device(pdev);
 
-	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
-		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
-		u32 wk_mask = 0;
+	if (!od)
+		return;
 
-		/* 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) {
-		case 0:
-			wk_mask = OMAP3430_ST_UART1_MASK;
-			break;
-		case 1:
-			wk_mask = OMAP3430_ST_UART2_MASK;
-			break;
-		case 2:
-			wk_mask = OMAP3430_ST_UART3_MASK;
-			break;
-		case 3:
-			wk_mask = OMAP3630_ST_UART4_MASK;
-			break;
-		}
-		uart->wk_mask = wk_mask;
-	} else if (cpu_is_omap24xx()) {
-		u32 wk_mask = 0;
-		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
-
-		switch (uart->num) {
-		case 0:
-			wk_mask = OMAP24XX_ST_UART1_MASK;
-			break;
-		case 1:
-			wk_mask = OMAP24XX_ST_UART2_MASK;
-			break;
-		case 2:
-			wk_en = OMAP24XX_PM_WKEN2;
-			wk_st = OMAP24XX_PM_WKST2;
-			wk_mask = OMAP24XX_ST_UART3_MASK;
-			break;
-		}
-		uart->wk_mask = wk_mask;
-		if (cpu_is_omap2430()) {
-			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
-			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
-		} else if (cpu_is_omap2420()) {
-			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
-			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
-		}
-	} else {
-		uart->wk_en = NULL;
-		uart->wk_st = NULL;
-		uart->wk_mask = 0;
-	}
+	if (enable)
+		omap_hwmod_enable_wakeup(od->hwmods[0]);
+	else
+		omap_hwmod_disable_wakeup(od->hwmods[0]);
 }
 
 /*
@@ -222,6 +150,8 @@ static void omap_uart_set_forceidle(struct platform_device *pdev)
 }
 
 #else
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+{}
 static void omap_uart_set_noidle(struct platform_device *pdev) {}
 static void omap_uart_set_forceidle(struct platform_device *pdev) {}
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -437,6 +367,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
 	omap_up.set_forceidle = omap_uart_set_forceidle;
 	omap_up.set_noidle = omap_uart_set_noidle;
+	omap_up.enable_wakeup = omap_uart_enable_wakeup;
 
 	/* Enable the MDR1 errata for OMAP2/3/4 */
 	if ((cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) &&
@@ -471,15 +402,12 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_hwmod_idle(uart->oh);
 
 	omap_device_enable(uart->pdev);
-	omap_uart_idle_init(uart);
-	omap_hwmod_enable_wakeup(uart->oh);
 	omap_device_idle(uart->pdev);
 
 	omap_uart_block_sleep(uart);
 	console_unlock();
 
-	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) ||
-		(pdata->wk_en && pdata->wk_mask))
+	if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
 		device_init_wakeup(&pdev->dev, true);
 }
 
arch/arm/plat-omap/include/plat/omap-serial.h +2 -0
index fd3d2f7..f3ecfb2 100644
@@ -69,6 +69,7 @@ struct omap_uart_port_info {
 	int (*get_context_loss_count)(struct device *);
 	void (*set_forceidle)(struct platform_device *);
 	void (*set_noidle)(struct platform_device *);
+	void (*enable_wakeup)(struct platform_device *, bool);
 };
 
 struct uart_omap_dma {
@@ -123,6 +124,7 @@ struct uart_omap_port {
 	unsigned long		port_activity;
 	u32			context_loss_cnt;
 	u32			errata;
+	u8			wakeups_enabled;
 };
 
 #endif /* __OMAP_SERIAL_H__ */
drivers/tty/serial/omap-serial.c +15 -0
index 77f0829..29cd401 100644
@@ -1496,9 +1496,24 @@ static int serial_omap_runtime_suspend(struct device *dev)
 	if (!up)
 		return -EINVAL;
 
+	if (!pdata->enable_wakeup)
+		return 0;
+
 	if (pdata->get_context_loss_count)
 		up->context_loss_cnt = pdata->get_context_loss_count(dev);
 
+	if (device_may_wakeup(dev)) {
+		if (!up->wakeups_enabled) {
+			pdata->enable_wakeup(up->pdev, true);
+			up->wakeups_enabled = true;
+		}
+	} else {
+		if (up->wakeups_enabled) {
+			pdata->enable_wakeup(up->pdev, false);
+			up->wakeups_enabled = false;
+		}
+	}
+
 	/* Errata i291 */
 	if (up->use_dma && pdata->set_forceidle)
 		pdata->set_forceidle(up->pdev);
Signature · 1 line
1.7.4.1
#6 lore raw

PATCH v8 13/20 OMAP2+: UART: Remove old and unused clocks handling funcs

In reply to Govindraj.R

With runtime adaptation done remove clock_enable/disbale API's

---
 arch/arm/mach-omap2/serial.c |   36 ------------------------------------
 1 files changed, 0 insertions(+), 36 deletions(-)
arch/arm/mach-omap2/serial.c +0 -36
index d1d8b88..6d574f0 100644
@@ -56,8 +56,6 @@ struct omap_uart_state {
 	int num;
 	int can_sleep;
 
-	int clocked;
-
 	struct list_head node;
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
@@ -66,36 +64,8 @@ struct omap_uart_state {
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-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_block_sleep(struct omap_uart_state *uart)
-{
-	omap_uart_enable_clocks(uart);
-
-	omap_uart_smart_idle_enable(uart, 0);
-	uart->can_sleep = 0;
-}
-
 int omap_uart_can_sleep(void)
 {
 	struct omap_uart_state *uart;
@@ -154,11 +124,6 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
 {}
 static void omap_uart_set_noidle(struct platform_device *pdev) {}
 static void omap_uart_set_forceidle(struct platform_device *pdev) {}
-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);
-}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
@@ -404,7 +369,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	omap_device_enable(uart->pdev);
 	omap_device_idle(uart->pdev);
 
-	omap_uart_block_sleep(uart);
 	console_unlock();
 
 	if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
Signature · 1 line
1.7.4.1