diff options
| author | Magnus Damm <damm@opensource.se> | 2011-08-02 23:47:36 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2011-08-03 02:07:44 -0400 |
| commit | 1ba762209491e2496e58baffa3fd65d661f54404 (patch) | |
| tree | 9950463aa989a0b53ebbc7ad0f5d1276ca41cd2b | |
| parent | c84b51e65ea2f256353c339bd87e991b7e64630f (diff) | |
serial: sh-sci: console Runtime PM support
Add Runtime PM context save/restore support to
the SCIF driver. Tested on the AP4EVB console.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
| -rw-r--r-- | drivers/tty/serial/sh-sci.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 38a81ae9b7df..ffcaceee0215 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
| @@ -96,6 +96,12 @@ struct sci_port { | |||
| 96 | #endif | 96 | #endif |
| 97 | 97 | ||
| 98 | struct notifier_block freq_transition; | 98 | struct notifier_block freq_transition; |
| 99 | |||
| 100 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | ||
| 101 | unsigned short saved_smr; | ||
| 102 | unsigned short saved_fcr; | ||
| 103 | unsigned char saved_brr; | ||
| 104 | #endif | ||
| 99 | }; | 105 | }; |
| 100 | 106 | ||
| 101 | /* Function prototypes */ | 107 | /* Function prototypes */ |
| @@ -1634,11 +1640,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | |||
| 1634 | return ((freq + 16 * bps) / (32 * bps) - 1); | 1640 | return ((freq + 16 * bps) / (32 * bps) - 1); |
| 1635 | } | 1641 | } |
| 1636 | 1642 | ||
| 1643 | static void sci_reset(struct uart_port *port) | ||
| 1644 | { | ||
| 1645 | unsigned int status; | ||
| 1646 | |||
| 1647 | do { | ||
| 1648 | status = sci_in(port, SCxSR); | ||
| 1649 | } while (!(status & SCxSR_TEND(port))); | ||
| 1650 | |||
| 1651 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | ||
| 1652 | |||
| 1653 | if (port->type != PORT_SCI) | ||
| 1654 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | ||
| 1655 | } | ||
| 1656 | |||
| 1637 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1657 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| 1638 | struct ktermios *old) | 1658 | struct ktermios *old) |
| 1639 | { | 1659 | { |
| 1640 | struct sci_port *s = to_sci_port(port); | 1660 | struct sci_port *s = to_sci_port(port); |
| 1641 | unsigned int status, baud, smr_val, max_baud; | 1661 | unsigned int baud, smr_val, max_baud; |
| 1642 | int t = -1; | 1662 | int t = -1; |
| 1643 | u16 scfcr = 0; | 1663 | u16 scfcr = 0; |
| 1644 | 1664 | ||
| @@ -1658,14 +1678,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1658 | 1678 | ||
| 1659 | sci_port_enable(s); | 1679 | sci_port_enable(s); |
| 1660 | 1680 | ||
| 1661 | do { | 1681 | sci_reset(port); |
| 1662 | status = sci_in(port, SCxSR); | ||
| 1663 | } while (!(status & SCxSR_TEND(port))); | ||
| 1664 | |||
| 1665 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | ||
| 1666 | |||
| 1667 | if (port->type != PORT_SCI) | ||
| 1668 | sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); | ||
| 1669 | 1682 | ||
| 1670 | smr_val = sci_in(port, SCSMR) & 3; | 1683 | smr_val = sci_in(port, SCSMR) & 3; |
| 1671 | 1684 | ||
| @@ -2037,7 +2050,8 @@ static int __devinit serial_console_setup(struct console *co, char *options) | |||
| 2037 | if (options) | 2050 | if (options) |
| 2038 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 2051 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| 2039 | 2052 | ||
| 2040 | /* TODO: disable clock */ | 2053 | sci_port_disable(sci_port); |
| 2054 | |||
| 2041 | return uart_set_options(port, co, baud, parity, bits, flow); | 2055 | return uart_set_options(port, co, baud, parity, bits, flow); |
| 2042 | } | 2056 | } |
| 2043 | 2057 | ||
| @@ -2080,6 +2094,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev) | |||
| 2080 | return 0; | 2094 | return 0; |
| 2081 | } | 2095 | } |
| 2082 | 2096 | ||
| 2097 | #define uart_console(port) ((port)->cons->index == (port)->line) | ||
| 2098 | |||
| 2099 | static int sci_runtime_suspend(struct device *dev) | ||
| 2100 | { | ||
| 2101 | struct sci_port *sci_port = dev_get_drvdata(dev); | ||
| 2102 | struct uart_port *port = &sci_port->port; | ||
| 2103 | |||
| 2104 | if (uart_console(port)) { | ||
| 2105 | sci_port->saved_smr = sci_in(port, SCSMR); | ||
| 2106 | sci_port->saved_brr = sci_in(port, SCBRR); | ||
| 2107 | sci_port->saved_fcr = sci_in(port, SCFCR); | ||
| 2108 | } | ||
| 2109 | return 0; | ||
| 2110 | } | ||
| 2111 | |||
| 2112 | static int sci_runtime_resume(struct device *dev) | ||
| 2113 | { | ||
| 2114 | struct sci_port *sci_port = dev_get_drvdata(dev); | ||
| 2115 | struct uart_port *port = &sci_port->port; | ||
| 2116 | |||
| 2117 | if (uart_console(port)) { | ||
| 2118 | sci_reset(port); | ||
| 2119 | sci_out(port, SCSMR, sci_port->saved_smr); | ||
| 2120 | sci_out(port, SCBRR, sci_port->saved_brr); | ||
| 2121 | sci_out(port, SCFCR, sci_port->saved_fcr); | ||
| 2122 | sci_out(port, SCSCR, sci_port->cfg->scscr); | ||
| 2123 | } | ||
| 2124 | return 0; | ||
| 2125 | } | ||
| 2126 | |||
| 2083 | #define SCI_CONSOLE (&serial_console) | 2127 | #define SCI_CONSOLE (&serial_console) |
| 2084 | 2128 | ||
| 2085 | #else | 2129 | #else |
| @@ -2089,6 +2133,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev) | |||
| 2089 | } | 2133 | } |
| 2090 | 2134 | ||
| 2091 | #define SCI_CONSOLE NULL | 2135 | #define SCI_CONSOLE NULL |
| 2136 | #define sci_runtime_suspend NULL | ||
| 2137 | #define sci_runtime_resume NULL | ||
| 2092 | 2138 | ||
| 2093 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ | 2139 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ |
| 2094 | 2140 | ||
| @@ -2204,6 +2250,8 @@ static int sci_resume(struct device *dev) | |||
| 2204 | } | 2250 | } |
| 2205 | 2251 | ||
| 2206 | static const struct dev_pm_ops sci_dev_pm_ops = { | 2252 | static const struct dev_pm_ops sci_dev_pm_ops = { |
| 2253 | .runtime_suspend = sci_runtime_suspend, | ||
| 2254 | .runtime_resume = sci_runtime_resume, | ||
| 2207 | .suspend = sci_suspend, | 2255 | .suspend = sci_suspend, |
| 2208 | .resume = sci_resume, | 2256 | .resume = sci_resume, |
| 2209 | }; | 2257 | }; |
