]> Pileus Git - ~andy/linux/blobdiff - drivers/tty/serial/8250/8250_pci.c
serial: set correct baud_base for EXSYS EX-41092 Dual 16950
[~andy/linux] / drivers / tty / serial / 8250 / 8250_pci.c
index 28e7c7cce8935acc8257fafaff86121fa55bf6dd..cd5f2575fd4721e6da82a85d47840d1159b032c8 100644 (file)
@@ -44,7 +44,7 @@ struct pci_serial_quirk {
        int     (*init)(struct pci_dev *dev);
        int     (*setup)(struct serial_private *,
                         const struct pciserial_board *,
-                        struct uart_port *, int);
+                        struct uart_8250_port *, int);
        void    (*exit)(struct pci_dev *dev);
 };
 
@@ -59,7 +59,7 @@ struct serial_private {
 };
 
 static int pci_default_setup(struct serial_private*,
-         const struct pciserial_board*, struct uart_port*, int);
+         const struct pciserial_board*, struct uart_8250_port *, int);
 
 static void moan_device(const char *str, struct pci_dev *dev)
 {
@@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
 }
 
 static int
-setup_port(struct serial_private *priv, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_8250_port *port,
           int bar, int offset, int regshift)
 {
        struct pci_dev *dev = priv->dev;
@@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_port *port,
                if (!priv->remapped_bar[bar])
                        return -ENOMEM;
 
-               port->iotype = UPIO_MEM;
-               port->iobase = 0;
-               port->mapbase = base + offset;
-               port->membase = priv->remapped_bar[bar] + offset;
-               port->regshift = regshift;
+               port->port.iotype = UPIO_MEM;
+               port->port.iobase = 0;
+               port->port.mapbase = base + offset;
+               port->port.membase = priv->remapped_bar[bar] + offset;
+               port->port.regshift = regshift;
        } else {
-               port->iotype = UPIO_PORT;
-               port->iobase = base + offset;
-               port->mapbase = 0;
-               port->membase = NULL;
-               port->regshift = 0;
+               port->port.iotype = UPIO_PORT;
+               port->port.iobase = base + offset;
+               port->port.mapbase = 0;
+               port->port.membase = NULL;
+               port->port.regshift = 0;
        }
        return 0;
 }
@@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,
  */
 static int addidata_apci7800_setup(struct serial_private *priv,
                                const struct pciserial_board *board,
-                               struct uart_port *port, int idx)
+                               struct uart_8250_port *port, int idx)
 {
        unsigned int bar = 0, offset = board->first_offset;
        bar = FL_GET_BASE(board->flags);
@@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
  */
 static int
 afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
-             struct uart_port *port, int idx)
+             struct uart_8250_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
 
@@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)
 static int
 pci_hp_diva_setup(struct serial_private *priv,
                const struct pciserial_board *board,
-               struct uart_port *port, int idx)
+               struct uart_8250_port *port, int idx)
 {
        unsigned int offset = board->first_offset;
        unsigned int bar = FL_GET_BASE(board->flags);
@@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev)
 /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
 static int
 sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
-               struct uart_port *port, int idx)
+               struct uart_8250_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
 
@@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev)
 
 static int pci_siig_setup(struct serial_private *priv,
                          const struct pciserial_board *board,
-                         struct uart_port *port, int idx)
+                         struct uart_8250_port *port, int idx)
 {
        unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
 
@@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev)
 static int
 pci_timedia_setup(struct serial_private *priv,
                  const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
+                 struct uart_8250_port *port, int idx)
 {
        unsigned int bar = 0, offset = board->first_offset;
 
@@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,
 static int
 titan_400l_800l_setup(struct serial_private *priv,
                      const struct pciserial_board *board,
-                     struct uart_port *port, int idx)
+                     struct uart_8250_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset;
 
@@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
 static int
 pci_ni8430_setup(struct serial_private *priv,
                 const struct pciserial_board *board,
-                struct uart_port *port, int idx)
+                struct uart_8250_port *port, int idx)
 {
        void __iomem *p;
        unsigned long base, len;
@@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv,
 
 static int pci_netmos_9900_setup(struct serial_private *priv,
                                const struct pciserial_board *board,
-                               struct uart_port *port, int idx)
+                               struct uart_8250_port *port, int idx)
 {
        unsigned int bar;
 
@@ -1032,10 +1032,17 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
        return number_uarts;
 }
 
