summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sh-sci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r--drivers/tty/serial/sh-sci.c65
1 files changed, 42 insertions, 23 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 919706988c72..cc0504f30a1d 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2391,6 +2391,27 @@ done:
uart_update_timeout(port, termios->c_cflag, baud);
+ /* byte size and parity */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ bits = 7;
+ break;
+ case CS6:
+ bits = 8;
+ break;
+ case CS7:
+ bits = 9;
+ break;
+ default:
+ bits = 10;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ bits++;
+ if (termios->c_cflag & PARENB)
+ bits++;
+
if (best_clk >= 0) {
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
switch (srr + 1) {
@@ -2407,8 +2428,27 @@ done:
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
serial_port_out(port, SCSMR, smr_val);
serial_port_out(port, SCBRR, brr);
- if (sci_getreg(port, HSSRR)->size)
- serial_port_out(port, HSSRR, srr | HSCIF_SRE);
+ if (sci_getreg(port, HSSRR)->size) {
+ unsigned int hssrr = srr | HSCIF_SRE;
+ /* Calculate deviation from intended rate at the
+ * center of the last stop bit in sampling clocks.
+ */
+ int last_stop = bits * 2 - 1;
+ int deviation = min_err * srr * last_stop / 2 / baud;
+
+ if (abs(deviation) >= 2) {
+ /* At least two sampling clocks off at the
+ * last stop bit; we can increase the error
+ * margin by shifting the sampling point.
+ */
+ int shift = min(-8, max(7, deviation / 2));
+
+ hssrr |= (shift << HSCIF_SRHP_SHIFT) &
+ HSCIF_SRHP_MASK;
+ hssrr |= HSCIF_SRDE;
+ }
+ serial_port_out(port, HSSRR, hssrr);
+ }
/* Wait one bit interval */
udelay((1000000 + (baud - 1)) / baud);
@@ -2475,27 +2515,6 @@ done:
* value obtained by this formula is too small. Therefore, if the value
* is smaller than 20ms, use 20ms as the timeout value for DMA.
*/
- /* byte size and parity */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- bits++;
- if (termios->c_cflag & PARENB)
- bits++;
-
s->rx_frame = (10000 * bits) / (baud / 100);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
OpenPOWER on IntegriCloud