X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Ftty%2Fserial%2Fsh-sci.c;h=1945c70539c2bb8326bdda5ec1e31d7c69980d43;hb=fba9569924e06da076cb2ad12474bbd82d69f54d;hp=dbd32a1286d32642b96108863ff261cb78114edd;hpb=4598fc2c94b68740e0269db03c98a1e7ad5af773;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dbd32a1286d3..1945c70539c2 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,12 @@ struct sci_port { #endif struct notifier_block freq_transition; + +#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE + unsigned short saved_smr; + unsigned short saved_fcr; + unsigned char saved_brr; +#endif }; /* Function prototypes */ @@ -1076,7 +1083,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port) /* This routine is used for getting signals of: DTR, DCD, DSR, RI, and CTS/RTS */ - return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; + return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR; } #ifdef CONFIG_SERIAL_SH_SCI_DMA @@ -1624,11 +1631,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, return ((freq + 16 * bps) / (32 * bps) - 1); } +static void sci_reset(struct uart_port *port) +{ + unsigned int status; + + do { + status = sci_in(port, SCxSR); + } while (!(status & SCxSR_TEND(port))); + + sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ + + if (port->type != PORT_SCI) + sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); +} + static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sci_port *s = to_sci_port(port); - unsigned int status, baud, smr_val, max_baud; + unsigned int baud, smr_val, max_baud; int t = -1; u16 scfcr = 0; @@ -1648,14 +1669,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_port_enable(s); - do { - status = sci_in(port, SCxSR); - } while (!(status & SCxSR_TEND(port))); - - sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ - - if (port->type != PORT_SCI) - sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); + sci_reset(port); smr_val = sci_in(port, SCSMR) & 3; @@ -1953,7 +1967,7 @@ static int __devinit sci_init_single(struct platform_device *dev, * For the muxed case there's nothing more to do. */ port->irq = p->irqs[SCIx_RXI_IRQ]; - port->irqflags = IRQF_DISABLED; + port->irqflags = 0; port->serial_in = sci_serial_in; port->serial_out = sci_serial_out; @@ -2028,7 +2042,8 @@ static int __devinit serial_console_setup(struct console *co, char *options) if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); - /* TODO: disable clock */ + sci_port_disable(sci_port); + return uart_set_options(port, co, baud, parity, bits, flow); } @@ -2071,6 +2086,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev) return 0; } +#define uart_console(port) ((port)->cons->index == (port)->line) + +static int sci_runtime_suspend(struct device *dev) +{ + struct sci_port *sci_port = dev_get_drvdata(dev); + struct uart_port *port = &sci_port->port; + + if (uart_console(port)) { + sci_port->saved_smr = sci_in(port, SCSMR); + sci_port->saved_brr = sci_in(port, SCBRR); + sci_port->saved_fcr = sci_in(port, SCFCR); + } + return 0; +} + +static int sci_runtime_resume(struct device *dev) +{ + struct sci_port *sci_port = dev_get_drvdata(dev); + struct uart_port *port = &sci_port->port; + + if (uart_console(port)) { + sci_reset(port); + sci_out(port, SCSMR, sci_port->saved_smr); + sci_out(port, SCBRR, sci_port->saved_brr); + sci_out(port, SCFCR, sci_port->saved_fcr); + sci_out(port, SCSCR, sci_port->cfg->scscr); + } + return 0; +} + #define SCI_CONSOLE (&serial_console) #else @@ -2080,6 +2125,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev) } #define SCI_CONSOLE NULL +#define sci_runtime_suspend NULL +#define sci_runtime_resume NULL #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ @@ -2195,6 +2242,8 @@ static int sci_resume(struct device *dev) } static const struct dev_pm_ops sci_dev_pm_ops = { + .runtime_suspend = sci_runtime_suspend, + .runtime_resume = sci_runtime_resume, .suspend = sci_suspend, .resume = sci_resume, };