[SERIAL] serial_cs: Convert Oxford 950 / Possio GCC wakeup quirk
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Sat, 16 Sep 2006 21:45:41 +0000 (22:45 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 1 Oct 2006 16:06:34 +0000 (17:06 +0100)
Move the Oxford Semi OX950 / Possio GCC wakeup handling to a quirk
wakeup handler.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/serial/serial_cs.c

index ac4571a25b30465627d4c4f235217effd461a537..8e48cb659b3d021efe734745227f4b4b8537c280 100644 (file)
@@ -84,6 +84,7 @@ struct serial_quirk {
        unsigned int manfid;
        unsigned int prodid;
        int multi;              /* 1 = multifunction, > 1 = # ports */
+       void (*wakeup)(struct pcmcia_device *);
        int (*post)(struct pcmcia_device *);
 };
 
@@ -130,16 +131,67 @@ static int quirk_post_ibm(struct pcmcia_device *link)
        return -ENODEV;
 }
 
+static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+
+       outb(12, info->c950ctrl + 1);
+}
+
+/* request_region? oxsemi branch does no request_region too... */
+/*
+ * This sequence is needed to properly initialize MC45 attached to OXCF950.
+ * I tried decreasing these msleep()s, but it worked properly (survived
+ * 1000 stop/start operations) with these timeouts (or bigger).
+ */
+static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       unsigned int ctrl = info->c950ctrl;
+
+       outb(0xA, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(300);
+       outb(0xC, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(200);
+       outb(0xF, ctrl + 1);
+       msleep(100);
+       outb(0xE, ctrl + 1);
+       msleep(100);
+       outb(0xC, ctrl + 1);
+}
+
 static const struct serial_quirk quirks[] = {
        {
                .manfid = MANFID_IBM,
                .prodid = ~0,
                .multi  = -1,
                .post   = quirk_post_ibm,
+       }, {
+               .manfid = MANFID_INTEL,
+               .prodid = PRODID_INTEL_DUAL_RS232,
+               .multi  = 2,
+       }, {
+               .manfid = MANFID_NATINST,
+               .prodid = PRODID_NATINST_QUAD_RS232,
+               .multi  = 4,
        }, {
                .manfid = MANFID_OMEGA,
                .prodid = PRODID_OMEGA_QSP_100,
                .multi  = 4,
+       }, {
+               .manfid = MANFID_OXSEMI,
+               .prodid = ~0,
+               .multi  = -1,
+               .wakeup = quirk_wakeup_oxsemi,
+       }, {
+               .manfid = MANFID_POSSIO,
+               .prodid = PRODID_POSSIO_GCC,
+               .multi  = -1,
+               .wakeup = quirk_wakeup_possio_gcc,
        }, {
                .manfid = MANFID_QUATECH,
                .prodid = PRODID_QUATECH_DUAL_RS232,
@@ -156,14 +208,6 @@ static const struct serial_quirk quirks[] = {
                .manfid = MANFID_SOCKET,
                .prodid = PRODID_SOCKET_DUAL_RS232,
                .multi  = 2,
-       }, {
-               .manfid = MANFID_INTEL,
-               .prodid = PRODID_INTEL_DUAL_RS232,
-               .multi  = 2,
-       }, {
-               .manfid = MANFID_NATINST,
-               .prodid = PRODID_NATINST_QUAD_RS232,
-               .multi  = 4,
        }
 };
 
@@ -171,33 +215,6 @@ static const struct serial_quirk quirks[] = {
 static int serial_config(struct pcmcia_device * link);
 
 
-static void wakeup_card(struct serial_info *info)
-{
-       int ctrl = info->c950ctrl;
-
-       if (info->manfid == MANFID_OXSEMI) {
-               outb(12, ctrl + 1);
-       } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
-               /* request_region? oxsemi branch does no request_region too... */
-               /* This sequence is needed to properly initialize MC45 attached to OXCF950.
-                * I tried decreasing these msleep()s, but it worked properly (survived
-                * 1000 stop/start operations) with these timeouts (or bigger). */
-               outb(0xA, ctrl + 1);
-               msleep(100);
-               outb(0xE, ctrl + 1);
-               msleep(300);
-               outb(0xC, ctrl + 1);
-               msleep(100);
-               outb(0xE, ctrl + 1);
-               msleep(200);
-               outb(0xF, ctrl + 1);
-               msleep(100);
-               outb(0xE, ctrl + 1);
-               msleep(100);
-               outb(0xC, ctrl + 1);
-       }
-}
-
 /*======================================================================
 
     After a card is removed, serial_remove() will unregister
@@ -243,7 +260,9 @@ static int serial_resume(struct pcmcia_device *link)
 
                for (i = 0; i < info->ndev; i++)
                        serial8250_resume_port(info->line[i]);
-               wakeup_card(info);
+
+               if (info->quirk && info->quirk->wakeup)
+                       info->quirk->wakeup(link);
        }
 
        return 0;
@@ -602,7 +621,14 @@ static int multi_config(struct pcmcia_device * link)
                                        link->irq.AssignedIRQ);
                }
                info->c950ctrl = base2;
-               wakeup_card(info);
+
+               /*
+                * FIXME: We really should wake up the port prior to
+                * handing it over to the serial layer.
+                */
+               if (info->quirk && info->quirk->wakeup)
+                       info->quirk->wakeup(link);
+
                rc = 0;
                goto free_cfg_mem;
        }