aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/serial_cs.c100
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 {
84 unsigned int manfid; 84 unsigned int manfid;
85 unsigned int prodid; 85 unsigned int prodid;
86 int multi; /* 1 = multifunction, > 1 = # ports */ 86 int multi; /* 1 = multifunction, > 1 = # ports */
87 void (*wakeup)(struct pcmcia_device *);
87 int (*post)(struct pcmcia_device *); 88 int (*post)(struct pcmcia_device *);
88}; 89};
89 90
@@ -130,6 +131,39 @@ static int quirk_post_ibm(struct pcmcia_device *link)
130 return -ENODEV; 131 return -ENODEV;
131} 132}
132 133
134static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
135{
136 struct serial_info *info = link->priv;
137
138 outb(12, info->c950ctrl + 1);
139}
140
141/* request_region? oxsemi branch does no request_region too... */
142/*
143 * This sequence is needed to properly initialize MC45 attached to OXCF950.
144 * I tried decreasing these msleep()s, but it worked properly (survived
145 * 1000 stop/start operations) with these timeouts (or bigger).
146 */
147static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
148{
149 struct serial_info *info = link->priv;
150 unsigned int ctrl = info->c950ctrl;
151
152 outb(0xA, ctrl + 1);
153 msleep(100);
154 outb(0xE, ctrl + 1);
155 msleep(300);
156 outb(0xC, ctrl + 1);
157 msleep(100);
158 outb(0xE, ctrl + 1);
159 msleep(200);
160 outb(0xF, ctrl + 1);
161 msleep(100);
162 outb(0xE, ctrl + 1);
163 msleep(100);
164 outb(0xC, ctrl + 1);
165}
166
133static const struct serial_quirk quirks[] = { 167static const struct serial_quirk quirks[] = {
134 { 168 {
135 .manfid = MANFID_IBM, 169 .manfid = MANFID_IBM,
@@ -137,10 +171,28 @@ static const struct serial_quirk quirks[] = {
137 .multi = -1, 171 .multi = -1,
138 .post = quirk_post_ibm, 172 .post = quirk_post_ibm,
139 }, { 173 }, {
174 .manfid = MANFID_INTEL,
175 .prodid = PRODID_INTEL_DUAL_RS232,
176 .multi = 2,
177 }, {
178 .manfid = MANFID_NATINST,
179 .prodid = PRODID_NATINST_QUAD_RS232,
180 .multi = 4,
181 }, {
140 .manfid = MANFID_OMEGA, 182 .manfid = MANFID_OMEGA,
141 .prodid = PRODID_OMEGA_QSP_100, 183 .prodid = PRODID_OMEGA_QSP_100,
142 .multi = 4, 184 .multi = 4,
143 }, { 185 }, {
186 .manfid = MANFID_OXSEMI,
187 .prodid = ~0,
188 .multi = -1,
189 .wakeup = quirk_wakeup_oxsemi,
190 }, {
191 .manfid = MANFID_POSSIO,
192 .prodid = PRODID_POSSIO_GCC,
193 .multi = -1,
194 .wakeup = quirk_wakeup_possio_gcc,
195 }, {
144 .manfid = MANFID_QUATECH, 196 .manfid = MANFID_QUATECH,
145 .prodid = PRODID_QUATECH_DUAL_RS232, 197 .prodid = PRODID_QUATECH_DUAL_RS232,
146 .multi = 2, 198 .multi = 2,
@@ -156,14 +208,6 @@ static const struct serial_quirk quirks[] = {
156 .manfid = MANFID_SOCKET, 208 .manfid = MANFID_SOCKET,
157 .prodid = PRODID_SOCKET_DUAL_RS232, 209 .prodid = PRODID_SOCKET_DUAL_RS232,
158 .multi = 2, 210 .multi = 2,
159 }, {
160 .manfid = MANFID_INTEL,
161 .prodid = PRODID_INTEL_DUAL_RS232,
162 .multi = 2,
163 }, {
164 .manfid = MANFID_NATINST,
165 .prodid = PRODID_NATINST_QUAD_RS232,
166 .multi = 4,
167 } 211 }
168}; 212};
169 213
@@ -171,33 +215,6 @@ static const struct serial_quirk quirks[] = {
171static int serial_config(struct pcmcia_device * link); 215static int serial_config(struct pcmcia_device * link);
172 216
173 217
174static void wakeup_card(struct serial_info *info)
175{
176 int ctrl = info->c950ctrl;
177
178 if (info->manfid == MANFID_OXSEMI) {
179 outb(12, ctrl + 1);
180 } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
181 /* request_region? oxsemi branch does no request_region too... */
182 /* This sequence is needed to properly initialize MC45 attached to OXCF950.
183 * I tried decreasing these msleep()s, but it worked properly (survived
184 * 1000 stop/start operations) with these timeouts (or bigger). */
185 outb(0xA, ctrl + 1);
186 msleep(100);
187 outb(0xE, ctrl + 1);
188 msleep(300);
189 outb(0xC, ctrl + 1);
190 msleep(100);
191 outb(0xE, ctrl + 1);
192 msleep(200);
193 outb(0xF, ctrl + 1);
194 msleep(100);
195 outb(0xE, ctrl + 1);
196 msleep(100);
197 outb(0xC, ctrl + 1);
198 }
199}
200
201/*====================================================================== 218/*======================================================================
202 219
203 After a card is removed, serial_remove() will unregister 220 After a card is removed, serial_remove() will unregister
@@ -243,7 +260,9 @@ static int serial_resume(struct pcmcia_device *link)
243 260
244 for (i = 0; i < info->ndev; i++) 261 for (i = 0; i < info->ndev; i++)
245 serial8250_resume_port(info->line[i]); 262 serial8250_resume_port(info->line[i]);
246 wakeup_card(info); 263
264 if (info->quirk && info->quirk->wakeup)
265 info->quirk->wakeup(link);
247 } 266 }
248 267
249 return 0; 268 return 0;
@@ -602,7 +621,14 @@ static int multi_config(struct pcmcia_device * link)
602 link->irq.AssignedIRQ); 621 link->irq.AssignedIRQ);
603 } 622 }
604 info->c950ctrl = base2; 623 info->c950ctrl = base2;
605 wakeup_card(info); 624
625 /*
626 * FIXME: We really should wake up the port prior to
627 * handing it over to the serial layer.
628 */
629 if (info->quirk && info->quirk->wakeup)
630 info->quirk->wakeup(link);
631
606 rc = 0; 632 rc = 0;
607 goto free_cfg_mem; 633 goto free_cfg_mem;
608 } 634 }