plumpcmcia.c revision 1.3 1 /* $NetBSD: plumpcmcia.c,v 1.3 2000/03/05 05:22:13 takemura Exp $ */
2
3 /*
4 * Copyright (c) 1999 UCHIYAMA Yasushi
5 * Copyright (c) 1997 Marc Horowitz.
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 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Marc Horowitz.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "opt_tx39_debug.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39
40 #include <machine/bus.h>
41
42 #include <dev/pcmcia/pcmciareg.h>
43 #include <dev/pcmcia/pcmciavar.h>
44 #include <dev/pcmcia/pcmciachip.h>
45
46 #include <hpcmips/tx/tx39var.h>
47 #include <hpcmips/dev/plumvar.h>
48 #include <hpcmips/dev/plumicuvar.h>
49 #include <hpcmips/dev/plumpowervar.h>
50 #include <hpcmips/dev/plumpcmciareg.h>
51
52 #ifdef PLUMPCMCIADEBUG
53 #define DPRINTF(arg) printf arg
54 #else
55 #define DPRINTF(arg)
56 #endif
57
58 int plumpcmcia_match __P((struct device*, struct cfdata*, void*));
59 void plumpcmcia_attach __P((struct device*, struct device*, void*));
60 int plumpcmcia_print __P((void*, const char*));
61 int plumpcmcia_submatch __P((struct device*, struct cfdata*, void*));
62
63 struct plumpcmcia_softc;
64
65 struct plumpcmcia_handle {
66 /* parent */
67 struct device *ph_parent;
68 /* child */
69 struct device *ph_pcmcia;
70
71 /* PCMCIA controller register space */
72 bus_space_tag_t ph_regt;
73 bus_space_handle_t ph_regh;
74
75 /* I/O port space */
76 int ph_ioarea; /* not PCMCIA window */
77 struct {
78 bus_addr_t pi_addr;
79 bus_size_t pi_size;
80 int pi_width;
81 } ph_io[PLUM_PCMCIA_IO_WINS];
82 int ph_ioalloc;
83 bus_space_tag_t ph_iot;
84 bus_space_handle_t ph_ioh;
85 bus_addr_t ph_iobase;
86 bus_size_t ph_iosize;
87
88 /* I/O Memory space */
89 int ph_memarea; /* not PCMCIA window */
90 struct {
91 bus_addr_t pm_addr;
92 bus_size_t pm_size;
93 int32_t pm_offset;
94 int pm_kind;
95 } ph_mem[PLUM_PCMCIA_MEM_WINS];
96 int ph_memalloc;
97 bus_space_tag_t ph_memt;
98 bus_space_handle_t ph_memh;
99 bus_addr_t ph_membase;
100 bus_size_t ph_memsize;
101
102 /* Interrupt handler */
103 int ph_plum_irq;
104 void *ph_card_ih;
105 };
106
107 struct plumpcmcia_softc {
108 struct device sc_dev;
109 plum_chipset_tag_t sc_pc;
110
111 /* Register space */
112 bus_space_tag_t sc_regt;
113 bus_space_handle_t sc_regh;
114
115 struct plumpcmcia_handle sc_ph[PLUMPCMCIA_NSLOTS];
116 };
117
118 void plumpcmcia_attach_socket __P((struct plumpcmcia_handle*));
119 void plumpcmcia_dump __P((struct plumpcmcia_softc*));
120
121 int plumpcmcia_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t, struct pcmcia_mem_handle*));
122 void plumpcmcia_chip_mem_free __P((pcmcia_chipset_handle_t, struct pcmcia_mem_handle*));
123 int plumpcmcia_chip_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t, struct pcmcia_mem_handle*, bus_addr_t*, int*));
124 void plumpcmcia_chip_mem_unmap __P((pcmcia_chipset_handle_t, int));
125 int plumpcmcia_chip_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t, bus_size_t, bus_size_t, struct pcmcia_io_handle*));
126 void plumpcmcia_chip_io_free __P((pcmcia_chipset_handle_t, struct pcmcia_io_handle*));
127 int plumpcmcia_chip_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t, struct pcmcia_io_handle*, int*));
128 void plumpcmcia_chip_io_unmap __P((pcmcia_chipset_handle_t, int));
129 void plumpcmcia_chip_socket_enable __P((pcmcia_chipset_handle_t));
130 void plumpcmcia_chip_socket_disable __P((pcmcia_chipset_handle_t));
131 void *plumpcmcia_chip_intr_establish __P((pcmcia_chipset_handle_t, struct pcmcia_function*, int, int (*) (void*), void*));
132 void plumpcmcia_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void*));
133
134 void plumpcmcia_wait_ready __P(( struct plumpcmcia_handle*));
135 void plumpcmcia_chip_do_mem_map __P((struct plumpcmcia_handle *, int));
136 void plumpcmcia_chip_do_io_map __P((struct plumpcmcia_handle *, int));
137
138 static struct pcmcia_chip_functions plumpcmcia_functions = {
139 plumpcmcia_chip_mem_alloc,
140 plumpcmcia_chip_mem_free,
141 plumpcmcia_chip_mem_map,
142 plumpcmcia_chip_mem_unmap,
143 plumpcmcia_chip_io_alloc,
144 plumpcmcia_chip_io_free,
145 plumpcmcia_chip_io_map,
146 plumpcmcia_chip_io_unmap,
147 plumpcmcia_chip_intr_establish,
148 plumpcmcia_chip_intr_disestablish,
149 plumpcmcia_chip_socket_enable,
150 plumpcmcia_chip_socket_disable
151 };
152
153 struct cfattach plumpcmcia_ca = {
154 sizeof(struct plumpcmcia_softc), plumpcmcia_match, plumpcmcia_attach
155 };
156
157 int
158 plumpcmcia_match(parent, cf, aux)
159 struct device *parent;
160 struct cfdata *cf;
161 void *aux;
162 {
163 return 1;
164 }
165
166 void
167 plumpcmcia_attach(parent, self, aux)
168 struct device *parent;
169 struct device *self;
170 void *aux;
171 {
172 struct plum_attach_args *pa = aux;
173 struct plumpcmcia_softc *sc = (void*)self;
174 struct plumpcmcia_handle *ph;
175
176 sc->sc_pc = pa->pa_pc;
177 sc->sc_regt = pa->pa_regt;
178 if (bus_space_map(sc->sc_regt, PLUM_PCMCIA_REGBASE,
179 PLUM_PCMCIA_REGSIZE, 0, &sc->sc_regh)) {
180 printf(": register map failed\n");
181 }
182
183 printf("\n");
184
185 /* Slot 0 */
186 ph = &sc->sc_ph[0];
187 ph->ph_plum_irq = PLUM_INT_C1IO;
188 ph->ph_memarea = PLUM_PCMCIA_MEMWINCTRL_MAP_AREA1;
189 ph->ph_membase = PLUM_PCMCIA_MEMBASE1;
190 ph->ph_memsize = PLUM_PCMCIA_MEMSIZE1;
191 ph->ph_ioarea = PLUM_PCMCIA_IOWINADDRCTRL_AREA1;
192 ph->ph_iobase = PLUM_PCMCIA_IOBASE1;
193 ph->ph_iosize = PLUM_PCMCIA_IOSIZE1;
194 ph->ph_regt = sc->sc_regt;
195 bus_space_subregion(sc->sc_regt, sc->sc_regh,
196 PLUM_PCMCIA_REGSPACE_SLOT0,
197 PLUM_PCMCIA_REGSPACE_SIZE,
198 &ph->ph_regh);
199 ph->ph_iot = pa->pa_iot;
200 ph->ph_memt = pa->pa_iot;
201 ph->ph_parent = (void*)sc;
202
203 plum_power_establish(sc->sc_pc, PLUM_PWR_PCC1);
204 plumpcmcia_attach_socket(ph);
205
206 /* Slot 1 */
207 ph = &sc->sc_ph[1];
208 ph->ph_plum_irq = PLUM_INT_C2IO;
209 ph->ph_memarea = PLUM_PCMCIA_MEMWINCTRL_MAP_AREA2;
210 ph->ph_membase = PLUM_PCMCIA_MEMBASE2;
211 ph->ph_memsize = PLUM_PCMCIA_MEMSIZE2;
212 ph->ph_ioarea = PLUM_PCMCIA_IOWINADDRCTRL_AREA2;
213 ph->ph_iobase = PLUM_PCMCIA_IOBASE2;
214 ph->ph_iosize = PLUM_PCMCIA_IOSIZE2;
215 ph->ph_regt = sc->sc_regt;
216 bus_space_subregion(sc->sc_regt, sc->sc_regh,
217 PLUM_PCMCIA_REGSPACE_SLOT1,
218 PLUM_PCMCIA_REGSPACE_SIZE,
219 &ph->ph_regh);
220 ph->ph_iot = pa->pa_iot;
221 ph->ph_memt = pa->pa_iot;
222 ph->ph_parent = (void*)sc;
223
224 plum_power_establish(sc->sc_pc, PLUM_PWR_PCC2);
225 plumpcmcia_attach_socket(ph);
226 }
227
228 int
229 plumpcmcia_print(arg, pnp)
230 void *arg;
231 const char *pnp;
232 {
233 if (pnp) {
234 printf("pcmcia at %s", pnp);
235 }
236
237 return UNCONF;
238 }
239
240 int
241 plumpcmcia_submatch(parent, cf, aux)
242 struct device *parent;
243 struct cfdata *cf;
244 void *aux;
245 {
246 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
247 }
248
249 void
250 plumpcmcia_attach_socket(ph)
251 struct plumpcmcia_handle *ph;
252 {
253 struct pcmciabus_attach_args paa;
254 struct plumpcmcia_softc *sc = (void*)ph->ph_parent;
255
256 paa.paa_busname = "pcmcia";
257 paa.pct = (pcmcia_chipset_tag_t)&plumpcmcia_functions;
258 paa.pch = (pcmcia_chipset_handle_t)ph;
259 paa.iobase = 0; /* I don't use them */
260 paa.iosize = 0;
261
262
263 if ((ph->ph_pcmcia = config_found_sm((void*)sc, &paa,
264 plumpcmcia_print,
265 plumpcmcia_submatch))) {
266 /* Enable slot */
267 plum_conf_write(ph->ph_regt, ph->ph_regh,
268 PLUM_PCMCIA_SLOTCTRL,
269 PLUM_PCMCIA_SLOTCTRL_ENABLE);
270 /* Support 3.3V card & enable Voltage Sense Status */
271 plum_conf_write(ph->ph_regt, ph->ph_regh,
272 PLUM_PCMCIA_FUNCCTRL,
273 PLUM_PCMCIA_FUNCCTRL_VSSEN |
274 PLUM_PCMCIA_FUNCCTRL_3VSUPPORT);
275 pcmcia_card_attach(ph->ph_pcmcia);
276 }
277 }
278
279 void *
280 plumpcmcia_chip_intr_establish(pch, pf, ipl, ih_fun, ih_arg)
281 pcmcia_chipset_handle_t pch;
282 struct pcmcia_function *pf;
283 int ipl;
284 int (*ih_fun) __P((void *));
285 void *ih_arg;
286 {
287 struct plumpcmcia_handle *ph = (void*)pch;
288 struct plumpcmcia_softc *sc = (void*)ph->ph_parent;
289
290 if (!(ph->ph_card_ih =
291 plum_intr_establish(sc->sc_pc, ph->ph_plum_irq,
292 IST_EDGE, IPL_BIO, ih_fun, ih_arg))) {
293 printf("plumpcmcia_chip_intr_establish: can't establish\n");
294 return 0;
295 }
296
297 return ph->ph_card_ih;
298 }
299
300 void
301 plumpcmcia_chip_intr_disestablish(pch, ih)
302 pcmcia_chipset_handle_t pch;
303 void *ih;
304 {
305 struct plumpcmcia_handle *ph = (void*)pch;
306 struct plumpcmcia_softc *sc = (void*)ph->ph_parent;
307
308 plum_intr_disestablish(sc->sc_pc, ih);
309 }
310
311 int
312 plumpcmcia_chip_mem_alloc(pch, size, pcmhp)
313 pcmcia_chipset_handle_t pch;
314 bus_size_t size;
315 struct pcmcia_mem_handle *pcmhp;
316 {
317 struct plumpcmcia_handle *ph = (void*)pch;
318 bus_size_t realsize;
319
320 /* convert size to PCIC pages */
321 realsize = ((size + (PLUM_PCMCIA_MEM_PAGESIZE - 1)) /
322 PLUM_PCMCIA_MEM_PAGESIZE) * PLUM_PCMCIA_MEM_PAGESIZE;
323
324 if (bus_space_alloc(ph->ph_memt, ph->ph_membase,
325 ph->ph_membase + ph->ph_memsize,
326 realsize, PLUM_PCMCIA_MEM_PAGESIZE,
327 0, 0, 0, &pcmhp->memh)) {
328 return 1;
329 }
330
331 pcmhp->memt = ph->ph_memt;
332 /* Address offset from MEM area base */
333 pcmhp->addr = pcmhp->memh - ph->ph_membase - ph->ph_memt->t_base;
334 pcmhp->size = size;
335 pcmhp->realsize = realsize;
336
337 DPRINTF(("plumpcmcia_chip_mem_alloc: size %#x->%#x addr %#x->%#x\n",
338 size, realsize, pcmhp->addr, pcmhp->memh));
339
340 return 0;
341 }
342
343 void
344 plumpcmcia_chip_mem_free(pch, pcmhp)
345 pcmcia_chipset_handle_t pch;
346 struct pcmcia_mem_handle *pcmhp;
347 {
348 bus_space_free(pcmhp->memt, pcmhp->memh, pcmhp->size);
349 }
350
351 int
352 plumpcmcia_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
353 pcmcia_chipset_handle_t pch;
354 int kind;
355 bus_addr_t card_addr;
356 bus_size_t size;
357 struct pcmcia_mem_handle *pcmhp;
358 bus_addr_t *offsetp;
359 int *windowp;
360 {
361 struct plumpcmcia_handle *ph = (void*)pch;
362 bus_addr_t busaddr;
363 int32_t card_offset;
364 int i, win;
365
366 for (win = -1, i = 0; i < PLUM_PCMCIA_MEM_WINS; i++) {
367 if ((ph->ph_memalloc & (1 << i)) == 0) {
368 win = i;
369 ph->ph_memalloc |= (1 << i);
370 break;
371 }
372 }
373 if (win == -1) {
374 DPRINTF(("plumpcmcia_chip_mem_map: no window\n"));
375 return 1;
376 }
377
378 busaddr = pcmhp->addr;
379
380 *offsetp = card_addr % PLUM_PCMCIA_MEM_PAGESIZE;
381 card_addr -= *offsetp;
382 size += *offsetp - 1;
383 *windowp = win;
384 card_offset = (((int32_t)card_addr) - ((int32_t)busaddr));
385
386 DPRINTF(("plumpcmcia_chip_mem_map window %d bus %#x(kv:%#x)+%#x"
387 " size %#x at card addr %#x offset %#x\n", win, busaddr,
388 pcmhp->memh, *offsetp, size, card_addr, card_offset));
389
390 ph->ph_mem[win].pm_addr = busaddr;
391 ph->ph_mem[win].pm_size = size;
392 ph->ph_mem[win].pm_offset = card_offset;
393 ph->ph_mem[win].pm_kind = kind;
394 ph->ph_memalloc |= (1 << win);
395
396 plumpcmcia_chip_do_mem_map(ph, win);
397
398 return 0;
399 }
400
401 void
402 plumpcmcia_chip_do_mem_map(ph, win)
403 struct plumpcmcia_handle *ph;
404 int win;
405 {
406 bus_space_tag_t regt = ph->ph_regt;
407 bus_space_handle_t regh = ph->ph_regh;
408 plumreg_t reg, addr, offset, size;
409
410 if (win < 0 || win > 4) {
411 panic("plumpcmcia_chip_do_mem_map: bogus window %d", win);
412 }
413
414 addr = (ph->ph_mem[win].pm_addr) >> PLUM_PCMCIA_MEM_SHIFT;
415 size = (ph->ph_mem[win].pm_size) >> PLUM_PCMCIA_MEM_SHIFT;
416 offset = (ph->ph_mem[win].pm_offset) >> PLUM_PCMCIA_MEM_SHIFT;
417
418 /* Attribute memory or not */
419 reg = ph->ph_mem[win].pm_kind == PCMCIA_MEM_ATTR ?
420 PLUM_PCMCIA_MEMWINCTRL_REGACTIVE : 0;
421
422 /* Notify I/O area to select for PCMCIA controller */
423 reg = PLUM_PCMCIA_MEMWINCTRL_MAP_SET(reg, ph->ph_memarea);
424
425 /* Zero wait & 16bit access */
426 reg |= (PLUM_PCMCIA_MEMWINCTRL_ZERO_WS |
427 PLUM_PCMCIA_MEMWINCTRL_DATASIZE16);
428 plum_conf_write(regt, regh, PLUM_PCMCIA_MEMWINCTRL(win), reg);
429
430 /* Map Host <-> PC-Card address */
431
432 /* host-side */
433 plum_conf_write(regt, regh, PLUM_PCMCIA_MEMWINSTARTADDR(win),
434 addr);
435 plum_conf_write(regt, regh, PLUM_PCMCIA_MEMWINSTOPADDR(win),
436 addr + size);
437
438 /* card-side */
439 plum_conf_write(regt, regh, PLUM_PCMCIA_MEMWINOFSADDR(win), offset);
440
441 /* Enable memory window */
442 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_WINEN);
443 reg |= PLUM_PCMCIA_WINEN_MEM(win);
444 plum_conf_write(regt, regh, PLUM_PCMCIA_WINEN, reg);
445
446 DPRINTF(("plumpcmcia_chip_do_mem_map: window:%d %#x(%#x)+%#x\n",
447 win, offset, addr, size));
448
449 delay(100);
450 }
451
452 void
453 plumpcmcia_chip_mem_unmap(pch, window)
454 pcmcia_chipset_handle_t pch;
455 int window;
456 {
457 struct plumpcmcia_handle *ph = (void*)pch;
458 bus_space_tag_t regt = ph->ph_regt;
459 bus_space_handle_t regh = ph->ph_regh;
460 plumreg_t reg;
461
462 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_WINEN);
463 reg &= ~PLUM_PCMCIA_WINEN_MEM(window);
464 plum_conf_write(regt, regh, PLUM_PCMCIA_WINEN, reg);
465
466 ph->ph_memalloc &= ~(1 << window);
467 }
468
469 int
470 plumpcmcia_chip_io_alloc(pch, start, size, align, pcihp)
471 pcmcia_chipset_handle_t pch;
472 bus_addr_t start;
473 bus_size_t size;
474 bus_size_t align;
475 struct pcmcia_io_handle *pcihp;
476 {
477 struct plumpcmcia_handle *ph = (void*)pch;
478
479 DPRINTF(("plumpcmcia_chip_io_alloc: start=%#x size=%#x ",
480 start, size));
481 if (start) {
482 if (bus_space_map(ph->ph_iot, ph->ph_iobase + start,
483 size, 0, &pcihp->ioh)) {
484 DPRINTF(("bus_space_map failed\n"));
485 return 1;
486 }
487 pcihp->flags = 0;
488 pcihp->addr = start;
489 DPRINTF(("(mapped) %#x+%#x\n", start, size));
490 } else {
491 if (bus_space_alloc(ph->ph_iot, ph->ph_iobase,
492 ph->ph_iobase + ph->ph_iosize, size,
493 align, 0, 0, 0, &pcihp->ioh)) {
494 DPRINTF(("bus_space_alloc failed\n"));
495 return 1;
496 }
497 /* Address offset from IO area base */
498 pcihp->addr = pcihp->ioh - ph->ph_iobase -
499 ph->ph_iot->t_base;
500 pcihp->flags = PCMCIA_IO_ALLOCATED;
501 DPRINTF(("(allocated) %#x+%#x\n", pcihp->addr, size));
502 }
503
504 pcihp->iot = ph->ph_iot;
505 pcihp->size = size;
506
507 return 0;
508 }
509
510 int
511 plumpcmcia_chip_io_map(pch, width, offset, size, pcihp, windowp)
512 pcmcia_chipset_handle_t pch;
513 int width;
514 bus_addr_t offset;
515 bus_size_t size;
516 struct pcmcia_io_handle *pcihp;
517 int *windowp;
518 {
519 #ifdef PLUMPCMCIADEBUG
520 static char *width_names[] = { "auto", "io8", "io16" };
521 #endif /* PLUMPCMCIADEBUG */
522 struct plumpcmcia_handle *ph = (void*)pch;
523 bus_addr_t winofs;
524 int i, win;
525
526 winofs = pcihp->addr + offset;
527
528 if (winofs > 0x3ff) {
529 printf("plumpcmcia_chip_io_map: WARNING port %#lx > 0x3ff\n",
530 winofs);
531 }
532
533 for (win = -1, i = 0; i < PLUM_PCMCIA_IO_WINS; i++) {
534 if ((ph->ph_ioalloc & (1 << i)) == 0) {
535 win = i;
536 ph->ph_ioalloc |= (1 << i);
537 break;
538 }
539 }
540 if (win == -1) {
541 DPRINTF(("plumpcmcia_chip_io_map: no window\n"));
542 return 1;
543 }
544 *windowp = win;
545
546 ph->ph_io[win].pi_addr = winofs;
547 ph->ph_io[win].pi_size = size;
548 ph->ph_io[win].pi_width = width;
549
550 plumpcmcia_chip_do_io_map(ph, win);
551
552 DPRINTF(("plumpcmcia_chip_io_map: %#x(kv:%#x)+%#x %s\n",
553 offset, pcihp->ioh, size, width_names[width]));
554
555 return 0;
556 }
557
558 void
559 plumpcmcia_chip_do_io_map(ph, win)
560 struct plumpcmcia_handle *ph;
561 int win;
562 {
563 bus_space_tag_t regt = ph->ph_regt;
564 bus_space_handle_t regh = ph->ph_regh;
565 plumreg_t reg;
566 bus_addr_t addr;
567 bus_size_t size;
568 int shift;
569 plumreg_t ioctlbits[3] = {
570 PLUM_PCMCIA_IOWINCTRL_IOCS16SRC,
571 0,
572 PLUM_PCMCIA_IOWINCTRL_DATASIZE16
573 };
574
575 if (win < 0 || win > 1) {
576 panic("plumpcmcia_chip_do_io_map: bogus window %d", win);
577 }
578
579 addr = ph->ph_io[win].pi_addr;
580 size = ph->ph_io[win].pi_size;
581
582 /* Notify I/O area to select for PCMCIA controller */
583 plum_conf_write(regt, regh, PLUM_PCMCIA_IOWINADDRCTRL(win),
584 ph->ph_ioarea);
585
586 /* Start/Stop addr */
587 plum_conf_write(regt, regh, PLUM_PCMCIA_IOWINSTARTADDR(win), addr);
588 plum_conf_write(regt, regh, PLUM_PCMCIA_IOWINSTOPADDR(win),
589 addr + size - 1);
590
591 /* Set bus width */
592 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_IOWINCTRL);
593 shift = win == 0 ? PLUM_PCMCIA_IOWINCTRL_WIN0SHIFT :
594 PLUM_PCMCIA_IOWINCTRL_WIN1SHIFT;
595
596 reg &= ~(PLUM_PCMCIA_IOWINCTRL_WINMASK << shift);
597 reg |= ((ioctlbits[ph->ph_io[win].pi_width] |
598 PLUM_PCMCIA_IOWINCTRL_ZEROWAIT) << shift);
599 plum_conf_write(regt, regh, PLUM_PCMCIA_IOWINCTRL, reg);
600
601 /* Enable window */
602 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_WINEN);
603 reg |= (win == 0 ? PLUM_PCMCIA_WINEN_IO0 :
604 PLUM_PCMCIA_WINEN_IO1);
605 plum_conf_write(regt, regh, PLUM_PCMCIA_WINEN, reg);
606
607 delay(100);
608 }
609
610
611 void
612 plumpcmcia_chip_io_free(pch, pcihp)
613 pcmcia_chipset_handle_t pch;
614 struct pcmcia_io_handle *pcihp;
615 {
616 if (pcihp->flags & PCMCIA_IO_ALLOCATED) {
617 bus_space_free(pcihp->iot, pcihp->ioh, pcihp->size);
618 } else {
619 bus_space_unmap(pcihp->iot, pcihp->ioh, pcihp->size);
620 }
621
622 DPRINTF(("plumpcmcia_chip_io_free %#x+%#x\n", pcihp->ioh,
623 pcihp->size));
624 }
625
626 void
627 plumpcmcia_chip_io_unmap(pch, window)
628 pcmcia_chipset_handle_t pch;
629 int window;
630 {
631 struct plumpcmcia_handle *ph = (void*)pch;
632 bus_space_tag_t regt = ph->ph_regt;
633 bus_space_handle_t regh = ph->ph_regh;
634 plumreg_t reg;
635
636 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_WINEN);
637 switch (window) {
638 default:
639 panic("plumpcmcia_chip_io_unmap: bogus window");
640 case 0:
641 reg &= ~PLUM_PCMCIA_WINEN_IO0;
642 break;
643 case 1:
644 reg &= ~PLUM_PCMCIA_WINEN_IO1;
645 break;
646 }
647 plum_conf_write(regt, regh, PLUM_PCMCIA_WINEN, reg);
648 ph->ph_ioalloc &= ~(1 << window);
649 }
650
651 void
652 plumpcmcia_wait_ready(ph)
653 struct plumpcmcia_handle *ph;
654 {
655 bus_space_tag_t regt = ph->ph_regt;
656 bus_space_handle_t regh = ph->ph_regh;
657 int i;
658
659 for (i = 0; i < 10000; i++) {
660 if ((plum_conf_read(regt, regh, PLUM_PCMCIA_STATUS) &
661 PLUM_PCMCIA_STATUS_READY) &&
662 (plum_conf_read(regt, regh, PLUM_PCMCIA_STATUS) &
663 PLUM_PCMCIA_STATUS_PWROK)) {
664 return;
665 }
666 delay(500);
667
668 if ((i > 5000) && (i % 100 == 99)) {
669 printf(".");
670 }
671 }
672 printf("plumpcmcia_wait_ready: failed\n");
673 }
674
675 void
676 plumpcmcia_chip_socket_enable(pch)
677 pcmcia_chipset_handle_t pch;
678 {
679 struct plumpcmcia_handle *ph = (void*)pch;
680 bus_space_tag_t regt = ph->ph_regt;
681 bus_space_handle_t regh = ph->ph_regh;
682 plumreg_t reg, power;
683 int win, cardtype;
684
685 /* this bit is mostly stolen from pcic_attach_card */
686
687 /* power down the socket to reset it, clear the card reset pin */
688
689 plum_conf_write(regt, regh, PLUM_PCMCIA_PWRCTRL, 0);
690
691 /*
692 * wait 300ms until power fails (Tpf). Then, wait 100ms since
693 * we are changing Vcc (Toff).
694 */
695 delay((300 + 100) * 1000);
696
697 /*
698 * power up the socket
699 */
700 /* detect voltage */
701 reg = plum_conf_read(regt, regh, PLUM_PCMCIA_GENCTRL2);
702 if ((reg & PLUM_PCMCIA_GENCTRL2_VCC5V) ==
703 PLUM_PCMCIA_GENCTRL2_VCC5V) {
704 power = PLUM_PCMCIA_PWRCTRL_VCC_CTRLBIT1; /* 5V */
705 } else {
706 power = PLUM_PCMCIA_PWRCTRL_VCC_CTRLBIT0; /* 3.3V */
707 }
708
709 plum_conf_write(regt, regh, PLUM_PCMCIA_PWRCTRL,
710 PLUM_PCMCIA_PWRCTRL_DISABLE_RESETDRV |
711 power |
712 PLUM_PCMCIA_PWRCTRL_PWR_ENABLE);
713
714 /*
715 * wait 100ms until power raise (Tpr) and 20ms to become
716 * stable (Tsu(Vcc)).
717 *
718 * some machines require some more time to be settled
719 * (300ms is added here).
720 */
721 delay((100 + 20 + 300) * 1000);
722
723 plum_conf_write(regt, regh, PLUM_PCMCIA_PWRCTRL,
724 PLUM_PCMCIA_PWRCTRL_DISABLE_RESETDRV |
725 power |
726 PLUM_PCMCIA_PWRCTRL_OE |
727 PLUM_PCMCIA_PWRCTRL_PWR_ENABLE);
728 plum_conf_write(regt, regh, PLUM_PCMCIA_GENCTRL, 0);
729
730 /*
731 * hold RESET at least 10us.
732 */
733 delay(10);
734
735 /* clear the reset flag */
736 plum_conf_write(regt, regh, PLUM_PCMCIA_GENCTRL,
737 PLUM_PCMCIA_GENCTRL_RESET);
738
739 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
740
741 delay(20000);
742
743 /* wait for the chip to finish initializing */
744 plumpcmcia_wait_ready(ph);
745
746 /* zero out the address windows */
747
748 plum_conf_write(regt, regh, PLUM_PCMCIA_WINEN, 0);
749
750 /* set the card type */
751
752 cardtype = pcmcia_card_gettype(ph->ph_pcmcia);
753
754 reg = (cardtype == PCMCIA_IFTYPE_IO) ?
755 PLUM_PCMCIA_GENCTRL_CARDTYPE_IO :
756 PLUM_PCMCIA_GENCTRL_CARDTYPE_MEM;
757 reg |= plum_conf_read(regt, regh, PLUM_PCMCIA_GENCTRL);
758 DPRINTF(("%s: plumpcmcia_chip_socket_enable cardtype %s\n",
759 ph->ph_parent->dv_xname,
760 ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem")));
761
762 plum_conf_write(regt, regh, PLUM_PCMCIA_GENCTRL, reg);
763
764 /* reinstall all the memory and io mappings */
765
766 for (win = 0; win < PLUM_PCMCIA_MEM_WINS; win++) {
767 if (ph->ph_memalloc & (1 << win)) {
768 plumpcmcia_chip_do_mem_map(ph, win);
769 }
770 }
771
772 for (win = 0; win < PLUM_PCMCIA_IO_WINS; win++) {
773 if (ph->ph_ioalloc & (1 << win)) {
774 plumpcmcia_chip_do_io_map(ph, win);
775 }
776 }
777
778 }
779
780 void
781 plumpcmcia_chip_socket_disable(pch)
782 pcmcia_chipset_handle_t pch;
783 {
784 struct plumpcmcia_handle *ph = (void*)pch;
785 bus_space_tag_t regt = ph->ph_regt;
786 bus_space_handle_t regh = ph->ph_regh;
787
788 /* power down the socket */
789 plum_conf_write(regt, regh, PLUM_PCMCIA_PWRCTRL, 0);
790
791 /*
792 * wait 300ms until power fails (Tpf).
793 */
794 delay(300 * 1000);
795 }
796
797 void __ioareadump __P((plumreg_t));
798 void __memareadump __P((plumreg_t));
799
800 void
801 __memareadump(reg)
802 plumreg_t reg;
803 {
804 int maparea;
805
806 maparea = PLUM_PCMCIA_MEMWINCTRL_MAP(reg);
807 switch (maparea) {
808 case PLUM_PCMCIA_MEMWINCTRL_MAP_AREA1:
809 printf("MEM Area1\n");
810 break;
811 case PLUM_PCMCIA_MEMWINCTRL_MAP_AREA2:
812 printf("MEM Area2\n");
813 break;
814 case PLUM_PCMCIA_MEMWINCTRL_MAP_AREA3:
815 printf("MEM Area3\n");
816 break;
817 case PLUM_PCMCIA_MEMWINCTRL_MAP_AREA4:
818 printf("MEM Area4\n");
819 break;
820 }
821 }
822
823 void
824 __ioareadump(reg)
825 plumreg_t reg;
826 {
827 if (reg & PLUM_PCMCIA_IOWINADDRCTRL_AREA2) {
828 printf("I/O Area 2\n");
829 } else {
830 printf("I/O Area 1\n");
831 }
832 }
833
834 void
835 plumpcmcia_dump(sc)
836 struct plumpcmcia_softc *sc;
837 {
838 bus_space_tag_t regt = sc->sc_regt;
839 bus_space_handle_t regh = sc->sc_regh;
840 plumreg_t reg;
841
842 int i, j;
843
844 __memareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_MEMWIN0CTRL));
845 __memareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_MEMWIN1CTRL));
846 __memareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_MEMWIN2CTRL));
847 __memareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_MEMWIN3CTRL));
848 __memareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_MEMWIN4CTRL));
849
850 __ioareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_IOWIN0ADDRCTRL));
851 __ioareadump(plum_conf_read(regt, regh, PLUM_PCMCIA_IOWIN1ADDRCTRL));
852
853 for (j = 0; j < 2; j++) {
854 printf("[slot %d]\n", j);
855 for (i = 0; i < 0x120; i += 4) {
856 reg = plum_conf_read(sc->sc_regt, sc->sc_regh, i + 0x800 * j);
857 printf("%03x %08x", i, reg);
858 bitdisp(reg);
859 }
860 }
861 printf("\n");
862 }
863