aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Schulte <matts@commtech-fastcom.com>2012-11-19 10:12:04 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-21 18:37:46 -0500
commitdc96efb72054985c0912f831da009a2da4e9f6dd (patch)
tree15a27b27040eb43fa2ff161d536a593623211e97
parentae8d8a146725a966bd7c59c94f4d0016dcf7a04f (diff)
Serial: Add support for new devices: Exar's XR17V35x family of multi-port PCIe UARTs
Add support for new devices: Exar's XR17V35x family of multi-port PCIe UARTs. Signed-off-by: Matt Schulte <matts@commtech-fastcom.com> Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/8250/8250.c71
-rw-r--r--drivers/tty/serial/8250/8250_pci.c96
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/uapi/linux/serial_core.h3
-rw-r--r--include/uapi/linux/serial_reg.h6
5 files changed, 178 insertions, 1 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 2af83a246499..3624df674a31 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -282,6 +282,15 @@ static const struct serial8250_config uart_config[] = {
282 .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, 282 .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
283 .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, 283 .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
284 }, 284 },
285 [PORT_XR17V35X] = {
286 .name = "XR17V35X",
287 .fifo_size = 256,
288 .tx_loadsz = 256,
289 .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
290 UART_FCR_T_TRIG_11,
291 .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
292 UART_CAP_SLEEP,
293 },
285 [PORT_LPC3220] = { 294 [PORT_LPC3220] = {
286 .name = "LPC3220", 295 .name = "LPC3220",
287 .fifo_size = 64, 296 .fifo_size = 64,
@@ -455,6 +464,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
455} 464}
456 465
457static int serial8250_default_handle_irq(struct uart_port *port); 466static int serial8250_default_handle_irq(struct uart_port *port);
467static int exar_handle_irq(struct uart_port *port);
458 468
459static void set_io_from_upio(struct uart_port *p) 469static void set_io_from_upio(struct uart_port *p)
460{ 470{
@@ -574,6 +584,18 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
574 */ 584 */
575static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) 585static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
576{ 586{
587 /*
588 * Exar UARTs have a SLEEP register that enables or disables
589 * each UART to enter sleep mode separately. On the XR17V35x the
590 * register is accessible to each UART at the UART_EXAR_SLEEP
591 * offset but the UART channel may only write to the corresponding
592 * bit.
593 */
594 if (p->port.type == PORT_XR17V35X) {
595 serial_out(p, UART_EXAR_SLEEP, 0xff);
596 return;
597 }
598
577 if (p->capabilities & UART_CAP_SLEEP) { 599 if (p->capabilities & UART_CAP_SLEEP) {
578 if (p->capabilities & UART_CAP_EFR) { 600 if (p->capabilities & UART_CAP_EFR) {
579 serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); 601 serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -882,6 +904,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
882 up->capabilities |= UART_CAP_FIFO; 904 up->capabilities |= UART_CAP_FIFO;
883 905
884 /* 906 /*
907 * XR17V35x UARTs have an extra divisor register, DLD
908 * that gets enabled with when DLAB is set which will
909 * cause the device to incorrectly match and assign
910 * port type to PORT_16650. The EFR for this UART is
911 * found at offset 0x09. Instead check the Deice ID (DVID)
912 * register for a 2, 4 or 8 port UART.
913 */
914 status1 = serial_in(up, UART_EXAR_DVID);
915 if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
916 if (up->port.flags & UPF_EXAR_EFR) {
917 DEBUG_AUTOCONF("Exar XR17V35x ");
918 up->port.type = PORT_XR17V35X;
919 up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
920 UART_CAP_SLEEP;
921
922 return;
923 }
924
925 }
926
927 /*
885 * Check for presence of the EFR when DLAB is set. 928 * Check for presence of the EFR when DLAB is set.
886 * Only ST16C650V1 UARTs pass this test. 929 * Only ST16C650V1 UARTs pass this test.
887 */ 930 */
@@ -1516,6 +1559,30 @@ static int serial8250_default_handle_irq(struct uart_port *port)
1516} 1559}
1517 1560
1518/* 1561/*
1562 * These Exar UARTs have an extra interrupt indicator that could
1563 * fire for a few unimplemented interrupts. One of which is a
1564 * wakeup event when coming out of sleep. Put this here just
1565 * to be on the safe side that these interrupts don't go unhandled.
1566 */
1567static int exar_handle_irq(struct uart_port *port)
1568{
1569 unsigned char int0, int1, int2, int3;
1570 unsigned int iir = serial_port_in(port, UART_IIR);
1571 int ret;
1572
1573 ret = serial8250_handle_irq(port, iir);
1574
1575 if (port->type == PORT_XR17V35X) {
1576 int0 = serial_port_in(port, 0x80);
1577 int1 = serial_port_in(port, 0x81);
1578 int2 = serial_port_in(port, 0x82);
1579 int3 = serial_port_in(port, 0x83);
1580 }
1581
1582 return ret;
1583}
1584
1585/*
1519 * This is the serial driver's interrupt routine. 1586 * This is the serial driver's interrupt routine.
1520 * 1587 *
1521 * Arjan thinks the old way was overly complex, so it got simplified. 1588 * Arjan thinks the old way was overly complex, so it got simplified.
@@ -2614,6 +2681,10 @@ static void serial8250_config_port(struct uart_port *port, int flags)
2614 serial8250_release_rsa_resource(up); 2681 serial8250_release_rsa_resource(up);
2615 if (port->type == PORT_UNKNOWN) 2682 if (port->type == PORT_UNKNOWN)
2616 serial8250_release_std_resource(up); 2683 serial8250_release_std_resource(up);
2684
2685 /* Fixme: probably not the best place for this */
2686 if (port->type == PORT_XR17V35X)
2687 port->handle_irq = exar_handle_irq;
2617} 2688}
2618 2689
2619static int 2690static int
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 97058c1d7d45..2285d3283b3b 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1165,6 +1165,39 @@ pci_xr17c154_setup(struct serial_private *priv,
1165} 1165}
1166 1166
1167static int 1167static int
1168pci_xr17v35x_setup(struct serial_private *priv,
1169 const struct pciserial_board *board,
1170 struct uart_8250_port *port, int idx)
1171{
1172 u8 __iomem *p;
1173
1174 p = pci_ioremap_bar(priv->dev, 0);
1175
1176 port->port.flags |= UPF_EXAR_EFR;
1177
1178 /*
1179 * Setup Multipurpose Input/Output pins.
1180 */
1181 if (idx == 0) {
1182 writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
1183 writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
1184 writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
1185 writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
1186 writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
1187 writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
1188 writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
1189 writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
1190 writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
1191 writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
1192 writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
1193 writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
1194 }
1195 iounmap(p);
1196
1197 return pci_default_setup(priv, board, port, idx);
1198}
1199
1200static int
1168pci_wch_ch353_setup(struct serial_private *priv, 1201pci_wch_ch353_setup(struct serial_private *priv,
1169 const struct pciserial_board *board, 1202 const struct pciserial_board *board,
1170 struct uart_8250_port *port, int idx) 1203 struct uart_8250_port *port, int idx)
@@ -1622,6 +1655,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
1622 .subdevice = PCI_ANY_ID, 1655 .subdevice = PCI_ANY_ID,
1623 .setup = pci_xr17c154_setup, 1656 .setup = pci_xr17c154_setup,
1624 }, 1657 },
1658 {
1659 .vendor = PCI_VENDOR_ID_EXAR,
1660 .device = PCI_DEVICE_ID_EXAR_XR17V352,
1661 .subvendor = PCI_ANY_ID,
1662 .subdevice = PCI_ANY_ID,
1663 .setup = pci_xr17v35x_setup,
1664 },
1665 {
1666 .vendor = PCI_VENDOR_ID_EXAR,
1667 .device = PCI_DEVICE_ID_EXAR_XR17V354,
1668 .subvendor = PCI_ANY_ID,
1669 .subdevice = PCI_ANY_ID,
1670 .setup = pci_xr17v35x_setup,
1671 },
1672 {
1673 .vendor = PCI_VENDOR_ID_EXAR,
1674 .device = PCI_DEVICE_ID_EXAR_XR17V358,
1675 .subvendor = PCI_ANY_ID,
1676 .subdevice = PCI_ANY_ID,
1677 .setup = pci_xr17v35x_setup,
1678 },
1625 /* 1679 /*
1626 * Xircom cards 1680 * Xircom cards
1627 */ 1681 */
@@ -1962,6 +2016,9 @@ enum pci_board_num_t {
1962 pbn_exar_XR17C152, 2016 pbn_exar_XR17C152,
1963 pbn_exar_XR17C154, 2017 pbn_exar_XR17C154,
1964 pbn_exar_XR17C158, 2018 pbn_exar_XR17C158,
2019 pbn_exar_XR17V352,
2020 pbn_exar_XR17V354,
2021 pbn_exar_XR17V358,
1965 pbn_exar_ibm_saturn, 2022 pbn_exar_ibm_saturn,
1966 pbn_pasemi_1682M, 2023 pbn_pasemi_1682M,
1967 pbn_ni8430_2, 2024 pbn_ni8430_2,
@@ -2580,6 +2637,30 @@ static struct pciserial_board pci_boards[] = {
2580 .base_baud = 921600, 2637 .base_baud = 921600,
2581 .uart_offset = 0x200, 2638 .uart_offset = 0x200,
2582 }, 2639 },
2640 [pbn_exar_XR17V352] = {
2641 .flags = FL_BASE0,
2642 .num_ports = 2,
2643 .base_baud = 7812500,
2644 .uart_offset = 0x400,
2645 .reg_shift = 0,
2646 .first_offset = 0,
2647 },
2648 [pbn_exar_XR17V354] = {
2649 .flags = FL_BASE0,
2650 .num_ports = 4,
2651 .base_baud = 7812500,
2652 .uart_offset = 0x400,
2653 .reg_shift = 0,
2654 .first_offset = 0,
2655 },
2656 [pbn_exar_XR17V358] = {
2657 .flags = FL_BASE0,
2658 .num_ports = 8,
2659 .base_baud = 7812500,
2660 .uart_offset = 0x400,
2661 .reg_shift = 0,
2662 .first_offset = 0,
2663 },
2583 [pbn_exar_ibm_saturn] = { 2664 [pbn_exar_ibm_saturn] = {
2584 .flags = FL_BASE0, 2665 .flags = FL_BASE0,
2585 .num_ports = 1, 2666 .num_ports = 1,
@@ -3826,6 +3907,21 @@ static struct pci_device_id serial_pci_tbl[] = {
3826 PCI_ANY_ID, PCI_ANY_ID, 3907 PCI_ANY_ID, PCI_ANY_ID,
3827 0, 3908 0,
3828 0, pbn_exar_XR17C158 }, 3909 0, pbn_exar_XR17C158 },
3910 /*
3911 * Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
3912 */
3913 { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
3914 PCI_ANY_ID, PCI_ANY_ID,
3915 0,
3916 0, pbn_exar_XR17V352 },
3917 { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
3918 PCI_ANY_ID, PCI_ANY_ID,
3919 0,
3920 0, pbn_exar_XR17V354 },
3921 { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
3922 PCI_ANY_ID, PCI_ANY_ID,
3923 0,
3924 0, pbn_exar_XR17V358 },
3829 3925
3830 /* 3926 /*
3831 * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) 3927 * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 9d36b829533a..0199a7a76fcb 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1985,6 +1985,9 @@
1985#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 1985#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152
1986#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 1986#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154
1987#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158 1987#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158
1988#define PCI_DEVICE_ID_EXAR_XR17V352 0x0352
1989#define PCI_DEVICE_ID_EXAR_XR17V354 0x0354
1990#define PCI_DEVICE_ID_EXAR_XR17V358 0x0358
1988 1991
1989#define PCI_VENDOR_ID_MICROGATE 0x13c0 1992#define PCI_VENDOR_ID_MICROGATE 0x13c0
1990#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 1993#define PCI_DEVICE_ID_MICROGATE_USC 0x0010
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index ebcc73f0418a..78f99d97475b 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -49,7 +49,8 @@
49#define PORT_XR17D15X 21 /* Exar XR17D15x UART */ 49#define PORT_XR17D15X 21 /* Exar XR17D15x UART */
50#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ 50#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */
51#define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ 51#define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */
52#define PORT_MAX_8250 23 /* max port ID */ 52#define PORT_XR17V35X 24 /* Exar XR17V35x UARTs */
53#define PORT_MAX_8250 24 /* max port ID */
53 54
54/* 55/*
55 * ARM specific type numbers. These are not currently guaranteed 56 * ARM specific type numbers. These are not currently guaranteed
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index 5ed325e88a81..d0b47607b90b 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -367,5 +367,11 @@
367#define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */ 367#define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */
368#define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */ 368#define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */
369 369
370/*
371 * These are definitions for the XR17V35X and XR17D15X
372 */
373#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
374#define UART_EXAR_DVID 0x8d /* Device identification */
375
370#endif /* _LINUX_SERIAL_REG_H */ 376#endif /* _LINUX_SERIAL_REG_H */
371 377