diff options
author | Govindraj.R <govindraj.raja@ti.com> | 2011-02-28 07:42:23 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-12-14 19:05:20 -0500 |
commit | fcdca75728ac376f3de74376c791e1078ee83820 (patch) | |
tree | 505fdb659fc4c54887128ca7c49d7eeba6cf3ab2 /drivers | |
parent | edd70ad757e9b336116433e6e62de79ae1dfef54 (diff) |
ARM: OMAP2+: UART: Add runtime pm support for omap-serial driver
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. Moving suspend/resume hooks
to dev_pm_ops structure and bind with config_suspend to avoid any
compilation warning if config_suspend is disabled.
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 autosuspend 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.
Also if uart is not wakeup capable we can prevent runtime autosuspend by
forbiding runtime.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
Acked-by: Alan Cox <alan@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 122 |
1 files changed, 109 insertions, 13 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 31f0cbf73c18..f16ef4b9363d 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -37,11 +37,14 @@ | |||
37 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
38 | #include <linux/serial_core.h> | 38 | #include <linux/serial_core.h> |
39 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/pm_runtime.h> | ||
40 | 41 | ||
41 | #include <plat/dma.h> | 42 | #include <plat/dma.h> |
42 | #include <plat/dmtimer.h> | 43 | #include <plat/dmtimer.h> |
43 | #include <plat/omap-serial.h> | 44 | #include <plat/omap-serial.h> |
44 | 45 | ||
46 | #define OMAP_UART_AUTOSUSPEND_DELAY -1 | ||
47 | |||
45 | static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; | 48 | static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; |
46 | 49 | ||
47 | /* Forward declaration of functions */ | 50 | /* Forward declaration of functions */ |
@@ -102,6 +105,8 @@ static void serial_omap_stop_rxdma(struct uart_omap_port *up) | |||
102 | omap_free_dma(up->uart_dma.rx_dma_channel); | 105 | omap_free_dma(up->uart_dma.rx_dma_channel); |
103 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | 106 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; |
104 | up->uart_dma.rx_dma_used = false; | 107 | up->uart_dma.rx_dma_used = false; |
108 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
109 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
105 | } | 110 | } |
106 | } | 111 | } |
107 | 112 | ||
@@ -110,8 +115,11 @@ static void serial_omap_enable_ms(struct uart_port *port) | |||
110 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 115 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
111 | 116 | ||
112 | dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id); | 117 | dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id); |
118 | |||
119 | pm_runtime_get_sync(&up->pdev->dev); | ||
113 | up->ier |= UART_IER_MSI; | 120 | up->ier |= UART_IER_MSI; |
114 | serial_out(up, UART_IER, up->ier); | 121 | serial_out(up, UART_IER, up->ier); |
122 | pm_runtime_put(&up->pdev->dev); | ||
115 | } | 123 | } |
116 | 124 | ||
117 | static void serial_omap_stop_tx(struct uart_port *port) | 125 | static void serial_omap_stop_tx(struct uart_port *port) |
@@ -129,23 +137,32 @@ static void serial_omap_stop_tx(struct uart_port *port) | |||
129 | omap_stop_dma(up->uart_dma.tx_dma_channel); | 137 | omap_stop_dma(up->uart_dma.tx_dma_channel); |
130 | omap_free_dma(up->uart_dma.tx_dma_channel); | 138 | omap_free_dma(up->uart_dma.tx_dma_channel); |
131 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; | 139 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; |
140 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
141 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
132 | } | 142 | } |
133 | 143 | ||
144 | pm_runtime_get_sync(&up->pdev->dev); | ||
134 | if (up->ier & UART_IER_THRI) { | 145 | if (up->ier & UART_IER_THRI) { |
135 | up->ier &= ~UART_IER_THRI; | 146 | up->ier &= ~UART_IER_THRI; |
136 | serial_out(up, UART_IER, up->ier); | 147 | serial_out(up, UART_IER, up->ier); |
137 | } | 148 | } |
149 | |||
150 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
151 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
138 | } | 152 | } |
139 | 153 | ||
140 | static void serial_omap_stop_rx(struct uart_port *port) | 154 | static void serial_omap_stop_rx(struct uart_port *port) |
141 | { | 155 | { |
142 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 156 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
143 | 157 | ||
158 | pm_runtime_get_sync(&up->pdev->dev); | ||
144 | if (up->use_dma) | 159 | if (up->use_dma) |
145 | serial_omap_stop_rxdma(up); | 160 | serial_omap_stop_rxdma(up); |
146 | up->ier &= ~UART_IER_RLSI; | 161 | up->ier &= ~UART_IER_RLSI; |
147 | up->port.read_status_mask &= ~UART_LSR_DR; | 162 | up->port.read_status_mask &= ~UART_LSR_DR; |
148 | serial_out(up, UART_IER, up->ier); | 163 | serial_out(up, UART_IER, up->ier); |
164 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
165 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
149 | } | 166 | } |
150 | 167 | ||
151 | static inline void receive_chars(struct uart_omap_port *up, int *status) | 168 | 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) | |||
262 | int ret = 0; | 279 | int ret = 0; |
263 | 280 | ||
264 | if (!up->use_dma) { | 281 | if (!up->use_dma) { |
282 | pm_runtime_get_sync(&up->pdev->dev); | ||
265 | serial_omap_enable_ier_thri(up); | 283 | serial_omap_enable_ier_thri(up); |
284 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
285 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
266 | return; | 286 | return; |
267 | } | 287 | } |
268 | 288 | ||
@@ -272,6 +292,7 @@ static void serial_omap_start_tx(struct uart_port *port) | |||
272 | xmit = &up->port.state->xmit; | 292 | xmit = &up->port.state->xmit; |
273 | 293 | ||
274 | if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { | 294 | if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { |
295 | pm_runtime_get_sync(&up->pdev->dev); | ||
275 | ret = omap_request_dma(up->uart_dma.uart_dma_tx, | 296 | ret = omap_request_dma(up->uart_dma.uart_dma_tx, |
276 | "UART Tx DMA", | 297 | "UART Tx DMA", |
277 | (void *)uart_tx_dma_callback, up, | 298 | (void *)uart_tx_dma_callback, up, |
@@ -354,9 +375,13 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) | |||
354 | unsigned int iir, lsr; | 375 | unsigned int iir, lsr; |
355 | unsigned long flags; | 376 | unsigned long flags; |
356 | 377 | ||
378 | pm_runtime_get_sync(&up->pdev->dev); | ||
357 | iir = serial_in(up, UART_IIR); | 379 | iir = serial_in(up, UART_IIR); |
358 | if (iir & UART_IIR_NO_INT) | 380 | if (iir & UART_IIR_NO_INT) { |
381 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
382 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
359 | return IRQ_NONE; | 383 | return IRQ_NONE; |
384 | } | ||
360 | 385 | ||
361 | spin_lock_irqsave(&up->port.lock, flags); | 386 | spin_lock_irqsave(&up->port.lock, flags); |
362 | lsr = serial_in(up, UART_LSR); | 387 | lsr = serial_in(up, UART_LSR); |
@@ -378,6 +403,9 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) | |||
378 | transmit_chars(up); | 403 | transmit_chars(up); |
379 | 404 | ||
380 | spin_unlock_irqrestore(&up->port.lock, flags); | 405 | spin_unlock_irqrestore(&up->port.lock, flags); |
406 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
407 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
408 | |||
381 | up->port_activity = jiffies; | 409 | up->port_activity = jiffies; |
382 | return IRQ_HANDLED; | 410 | return IRQ_HANDLED; |
383 | } | 411 | } |
@@ -388,11 +416,12 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) | |||
388 | unsigned long flags = 0; | 416 | unsigned long flags = 0; |
389 | unsigned int ret = 0; | 417 | unsigned int ret = 0; |
390 | 418 | ||
419 | pm_runtime_get_sync(&up->pdev->dev); | ||
391 | dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id); | 420 | dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id); |
392 | spin_lock_irqsave(&up->port.lock, flags); | 421 | spin_lock_irqsave(&up->port.lock, flags); |
393 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | 422 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; |
394 | spin_unlock_irqrestore(&up->port.lock, flags); | 423 | spin_unlock_irqrestore(&up->port.lock, flags); |
395 | 424 | pm_runtime_put(&up->pdev->dev); | |
396 | return ret; | 425 | return ret; |
397 | } | 426 | } |
398 | 427 | ||
@@ -402,7 +431,10 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) | |||
402 | unsigned char status; | 431 | unsigned char status; |
403 | unsigned int ret = 0; | 432 | unsigned int ret = 0; |
404 | 433 | ||
434 | pm_runtime_get_sync(&up->pdev->dev); | ||
405 | status = check_modem_status(up); | 435 | status = check_modem_status(up); |
436 | pm_runtime_put(&up->pdev->dev); | ||
437 | |||
406 | dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id); | 438 | dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id); |
407 | 439 | ||
408 | if (status & UART_MSR_DCD) | 440 | if (status & UART_MSR_DCD) |
@@ -433,8 +465,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
433 | if (mctrl & TIOCM_LOOP) | 465 | if (mctrl & TIOCM_LOOP) |
434 | mcr |= UART_MCR_LOOP; | 466 | mcr |= UART_MCR_LOOP; |
435 | 467 | ||
468 | pm_runtime_get_sync(&up->pdev->dev); | ||
436 | mcr |= up->mcr; | 469 | mcr |= up->mcr; |
437 | serial_out(up, UART_MCR, mcr); | 470 | serial_out(up, UART_MCR, mcr); |
471 | pm_runtime_put(&up->pdev->dev); | ||
438 | } | 472 | } |
439 | 473 | ||
440 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) | 474 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) |
@@ -443,6 +477,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) | |||
443 | unsigned long flags = 0; | 477 | unsigned long flags = 0; |
444 | 478 | ||
445 | dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id); | 479 | dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id); |
480 | pm_runtime_get_sync(&up->pdev->dev); | ||
446 | spin_lock_irqsave(&up->port.lock, flags); | 481 | spin_lock_irqsave(&up->port.lock, flags); |
447 | if (break_state == -1) | 482 | if (break_state == -1) |
448 | up->lcr |= UART_LCR_SBC; | 483 | up->lcr |= UART_LCR_SBC; |
@@ -450,6 +485,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) | |||
450 | up->lcr &= ~UART_LCR_SBC; | 485 | up->lcr &= ~UART_LCR_SBC; |
451 | serial_out(up, UART_LCR, up->lcr); | 486 | serial_out(up, UART_LCR, up->lcr); |
452 | spin_unlock_irqrestore(&up->port.lock, flags); | 487 | spin_unlock_irqrestore(&up->port.lock, flags); |
488 | pm_runtime_put(&up->pdev->dev); | ||
453 | } | 489 | } |
454 | 490 | ||
455 | static int serial_omap_startup(struct uart_port *port) | 491 | static int serial_omap_startup(struct uart_port *port) |
@@ -468,6 +504,7 @@ static int serial_omap_startup(struct uart_port *port) | |||
468 | 504 | ||
469 | dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id); | 505 | dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id); |
470 | 506 | ||
507 | pm_runtime_get_sync(&up->pdev->dev); | ||
471 | /* | 508 | /* |
472 | * Clear the FIFO buffers and disable them. | 509 | * Clear the FIFO buffers and disable them. |
473 | * (they will be reenabled in set_termios()) | 510 | * (they will be reenabled in set_termios()) |
@@ -523,6 +560,8 @@ static int serial_omap_startup(struct uart_port *port) | |||
523 | /* Enable module level wake up */ | 560 | /* Enable module level wake up */ |
524 | serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); | 561 | serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); |
525 | 562 | ||
563 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
564 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
526 | up->port_activity = jiffies; | 565 | up->port_activity = jiffies; |
527 | return 0; | 566 | return 0; |
528 | } | 567 | } |
@@ -533,6 +572,8 @@ static void serial_omap_shutdown(struct uart_port *port) | |||
533 | unsigned long flags = 0; | 572 | unsigned long flags = 0; |
534 | 573 | ||
535 | dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id); | 574 | dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id); |
575 | |||
576 | pm_runtime_get_sync(&up->pdev->dev); | ||
536 | /* | 577 | /* |
537 | * Disable interrupts from this port | 578 | * Disable interrupts from this port |
538 | */ | 579 | */ |
@@ -566,6 +607,8 @@ static void serial_omap_shutdown(struct uart_port *port) | |||
566 | up->uart_dma.rx_buf_dma_phys); | 607 | up->uart_dma.rx_buf_dma_phys); |
567 | up->uart_dma.rx_buf = NULL; | 608 | up->uart_dma.rx_buf = NULL; |
568 | } | 609 | } |
610 | |||
611 | pm_runtime_put(&up->pdev->dev); | ||
569 | free_irq(up->port.irq, up); | 612 | free_irq(up->port.irq, up); |
570 | } | 613 | } |
571 | 614 | ||
@@ -680,6 +723,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
680 | * Ok, we're now changing the port state. Do it with | 723 | * Ok, we're now changing the port state. Do it with |
681 | * interrupts disabled. | 724 | * interrupts disabled. |
682 | */ | 725 | */ |
726 | pm_runtime_get_sync(&up->pdev->dev); | ||
683 | spin_lock_irqsave(&up->port.lock, flags); | 727 | spin_lock_irqsave(&up->port.lock, flags); |
684 | 728 | ||
685 | /* | 729 | /* |
@@ -809,6 +853,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
809 | serial_omap_configure_xonxoff(up, termios); | 853 | serial_omap_configure_xonxoff(up, termios); |
810 | 854 | ||
811 | spin_unlock_irqrestore(&up->port.lock, flags); | 855 | spin_unlock_irqrestore(&up->port.lock, flags); |
856 | pm_runtime_put(&up->pdev->dev); | ||
812 | dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); | 857 | dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); |
813 | } | 858 | } |
814 | 859 | ||
@@ -820,6 +865,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state, | |||
820 | unsigned char efr; | 865 | unsigned char efr; |
821 | 866 | ||
822 | dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id); | 867 | dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id); |
868 | |||
869 | pm_runtime_get_sync(&up->pdev->dev); | ||
823 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 870 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
824 | efr = serial_in(up, UART_EFR); | 871 | efr = serial_in(up, UART_EFR); |
825 | serial_out(up, UART_EFR, efr | UART_EFR_ECB); | 872 | serial_out(up, UART_EFR, efr | UART_EFR_ECB); |
@@ -829,6 +876,15 @@ serial_omap_pm(struct uart_port *port, unsigned int state, | |||
829 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 876 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
830 | serial_out(up, UART_EFR, efr); | 877 | serial_out(up, UART_EFR, efr); |
831 | serial_out(up, UART_LCR, 0); | 878 | serial_out(up, UART_LCR, 0); |
879 | |||
880 | if (!device_may_wakeup(&up->pdev->dev)) { | ||
881 | if (!state) | ||
882 | pm_runtime_forbid(&up->pdev->dev); | ||
883 | else | ||
884 | pm_runtime_allow(&up->pdev->dev); | ||
885 | } | ||
886 | |||
887 | pm_runtime_put(&up->pdev->dev); | ||
832 | } | 888 | } |
833 | 889 | ||
834 | static void serial_omap_release_port(struct uart_port *port) | 890 | static void serial_omap_release_port(struct uart_port *port) |
@@ -906,19 +962,26 @@ static inline void wait_for_xmitr(struct uart_omap_port *up) | |||
906 | static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) | 962 | static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) |
907 | { | 963 | { |
908 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 964 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
965 | |||
966 | pm_runtime_get_sync(&up->pdev->dev); | ||
909 | wait_for_xmitr(up); | 967 | wait_for_xmitr(up); |
910 | serial_out(up, UART_TX, ch); | 968 | serial_out(up, UART_TX, ch); |
969 | pm_runtime_put(&up->pdev->dev); | ||
911 | } | 970 | } |
912 | 971 | ||
913 | static int serial_omap_poll_get_char(struct uart_port *port) | 972 | static int serial_omap_poll_get_char(struct uart_port *port) |
914 | { | 973 | { |
915 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 974 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
916 | unsigned int status = serial_in(up, UART_LSR); | 975 | unsigned int status; |
917 | 976 | ||
977 | pm_runtime_get_sync(&up->pdev->dev); | ||
978 | status = serial_in(up, UART_LSR); | ||
918 | if (!(status & UART_LSR_DR)) | 979 | if (!(status & UART_LSR_DR)) |
919 | return NO_POLL_CHAR; | 980 | return NO_POLL_CHAR; |
920 | 981 | ||
921 | return serial_in(up, UART_RX); | 982 | status = serial_in(up, UART_RX); |
983 | pm_runtime_put(&up->pdev->dev); | ||
984 | return status; | ||
922 | } | 985 | } |
923 | 986 | ||
924 | #endif /* CONFIG_CONSOLE_POLL */ | 987 | #endif /* CONFIG_CONSOLE_POLL */ |
@@ -946,6 +1009,8 @@ serial_omap_console_write(struct console *co, const char *s, | |||
946 | unsigned int ier; | 1009 | unsigned int ier; |
947 | int locked = 1; | 1010 | int locked = 1; |
948 | 1011 | ||
1012 | pm_runtime_get_sync(&up->pdev->dev); | ||
1013 | |||
949 | local_irq_save(flags); | 1014 | local_irq_save(flags); |
950 | if (up->port.sysrq) | 1015 | if (up->port.sysrq) |
951 | locked = 0; | 1016 | locked = 0; |
@@ -978,6 +1043,8 @@ serial_omap_console_write(struct console *co, const char *s, | |||
978 | if (up->msr_saved_flags) | 1043 | if (up->msr_saved_flags) |
979 | check_modem_status(up); | 1044 | check_modem_status(up); |
980 | 1045 | ||
1046 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
1047 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
981 | if (locked) | 1048 | if (locked) |
982 | spin_unlock(&up->port.lock); | 1049 | spin_unlock(&up->port.lock); |
983 | local_irq_restore(flags); | 1050 | local_irq_restore(flags); |
@@ -1060,24 +1127,25 @@ static struct uart_driver serial_omap_reg = { | |||
1060 | .cons = OMAP_CONSOLE, | 1127 | .cons = OMAP_CONSOLE, |
1061 | }; | 1128 | }; |
1062 | 1129 | ||
1063 | static int | 1130 | #ifdef CONFIG_SUSPEND |
1064 | serial_omap_suspend(struct platform_device *pdev, pm_message_t state) | 1131 | static int serial_omap_suspend(struct device *dev) |
1065 | { | 1132 | { |
1066 | struct uart_omap_port *up = platform_get_drvdata(pdev); | 1133 | struct uart_omap_port *up = dev_get_drvdata(dev); |
1067 | 1134 | ||
1068 | if (up) | 1135 | if (up) |
1069 | uart_suspend_port(&serial_omap_reg, &up->port); | 1136 | uart_suspend_port(&serial_omap_reg, &up->port); |
1070 | return 0; | 1137 | return 0; |
1071 | } | 1138 | } |
1072 | 1139 | ||
1073 | static int serial_omap_resume(struct platform_device *dev) | 1140 | static int serial_omap_resume(struct device *dev) |
1074 | { | 1141 | { |
1075 | struct uart_omap_port *up = platform_get_drvdata(dev); | 1142 | struct uart_omap_port *up = dev_get_drvdata(dev); |
1076 | 1143 | ||
1077 | if (up) | 1144 | if (up) |
1078 | uart_resume_port(&serial_omap_reg, &up->port); | 1145 | uart_resume_port(&serial_omap_reg, &up->port); |
1079 | return 0; | 1146 | return 0; |
1080 | } | 1147 | } |
1148 | #endif | ||
1081 | 1149 | ||
1082 | static void serial_omap_rx_timeout(unsigned long uart_no) | 1150 | static void serial_omap_rx_timeout(unsigned long uart_no) |
1083 | { | 1151 | { |
@@ -1135,6 +1203,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up) | |||
1135 | int ret = 0; | 1203 | int ret = 0; |
1136 | 1204 | ||
1137 | if (up->uart_dma.rx_dma_channel == -1) { | 1205 | if (up->uart_dma.rx_dma_channel == -1) { |
1206 | pm_runtime_get_sync(&up->pdev->dev); | ||
1138 | ret = omap_request_dma(up->uart_dma.uart_dma_rx, | 1207 | ret = omap_request_dma(up->uart_dma.uart_dma_rx, |
1139 | "UART Rx DMA", | 1208 | "UART Rx DMA", |
1140 | (void *)uart_rx_dma_callback, up, | 1209 | (void *)uart_rx_dma_callback, up, |
@@ -1299,6 +1368,14 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1299 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | 1368 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; |
1300 | } | 1369 | } |
1301 | 1370 | ||
1371 | pm_runtime_use_autosuspend(&pdev->dev); | ||
1372 | pm_runtime_set_autosuspend_delay(&pdev->dev, | ||
1373 | OMAP_UART_AUTOSUSPEND_DELAY); | ||
1374 | |||
1375 | pm_runtime_irq_safe(&pdev->dev); | ||
1376 | pm_runtime_enable(&pdev->dev); | ||
1377 | pm_runtime_get_sync(&pdev->dev); | ||
1378 | |||
1302 | ui[pdev->id] = up; | 1379 | ui[pdev->id] = up; |
1303 | serial_omap_add_console_port(up); | 1380 | serial_omap_add_console_port(up); |
1304 | 1381 | ||
@@ -1306,6 +1383,7 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1306 | if (ret != 0) | 1383 | if (ret != 0) |
1307 | goto do_release_region; | 1384 | goto do_release_region; |
1308 | 1385 | ||
1386 | pm_runtime_put(&pdev->dev); | ||
1309 | platform_set_drvdata(pdev, up); | 1387 | platform_set_drvdata(pdev, up); |
1310 | return 0; | 1388 | return 0; |
1311 | err: | 1389 | err: |
@@ -1320,22 +1398,40 @@ static int serial_omap_remove(struct platform_device *dev) | |||
1320 | { | 1398 | { |
1321 | struct uart_omap_port *up = platform_get_drvdata(dev); | 1399 | struct uart_omap_port *up = platform_get_drvdata(dev); |
1322 | 1400 | ||
1323 | platform_set_drvdata(dev, NULL); | ||
1324 | if (up) { | 1401 | if (up) { |
1402 | pm_runtime_disable(&up->pdev->dev); | ||
1325 | uart_remove_one_port(&serial_omap_reg, &up->port); | 1403 | uart_remove_one_port(&serial_omap_reg, &up->port); |
1326 | kfree(up); | 1404 | kfree(up); |
1327 | } | 1405 | } |
1406 | |||
1407 | platform_set_drvdata(dev, NULL); | ||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1411 | #ifdef CONFIG_PM_RUNTIME | ||
1412 | static int serial_omap_runtime_suspend(struct device *dev) | ||
1413 | { | ||
1328 | return 0; | 1414 | return 0; |
1329 | } | 1415 | } |
1330 | 1416 | ||
1417 | static int serial_omap_runtime_resume(struct device *dev) | ||
1418 | { | ||
1419 | return 0; | ||
1420 | } | ||
1421 | #endif | ||
1422 | |||
1423 | static const struct dev_pm_ops serial_omap_dev_pm_ops = { | ||
1424 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) | ||
1425 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, | ||
1426 | serial_omap_runtime_resume, NULL) | ||
1427 | }; | ||
1428 | |||
1331 | static struct platform_driver serial_omap_driver = { | 1429 | static struct platform_driver serial_omap_driver = { |
1332 | .probe = serial_omap_probe, | 1430 | .probe = serial_omap_probe, |
1333 | .remove = serial_omap_remove, | 1431 | .remove = serial_omap_remove, |
1334 | |||
1335 | .suspend = serial_omap_suspend, | ||
1336 | .resume = serial_omap_resume, | ||
1337 | .driver = { | 1432 | .driver = { |
1338 | .name = DRIVER_NAME, | 1433 | .name = DRIVER_NAME, |
1434 | .pm = &serial_omap_dev_pm_ops, | ||
1339 | }, | 1435 | }, |
1340 | }; | 1436 | }; |
1341 | 1437 | ||