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 /drivers/tty/serial/sh-sci.c | |
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>
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-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 | }; |