-static int
-pci_default_setup(struct serial_private *priv,
+static int pci_asix_setup(struct serial_private *priv,
+                 const struct pciserial_board *board,
+                 struct uart_8250_port *port, int idx)
+{
+       port->bugs |= UART_BUG_PARITY;
+       return pci_default_setup(priv, board, port, idx);
+}
+
+static int pci_default_setup(struct serial_private *priv,
                  const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
+                 struct uart_8250_port *port, int idx)
 {
        unsigned int bar, offset = board->first_offset, maxnr;
 
@@ -1057,15 +1064,15 @@ pci_default_setup(struct serial_private *priv,
 static int
 ce4100_serial_setup(struct serial_private *priv,
                  const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
+                 struct uart_8250_port *port, int idx)
 {
        int ret;
 
        ret = setup_port(priv, port, 0, 0, board->reg_shift);
-       port->iotype = UPIO_MEM32;
-       port->type = PORT_XSCALE;
-       port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
-       port->regshift = 2;
+       port->port.iotype = UPIO_MEM32;
+       port->port.type = PORT_XSCALE;
+       port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+       port->port.regshift = 2;
 
        return ret;
 }
@@ -1073,16 +1080,16 @@ ce4100_serial_setup(struct serial_private *priv,
 static int
 pci_omegapci_setup(struct serial_private *priv,
                      const struct pciserial_board *board,
-                     struct uart_port *port, int idx)
+                     struct uart_8250_port *port, int idx)
 {
        return setup_port(priv, port, 2, idx * 8, 0);
 }
 
 static int skip_tx_en_setup(struct serial_private *priv,
                        const struct pciserial_board *board,
-                       struct uart_port *port, int idx)
+                       struct uart_8250_port *port, int idx)
 {
-       port->flags |= UPF_NO_TXEN_TEST;
+       port->port.flags |= UPF_NO_TXEN_TEST;
        printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
                          "[%04x:%04x] subsystem [%04x:%04x]\n",
                          priv->dev->vendor,
@@ -1131,11 +1138,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)
 
 static int kt_serial_setup(struct serial_private *priv,
                           const struct pciserial_board *board,
-                          struct uart_port *port, int idx)
+                          struct uart_8250_port *port, int idx)
 {
-       port->flags |= UPF_BUG_THRE;
-       port->serial_in = kt_serial_in;
-       port->handle_break = kt_handle_break;
+       port->port.flags |= UPF_BUG_THRE;
+       port->port.serial_in = kt_serial_in;
+       port->port.handle_break = kt_handle_break;
        return skip_tx_en_setup(priv, board, port, idx);
 }
 
@@ -1151,9 +1158,19 @@ static int pci_eg20t_init(struct pci_dev *dev)
 static int
 pci_xr17c154_setup(struct serial_private *priv,
                  const struct pciserial_board *board,
-                 struct uart_port *port, int idx)
+                 struct uart_8250_port *port, int idx)
 {
-       port->flags |= UPF_EXAR_EFR;
+       port->port.flags |= UPF_EXAR_EFR;
+       return pci_default_setup(priv, board, port, idx);
+}
+
+static int
+pci_wch_ch353_setup(struct serial_private *priv,
+                    const struct pciserial_board *board,
+                    struct uart_8250_port *port, int idx)
+{
+       port->port.flags |= UPF_FIXED_TYPE;
+       port->port.type = PORT_16550A;
        return pci_default_setup(priv, board, port, idx);
 }
 
@@ -1164,6 +1181,8 @@ pci_xr17c154_setup(struct serial_private *priv,
 #define PCI_SUBDEVICE_ID_OCTPRO422     0x0208
 #define PCI_SUBDEVICE_ID_POCTAL232     0x0308
 #define PCI_SUBDEVICE_ID_POCTAL422     0x0408
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_00  0x2500
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_30  0x2530
 #define PCI_VENDOR_ID_ADVANTECH                0x13fe
 #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
 #define PCI_DEVICE_ID_ADVANTECH_PCI3620        0x3620
@@ -1187,6 +1206,13 @@ pci_xr17c154_setup(struct serial_private *priv,
 #define PCIE_DEVICE_ID_NEO_2_OX_IBM    0x00F6
 #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
 #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+#define PCI_VENDOR_ID_WCH              0x4348
+#define PCI_DEVICE_ID_WCH_CH353_4S     0x3453
+#define PCI_DEVICE_ID_WCH_CH353_2S1PF  0x5046
+#define PCI_DEVICE_ID_WCH_CH353_2S1P   0x7053
+#define PCI_VENDOR_ID_AGESTAR          0x5372
+#define PCI_DEVICE_ID_AGESTAR_9375     0x6872
+#define PCI_VENDOR_ID_ASIX             0x9710
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
@@ -1726,7 +1752,41 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_omegapci_setup,
-        },
+       },
+       /* WCH CH353 2S1P card (16550 clone) */
+       {
+               .vendor         = PCI_VENDOR_ID_WCH,
+               .device         = PCI_DEVICE_ID_WCH_CH353_2S1P,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_wch_ch353_setup,
+       },
+       /* WCH CH353 4S card (16550 clone) */
+       {
+               .vendor         = PCI_VENDOR_ID_WCH,
+               .device         = PCI_DEVICE_ID_WCH_CH353_4S,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_wch_ch353_setup,
+       },
+       /* WCH CH353 2S1PF card (16550 clone) */
+       {
+               .vendor         = PCI_VENDOR_ID_WCH,
+               .device         = PCI_DEVICE_ID_WCH_CH353_2S1PF,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_wch_ch353_setup,
+       },
+       /*
+        * ASIX devices with FIFO bug
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_ASIX,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_asix_setup,
+       },
        /*
         * Default "match everything" terminator entry
         */
