| From 2853a76c42b6ce0f1cad26374714ac91f163c7f4 Mon Sep 17 00:00:00 2001 |
| From: Ulrich Hecht <ulrich.hecht+renesas@gmail.com> |
| Date: Wed, 4 Apr 2018 17:48:51 +0200 |
| Subject: [PATCH 1263/1795] serial: sh-sci: Support for HSCIF RX sampling point |
| adjustment |
| |
| HSCIF has facilities that allow moving the RX sampling point by between |
| -8 and 7 sampling cycles (one sampling cycles equals 1/15 of a bit |
| by default) to improve the error margin in case of slightly mismatched |
| bit rates between sender and receiver. |
| |
| This patch tries to determine if shifting the sampling point can improve |
| the error margin and will enable it if so. |
| |
| Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit 63ba1e00f178a4483b473489cadc4eb52a77df2a) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/tty/serial/sh-sci.c | 65 ++++++++++++++++++++++++------------- |
| drivers/tty/serial/sh-sci.h | 4 +++ |
| 2 files changed, 46 insertions(+), 23 deletions(-) |
| |
| diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c |
| index 59fac9761e9c..c181eb37f985 100644 |
| --- a/drivers/tty/serial/sh-sci.c |
| +++ b/drivers/tty/serial/sh-sci.c |
| @@ -2391,6 +2391,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| |
| 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 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| 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 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| * 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; |
| diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h |
| index a5f792fd48d9..0b9e804e61a9 100644 |
| --- a/drivers/tty/serial/sh-sci.h |
| +++ b/drivers/tty/serial/sh-sci.h |
| @@ -130,6 +130,10 @@ enum { |
| |
| /* HSSRR HSCIF */ |
| #define HSCIF_SRE BIT(15) /* Sampling Rate Register Enable */ |
| +#define HSCIF_SRDE BIT(14) /* Sampling Point Register Enable */ |
| + |
| +#define HSCIF_SRHP_SHIFT 8 |
| +#define HSCIF_SRHP_MASK 0x0f00 |
| |
| /* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */ |
| #define SCPCR_RTSC BIT(4) /* Serial Port RTS# Pin / Output Pin */ |
| -- |
| 2.19.0 |
| |