aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250/8250_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250/8250_pci.c')
-rw-r--r--drivers/tty/serial/8250/8250_pci.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 858dca865d6a..28e7c7cce893 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -17,6 +17,7 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/tty.h> 19#include <linux/tty.h>
20#include <linux/serial_reg.h>
20#include <linux/serial_core.h> 21#include <linux/serial_core.h>
21#include <linux/8250_pci.h> 22#include <linux/8250_pci.h>
22#include <linux/bitops.h> 23#include <linux/bitops.h>
@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv,
1092 return pci_default_setup(priv, board, port, idx); 1093 return pci_default_setup(priv, board, port, idx);
1093} 1094}
1094 1095
1096static void kt_handle_break(struct uart_port *p)
1097{
1098 struct uart_8250_port *up =
1099 container_of(p, struct uart_8250_port, port);
1100 /*
1101 * On receipt of a BI, serial device in Intel ME (Intel
1102 * management engine) needs to have its fifos cleared for sane
1103 * SOL (Serial Over Lan) output.
1104 */
1105 serial8250_clear_and_reinit_fifos(up);
1106}
1107
1108static unsigned int kt_serial_in(struct uart_port *p, int offset)
1109{
1110 struct uart_8250_port *up =
1111 container_of(p, struct uart_8250_port, port);
1112 unsigned int val;
1113
1114 /*
1115 * When the Intel ME (management engine) gets reset its serial
1116 * port registers could return 0 momentarily. Functions like
1117 * serial8250_console_write, read and save the IER, perform
1118 * some operation and then restore it. In order to avoid
1119 * setting IER register inadvertently to 0, if the value read
1120 * is 0, double check with ier value in uart_8250_port and use
1121 * that instead. up->ier should be the same value as what is
1122 * currently configured.
1123 */
1124 val = inb(p->iobase + offset);
1125 if (offset == UART_IER) {
1126 if (val == 0)
1127 val = up->ier;
1128 }
1129 return val;
1130}
1131
1095static int kt_serial_setup(struct serial_private *priv, 1132static int kt_serial_setup(struct serial_private *priv,
1096 const struct pciserial_board *board, 1133 const struct pciserial_board *board,
1097 struct uart_port *port, int idx) 1134 struct uart_port *port, int idx)
1098{ 1135{
1099 port->flags |= UPF_BUG_THRE; 1136 port->flags |= UPF_BUG_THRE;
1137 port->serial_in = kt_serial_in;
1138 port->handle_break = kt_handle_break;
1100 return skip_tx_en_setup(priv, board, port, idx); 1139 return skip_tx_en_setup(priv, board, port, idx);
1101} 1140}
1102 1141
@@ -1609,54 +1648,72 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
1609 { 1648 {
1610 .vendor = PCI_VENDOR_ID_INTEL, 1649 .vendor = PCI_VENDOR_ID_INTEL,
1611 .device = 0x8811, 1650 .device = 0x8811,
1651 .subvendor = PCI_ANY_ID,
1652 .subdevice = PCI_ANY_ID,
1612 .init = pci_eg20t_init, 1653 .init = pci_eg20t_init,
1613 .setup = pci_default_setup, 1654 .setup = pci_default_setup,
1614 }, 1655 },
1615 { 1656 {
1616 .vendor = PCI_VENDOR_ID_INTEL, 1657 .vendor = PCI_VENDOR_ID_INTEL,
1617 .device = 0x8812, 1658 .device = 0x8812,
1659 .subvendor = PCI_ANY_ID,
1660 .subdevice = PCI_ANY_ID,
1618 .init = pci_eg20t_init, 1661 .init = pci_eg20t_init,
1619 .setup = pci_default_setup, 1662 .setup = pci_default_setup,
1620 }, 1663 },
1621 { 1664 {
1622 .vendor = PCI_VENDOR_ID_INTEL, 1665 .vendor = PCI_VENDOR_ID_INTEL,
1623 .device = 0x8813, 1666 .device = 0x8813,
1667 .subvendor = PCI_ANY_ID,
1668 .subdevice = PCI_ANY_ID,
1624 .init = pci_eg20t_init, 1669 .init = pci_eg20t_init,
1625 .setup = pci_default_setup, 1670 .setup = pci_default_setup,
1626 }, 1671 },
1627 { 1672 {
1628 .vendor = PCI_VENDOR_ID_INTEL, 1673 .vendor = PCI_VENDOR_ID_INTEL,
1629 .device = 0x8814, 1674 .device = 0x8814,
1675 .subvendor = PCI_ANY_ID,
1676 .subdevice = PCI_ANY_ID,
1630 .init = pci_eg20t_init, 1677 .init = pci_eg20t_init,
1631 .setup = pci_default_setup, 1678 .setup = pci_default_setup,
1632 }, 1679 },
1633 { 1680 {
1634 .vendor = 0x10DB, 1681 .vendor = 0x10DB,
1635 .device = 0x8027, 1682 .device = 0x8027,
1683 .subvendor = PCI_ANY_ID,
1684 .subdevice = PCI_ANY_ID,
1636 .init = pci_eg20t_init, 1685 .init = pci_eg20t_init,
1637 .setup = pci_default_setup, 1686 .setup = pci_default_setup,
1638 }, 1687 },
1639 { 1688 {
1640 .vendor = 0x10DB, 1689 .vendor = 0x10DB,
1641 .device = 0x8028, 1690 .device = 0x8028,
1691 .subvendor = PCI_ANY_ID,
1692 .subdevice = PCI_ANY_ID,
1642 .init = pci_eg20t_init, 1693 .init = pci_eg20t_init,
1643 .setup = pci_default_setup, 1694 .setup = pci_default_setup,
1644 }, 1695 },
1645 { 1696 {
1646 .vendor = 0x10DB, 1697 .vendor = 0x10DB,
1647 .device = 0x8029, 1698 .device = 0x8029,
1699 .subvendor = PCI_ANY_ID,
1700 .subdevice = PCI_ANY_ID,
1648 .init = pci_eg20t_init, 1701 .init = pci_eg20t_init,
1649 .setup = pci_default_setup, 1702 .setup = pci_default_setup,
1650 }, 1703 },
1651 { 1704 {
1652 .vendor = 0x10DB, 1705 .vendor = 0x10DB,
1653 .device = 0x800C, 1706 .device = 0x800C,
1707 .subvendor = PCI_ANY_ID,
1708 .subdevice = PCI_ANY_ID,
1654 .init = pci_eg20t_init, 1709 .init = pci_eg20t_init,
1655 .setup = pci_default_setup, 1710 .setup = pci_default_setup,
1656 }, 1711 },
1657 { 1712 {
1658 .vendor = 0x10DB, 1713 .vendor = 0x10DB,
1659 .device = 0x800D, 1714 .device = 0x800D,
1715 .subvendor = PCI_ANY_ID,
1716 .subdevice = PCI_ANY_ID,
1660 .init = pci_eg20t_init, 1717 .init = pci_eg20t_init,
1661 .setup = pci_default_setup, 1718 .setup = pci_default_setup,
1662 }, 1719 },
@@ -2775,6 +2832,12 @@ void pciserial_suspend_ports(struct serial_private *priv)
2775 for (i = 0; i < priv->nr; i++) 2832 for (i = 0; i < priv->nr; i++)
2776 if (priv->line[i] >= 0) 2833 if (priv->line[i] >= 0)
2777 serial8250_suspend_port(priv->line[i]); 2834 serial8250_suspend_port(priv->line[i]);
2835
2836 /*
2837 * Ensure that every init quirk is properly torn down
2838 */
2839 if (priv->quirk->exit)
2840 priv->quirk->exit(priv->dev);
2778} 2841}
2779EXPORT_SYMBOL_GPL(pciserial_suspend_ports); 2842EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
2780 2843