Commit 7ef057fa authored by Russell King's avatar Russell King Committed by Russell King

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent eee3a883
...@@ -84,6 +84,7 @@ struct serial_quirk { ...@@ -84,6 +84,7 @@ struct serial_quirk {
unsigned int manfid; unsigned int manfid;
unsigned int prodid; unsigned int prodid;
int multi; /* 1 = multifunction, > 1 = # ports */ int multi; /* 1 = multifunction, > 1 = # ports */
void (*wakeup)(struct pcmcia_device *);
int (*post)(struct pcmcia_device *); int (*post)(struct pcmcia_device *);
}; };
...@@ -130,16 +131,67 @@ static int quirk_post_ibm(struct pcmcia_device *link) ...@@ -130,16 +131,67 @@ static int quirk_post_ibm(struct pcmcia_device *link)
return -ENODEV; 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[] = { static const struct serial_quirk quirks[] = {
{ {
.manfid = MANFID_IBM, .manfid = MANFID_IBM,
.prodid = ~0, .prodid = ~0,
.multi = -1, .multi = -1,
.post = quirk_post_ibm, .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, .manfid = MANFID_OMEGA,
.prodid = PRODID_OMEGA_QSP_100, .prodid = PRODID_OMEGA_QSP_100,
.multi = 4, .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, .manfid = MANFID_QUATECH,
.prodid = PRODID_QUATECH_DUAL_RS232, .prodid = PRODID_QUATECH_DUAL_RS232,
...@@ -156,14 +208,6 @@ static const struct serial_quirk quirks[] = { ...@@ -156,14 +208,6 @@ static const struct serial_quirk quirks[] = {
.manfid = MANFID_SOCKET, .manfid = MANFID_SOCKET,
.prodid = PRODID_SOCKET_DUAL_RS232, .prodid = PRODID_SOCKET_DUAL_RS232,
.multi = 2, .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[] = { ...@@ -171,33 +215,6 @@ static const struct serial_quirk quirks[] = {
static int serial_config(struct pcmcia_device * link); 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 After a card is removed, serial_remove() will unregister
...@@ -243,7 +260,9 @@ static int serial_resume(struct pcmcia_device *link) ...@@ -243,7 +260,9 @@ static int serial_resume(struct pcmcia_device *link)
for (i = 0; i < info->ndev; i++) for (i = 0; i < info->ndev; i++)
serial8250_resume_port(info->line[i]); serial8250_resume_port(info->line[i]);
wakeup_card(info);
if (info->quirk && info->quirk->wakeup)
info->quirk->wakeup(link);
} }
return 0; return 0;
...@@ -602,7 +621,14 @@ static int multi_config(struct pcmcia_device * link) ...@@ -602,7 +621,14 @@ static int multi_config(struct pcmcia_device * link)
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
} }
info->c950ctrl = base2; 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; rc = 0;
goto free_cfg_mem; goto free_cfg_mem;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment