serial: 8250_pci: add support for Fintek 4, 8, and 12 port cards

This adds support for Fintek's 4, 8, and 12 port PCIE serial cards.

Thanks to Fintek for the sample devices, and the spec needed in order to
implement this.

Cc: Amanda Ying <amanda_ying@fintek.com.tw>
Cc: Felix Shih <felix_shih@fintek.com.tw>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2013-10-17 10:44:26 -07:00
parent 7cb92fd2a0
commit 2c62a3c899
1 changed files with 112 additions and 0 deletions

View File

@ -1457,6 +1457,71 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
return ret;
}
static int pci_fintek_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
unsigned long base;
unsigned long iobase;
unsigned long ciobase = 0;
u8 config_base;
/*
* We are supposed to be able to read these from the PCI config space,
* but the values there don't seem to match what we need to use, so
* just use these hard-coded values for now, as they are correct.
*/
switch (idx) {
case 0: iobase = 0xe000; config_base = 0x40; break;
case 1: iobase = 0xe008; config_base = 0x48; break;
case 2: iobase = 0xe010; config_base = 0x50; break;
case 3: iobase = 0xe018; config_base = 0x58; break;
case 4: iobase = 0xe020; config_base = 0x60; break;
case 5: iobase = 0xe028; config_base = 0x68; break;
case 6: iobase = 0xe030; config_base = 0x70; break;
case 7: iobase = 0xe038; config_base = 0x78; break;
case 8: iobase = 0xe040; config_base = 0x80; break;
case 9: iobase = 0xe048; config_base = 0x88; break;
case 10: iobase = 0xe050; config_base = 0x90; break;
case 11: iobase = 0xe058; config_base = 0x98; break;
default:
/* Unknown number of ports, get out of here */
return -EINVAL;
}
if (idx < 4) {
base = pci_resource_start(priv->dev, 3);
ciobase = (int)(base + (0x8 * idx));
}
dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n",
__func__, idx, iobase, ciobase, config_base);
/* Enable UART I/O port */
pci_write_config_byte(pdev, config_base + 0x00, 0x01);
/* Select 128-byte FIFO and 8x FIFO threshold */
pci_write_config_byte(pdev, config_base + 0x01, 0x33);
/* LSB UART */
pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff));
/* MSB UART */
pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8));
/* irq number, this usually fails, but the spec says to do it anyway. */
pci_write_config_byte(pdev, config_base + 0x06, pdev->irq);
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
port->port.mapbase = 0;
port->port.membase = NULL;
port->port.regshift = 0;
return 0;
}
static int skip_tx_en_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@ -2380,6 +2445,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = pci_brcm_trumanage_setup,
},
{
.vendor = 0x1c29,
.device = 0x1104,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
{
.vendor = 0x1c29,
.device = 0x1108,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
{
.vendor = 0x1c29,
.device = 0x1112,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
/*
* Default "match everything" terminator entry
@ -2578,6 +2664,9 @@ enum pci_board_num_t {
pbn_omegapci,
pbn_NETMOS9900_2s_115200,
pbn_brcm_trumanage,
pbn_fintek_4,
pbn_fintek_8,
pbn_fintek_12,
};
/*
@ -3335,6 +3424,24 @@ static struct pciserial_board pci_boards[] = {
.reg_shift = 2,
.base_baud = 115200,
},
[pbn_fintek_4] = {
.num_ports = 4,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
[pbn_fintek_8] = {
.num_ports = 8,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
[pbn_fintek_12] = {
.num_ports = 12,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
};
static const struct pci_device_id blacklist[] = {
@ -5059,6 +5166,11 @@ static struct pci_device_id serial_pci_tbl[] = {
0,
0, pbn_exar_XR17V358 },
/* Fintek PCI serial cards */
{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
/*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL