Revert "clocksource: tegra20: use the device_node pointer passed to init"
[linux-3.10.git] / drivers / parport / parport_serial.c
index bd6ad8b..1b8bdb7 100644 (file)
@@ -20,7 +20,9 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 #include <linux/8250_pci.h>
@@ -30,6 +32,10 @@ enum parport_pc_pci_cards {
        titan_210l,
        netmos_9xx5_combo,
        netmos_9855,
+       netmos_9855_2p,
+       netmos_9900,
+       netmos_9900_2p,
+       netmos_99xx_1p,
        avlab_1s1p,
        avlab_1s2p,
        avlab_2s1p,
@@ -38,6 +44,26 @@ enum parport_pc_pci_cards {
        siig_2p1s_20x,
        siig_1s1p_20x,
        siig_2s1p_20x,
+       timedia_4078a,
+       timedia_4079h,
+       timedia_4085h,
+       timedia_4088a,
+       timedia_4089a,
+       timedia_4095a,
+       timedia_4096a,
+       timedia_4078u,
+       timedia_4079a,
+       timedia_4085u,
+       timedia_4079r,
+       timedia_4079s,
+       timedia_4079d,
+       timedia_4079e,
+       timedia_4079f,
+       timedia_9079a,
+       timedia_9079b,
+       timedia_9079c,
+       wch_ch353_2s1p,
+       sunix_2s1p,
 };
 
 /* each element directly indexed from enum list, above */
@@ -62,22 +88,40 @@ struct parport_pc_pci {
                                struct parport_pc_pci *card, int failed);
 };
 
-static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *card, int autoirq, int autodma)
+static int netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par,
+                               int autoirq, int autodma)
 {
-       /*
-        * Netmos uses the subdevice ID to indicate the number of parallel
-        * and serial ports.  The form is 0x00PS, where <P> is the number of
-        * parallel ports and <S> is the number of serial ports.
-        */
-       card->numports = (dev->subsystem_device & 0xf0) >> 4;
+       /* the rule described below doesn't hold for this device */
+       if (dev->device == PCI_DEVICE_ID_NETMOS_9835 &&
+                       dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+                       dev->subsystem_device == 0x0299)
+               return -ENODEV;
+
+       if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
+               par->numports = 1;
+       } else {
+               /*
+                * Netmos uses the subdevice ID to indicate the number of parallel
+                * and serial ports.  The form is 0x00PS, where <P> is the number of
+                * parallel ports and <S> is the number of serial ports.
+                */
+               par->numports = (dev->subsystem_device & 0xf0) >> 4;
+               if (par->numports > ARRAY_SIZE(par->addr))
+                       par->numports = ARRAY_SIZE(par->addr);
+       }
+
        return 0;
 }
 
