diff options
author | Peter Hung <hpeter@gmail.com> | 2014-11-19 00:22:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-25 20:06:39 -0500 |
commit | cb8ee9f08c4abfd8744eabffc467c06795c835d9 (patch) | |
tree | 827e0e0dec89521d40bf3f540401e2773c434779 /drivers/tty | |
parent | 2b310ec7934f69c6e9a49dd675f413e112b82e5c (diff) |
serial: Fix io address assign flow with Fintek PCI-to-UART Product
The original driver fixed the io address with 0xe000+idx*8,
but real io address assigned from BIOS is dynamically from
read PCI configure space 0x24, 0x20, 0x1c.
The Fintek F81504/F81508/F81512 maybe malfunction without
this patch and malfunction surely when more then 1 PCI card.
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 | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0468e15e6f10..31feeb2d0a66 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1554,25 +1554,48 @@ static int pci_fintek_setup(struct serial_private *priv, | |||
1554 | unsigned long iobase; | 1554 | unsigned long iobase; |
1555 | unsigned long ciobase = 0; | 1555 | unsigned long ciobase = 0; |
1556 | u8 config_base; | 1556 | u8 config_base; |
1557 | u32 bar_data[3]; | ||
1557 | 1558 | ||
1558 | /* | 1559 | /* |
1559 | * We are supposed to be able to read these from the PCI config space, | 1560 | * Find each UARTs offset in PCI configuraion space |
1560 | * but the values there don't seem to match what we need to use, so | ||
1561 | * just use these hard-coded values for now, as they are correct. | ||
1562 | */ | 1561 | */ |
1563 | switch (idx) { | 1562 | switch (idx) { |
1564 | case 0: iobase = 0xe000; config_base = 0x40; break; | 1563 | case 0: |
1565 | case 1: iobase = 0xe008; config_base = 0x48; break; | 1564 | config_base = 0x40; |
1566 | case 2: iobase = 0xe010; config_base = 0x50; break; | 1565 | break; |
1567 | case 3: iobase = 0xe018; config_base = 0x58; break; | 1566 | case 1: |
1568 | case 4: iobase = 0xe020; config_base = 0x60; break; | 1567 | config_base = 0x48; |
1569 | case 5: iobase = 0xe028; config_base = 0x68; break; | 1568 | break; |
1570 | case 6: iobase = 0xe030; config_base = 0x70; break; | 1569 | case 2: |
1571 | case 7: iobase = 0xe038; config_base = 0x78; break; | 1570 | config_base = 0x50; |
1572 | case 8: iobase = 0xe040; config_base = 0x80; break; | 1571 | break; |
1573 | case 9: iobase = 0xe048; config_base = 0x88; break; | 1572 | case 3: |
1574 | case 10: iobase = 0xe050; config_base = 0x90; break; | 1573 | config_base = 0x58; |
1575 | case 11: iobase = 0xe058; config_base = 0x98; break; | 1574 | break; |
1575 | case 4: | ||
1576 | config_base = 0x60; | ||
1577 | break; | ||
1578 | case 5: | ||
1579 | config_base = 0x68; | ||
1580 | break; | ||
1581 | case 6: | ||
1582 | config_base = 0x70; | ||
1583 | break; | ||
1584 | case 7: | ||
1585 | config_base = 0x78; | ||
1586 | break; | ||
1587 | case 8: | ||
1588 | config_base = 0x80; | ||
1589 | break; | ||
1590 | case 9: | ||
1591 | config_base = 0x88; | ||
1592 | break; | ||
1593 | case 10: | ||
1594 | config_base = 0x90; | ||
1595 | break; | ||
1596 | case 11: | ||
1597 | config_base = 0x98; | ||
1598 | break; | ||
1576 | default: | 1599 | default: |
1577 | /* Unknown number of ports, get out of here */ | 1600 | /* Unknown number of ports, get out of here */ |
1578 | return -EINVAL; | 1601 | return -EINVAL; |
@@ -1583,6 +1606,14 @@ static int pci_fintek_setup(struct serial_private *priv, | |||
1583 | ciobase = (int)(base + (0x8 * idx)); | 1606 | ciobase = (int)(base + (0x8 * idx)); |
1584 | } | 1607 | } |
1585 | 1608 | ||
1609 | /* Get the io address dispatch from the BIOS */ | ||
1610 | pci_read_config_dword(pdev, 0x24, &bar_data[0]); | ||
1611 | pci_read_config_dword(pdev, 0x20, &bar_data[1]); | ||
1612 | pci_read_config_dword(pdev, 0x1c, &bar_data[2]); | ||
1613 | |||
1614 | /* Calculate Real IO Port */ | ||
1615 | iobase = (bar_data[idx/4] & 0xffffffe0) + (idx % 4) * 8; | ||
1616 | |||
1586 | dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n", | 1617 | dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n", |
1587 | __func__, idx, iobase, ciobase, config_base); | 1618 | __func__, idx, iobase, ciobase, config_base); |
1588 | 1619 | ||