]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates
authorGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 4 Jan 2016 13:45:22 +0000 (14:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Feb 2016 06:54:55 +0000 (22:54 -0800)
Add support for sparse variable sampling rates on SCIFA and SCIFB.
According to the datasheet, sampling rate 1/5 needs a small quirk to
avoid corrupting the first byte received.

This increases the range and accuracy of supported baud rates.
E.g. on r8a7791/koelsch:
  - Supports now 134, 150, and standard 500000-4000000 bps,
  - Perfect match for 134, 150, 500000, 10000002000000, and 4000000
    bps,
  - Accuracy has increased for most standard bps values.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sh-sci.c

index dbf488b9ae27923a523c2450925f846968359227..4678d8f2dd7d1da56d2e2455ee5bcf607ed7b952 100644 (file)
@@ -88,6 +88,10 @@ enum SCI_CLKS {
 #define SCI_SR(x)              BIT((x) - 1)
 #define SCI_SR_RANGE(x, y)     GENMASK((y) - 1, (x) - 1)
 
+#define SCI_SR_SCIFAB          SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \
+                               SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \
+                               SCI_SR(19) | SCI_SR(27)
+
 #define min_sr(_port)          ffs((_port)->sampling_rate_mask)
 #define max_sr(_port)          fls((_port)->sampling_rate_mask)
 
@@ -2179,6 +2183,17 @@ done:
        uart_update_timeout(port, termios->c_cflag, baud);
 
        if (best_clk >= 0) {
+               if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+                       switch (srr + 1) {
+                       case 5:  smr_val |= SCSMR_SRC_5;  break;
+                       case 7:  smr_val |= SCSMR_SRC_7;  break;
+                       case 11: smr_val |= SCSMR_SRC_11; break;
+                       case 13: smr_val |= SCSMR_SRC_13; break;
+                       case 16: smr_val |= SCSMR_SRC_16; break;
+                       case 17: smr_val |= SCSMR_SRC_17; break;
+                       case 19: smr_val |= SCSMR_SRC_19; break;
+                       case 27: smr_val |= SCSMR_SRC_27; break;
+                       }
                smr_val |= cks;
                dev_dbg(port->dev,
                         "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n",
@@ -2227,6 +2242,16 @@ done:
        scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
        dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
        serial_port_out(port, SCSCR, scr_val);
+       if ((srr + 1 == 5) &&
+           (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
+               /*
+                * In asynchronous mode, when the sampling rate is 1/5, first
+                * received data may become invalid on some SCIFA and SCIFB.
+                * To avoid this problem wait more than 1 serial data time (1
+                * bit time x serial data number) after setting SCSCR.RE = 1.
+                */
+               udelay(DIV_ROUND_UP(10 * 1000000, baud));
+       }
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        /*
@@ -2523,7 +2548,7 @@ static int sci_init_single(struct platform_device *dev,
                port->fifosize = 256;
                sci_port->overrun_reg = SCxSR;
                sci_port->overrun_mask = SCIFA_ORER;
-               sci_port->sampling_rate_mask = SCI_SR(16);
+               sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
                break;
        case PORT_HSCIF:
                port->fifosize = 128;
@@ -2535,7 +2560,7 @@ static int sci_init_single(struct platform_device *dev,
                port->fifosize = 64;
                sci_port->overrun_reg = SCxSR;
                sci_port->overrun_mask = SCIFA_ORER;
-               sci_port->sampling_rate_mask = SCI_SR(16);
+               sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
                break;
        case PORT_SCIF:
                port->fifosize = 16;