-static struct parport_pc_pci cards[] __devinitdata = {
+static struct parport_pc_pci cards[] = {
        /* titan_110l */                { 1, { { 3, -1 }, } },
        /* titan_210l */                { 1, { { 3, -1 }, } },
        /* netmos_9xx5_combo */         { 1, { { 2, -1 }, }, netmos_parallel_init },
        /* netmos_9855 */               { 1, { { 0, -1 }, }, netmos_parallel_init },
+       /* netmos_9855_2p */            { 2, { { 0, -1 }, { 2, -1 }, } },
+       /* netmos_9900 */               {1, { { 3, 4 }, }, netmos_parallel_init },
+       /* netmos_9900_2p */            {2, { { 0, 1 }, { 3, 4 }, } },
+       /* netmos_99xx_1p */            {1, { { 0, 1 }, } },
        /* avlab_1s1p     */            { 1, { { 1, 2}, } },
        /* avlab_1s2p     */            { 2, { { 1, 2}, { 3, 4 },} },
        /* avlab_2s1p     */            { 1, { { 2, 3}, } },
@@ -86,8 +130,31 @@ static struct parport_pc_pci cards[] __devinitdata = {
        /* siig_2p1s_20x */             { 2, { { 1, 2 }, { 3, 4 }, } },
        /* siig_1s1p_20x */             { 1, { { 1, 2 }, } },
        /* siig_2s1p_20x */             { 1, { { 2, 3 }, } },
+       /* timedia_4078a */             { 1, { { 2, -1 }, } },
+       /* timedia_4079h */             { 1, { { 2, 3 }, } },
+       /* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
+       /* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+       /* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+       /* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+       /* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+       /* timedia_4078u */             { 1, { { 2, -1 }, } },
+       /* timedia_4079a */             { 1, { { 2, 3 }, } },
+       /* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
+       /* timedia_4079r */             { 1, { { 2, 3 }, } },
+       /* timedia_4079s */             { 1, { { 2, 3 }, } },
+       /* timedia_4079d */             { 1, { { 2, 3 }, } },
+       /* timedia_4079e */             { 1, { { 2, 3 }, } },
+       /* timedia_4079f */             { 1, { { 2, 3 }, } },
+       /* timedia_9079a */             { 1, { { 2, 3 }, } },
+       /* timedia_9079b */             { 1, { { 2, 3 }, } },
+       /* timedia_9079c */             { 1, { { 2, 3 }, } },
+       /* wch_ch353_2s1p*/             { 1, { { 2, -1}, } },
+       /* sunix_2s1p */                { 1, { { 3, -1 }, } },
 };
 
+#define PCI_VENDOR_ID_SUNIX            0x1fd4
+#define PCI_DEVICE_ID_SUNIX_1999       0x1999
+
 static struct pci_device_id parport_serial_pci_tbl[] = {
        /* PCI cards */
        { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
@@ -103,7 +170,19 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
+         0x1000, 0x0020, 0, 0, netmos_9855_2p },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
+         0x1000, 0x0022, 0, 0, netmos_9855_2p },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+         0xA000, 0x3011, 0, 0, netmos_9900 },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+         0xA000, 0x3012, 0, 0, netmos_9900 },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+         0xA000, 0x3020, 0, 0, netmos_9900_2p },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+         0xA000, 0x2000, 0, 0, netmos_99xx_1p },
        /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
        { PCI_VENDOR_ID_AFAVLAB, 0x2110,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@@ -153,6 +232,36 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
        { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+       /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
+       { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
+       { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
+       { 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
+       { 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
+       { 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
+       { 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
+       { 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
+       { 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
+       { 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
+       { 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
+       { 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
+       { 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
+       { 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
+       { 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
+       { 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
+       { 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
+       { 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
+       { 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
+
+       /* WCH CARDS */
+       { 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
+
+       /*
+        * More SUNIX variations. At least one of these has part number
+        * '5079A but subdevice 0x102. That board reports 0x0708 as
+        * its PCI Class.
+        */
+       { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
+         0x0102, 0, 0, sunix_2s1p },
 
        { 0, } /* terminate list */
 };
@@ -165,7 +274,7 @@ MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
  * Cards not tested are marked n/t
  * If you have one of these cards and it works for you, please tell me..
  */
-static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
+static struct pciserial_board pci_parport_serial_boards[] = {
        [titan_110l] = {
                .flags          = FL_BASE1 | FL_BASE_BARS,
                .num_ports      = 1,
@@ -190,6 +299,30 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
                .base_baud      = 115200,
                .uart_offset    = 8,
        },
+       [netmos_9855_2p] = {
+               .flags          = FL_BASE4 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [netmos_9900] = { /* n/t */
+               .flags          = FL_BASE0 | FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [netmos_9900_2p] = { /* parallel only */ /* n/t */
+               .flags          = FL_BASE0,
+               .num_ports      = 0,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [netmos_99xx_1p] = { /* parallel only */ /* n/t */
+               .flags          = FL_BASE0,
+               .num_ports      = 0,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
        [avlab_1s1p] = { /* n/t */
                .flags          = FL_BASE0 | FL_BASE_BARS,
                .num_ports      = 1,
@@ -238,6 +371,126 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
                .base_baud      = 921600,
                .uart_offset    = 8,
        },
+       [timedia_4078a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079h] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4085h] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4088a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4089a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4095a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4096a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4078u] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4085u] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079r] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079s] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079d] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079e] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_4079f] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_9079a] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_9079b] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [timedia_9079c] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [wch_ch353_2s1p] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+       },
+       [sunix_2s1p] = {
+               .flags          = FL_BASE0|FL_BASE_BARS,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
 };
 
 struct parport_serial_private {
@@ -248,14 +501,17 @@ struct parport_serial_private {
 };
 
 /* Register the serial port(s) of a PCI card. */
-static int __devinit serial_register (struct pci_dev *dev,
-                                     const struct pci_device_id *id)
+static int serial_register(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        struct pciserial_board *board;
        struct serial_private *serial;
 
        board = &pci_parport_serial_boards[id->driver_data];
+
+       if (board->num_ports == 0)
+               return 0;
+
        serial = pciserial_init_ports(dev, board);
 
        if (IS_ERR(serial))
@@ -266,8 +522,7 @@ static int __devinit serial_register (struct pci_dev *dev,
 }
 
 /* Register the parallel port(s) of a PCI card. */
-static int __devinit parport_register (struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct parport_pc_pci *card;
        struct parport_serial_private *priv = pci_get_drvdata (dev);
@@ -284,6 +539,7 @@ static int __devinit parport_register (struct pci_dev *dev,
                int lo = card->addr[n].lo;
                int hi = card->addr[n].hi;
                unsigned long io_lo, io_hi;
+               int irq;
 
                if (priv->num_par == ARRAY_SIZE (priv->port)) {
                        printk (KERN_WARNING
@@ -302,10 +558,19 @@ static int __devinit parport_register (struct pci_dev *dev,
                                         "hi" as an offset (see SYBA
                                         def.) */
                /* TODO: test if sharing interrupts works */
-               dev_dbg(&dev->dev, "PCI parallel port detected: I/O at "
-                       "%#lx(%#lx)\n", io_lo, io_hi);
-               port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-                                             PARPORT_DMA_NONE, &dev->dev);
+               irq = dev->irq;
+               if (irq == IRQ_NONE) {
+                       dev_dbg(&dev->dev,
+                       "PCI parallel port detected: I/O at %#lx(%#lx)\n",
+                               io_lo, io_hi);
+                       irq = PARPORT_IRQ_NONE;
+               } else {
+                       dev_dbg(&dev->dev,
+               "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
+                               io_lo, io_hi, irq);
+               }
+               port = parport_pc_probe_port (io_lo, io_hi, irq,
+                             PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED);
                if (port) {
                        priv->port[priv->num_par++] = port;
                        success = 1;
@@ -318,8 +583,8 @@ static int __devinit parport_register (struct pci_dev *dev,
        return 0;
 }
 
-static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
-                                              const struct pci_device_id *id)
+static int parport_serial_pci_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
 {
        struct parport_serial_private *priv;
        int err;
@@ -354,7 +619,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
        return 0;
 }
 
-static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
+static void parport_serial_pci_remove(struct pci_dev *dev)
 {
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        int i;
@@ -419,7 +684,7 @@ static struct pci_driver parport_serial_pci_driver = {
        .name           = "parport_serial",
        .id_table       = parport_serial_pci_tbl,
        .probe          = parport_serial_pci_probe,
-       .remove         = __devexit_p(parport_serial_pci_remove),
+       .remove         = parport_serial_pci_remove,
 #ifdef CONFIG_PM
        .suspend        = parport_serial_pci_suspend,
        .resume         = parport_serial_pci_resume,