diff options
| author | Peter Hung <hpeter@gmail.com> | 2015-04-01 02:00:21 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-04-10 08:43:48 -0400 |
| commit | 6a8bc239a8c3e6ad34fceabb61ff8ec6222dad4e (patch) | |
| tree | cf6b21ba068e44a29232ec1bd366dc6f07bdd954 /drivers/tty | |
| parent | ca782f16ce02e3f4fa2ae28a5ff256ac69f731e2 (diff) | |
serial: 8250_pci: port failed after wakeup from S3
Serial ports of F81504/F81508/F81512 will failed when wakeup from S3(STR).
It's due to when the system wakeup from S3(STR), this PCI device's
configuration space from 0x40 to 0x40 + max_port * 0x08 should be
re-configured.
We move all initialization from pci_fintek_setup() to pci_fintek_init() and
set it to pci_serial_quirks .init section. It's will re-init this device when
system wakeup from pciserial_resume_ports().
Signed-off-by: Peter Hung <hpeter+linux_kernel@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
| -rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 114 |
1 files changed, 50 insertions, 64 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 98e5a6d9cfef..08da4d3e2162 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
| @@ -1690,88 +1690,71 @@ static int pci_fintek_setup(struct serial_private *priv, | |||
| 1690 | struct uart_8250_port *port, int idx) | 1690 | struct uart_8250_port *port, int idx) |
| 1691 | { | 1691 | { |
| 1692 | struct pci_dev *pdev = priv->dev; | 1692 | struct pci_dev *pdev = priv->dev; |
| 1693 | unsigned long iobase; | ||
| 1694 | u8 config_base; | 1693 | u8 config_base; |
| 1694 | u16 iobase; | ||
| 1695 | |||
| 1696 | config_base = 0x40 + 0x08 * idx; | ||
| 1697 | |||
| 1698 | /* Get the io address from configuration space */ | ||
| 1699 | pci_read_config_word(pdev, config_base + 4, &iobase); | ||
| 1700 | |||
| 1701 | dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase); | ||
| 1702 | |||
| 1703 | port->port.iotype = UPIO_PORT; | ||
| 1704 | port->port.iobase = iobase; | ||
| 1705 | |||
| 1706 | return 0; | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | static int pci_fintek_init(struct pci_dev *dev) | ||
| 1710 | { | ||
| 1711 | unsigned long iobase; | ||
| 1712 | u32 max_port, i; | ||
| 1695 | u32 bar_data[3]; | 1713 | u32 bar_data[3]; |
| 1714 | u8 config_base; | ||
| 1696 | 1715 | ||
| 1697 | /* | 1716 | switch (dev->device) { |
| 1698 | * Find each UARTs offset in PCI configuraion space | 1717 | case 0x1104: /* 4 ports */ |
| 1699 | */ | 1718 | case 0x1108: /* 8 ports */ |
| 1700 | switch (idx) { | 1719 | max_port = dev->device & 0xff; |
| 1701 | case 0: | ||
| 1702 | config_base = 0x40; | ||
| 1703 | break; | 1720 | break; |
| 1704 | case 1: | 1721 | case 0x1112: /* 12 ports */ |
| 1705 | config_base = 0x48; | 1722 | max_port = 12; |
| 1706 | break; | ||
| 1707 | case 2: | ||
| 1708 | config_base = 0x50; | ||
| 1709 | break; | ||
| 1710 | case 3: | ||
| 1711 | config_base = 0x58; | ||
| 1712 | break; | ||
| 1713 | case 4: | ||
| 1714 | config_base = 0x60; | ||
| 1715 | break; | ||
| 1716 | case 5: | ||
| 1717 | config_base = 0x68; | ||
| 1718 | break; | ||
| 1719 | case 6: | ||
| 1720 | config_base = 0x70; | ||
| 1721 | break; | ||
| 1722 | case 7: | ||
| 1723 | config_base = 0x78; | ||
| 1724 | break; | ||
| 1725 | case 8: | ||
| 1726 | config_base = 0x80; | ||
| 1727 | break; | ||
| 1728 | case 9: | ||
| 1729 | config_base = 0x88; | ||
| 1730 | break; | ||
| 1731 | case 10: | ||
| 1732 | config_base = 0x90; | ||
| 1733 | break; | ||
| 1734 | case 11: | ||
| 1735 | config_base = 0x98; | ||
| 1736 | break; | 1723 | break; |
| 1737 | default: | 1724 | default: |
| 1738 | /* Unknown number of ports, get out of here */ | ||
| 1739 | return -EINVAL; | 1725 | return -EINVAL; |
| 1740 | } | 1726 | } |
| 1741 | 1727 | ||
| 1742 | /* Get the io address dispatch from the BIOS */ | 1728 | /* Get the io address dispatch from the BIOS */ |
| 1743 | pci_read_config_dword(pdev, 0x24, &bar_data[0]); | 1729 | pci_read_config_dword(dev, 0x24, &bar_data[0]); |
| 1744 | pci_read_config_dword(pdev, 0x20, &bar_data[1]); | 1730 | pci_read_config_dword(dev, 0x20, &bar_data[1]); |
| 1745 | pci_read_config_dword(pdev, 0x1c, &bar_data[2]); | 1731 | pci_read_config_dword(dev, 0x1c, &bar_data[2]); |
| 1746 | |||
| 1747 | /* Calculate Real IO Port */ | ||
| 1748 | iobase = (bar_data[idx/4] & 0xffffffe0) + (idx % 4) * 8; | ||
| 1749 | 1732 | ||
| 1750 | dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx config_base=0x%2x\n", | 1733 | for (i = 0; i < max_port; ++i) { |
| 1751 | __func__, idx, iobase, config_base); | 1734 | /* UART0 configuration offset start from 0x40 */ |
| 1735 | config_base = 0x40 + 0x08 * i; | ||
| 1752 | 1736 | ||
| 1753 | /* Enable UART I/O port */ | 1737 | /* Calculate Real IO Port */ |
| 1754 | pci_write_config_byte(pdev, config_base + 0x00, 0x01); | 1738 | iobase = (bar_data[i / 4] & 0xffffffe0) + (i % 4) * 8; |
| 1755 | 1739 | ||
| 1756 | /* Select 128-byte FIFO and 8x FIFO threshold */ | 1740 | /* Enable UART I/O port */ |
| 1757 | pci_write_config_byte(pdev, config_base + 0x01, 0x33); | 1741 | pci_write_config_byte(dev, config_base + 0x00, 0x01); |
| 1758 | 1742 | ||
| 1759 | /* LSB UART */ | 1743 | /* Select 128-byte FIFO and 8x FIFO threshold */ |
| 1760 | pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff)); | 1744 | pci_write_config_byte(dev, config_base + 0x01, 0x33); |
| 1761 | 1745 | ||
| 1762 | /* MSB UART */ | 1746 | /* LSB UART */ |
| 1763 | pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8)); | 1747 | pci_write_config_byte(dev, config_base + 0x04, |
| 1748 | (u8)(iobase & 0xff)); | ||
| 1764 | 1749 | ||
| 1765 | /* irq number, this usually fails, but the spec says to do it anyway. */ | 1750 | /* MSB UART */ |
| 1766 | pci_write_config_byte(pdev, config_base + 0x06, pdev->irq); | 1751 | pci_write_config_byte(dev, config_base + 0x05, |
| 1752 | (u8)((iobase & 0xff00) >> 8)); | ||
| 1767 | 1753 | ||
| 1768 | port->port.iotype = UPIO_PORT; | 1754 | pci_write_config_byte(dev, config_base + 0x06, dev->irq); |
| 1769 | port->port.iobase = iobase; | 1755 | } |
| 1770 | port->port.mapbase = 0; | ||
| 1771 | port->port.membase = NULL; | ||
| 1772 | port->port.regshift = 0; | ||
| 1773 | 1756 | ||
| 1774 | return 0; | 1757 | return max_port; |
| 1775 | } | 1758 | } |
| 1776 | 1759 | ||
| 1777 | static int skip_tx_en_setup(struct serial_private *priv, | 1760 | static int skip_tx_en_setup(struct serial_private *priv, |
| @@ -2814,6 +2797,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
| 2814 | .subvendor = PCI_ANY_ID, | 2797 | .subvendor = PCI_ANY_ID, |
| 2815 | .subdevice = PCI_ANY_ID, | 2798 | .subdevice = PCI_ANY_ID, |
| 2816 | .setup = pci_fintek_setup, | 2799 | .setup = pci_fintek_setup, |
| 2800 | .init = pci_fintek_init, | ||
| 2817 | }, | 2801 | }, |
| 2818 | { | 2802 | { |
| 2819 | .vendor = 0x1c29, | 2803 | .vendor = 0x1c29, |
| @@ -2821,6 +2805,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
| 2821 | .subvendor = PCI_ANY_ID, | 2805 | .subvendor = PCI_ANY_ID, |
| 2822 | .subdevice = PCI_ANY_ID, | 2806 | .subdevice = PCI_ANY_ID, |
| 2823 | .setup = pci_fintek_setup, | 2807 | .setup = pci_fintek_setup, |
| 2808 | .init = pci_fintek_init, | ||
| 2824 | }, | 2809 | }, |
| 2825 | { | 2810 | { |
| 2826 | .vendor = 0x1c29, | 2811 | .vendor = 0x1c29, |
| @@ -2828,6 +2813,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
| 2828 | .subvendor = PCI_ANY_ID, | 2813 | .subvendor = PCI_ANY_ID, |
| 2829 | .subdevice = PCI_ANY_ID, | 2814 | .subdevice = PCI_ANY_ID, |
| 2830 | .setup = pci_fintek_setup, | 2815 | .setup = pci_fintek_setup, |
| 2816 | .init = pci_fintek_init, | ||
| 2831 | }, | 2817 | }, |
| 2832 | 2818 | ||
| 2833 | /* | 2819 | /* |
