aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/serial_cs.c52
-rw-r--r--include/pcmcia/ciscode.h3
2 files changed, 49 insertions, 6 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 389d847cd1b4..2c70773543e0 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -41,6 +41,7 @@
41#include <linux/string.h> 41#include <linux/string.h>
42#include <linux/timer.h> 42#include <linux/timer.h>
43#include <linux/serial_core.h> 43#include <linux/serial_core.h>
44#include <linux/delay.h>
44#include <linux/major.h> 45#include <linux/major.h>
45#include <asm/io.h> 46#include <asm/io.h>
46#include <asm/system.h> 47#include <asm/system.h>
@@ -102,6 +103,8 @@ struct serial_info {
102 int multi; 103 int multi;
103 int slave; 104 int slave;
104 int manfid; 105 int manfid;
106 int prodid;
107 int c950ctrl;
105 dev_node_t node[4]; 108 dev_node_t node[4];
106 int line[4]; 109 int line[4];
107}; 110};
@@ -116,6 +119,33 @@ struct serial_cfg_mem {
116static int serial_config(struct pcmcia_device * link); 119static int serial_config(struct pcmcia_device * link);
117 120
118 121
122static void wakeup_card(struct serial_info *info)
123{
124 int ctrl = info->c950ctrl;
125
126 if (info->manfid == MANFID_OXSEMI) {
127 outb(12, ctrl + 1);
128 } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
129 /* request_region? oxsemi branch does no request_region too... */
130 /* This sequence is needed to properly initialize MC45 attached to OXCF950.
131 * I tried decreasing these msleep()s, but it worked properly (survived
132 * 1000 stop/start operations) with these timeouts (or bigger). */
133 outb(0xA, ctrl + 1);
134 msleep(100);
135 outb(0xE, ctrl + 1);
136 msleep(300);
137 outb(0xC, ctrl + 1);
138 msleep(100);
139 outb(0xE, ctrl + 1);
140 msleep(200);
141 outb(0xF, ctrl + 1);
142 msleep(100);
143 outb(0xE, ctrl + 1);
144 msleep(100);
145 outb(0xC, ctrl + 1);
146 }
147}
148
119/*====================================================================== 149/*======================================================================
120 150
121 After a card is removed, serial_remove() will unregister 151 After a card is removed, serial_remove() will unregister
@@ -161,6 +191,7 @@ static int serial_resume(struct pcmcia_device *link)
161 191
162 for (i = 0; i < info->ndev; i++) 192 for (i = 0; i < info->ndev; i++)
163 serial8250_resume_port(info->line[i]); 193 serial8250_resume_port(info->line[i]);
194 wakeup_card(info);
164 } 195 }
165 196
166 return 0; 197 return 0;
@@ -503,15 +534,23 @@ static int multi_config(struct pcmcia_device * link)
503 } 534 }
504 535
505 /* The Oxford Semiconductor OXCF950 cards are in fact single-port: 536 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
506 8 registers are for the UART, the others are extra registers */ 537 * 8 registers are for the UART, the others are extra registers.
507 if (info->manfid == MANFID_OXSEMI) { 538 * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
539 */
540 if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
541 info->prodid == PRODID_POSSIO_GCC)) {
542 int err;
543
508 if (cf->index == 1 || cf->index == 3) { 544 if (cf->index == 1 || cf->index == 3) {
509 setup_serial(link, info, base2, link->irq.AssignedIRQ); 545 err = setup_serial(link, info, base2,
510 outb(12, link->io.BasePort1 + 1); 546 link->irq.AssignedIRQ);
547 base2 = link->io.BasePort1;
511 } else { 548 } else {
512 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); 549 err = setup_serial(link, info, link->io.BasePort1,
513 outb(12, base2 + 1); 550 link->irq.AssignedIRQ);
514 } 551 }
552 info->c950ctrl = base2;
553 wakeup_card(info);
515 rc = 0; 554 rc = 0;
516 goto free_cfg_mem; 555 goto free_cfg_mem;
517 } 556 }
@@ -583,6 +622,7 @@ static int serial_config(struct pcmcia_device * link)
583 tuple->DesiredTuple = CISTPL_MANFID; 622 tuple->DesiredTuple = CISTPL_MANFID;
584 if (first_tuple(link, tuple, parse) == CS_SUCCESS) { 623 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
585 info->manfid = parse->manfid.manf; 624 info->manfid = parse->manfid.manf;
625 info->prodid = le16_to_cpu(buf[1]);
586 for (i = 0; i < MULTI_COUNT; i++) 626 for (i = 0; i < MULTI_COUNT; i++)
587 if ((info->manfid == multi_id[i].manfid) && 627 if ((info->manfid == multi_id[i].manfid) &&
588 (parse->manfid.card == multi_id[i].prodid)) 628 (parse->manfid.card == multi_id[i].prodid))
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index 951cdb5d5499..c1da8558339a 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -122,4 +122,7 @@
122 122
123#define MANFID_XIRCOM 0x0105 123#define MANFID_XIRCOM 0x0105
124 124
125#define MANFID_POSSIO 0x030c
126#define PRODID_POSSIO_GCC 0x0003
127
125#endif /* _LINUX_CISCODE_H */ 128#endif /* _LINUX_CISCODE_H */