aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sh-sci.c
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-08-02 23:47:36 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-08-03 02:07:44 -0400
commit1ba762209491e2496e58baffa3fd65d661f54404 (patch)
tree9950463aa989a0b53ebbc7ad0f5d1276ca41cd2b /drivers/tty/serial/sh-sci.c
parentc84b51e65ea2f256353c339bd87e991b7e64630f (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.c68
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
1643static 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
1637static void sci_set_termios(struct uart_port *port, struct ktermios *termios, 1657static 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
2099static 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
2112static 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
2206static const struct dev_pm_ops sci_dev_pm_ops = { 2252static 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};