Re: [PATCH v5 09/15] OMAP2+: UART: Add runtime pm support for omap-serial driver

2011-09-22 Thread Ming Lei
Hi,

On Wed, Sep 21, 2011 at 8:13 PM, Govindraj.R govindraj.r...@ti.com wrote:
 Adapts omap-serial driver to use pm_runtime API's.

        console_unlock();

 -       if ((cpu_is_omap34xx()  bdata-pads) ||
 -               (pdata-wk_en  pdata-wk_mask))
 +       if ((cpu_is_omap34xx()  bdata-pads))
                device_init_wakeup(pdev-dev, true);

Just a bit curious, why doesn't the code enable wakeup at default
on omap4, which will disable runtime pm of serial port on omap4.

I have tested your patches on omap4 panda(enable wakeup at
default manually), runtime pm of serial port 2 can work well and
remote wakeup too.


        kfree(pdata);
 diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h 
 b/arch/arm/plat-omap/include/plat/omap-serial.h
 index 74822b3..8ef81ce 100644
 --- a/arch/arm/plat-omap/include/plat/omap-serial.h
 +++ b/arch/arm/plat-omap/include/plat/omap-serial.h
 @@ -62,6 +62,9 @@ struct omap_uart_port_info {
        upf_t                   flags;          /* UPF_* flags */

        u32                     errata;
 +
 +       void (*enable_wakeup)(struct platform_device *, bool);
 +       u32 (*get_context_loss_count)(struct device *);
  };

  struct uart_omap_dma {
 @@ -113,6 +116,8 @@ struct uart_omap_port {
        unsigned char           msr_saved_flags;
        char                    name[20];
        unsigned long           port_activity;
 +       u32                     context_loss_cnt;
 +       u8                      wakeups_enabled;
  };

  #endif /* __OMAP_SERIAL_H__ */
 diff --git a/drivers/tty/serial/omap-serial.c 
 b/drivers/tty/serial/omap-serial.c
 index 9a0eac2..43c33da 100644
 --- a/drivers/tty/serial/omap-serial.c
 +++ b/drivers/tty/serial/omap-serial.c
 @@ -37,11 +37,14 @@
  #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

 +#define OMAP_UART_AUTOSUSPEND_DELAY -1
 +
  static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];

  /* Forward declaration of functions */
 @@ -102,6 +105,8 @@ static void serial_omap_stop_rxdma(struct uart_omap_port 
 *up)
                omap_free_dma(up-uart_dma.rx_dma_channel);
                up-uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
                up-uart_dma.rx_dma_used = false;
 +               pm_runtime_mark_last_busy(up-pdev-dev);
 +               pm_runtime_put_autosuspend(up-pdev-dev);
        }
  }

 @@ -110,8 +115,11 @@ static void serial_omap_enable_ms(struct uart_port *port)
        struct uart_omap_port *up = (struct uart_omap_port *)port;

        dev_dbg(up-port.dev, serial_omap_enable_ms+%d\n, up-pdev-id);
 +
 +       pm_runtime_get_sync(up-pdev-dev);
        up-ier |= UART_IER_MSI;
        serial_out(up, UART_IER, up-ier);
 +       pm_runtime_put(up-pdev-dev);
  }

  static void serial_omap_stop_tx(struct uart_port *port)
 @@ -129,23 +137,32 @@ static void serial_omap_stop_tx(struct uart_port *port)
                omap_stop_dma(up-uart_dma.tx_dma_channel);
                omap_free_dma(up-uart_dma.tx_dma_channel);
                up-uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
 +               pm_runtime_mark_last_busy(up-pdev-dev);
 +               pm_runtime_put_autosuspend(up-pdev-dev);
        }

 +       pm_runtime_get_sync(up-pdev-dev);
        if (up-ier  UART_IER_THRI) {
                up-ier = ~UART_IER_THRI;
                serial_out(up, UART_IER, up-ier);
        }
 +
 +       pm_runtime_mark_last_busy(up-pdev-dev);
 +       pm_runtime_put_autosuspend(up-pdev-dev);
  }

  static void serial_omap_stop_rx(struct uart_port *port)
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;

 +       pm_runtime_get_sync(up-pdev-dev);
        if (up-use_dma)
                serial_omap_stop_rxdma(up);
        up-ier = ~UART_IER_RLSI;
        up-port.read_status_mask = ~UART_LSR_DR;
        serial_out(up, UART_IER, up-ier);
 +       pm_runtime_mark_last_busy(up-pdev-dev);
 +       pm_runtime_put_autosuspend(up-pdev-dev);
  }

  static inline void receive_chars(struct uart_omap_port *up, int *status)
 @@ -262,7 +279,10 @@ static void serial_omap_start_tx(struct uart_port *port)
        int ret = 0;

        if (!up-use_dma) {
 +               pm_runtime_get_sync(up-pdev-dev);
                serial_omap_enable_ier_thri(up);
 +               pm_runtime_mark_last_busy(up-pdev-dev);
 +               pm_runtime_put_autosuspend(up-pdev-dev);
                return;
        }

 @@ -272,6 +292,7 @@ static void serial_omap_start_tx(struct uart_port *port)
        xmit = up-port.state-xmit;

        if (up-uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
 +               pm_runtime_get_sync(up-pdev-dev);
                ret = omap_request_dma(up-uart_dma.uart_dma_tx,
                                UART Tx DMA,
                                (void *)uart_tx_dma_callback, up,
 @@ -354,9 +375,13 @@ static inline irqreturn_t serial_omap_irq(int irq, void 
 

Re: [PATCH v5 09/15] OMAP2+: UART: Add runtime pm support for omap-serial driver

2011-09-22 Thread Govindraj
On Thu, Sep 22, 2011 at 1:18 PM, Ming Lei tom.leim...@gmail.com wrote:
 Hi,

 On Wed, Sep 21, 2011 at 8:13 PM, Govindraj.R govindraj.r...@ti.com wrote:
 Adapts omap-serial driver to use pm_runtime API's.

        console_unlock();

 -       if ((cpu_is_omap34xx()  bdata-pads) ||
 -               (pdata-wk_en  pdata-wk_mask))
 +       if ((cpu_is_omap34xx()  bdata-pads))
                device_init_wakeup(pdev-dev, true);

 Just a bit curious, why doesn't the code enable wakeup at default
 on omap4, which will disable runtime pm of serial port on omap4.


yes sure will add for omap4.


 I have tested your patches on omap4 panda(enable wakeup at
 default manually), runtime pm of serial port 2 can work well and
 remote wakeup too.


Thanks, for testing.

--
Govindraj.R
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 09/15] OMAP2+: UART: Add runtime pm support for omap-serial driver

2011-09-21 Thread Govindraj.R
Adapts omap-serial driver to use pm_runtime API's.

Use runtime runtime API's to handle uart clocks and obtain
device_usage statics. Set runtime API's usage to irq_safe so that
we can use get_sync from irq context. Auto-suspend for port specific
activities and put for reg access. Use device_may_wakeup to check
whether uart has wakeup capabilities and then enable uart runtime
usage for the uart.

Removing save_context/restore_context functions from serial.c
Adding context restore to .runtime_suspend and using reg values from port
structure to restore the uart port context based on context_loss_count.
Maintain internal state machine using wakeups_enabled field for avoiding
repeated enable/disable of uart port wakeup mechanism.

Remove omap_uart_disable_wakeup and modify omap_uart_enable_wakeup
to accept pdev and bool value to enable/disable the uart wakeup mechanism
after uart clock's are cut. omap_hwmod_enable_wakeup is used to set
pad wakeup for the uarts. PM_WKEN reg values are left to default.
Removed omap_uart_enable/disable_clocks in serial.c now clock handling
done with runtime API's.

By default uart autosuspend delay is set to -1 to avoid character loss
if uart's are autoidled and woken up on rx pin.

After boot up UART's can be autoidled by setting autosuspendi delay from sysfs.

echo 3000  /sys/devices/platform/omap/omap_uart.X/power/autosuspend_delay_ms
X=0,1,2,3 for UART1/2/3/4. Number of uarts available may vary across omap_soc.

Acked-by: Alan Cox a...@linux.intel.com
Signed-off-by: Govindraj.R govindraj.r...@ti.com
---
 arch/arm/mach-omap2/serial.c  |  206 ++--
 arch/arm/plat-omap/include/plat/omap-serial.h |5 +
 drivers/tty/serial/omap-serial.c  |  169 +++--
 3 files changed, 179 insertions(+), 201 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1561140..43d8f0d 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -32,6 +32,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
@@ -40,8 +41,6 @@
 #include control.h
 #include mux.h
 
-#define UART_OMAP_WER  0x17/* Wake-up enable register */
-
 #define UART_ERRATA_i202_MDR1_ACCESS   (0x1  1)
 
 /*
@@ -56,24 +55,7 @@
 
 struct omap_uart_state {
int num;
-   int can_sleep;
u32 dma_enabled;
-
-   int clocked;
-
-   int regshift;
-#if defined(CONFIG_ARCH_OMAP3)  defined(CONFIG_PM)
-   int context_valid;
-
-   /* Registers to be saved/restored for OFF-mode */
-   u16 dll;
-   u16 dlh;
-   u16 ier;
-   u16 sysc;
-   u16 scr;
-   u16 wer;
-   u16 mcr;
-#endif
 };
 
 static u8 num_uarts;
@@ -100,34 +82,6 @@ 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);
-}
-
 #if defined(CONFIG_PM)
 
 /*
@@ -164,134 +118,8 @@ static void omap_uart_mdr1_errataset(struct 
omap_uart_state *uart, u8 mdr1_val,
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;
-
-