|
@@ -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
|