Add support for new devices: Exar's XR17V35x family of multi-port PCIe UARTs.
Unified · Split
| @@ -282,6 +282,15 @@ static const struct serial8250_config uart_config[] = { · 281 unmodified lines | ||
| 282 | 282 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
| 283 | 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 | 294 | [PORT_LPC3220] = { |
| 286 | 295 | .name = "LPC3220", |
| 287 | 296 | .fifo_size = 64, |
| @@ -455,6 +464,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value) · 167 unmodified lines | ||
| 455 | 464 | } |
| 456 | 465 | |
| 457 | 466 | static int serial8250_default_handle_irq(struct uart_port *port); |
| 467 | +static int exar_handle_irq(struct uart_port *port); | |
| 458 | 468 | |
| 459 | 469 | static void set_io_from_upio(struct uart_port *p) |
| 460 | 470 | { |
| @@ -574,6 +584,18 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); · 113 unmodified lines | ||
| 574 | 584 | */ |
| 575 | 585 | static 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 | 599 | if (p->capabilities & UART_CAP_SLEEP) { |
| 578 | 600 | if (p->capabilities & UART_CAP_EFR) { |
| 579 | 601 | serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); |
| @@ -881,6 +903,27 @@ static void autoconfig_16550a(struct uart_8250_port *up) · 301 unmodified lines | ||
| 881 | 903 | up->port.type = PORT_16550A; |
| 882 | 904 | up->capabilities |= UART_CAP_FIFO; |
| 883 | 905 | |
| 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 | + | |
| 884 | 927 | /* |
| 885 | 928 | * Check for presence of the EFR when DLAB is set. |
| 886 | 929 | * Only ST16C650V1 UARTs pass this test. |
| @@ -1515,6 +1558,30 @@ static int serial8250_default_handle_irq(struct uart_port *port) · 628 unmodified lines | ||
| 1515 | 1558 | return serial8250_handle_irq(port, iir); |
| 1516 | 1559 | } |
| 1517 | 1560 | |
| 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 | + */ | |
| 1567 | +static 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 | + | |
| 1518 | 1585 | /* |
| 1519 | 1586 | * This is the serial driver's interrupt routine. |
| 1520 | 1587 | * |
| @@ -2614,6 +2681,10 @@ static void serial8250_config_port(struct uart_port *port, int flags) · 1093 unmodified lines | ||
| 2614 | 2681 | serial8250_release_rsa_resource(up); |
| 2615 | 2682 | if (port->type == PORT_UNKNOWN) |
| 2616 | 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 | |
| 2619 | 2690 | static int |
| @@ -1164,6 +1164,39 @@ pci_xr17c154_setup(struct serial_private *priv, · 1163 unmodified lines | ||
| 1164 | 1164 | return pci_default_setup(priv, board, port, idx); |
| 1165 | 1165 | } |
| 1166 | 1166 | |
| 1167 | +static int | |
| 1168 | +pci_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 | + | |
| 1167 | 1200 | static int |
| 1168 | 1201 | pci_wch_ch353_setup(struct serial_private *priv, |
| 1169 | 1202 | const struct pciserial_board *board, |
| @@ -1622,6 +1655,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { · 452 unmodified lines | ||
| 1622 | 1655 | .subdevice = PCI_ANY_ID, |
| 1623 | 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 | 1680 | * Xircom cards |
| 1627 | 1681 | */ |
| @@ -1962,6 +2016,9 @@ enum pci_board_num_t { · 334 unmodified lines | ||
| 1962 | 2016 | pbn_exar_XR17C152, |
| 1963 | 2017 | pbn_exar_XR17C154, |
| 1964 | 2018 | pbn_exar_XR17C158, |
| 2019 | + pbn_exar_XR17V352, | |
| 2020 | + pbn_exar_XR17V354, | |
| 2021 | + pbn_exar_XR17V358, | |
| 1965 | 2022 | pbn_exar_ibm_saturn, |
| 1966 | 2023 | pbn_pasemi_1682M, |
| 1967 | 2024 | pbn_ni8430_2, |
| @@ -2580,6 +2637,30 @@ static struct pciserial_board pci_boards[] = { · 612 unmodified lines | ||
| 2580 | 2637 | .base_baud = 921600, |
| 2581 | 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 | 2664 | [pbn_exar_ibm_saturn] = { |
| 2584 | 2665 | .flags = FL_BASE0, |
| 2585 | 2666 | .num_ports = 1, |
| @@ -3826,6 +3907,21 @@ static struct pci_device_id serial_pci_tbl[] = { · 1240 unmodified lines | ||
| 3826 | 3907 | PCI_ANY_ID, PCI_ANY_ID, |
| 3827 | 3908 | 0, |
| 3828 | 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 | 3927 | * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) |
| @@ -1985,6 +1985,9 @@ · 1984 unmodified lines | ||
| 1985 | 1985 | #define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 |
| 1986 | 1986 | #define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 |
| 1987 | 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 | 1992 | #define PCI_VENDOR_ID_MICROGATE 0x13c0 |
| 1990 | 1993 | #define PCI_DEVICE_ID_MICROGATE_USC 0x0010 |
| @@ -49,7 +49,8 @@ · 48 unmodified lines | ||
| 49 | 49 | #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ |
| 50 | 50 | #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ |
| 51 | 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 | 56 | * ARM specific type numbers. These are not currently guaranteed |
| @@ -367,5 +367,11 @@ · 366 unmodified lines | ||
| 367 | 367 | #define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */ |
| 368 | 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 | 376 | #endif /* _LINUX_SERIAL_REG_H */ |
| 371 | 377 | |