serial: 8250: Add CAP_MINI, set for bcm2835aux
authorPhil Elwell <phil@raspberrypi.org>
Fri, 19 May 2017 15:07:23 +0000 (16:07 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 May 2017 13:15:56 +0000 (15:15 +0200)
The AUX/mini-UART in the BCM2835 family of procesors is a cut-down
8250 clone. In particular it is lacking support for the following
features: CSTOPB PARENB PARODD CMSPAR CS5 CS6

Add a new capability (UART_CAP_MINI) that exposes the restrictions to
the user of the termios API by turning off the unsupported features in
the request.

N.B. It is almost possible to automatically discover the missing
features by reading back the LCR register, but the CSIZE bits don't
cooperate (contrary to the documentation, both bits are significant,
but CS5 and CS6 are mapped to CS7) and the code is much longer.

See: https://github.com/raspberrypi/linux/issues/1561

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
Acked-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_bcm2835aux.c
drivers/tty/serial/8250/8250_port.c

index ce8d4ffcc425b045377305f176aa8fa85af0068f..b2bdc35f74955fe134606ad9103811d227de8abf 100644 (file)
@@ -81,6 +81,9 @@ struct serial8250_config {
 #define UART_CAP_HFIFO (1 << 14)       /* UART has a "hidden" FIFO */
 #define UART_CAP_RPM   (1 << 15)       /* Runtime PM is active while idle */
 #define UART_CAP_IRDA  (1 << 16)       /* UART supports IrDA line discipline */
+#define UART_CAP_MINI  (1 << 17)       /* Mini UART on BCM283X family lacks:
+                                        * STOP PARITY EPAR SPAR WLEN5 WLEN6
+                                        */
 
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
index e10f1244409b344b850ffbbd4af5757a66c875f1..a23c7da42ea81342efc26fb35a92a69d535b7cd0 100644 (file)
@@ -39,7 +39,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
 
        /* initialize data */
        spin_lock_init(&data->uart.port.lock);
-       data->uart.capabilities = UART_CAP_FIFO;
+       data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
        data->uart.port.dev = &pdev->dev;
        data->uart.port.regshift = 2;
        data->uart.port.type = PORT_16550;
index d5b6cee87801b9b5bff5c18e3514a672aed3cec5..b4e71380a13c179535ef29edf3b70049475a0f2b 100644 (file)
@@ -2584,6 +2584,12 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned long flags;
        unsigned int baud, quot, frac = 0;
 
+       if (up->capabilities & UART_CAP_MINI) {
+               termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR);
+               if ((termios->c_cflag & CSIZE) == CS5 ||
+                   (termios->c_cflag & CSIZE) == CS6)
+                       termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7;
+       }
        cval = serial8250_compute_lcr(up, termios->c_cflag);
 
        baud = serial8250_get_baud_rate(port, termios, old);