1 /* $OpenBSD: com_cardbus.c,v 1.12 2005/06/29 18:22:49 deraadt Exp $ */
2 /* $NetBSD: com_cardbus.c,v 1.4 2000/04/17 09:21:59 joda Exp $ */
3
4 /*
5 * Copyright (c) 2000 Johan Danielsson
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of author nor the names of any contributors may
20 * be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /* This is a driver for CardBus based serial devices. It is less
37 generic than it could be, but it keeps the complexity down. So far
38 it assumes that anything that reports itself as a `serial' device
39 is infact a 16x50 or 8250, which is not necessarily true (in
40 practice this shouldn't be a problem). It also does not handle
41 devices in the `multiport serial' or `modem' sub-classes, I've
42 never seen any of these, so I don't know what they might look like.
43
44 If the CardBus device only has one BAR (that is not also the CIS
45 BAR) listed in the CIS, it is assumed to be the one to use. For
46 devices with more than one BAR, the list of known devies has to be
47 updated below. */
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/tty.h>
52 #include <sys/device.h>
53
54 #include <dev/cardbus/cardbusvar.h>
55 #include <dev/pci/pcidevs.h>
56
57 #include <dev/pcmcia/pcmciareg.h>
58
59 #include <dev/isa/isavar.h>
60
61 #include "com.h"
62 #ifdef i386
63 #include "pccom.h"
64 #endif
65
66 #include <dev/ic/comreg.h>
67 #if NPCCOM > 0
68 #include <i386/isa/pccomvar.h>
69 #endif
70 #if NCOM > 0
71 #include <dev/ic/comvar.h>
72 #endif
73 #include <dev/ic/ns16550reg.h>
74
75 #define com_lcr com_cfcr
76
77 struct com_cardbus_softc {
78 struct com_softc cc_com;
79 void *cc_ih;
80 cardbus_devfunc_t cc_ct;
81 bus_addr_t cc_addr;
82 cardbusreg_t cc_base;
83 bus_size_t cc_size;
84 cardbusreg_t cc_csr;
85 int cc_cben;
86 cardbustag_t cc_tag;
87 cardbusreg_t cc_reg;
88 int cc_type;
89 };
90
91 #define DEVNAME(CSC) ((CSC)->cc_com.sc_dev.dv_xname)
92
93 int com_cardbus_match(struct device *, void *, void *);
94 void com_cardbus_attach(struct device *, struct device *, void *);
95 int com_cardbus_detach(struct device *, int);
96
97 void com_cardbus_setup(struct com_cardbus_softc *);
98 int com_cardbus_enable(struct com_softc *);
99 void com_cardbus_disable(struct com_softc *);
100 struct csdev *com_cardbus_find_csdev(struct cardbus_attach_args *);
101 int com_cardbus_gofigure(struct cardbus_attach_args *,
102 struct com_cardbus_softc *);
103 void com_cardbus_attach2(struct com_softc *);
104
105 #if NCOM_CARDBUS
106 struct cfattach com_cardbus_ca = {
107 sizeof(struct com_cardbus_softc), com_cardbus_match,
108 com_cardbus_attach, com_cardbus_detach, com_activate
109 };
110 #elif NPCCOM_CARDBUS
111 struct cfattach pccom_cardbus_ca = {
112 sizeof(struct com_cardbus_softc), com_cardbus_match,
113 com_cardbus_attach, com_cardbus_detach, com_activate
114 };
115 #endif
116
117 static struct csdev {
118 int vendor;
119 int product;
120 cardbusreg_t reg;
121 int type;
122 } csdevs[] = {
123 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_MODEM56,
124 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
125 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_CBEM56G,
126 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
127 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MODEM56,
128 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
129 { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_MODEM56,
130 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
131 { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_GLOBALMODEM56,
132 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
133 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_SERIAL,
134 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO }
135 };
136
137 static const int ncsdevs = sizeof(csdevs) / sizeof(csdevs[0]);
138
139 struct csdev*
com_cardbus_find_csdev(struct cardbus_attach_args * ca)140 com_cardbus_find_csdev(struct cardbus_attach_args *ca)
141 {
142 struct csdev *cp;
143
144 for (cp = csdevs; cp < csdevs + ncsdevs; cp++)
145 if (cp->vendor == CARDBUS_VENDOR(ca->ca_id) &&
146 cp->product == CARDBUS_PRODUCT(ca->ca_id))
147 return (cp);
148 return (NULL);
149 }
150
151 int
com_cardbus_match(struct device * parent,void * match,void * aux)152 com_cardbus_match(struct device *parent, void *match, void *aux)
153 {
154 struct cardbus_attach_args *ca = aux;
155
156 /* known devices are ok */
157 if (com_cardbus_find_csdev(ca) != NULL)
158 return (10);
159
160 /* as are serial devices with a known UART */
161 if (ca->ca_cis.funcid == PCMCIA_FUNCTION_SERIAL &&
162 ca->ca_cis.funce.serial.uart_present != 0 &&
163 (ca->ca_cis.funce.serial.uart_type == 0 || /* 8250 */
164 ca->ca_cis.funce.serial.uart_type == 1 || /* 16450 */
165 ca->ca_cis.funce.serial.uart_type == 2)) /* 16550 */
166 return (1);
167
168 return (0);
169 }
170
171 int
com_cardbus_gofigure(struct cardbus_attach_args * ca,struct com_cardbus_softc * csc)172 com_cardbus_gofigure(struct cardbus_attach_args *ca,
173 struct com_cardbus_softc *csc)
174 {
175 int i, index = -1;
176 cardbusreg_t cis_ptr;
177 struct csdev *cp;
178
179 /* If this device is listed above, use the known values, */
180 cp = com_cardbus_find_csdev(ca);
181 if (cp != NULL) {
182 csc->cc_reg = cp->reg;
183 csc->cc_type = cp->type;
184 return (0);
185 }
186
187 cis_ptr = Cardbus_conf_read(csc->cc_ct, csc->cc_tag, CARDBUS_CIS_REG);
188
189 /* otherwise try to deduce which BAR and type to use from CIS. If
190 there is only one BAR, it must be the one we should use, if
191 there are more, we're out of luck. */
192 for (i = 0; i < 7; i++) {
193 /* ignore zero sized BARs */
194 if (ca->ca_cis.bar[i].size == 0)
195 continue;
196 /* ignore the CIS BAR */
197 if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
198 CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
199 continue;
200 if (index != -1)
201 goto multi_bar;
202 index = i;
203 }
204 if (index == -1) {
205 printf(": couldn't find any base address tuple\n");
206 return (1);
207 }
208 csc->cc_reg = CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[index].flags);
209 if ((ca->ca_cis.bar[index].flags & 0x10) == 0)
210 csc->cc_type = CARDBUS_MAPREG_TYPE_MEM;
211 else
212 csc->cc_type = CARDBUS_MAPREG_TYPE_IO;
213 return (0);
214
215 multi_bar:
216 printf(": there are more than one possible base\n");
217
218 printf("%s: address for this device, "
219 "please report the following information\n",
220 DEVNAME(csc));
221 printf("%s: vendor 0x%x product 0x%x\n", DEVNAME(csc),
222 CARDBUS_VENDOR(ca->ca_id), CARDBUS_PRODUCT(ca->ca_id));
223 for (i = 0; i < 7; i++) {
224 /* ignore zero sized BARs */
225 if (ca->ca_cis.bar[i].size == 0)
226 continue;
227 /* ignore the CIS BAR */
228 if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
229 CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
230 continue;
231 printf("%s: base address %x type %s size %x\n",
232 DEVNAME(csc), CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags),
233 (ca->ca_cis.bar[i].flags & 0x10) ? "i/o" : "mem",
234 ca->ca_cis.bar[i].size);
235 }
236 return (1);
237 }
238
239 void
com_cardbus_attach(struct device * parent,struct device * self,void * aux)240 com_cardbus_attach(struct device *parent, struct device *self, void *aux)
241 {
242 struct com_softc *sc = (struct com_softc*)self;
243 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)self;
244 struct cardbus_attach_args *ca = aux;
245
246 csc->cc_ct = ca->ca_ct;
247 csc->cc_tag = Cardbus_make_tag(csc->cc_ct);
248
249 if (com_cardbus_gofigure(ca, csc) != 0)
250 return;
251
252 if (Cardbus_mapreg_map(ca->ca_ct, csc->cc_reg, csc->cc_type, 0,
253 &sc->sc_iot, &sc->sc_ioh, &csc->cc_addr, &csc->cc_size) != 0) {
254 printf("failed to map memory");
255 return;
256 }
257
258 csc->cc_base = csc->cc_addr;
259 csc->cc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
260 if (csc->cc_type == CARDBUS_MAPREG_TYPE_IO) {
261 csc->cc_base |= CARDBUS_MAPREG_TYPE_IO;
262 csc->cc_csr |= CARDBUS_COMMAND_IO_ENABLE;
263 csc->cc_cben = CARDBUS_IO_ENABLE;
264 } else {
265 csc->cc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
266 csc->cc_cben = CARDBUS_MEM_ENABLE;
267 }
268
269 sc->sc_iobase = csc->cc_addr;
270 sc->sc_frequency = COM_FREQ;
271
272 timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc);
273 timeout_set(&sc->sc_diag_tmo, comdiag, sc);
274
275 sc->enable = com_cardbus_enable;
276 sc->disable = com_cardbus_disable;
277 sc->enabled = 0;
278
279 if (ca->ca_cis.cis1_info[0] && ca->ca_cis.cis1_info[1]) {
280 printf(": %s %s\n", ca->ca_cis.cis1_info[0],
281 ca->ca_cis.cis1_info[1]);
282 printf("%s", DEVNAME(csc));
283 }
284
285 if (com_cardbus_enable(sc))
286 printf(": function enable failed\n");
287 sc->enabled = 1;
288 com_cardbus_attach2(sc);
289 }
290
291 void
com_cardbus_setup(struct com_cardbus_softc * csc)292 com_cardbus_setup(struct com_cardbus_softc *csc)
293 {
294 cardbus_devfunc_t ct = csc->cc_ct;
295 cardbus_chipset_tag_t cc = ct->ct_cc;
296 cardbus_function_tag_t cf = ct->ct_cf;
297 cardbusreg_t reg;
298
299 Cardbus_conf_write(ct, csc->cc_tag, csc->cc_reg, csc->cc_base);
300
301 /* enable accesses on cardbus bridge */
302 cf->cardbus_ctrl(cc, csc->cc_cben);
303 cf->cardbus_ctrl(cc, CARDBUS_BM_ENABLE);
304
305 /* and the card itself */
306 reg = Cardbus_conf_read(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG);
307 reg &= ~(CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE);
308 reg |= csc->cc_csr;
309 Cardbus_conf_write(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG, reg);
310
311 /*
312 * Make sure the latency timer is set to some reasonable
313 * value.
314 */
315 reg = cardbus_conf_read(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG);
316 if (CARDBUS_LATTIMER(reg) < 0x20) {
317 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
318 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
319 cardbus_conf_write(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG, reg);
320 }
321 }
322
323 int
com_cardbus_enable(struct com_softc * sc)324 com_cardbus_enable(struct com_softc *sc)
325 {
326 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
327 struct cardbus_softc *psc =
328 (struct cardbus_softc *)sc->sc_dev.dv_parent;
329 cardbus_chipset_tag_t cc = psc->sc_cc;
330 cardbus_function_tag_t cf = psc->sc_cf;
331
332 Cardbus_function_enable(csc->cc_ct);
333
334 com_cardbus_setup(csc);
335
336 /* establish the interrupt. */
337 csc->cc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline,
338 IPL_TTY, comintr, sc);
339 if (csc->cc_ih == NULL) {
340 printf("%s: couldn't establish interrupt\n", DEVNAME(csc));
341 return (1);
342 }
343
344 printf(": irq %d,", psc->sc_intrline);
345
346 return (0);
347 }
348
349 void
com_cardbus_disable(struct com_softc * sc)350 com_cardbus_disable(struct com_softc *sc)
351 {
352 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
353 struct cardbus_softc *psc =
354 (struct cardbus_softc *)sc->sc_dev.dv_parent;
355 cardbus_chipset_tag_t cc = psc->sc_cc;
356 cardbus_function_tag_t cf = psc->sc_cf;
357
358 cardbus_intr_disestablish(cc, cf, csc->cc_ih);
359 Cardbus_function_disable(csc->cc_ct);
360 }
361
362 int
com_cardbus_detach(struct device * self,int flags)363 com_cardbus_detach(struct device *self, int flags)
364 {
365 struct com_cardbus_softc *csc = (struct com_cardbus_softc *) self;
366 struct com_softc *sc = (struct com_softc *) self;
367 struct cardbus_softc *psc = (struct cardbus_softc *)self->dv_parent;
368 int error;
369
370 if ((error = com_detach(self, flags)) != 0)
371 return (error);
372
373 cardbus_intr_disestablish(psc->sc_cc, psc->sc_cf, csc->cc_ih);
374
375 Cardbus_mapreg_unmap(csc->cc_ct, csc->cc_reg, sc->sc_iot, sc->sc_ioh,
376 csc->cc_size);
377
378 return (0);
379 }
380
381
382 /*
383 * XXX This should be handled by a generic attach
384 */
385 void
com_cardbus_attach2(sc)386 com_cardbus_attach2(sc)
387 struct com_softc *sc;
388 {
389 bus_space_tag_t iot = sc->sc_iot;
390 bus_space_handle_t ioh = sc->sc_ioh;
391 u_int8_t lcr;
392
393 sc->sc_hwflags = 0;
394 sc->sc_swflags = 0;
395
396 /*
397 * Probe for all known forms of UART.
398 */
399 lcr = bus_space_read_1(iot, ioh, com_lcr);
400
401 bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
402 bus_space_write_1(iot, ioh, com_efr, 0);
403 bus_space_write_1(iot, ioh, com_lcr, 0);
404
405 bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
406 delay(100);
407
408 switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {
409 case 0:
410 sc->sc_uarttype = COM_UART_16450;
411 break;
412 case 2:
413 sc->sc_uarttype = COM_UART_16550;
414 break;
415 case 3:
416 sc->sc_uarttype = COM_UART_16550A;
417 break;
418 default:
419 sc->sc_uarttype = COM_UART_UNKNOWN;
420 break;
421 }
422
423 if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */
424 bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
425 if (bus_space_read_1(iot, ioh, com_efr) == 0) {
426 sc->sc_uarttype = COM_UART_ST16650;
427 } else {
428 bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
429 if (bus_space_read_1(iot, ioh, com_efr) == 0)
430 sc->sc_uarttype = COM_UART_ST16650V2;
431 }
432 }
433
434 #if NPCCOM > 0
435 #ifdef i386
436 if (sc->sc_uarttype == COM_UART_ST16650V2) { /* Probe for XR16850s */
437 u_int8_t dlbl, dlbh;
438
439 /* Enable latch access and get the current values. */
440 bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
441 dlbl = bus_space_read_1(iot, ioh, com_dlbl);
442 dlbh = bus_space_read_1(iot, ioh, com_dlbh);
443
444 /* Zero out the latch divisors */
445 bus_space_write_1(iot, ioh, com_dlbl, 0);
446 bus_space_write_1(iot, ioh, com_dlbh, 0);
447
448 if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) {
449 sc->sc_uarttype = COM_UART_XR16850;
450 sc->sc_uartrev = bus_space_read_1(iot, ioh, com_dlbl);
451 }
452
453 /* Reset to original. */
454 bus_space_write_1(iot, ioh, com_dlbl, dlbl);
455 bus_space_write_1(iot, ioh, com_dlbh, dlbh);
456 }
457 #endif
458 #endif
459
460 /* Reset the LCR (latch access is probably enabled). */
461 bus_space_write_1(iot, ioh, com_lcr, lcr);
462 if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */
463 u_int8_t scr0, scr1, scr2;
464
465 scr0 = bus_space_read_1(iot, ioh, com_scratch);
466 bus_space_write_1(iot, ioh, com_scratch, 0xa5);
467 scr1 = bus_space_read_1(iot, ioh, com_scratch);
468 bus_space_write_1(iot, ioh, com_scratch, 0x5a);
469 scr2 = bus_space_read_1(iot, ioh, com_scratch);
470 bus_space_write_1(iot, ioh, com_scratch, scr0);
471
472 if ((scr1 != 0xa5) || (scr2 != 0x5a))
473 sc->sc_uarttype = COM_UART_8250;
474 }
475
476 /*
477 * Print UART type and initialize ourself.
478 */
479 sc->sc_fifolen = 1; /* default */
480 printf(" ");
481 switch (sc->sc_uarttype) {
482 case COM_UART_UNKNOWN:
483 printf("unknown uart\n");
484 break;
485 case COM_UART_8250:
486 printf("ns8250, no fifo\n");
487 break;
488 case COM_UART_16450:
489 printf("ns16450, no fifo\n");
490 break;
491 case COM_UART_16550:
492 printf("ns16550, no working fifo\n");
493 break;
494 case COM_UART_16550A:
495 printf("ns16550a, 16 byte fifo\n");
496 SET(sc->sc_hwflags, COM_HW_FIFO);
497 sc->sc_fifolen = 16;
498 break;
499 case COM_UART_ST16650:
500 printf("st16650, no working fifo\n");
501 break;
502 case COM_UART_ST16650V2:
503 printf("st16650, 32 byte fifo\n");
504 SET(sc->sc_hwflags, COM_HW_FIFO);
505 sc->sc_fifolen = 32;
506 break;
507 #if NPCCOM > 0
508 #ifdef i386
509 case COM_UART_XR16850:
510 printf("xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
511 SET(sc->sc_hwflags, COM_HW_FIFO);
512 sc->sc_fifolen = 128;
513 break;
514 #endif
515 #endif
516 default:
517 panic("comattach: bad fifo type");
518 }
519
520 /* clear and disable fifo */
521 bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
522 (void)bus_space_read_1(iot, ioh, com_data);
523 bus_space_write_1(iot, ioh, com_fifo, 0);
524 }
525