diff options
-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 { | |||
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 | ||
134 | static 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 | */ | ||
147 | static 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 | |||
133 | static const struct serial_quirk quirks[] = { | 167 | static 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[] = { | |||
171 | static int serial_config(struct pcmcia_device * link); | 215 | static int serial_config(struct pcmcia_device * link); |
172 | 216 | ||
173 | 217 | ||
174 | static 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 | } |