@@ -1887,7 +1947,6 @@ enum pci_board_num_t {
        pbn_panacom,
        pbn_panacom2,
        pbn_panacom4,
-       pbn_exsys_4055,
        pbn_plx_romulus,
        pbn_oxsemi,
        pbn_oxsemi_1_4000000,
@@ -2393,13 +2452,6 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .reg_shift      = 7,
        },
 
-       [pbn_exsys_4055] = {
-               .flags          = FL_BASE2,
-               .num_ports      = 4,
-               .base_baud      = 115200,
-               .uart_offset    = 8,
-       },
-
        /* I think this entry is broken - the first_offset looks wrong --rmk */
        [pbn_plx_romulus] = {
                .flags          = FL_BASE2,
@@ -2624,10 +2676,14 @@ static struct pciserial_board pci_boards[] __devinitdata = {
        },
 };
 
-static const struct pci_device_id softmodem_blacklist[] = {
+static const struct pci_device_id blacklist[] = {
+       /* softmodems */
        { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */
        { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */
        { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */
+
+       /* multi-io cards handled by parport_serial */
+       { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
 };
 
 /*
@@ -2638,7 +2694,7 @@ static const struct pci_device_id softmodem_blacklist[] = {
 static int __devinit
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
-       const struct pci_device_id *blacklist;
+       const struct pci_device_id *bldev;
        int num_iomem, num_port, first_port = -1, i;
 
        /*
@@ -2655,13 +2711,13 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 
        /*
         * Do not access blacklisted devices that are known not to
-        * feature serial ports.
+        * feature serial ports or are handled by other modules.
         */
-       for (blacklist = softmodem_blacklist;
-            blacklist < softmodem_blacklist + ARRAY_SIZE(softmodem_blacklist);
-            blacklist++) {
-               if (dev->vendor == blacklist->vendor &&
-                   dev->device == blacklist->device)
+       for (bldev = blacklist;
+            bldev < blacklist + ARRAY_SIZE(blacklist);
+            bldev++) {
+               if (dev->vendor == bldev->vendor &&
+                   dev->device == bldev->device)
                        return -ENODEV;
        }
 
@@ -2728,7 +2784,7 @@ serial_pci_matches(const struct pciserial_board *board,
 struct serial_private *
 pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
 {
-       struct uart_port serial_port;
+       struct uart_8250_port uart;
        struct serial_private *priv;
        struct pci_serial_quirk *quirk;
        int rc, nr_ports, i;
@@ -2768,22 +2824,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
        priv->dev = dev;
        priv->quirk = quirk;
 
-       memset(&serial_port, 0, sizeof(struct uart_port));
-       serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-       serial_port.uartclk = board->base_baud * 16;
-       serial_port.irq = get_pci_irq(dev, board);
-       serial_port.dev = &dev->dev;
+       memset(&uart, 0, sizeof(uart));
+       uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+       uart.port.uartclk = board->base_baud * 16;
+       uart.port.irq = get_pci_irq(dev, board);
+       uart.port.dev = &dev->dev;
 
        for (i = 0; i < nr_ports; i++) {
-               if (quirk->setup(priv, board, &serial_port, i))
+               if (quirk->setup(priv, board, &uart, i))
                        break;
 
 #ifdef SERIAL_DEBUG_PCI
                printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
-                      serial_port.iobase, serial_port.irq, serial_port.iotype);
+                      uart.port.iobase, uart.port.irq, uart.port.iotype);
 #endif
 
-               priv->line[i] = serial8250_register_port(&serial_port);
+               priv->line[i] = serial8250_register_8250_port(&uart);
                if (priv->line[i] < 0) {
                        printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
                        break;
@@ -3193,7 +3249,7 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_SUBVENDOR_ID_EXSYS,
                PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
-               pbn_exsys_4055 },
+               pbn_b2_4_115200 },
        /*
         * Megawolf Romulus PCI Serial Card, from Mike Hudson
         * (Exoray@isys.ca)
@@ -3232,8 +3288,11 @@ static struct pci_device_id serial_pci_tbl[] = {
                 * For now just used the hex ID 0x950a.
                 */
        {       PCI_VENDOR_ID_OXSEMI, 0x950a,
-               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
-               pbn_b0_2_115200 },
+               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00,
+               0, 0, pbn_b0_2_115200 },
+       {       PCI_VENDOR_ID_OXSEMI, 0x950a,
+               PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30,
+               0, 0, pbn_b0_2_115200 },
        {       PCI_VENDOR_ID_OXSEMI, 0x950a,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b0_2_1130000 },
@@ -4178,6 +4237,25 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_omegapci },
 
+       /*
+        * AgeStar as-prs2-009
+        */
+       {       PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_bt_2_115200 },
+
+       /*
+        * WCH CH353 series devices: The 2S1P is handled by parport_serial
+        * so not listed here.
+        */
+       {       PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_4S,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_bt_4_115200 },
+
+       {       PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_2S1PF,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_bt_2_115200 },
+
        /*
         * These entries match devices with class COMMUNICATION_SERIAL,
         * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL