diff options
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0774c02d6c49..4ea45c15388c 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1457,6 +1457,71 @@ pci_brcm_trumanage_setup(struct serial_private *priv, | |||
1457 | return ret; | 1457 | return ret; |
1458 | } | 1458 | } |
1459 | 1459 | ||
1460 | static int pci_fintek_setup(struct serial_private *priv, | ||
1461 | const struct pciserial_board *board, | ||
1462 | struct uart_8250_port *port, int idx) | ||
1463 | { | ||
1464 | struct pci_dev *pdev = priv->dev; | ||
1465 | unsigned long base; | ||
1466 | unsigned long iobase; | ||
1467 | unsigned long ciobase = 0; | ||
1468 | u8 config_base; | ||
1469 | |||
1470 | /* | ||
1471 | * We are supposed to be able to read these from the PCI config space, | ||
1472 | * but the values there don't seem to match what we need to use, so | ||
1473 | * just use these hard-coded values for now, as they are correct. | ||
1474 | */ | ||
1475 | switch (idx) { | ||
1476 | case 0: iobase = 0xe000; config_base = 0x40; break; | ||
1477 | case 1: iobase = 0xe008; config_base = 0x48; break; | ||
1478 | case 2: iobase = 0xe010; config_base = 0x50; break; | ||
1479 | case 3: iobase = 0xe018; config_base = 0x58; break; | ||
1480 | case 4: iobase = 0xe020; config_base = 0x60; break; | ||
1481 | case 5: iobase = 0xe028; config_base = 0x68; break; | ||
1482 | case 6: iobase = 0xe030; config_base = 0x70; break; | ||
1483 | case 7: iobase = 0xe038; config_base = 0x78; break; | ||
1484 | case 8: iobase = 0xe040; config_base = 0x80; break; | ||
1485 | case 9: iobase = 0xe048; config_base = 0x88; break; | ||
1486 | case 10: iobase = 0xe050; config_base = 0x90; break; | ||
1487 | case 11: iobase = 0xe058; config_base = 0x98; break; | ||
1488 | default: | ||
1489 | /* Unknown number of ports, get out of here */ | ||
1490 | return -EINVAL; | ||
1491 | } | ||
1492 | |||
1493 | if (idx < 4) { | ||
1494 | base = pci_resource_start(priv->dev, 3); | ||
1495 | ciobase = (int)(base + (0x8 * idx)); | ||
1496 | } | ||
1497 | |||
1498 | dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n", | ||
1499 | __func__, idx, iobase, ciobase, config_base); | ||
1500 | |||
1501 | /* Enable UART I/O port */ | ||
1502 | pci_write_config_byte(pdev, config_base + 0x00, 0x01); | ||
1503 | |||
1504 | /* Select 128-byte FIFO and 8x FIFO threshold */ | ||
1505 | pci_write_config_byte(pdev, config_base + 0x01, 0x33); | ||
1506 | |||
1507 | /* LSB UART */ | ||
1508 | pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff)); | ||
1509 | |||
1510 | /* MSB UART */ | ||
1511 | pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8)); | ||
1512 | |||
1513 | /* irq number, this usually fails, but the spec says to do it anyway. */ | ||
1514 | pci_write_config_byte(pdev, config_base + 0x06, pdev->irq); | ||
1515 | |||
1516 | port->port.iotype = UPIO_PORT; | ||
1517 | port->port.iobase = iobase; | ||
1518 | port->port.mapbase = 0; | ||
1519 | port->port.membase = NULL; | ||
1520 | port->port.regshift = 0; | ||
1521 | |||
1522 | return 0; | ||
1523 | } | ||
1524 | |||
1460 | static int skip_tx_en_setup(struct serial_private *priv, | 1525 | static int skip_tx_en_setup(struct serial_private *priv, |
1461 | const struct pciserial_board *board, | 1526 | const struct pciserial_board *board, |
1462 | struct uart_8250_port *port, int idx) | 1527 | struct uart_8250_port *port, int idx) |
@@ -2380,6 +2445,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
2380 | .subdevice = PCI_ANY_ID, | 2445 | .subdevice = PCI_ANY_ID, |
2381 | .setup = pci_brcm_trumanage_setup, | 2446 | .setup = pci_brcm_trumanage_setup, |
2382 | }, | 2447 | }, |
2448 | { | ||
2449 | .vendor = 0x1c29, | ||
2450 | .device = 0x1104, | ||
2451 | .subvendor = PCI_ANY_ID, | ||
2452 | .subdevice = PCI_ANY_ID, | ||
2453 | .setup = pci_fintek_setup, | ||
2454 | }, | ||
2455 | { | ||
2456 | .vendor = 0x1c29, | ||
2457 | .device = 0x1108, | ||
2458 | .subvendor = PCI_ANY_ID, | ||
2459 | .subdevice = PCI_ANY_ID, | ||
2460 | .setup = pci_fintek_setup, | ||
2461 | }, | ||
2462 | { | ||
2463 | .vendor = 0x1c29, | ||
2464 | .device = 0x1112, | ||
2465 | .subvendor = PCI_ANY_ID, | ||
2466 | .subdevice = PCI_ANY_ID, | ||
2467 | .setup = pci_fintek_setup, | ||
2468 | }, | ||
2383 | 2469 | ||
2384 | /* | 2470 | /* |
2385 | * Default "match everything" terminator entry | 2471 | * Default "match everything" terminator entry |
@@ -2578,6 +2664,9 @@ enum pci_board_num_t { | |||
2578 | pbn_omegapci, | 2664 | pbn_omegapci, |
2579 | pbn_NETMOS9900_2s_115200, | 2665 | pbn_NETMOS9900_2s_115200, |
2580 | pbn_brcm_trumanage, | 2666 | pbn_brcm_trumanage, |
2667 | pbn_fintek_4, | ||
2668 | pbn_fintek_8, | ||
2669 | pbn_fintek_12, | ||
2581 | }; | 2670 | }; |
2582 | 2671 | ||
2583 | /* | 2672 | /* |
@@ -3335,6 +3424,24 @@ static struct pciserial_board pci_boards[] = { | |||
3335 | .reg_shift = 2, | 3424 | .reg_shift = 2, |
3336 | .base_baud = 115200, | 3425 | .base_baud = 115200, |
3337 | }, | 3426 | }, |
3427 | [pbn_fintek_4] = { | ||
3428 | .num_ports = 4, | ||
3429 | .uart_offset = 8, | ||
3430 | .base_baud = 115200, | ||
3431 | .first_offset = 0x40, | ||
3432 | }, | ||
3433 | [pbn_fintek_8] = { | ||
3434 | .num_ports = 8, | ||
3435 | .uart_offset = 8, | ||
3436 | .base_baud = 115200, | ||
3437 | .first_offset = 0x40, | ||
3438 | }, | ||
3439 | [pbn_fintek_12] = { | ||
3440 | .num_ports = 12, | ||
3441 | .uart_offset = 8, | ||
3442 | .base_baud = 115200, | ||
3443 | .first_offset = 0x40, | ||
3444 | }, | ||
3338 | }; | 3445 | }; |
3339 | 3446 | ||
3340 | static const struct pci_device_id blacklist[] = { | 3447 | static const struct pci_device_id blacklist[] = { |
@@ -5059,6 +5166,11 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
5059 | 0, | 5166 | 0, |
5060 | 0, pbn_exar_XR17V358 }, | 5167 | 0, pbn_exar_XR17V358 }, |
5061 | 5168 | ||
5169 | /* Fintek PCI serial cards */ | ||
5170 | { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 }, | ||
5171 | { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, | ||
5172 | { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, | ||
5173 | |||
5062 | /* | 5174 | /* |
5063 | * These entries match devices with class COMMUNICATION_SERIAL, | 5175 | * These entries match devices with class COMMUNICATION_SERIAL, |
5064 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL | 5176 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |