diff options
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/vt8500_serial.c | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 15ad6fcda88b..f22571915185 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -33,8 +33,8 @@ #include <linux/serial.h> #include <linux/slab.h> #include <linux/clk.h> -#include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/err.h> /* @@ -78,6 +78,29 @@ #define RX_FIFO_INTS (RXFAF | RXFF | RXOVER | PER | FER | RXTOUT) #define TX_FIFO_INTS (TXFAE | TXFE | TXUDR) +/* + * Line control bits + */ + +#define VT8500_TXEN (1 << 0) /* Enable transmit logic */ +#define VT8500_RXEN (1 << 1) /* Enable receive logic */ +#define VT8500_CS8 (1 << 2) /* 8-bit data length (vs. 7-bit) */ +#define VT8500_CSTOPB (1 << 3) /* 2 stop bits (vs. 1) */ +#define VT8500_PARENB (1 << 4) /* Enable parity */ +#define VT8500_PARODD (1 << 5) /* Odd parity (vs. even) */ +#define VT8500_RTS (1 << 6) /* Ready to send */ +#define VT8500_LOOPBK (1 << 7) /* Enable internal loopback */ +#define VT8500_DMA (1 << 8) /* Enable DMA mode (needs FIFO) */ +#define VT8500_BREAK (1 << 9) /* Initiate break signal */ +#define VT8500_PSLVERR (1 << 10) /* APB error upon empty RX FIFO read */ +#define VT8500_SWRTSCTS (1 << 11) /* Software-controlled RTS/CTS */ + +/* + * Capability flags (driver-internal) + */ + +#define VT8500_HAS_SWRTSCTS_SWITCH (1 << 1) + #define VT8500_MAX_PORTS 6 struct vt8500_port { @@ -85,6 +108,7 @@ struct vt8500_port { char name[16]; struct clk *clk; unsigned int ier; + unsigned int vt8500_uart_flags; }; /* @@ -272,7 +296,8 @@ static void vt8500_set_mctrl(struct uart_port *port, unsigned int mctrl) static void vt8500_break_ctl(struct uart_port *port, int break_ctl) { if (break_ctl) - vt8500_write(port, vt8500_read(port, VT8500_URLCR) | (1 << 9), + vt8500_write(port, + vt8500_read(port, VT8500_URLCR) | VT8500_BREAK, VT8500_URLCR); } @@ -347,31 +372,35 @@ static void vt8500_set_termios(struct uart_port *port, /* calculate parity */ lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR); - lcr &= ~((1 << 5) | (1 << 4)); + lcr &= ~(VT8500_PARENB | VT8500_PARODD); if (termios->c_cflag & PARENB) { - lcr |= (1 << 4); + lcr |= VT8500_PARENB; termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & PARODD) - lcr |= (1 << 5); + lcr |= VT8500_PARODD; } /* calculate bits per char */ - lcr &= ~(1 << 2); + lcr &= ~VT8500_CS8; switch (termios->c_cflag & CSIZE) { case CS7: break; case CS8: default: - lcr |= (1 << 2); + lcr |= VT8500_CS8; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* calculate stop bits */ - lcr &= ~(1 << 3); + lcr &= ~VT8500_CSTOPB; if (termios->c_cflag & CSTOPB) - lcr |= (1 << 3); + lcr |= VT8500_CSTOPB; + + lcr &= ~VT8500_SWRTSCTS; + if (vt8500_port->vt8500_uart_flags & VT8500_HAS_SWRTSCTS_SWITCH) + lcr |= VT8500_SWRTSCTS; /* set parity, bits per char, and stop bit */ vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR); @@ -548,14 +577,31 @@ static struct uart_driver vt8500_uart_driver = { .cons = VT8500_CONSOLE, }; +static unsigned int vt8500_flags; /* none required so far */ +static unsigned int wm8880_flags = VT8500_HAS_SWRTSCTS_SWITCH; + +static const struct of_device_id wmt_dt_ids[] = { + { .compatible = "via,vt8500-uart", .data = &vt8500_flags}, + { .compatible = "wm,wm8880-uart", .data = &wm8880_flags}, + {} +}; + static int vt8500_serial_probe(struct platform_device *pdev) { struct vt8500_port *vt8500_port; struct resource *mmres, *irqres; struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + const unsigned int *flags; int ret; int port; + match = of_match_device(wmt_dt_ids, &pdev->dev); + if (!match) + return -EINVAL; + + flags = match->data; + mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mmres || !irqres) @@ -605,6 +651,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) return ret; } + vt8500_port->vt8500_uart_flags = *flags; vt8500_port->uart.type = PORT_VT8500; vt8500_port->uart.iotype = UPIO_MEM; vt8500_port->uart.mapbase = mmres->start; @@ -639,11 +686,6 @@ static int vt8500_serial_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id wmt_dt_ids[] = { - { .compatible = "via,vt8500-uart", }, - {} -}; - static struct platform_driver vt8500_platform_driver = { .probe = vt8500_serial_probe, .remove = vt8500_serial_remove, |