diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-09-16 23:45:41 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-10-01 18:06:34 +0200 |
commit | 7ef057fa707897c19725d7e07123e57f6aea79db (patch) | |
tree | 16e3ba605a9b768362aba21cefd618bc9ca89053 /drivers/serial | |
parent | [SERIAL] serial_cs: convert IBM post-init handling to a quirk (diff) | |
download | linux-7ef057fa707897c19725d7e07123e57f6aea79db.tar.xz linux-7ef057fa707897c19725d7e07123e57f6aea79db.zip |
[SERIAL] serial_cs: Convert Oxford 950 / Possio GCC wakeup quirk
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>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/serial_cs.c | 100 |
1 files changed, 63 insertions, 37 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ac4571a25b30..8e48cb659b3d 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -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,6 +131,39 @@ 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, @@ -137,10 +171,28 @@ static const struct serial_quirk quirks[] = { .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, .multi = 2, @@ -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; } |