1 /* $NetBSD: pxa2x0_pcic.c,v 1.4 2007/10/17 19:53:44 garbled Exp $ */ 2 /* $OpenBSD: pxa2x0_pcic.c,v 1.17 2005/12/14 15:08:51 uwe Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: pxa2x0_pcic.c,v 1.4 2007/10/17 19:53:44 garbled Exp $"); 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 #include <sys/kernel.h> 27 #include <sys/kthread.h> 28 #include <sys/malloc.h> 29 30 #include <uvm/uvm.h> 31 32 #include <machine/bus.h> 33 #include <machine/intr.h> 34 35 #include <dev/pcmcia/pcmciareg.h> 36 #include <dev/pcmcia/pcmciavar.h> 37 #include <dev/pcmcia/pcmciachip.h> 38 39 #include <arm/xscale/pxa2x0cpu.h> 40 #include <arm/xscale/pxa2x0reg.h> 41 #include <arm/xscale/pxa2x0var.h> 42 #include <arm/xscale/pxa2x0_gpio.h> 43 #include <arm/xscale/pxa2x0_pcic.h> 44 45 static int pxapcic_print(void *, const char *); 46 47 static void pxapcic_event_thread(void *); 48 static void pxapcic_event_process(struct pxapcic_socket *); 49 static void pxapcic_attach_card(struct pxapcic_socket *); 50 static void pxapcic_detach_card(struct pxapcic_socket *, int); 51 52 static int pxapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 53 struct pcmcia_mem_handle *); 54 static void pxapcic_mem_free(pcmcia_chipset_handle_t, 55 struct pcmcia_mem_handle *); 56 static int pxapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, 57 bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *); 58 static void pxapcic_mem_unmap(pcmcia_chipset_handle_t, int); 59 60 static int pxapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, 61 bus_size_t, bus_size_t, struct pcmcia_io_handle *); 62 static void pxapcic_io_free(pcmcia_chipset_handle_t, 63 struct pcmcia_io_handle *); 64 static int pxapcic_io_map(pcmcia_chipset_handle_t, int, 65 bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *); 66 static void pxapcic_io_unmap(pcmcia_chipset_handle_t, int); 67 68 static void *pxapcic_intr_establish(pcmcia_chipset_handle_t, 69 struct pcmcia_function *, int, int (*)(void *), void *); 70 static void pxapcic_intr_disestablish(pcmcia_chipset_handle_t, void *); 71 72 static void pxapcic_socket_enable(pcmcia_chipset_handle_t); 73 static void pxapcic_socket_disable(pcmcia_chipset_handle_t); 74 static void pxapcic_socket_settype(pcmcia_chipset_handle_t, int); 75 76 /* 77 * PCMCIA chipset methods 78 */ 79 static struct pcmcia_chip_functions pxapcic_pcmcia_functions = { 80 pxapcic_mem_alloc, 81 pxapcic_mem_free, 82 pxapcic_mem_map, 83 pxapcic_mem_unmap, 84 85 pxapcic_io_alloc, 86 pxapcic_io_free, 87 pxapcic_io_map, 88 pxapcic_io_unmap, 89 90 pxapcic_intr_establish, 91 pxapcic_intr_disestablish, 92 93 pxapcic_socket_enable, 94 pxapcic_socket_disable, 95 pxapcic_socket_settype, 96 }; 97 98 #define PXAPCIC_ATTR_OFFSET 0x08000000 99 #define PXAPCIC_COMMON_OFFSET 0x0C000000 100 101 /* 102 * PCMCIA Helpers 103 */ 104 static int 105 pxapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 106 struct pcmcia_mem_handle *pmh) 107 { 108 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 109 110 /* All we need is the bus space tag */ 111 memset(pmh, 0, sizeof(*pmh)); 112 pmh->memt = so->sc->sc_iot; 113 114 return 0; 115 } 116 117 static void 118 pxapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh) 119 { 120 121 /* Nothing to do */ 122 } 123 124 static int 125 pxapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr, 126 bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp, 127 int *windowp) 128 { 129 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 130 int error; 131 bus_addr_t pa; 132 133 pa = trunc_page(card_addr); 134 *offsetp = card_addr - pa; 135 size = round_page(card_addr + size) - pa; 136 pmh->realsize = size; 137 138 pa += PXA2X0_PCIC_SOCKET_BASE; 139 pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket; 140 141 switch (kind & ~PCMCIA_WIDTH_MEM_MASK) { 142 case PCMCIA_MEM_ATTR: 143 pa += PXAPCIC_ATTR_OFFSET; 144 break; 145 case PCMCIA_MEM_COMMON: 146 pa += PXAPCIC_COMMON_OFFSET; 147 break; 148 default: 149 panic("pxapcic_mem_map: bogus kind"); 150 } 151 152 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh); 153 if (error) 154 return error; 155 156 *windowp = (int)pmh->memh; 157 return 0; 158 } 159 160 static void 161 pxapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window) 162 { 163 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 164 165 bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */ 166 } 167 168 static int 169 pxapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, 170 bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih) 171 { 172 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 173 bus_addr_t pa; 174 int error; 175 176 memset(pih, 0, sizeof(*pih)); 177 pih->iot = so->sc->sc_iot; 178 pih->addr = start; 179 pih->size = size; 180 181 pa = pih->addr; 182 pa += PXA2X0_PCIC_SOCKET_BASE; 183 pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket; 184 185 /* XXX Are we ignoring alignment constraints? */ 186 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh); 187 188 return error; 189 } 190 191 static void 192 pxapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih) 193 { 194 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 195 196 bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size); 197 } 198 199 static int 200 pxapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 201 bus_size_t size, struct pcmcia_io_handle *pih, int *windowp) 202 { 203 204 return 0; 205 } 206 207 static void 208 pxapcic_io_unmap(pcmcia_chipset_handle_t pch, int window) 209 { 210 211 /* Nothing to do */ 212 } 213 214 static void * 215 pxapcic_intr_establish(pcmcia_chipset_handle_t pch, 216 struct pcmcia_function *pf, int ipl, int (*fct)(void *), void *arg) 217 { 218 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 219 /* XXX need to check if something should be done here */ 220 221 return (*so->pcictag->intr_establish)(so, ipl, fct, arg); 222 } 223 224 static void 225 pxapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih) 226 { 227 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 228 229 (*so->pcictag->intr_disestablish)(so, ih); 230 } 231 232 static void 233 pxapcic_socket_enable(pcmcia_chipset_handle_t pch) 234 { 235 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 236 int i; 237 238 /* Power down the card and socket before setting the voltage. */ 239 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF); 240 (*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF); 241 242 /* 243 * Wait 300ms until power fails (Tpf). Then, wait 100ms since 244 * we are changing Vcc (Toff). 245 */ 246 delay((300 + 100) * 1000); 247 248 /* Power up the socket and card at appropriate voltage. */ 249 if (so->power_capability & PXAPCIC_POWER_5V) { 250 (*so->pcictag->set_power)(so, PXAPCIC_POWER_5V); 251 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, 252 PXAPCIC_POWER_5V); 253 } else { 254 (*so->pcictag->set_power)(so, PXAPCIC_POWER_3V); 255 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, 256 PXAPCIC_POWER_3V); 257 } 258 259 /* 260 * Wait 100ms until power raise (Tpr) and 20ms to become 261 * stable (Tsu(Vcc)). 262 * 263 * Some machines require some more time to be settled 264 * (another 200ms is added here). 265 */ 266 delay((100 + 20 + 200) * 1000); 267 268 /* Hold RESET at least 10us. */ 269 (*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 1); 270 delay(10); 271 /* XXX wrong, but lets TE-CF100 cards work for some reason. */ 272 delay(3000); 273 (*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 0); 274 275 /* Wait 20ms as per PC Card standard (r2.01) section 4.3.6. */ 276 delay(20 * 1000); 277 278 /* Wait for the card to become ready. */ 279 for (i = 0; i < 10000; i++) { 280 if ((*so->pcictag->read)(so, PXAPCIC_CARD_READY)) 281 break; 282 delay(500); 283 } 284 } 285 286 static void 287 pxapcic_socket_disable(pcmcia_chipset_handle_t pch) 288 { 289 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 290 291 #ifdef PCICDEBUG 292 printf("pxapcic_socket_disable: socket %d\n", so->socket); 293 #endif 294 295 /* Power down the card and socket. */ 296 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF); 297 (*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF); 298 } 299 300 static void 301 pxapcic_socket_settype(pcmcia_chipset_handle_t pch, int type) 302 { 303 304 #ifdef PCICDEBUG 305 printf("pxapcic_socket_settype: type=%d",type); 306 307 switch (type) { 308 case PCMCIA_IFTYPE_MEMORY: 309 printf("(Memory)\n"); 310 break; 311 case PCMCIA_IFTYPE_IO: 312 printf("(I/O)\n"); 313 break; 314 default: 315 printf("(unknown)\n"); 316 break; 317 } 318 #endif 319 } 320 321 /* 322 * Attachment and initialization 323 */ 324 static int 325 pxapcic_print(void *aux, const char *name) 326 { 327 328 return UNCONF; 329 } 330 331 void 332 pxapcic_attach_common(struct pxapcic_softc *sc, 333 void (*socket_setup_hook)(struct pxapcic_socket *)) 334 { 335 struct pcmciabus_attach_args paa; 336 struct pxapcic_socket *so; 337 int s[PXAPCIC_NSLOT]; 338 u_int cs; 339 int i; 340 341 printf(": %d slot%s\n", sc->sc_nslots, sc->sc_nslots < 2 ? "" : "s"); 342 343 if (sc->sc_nslots == 0) { 344 aprint_error("%s: can't attach\n", sc->sc_dev.dv_xname); 345 return; 346 } 347 348 if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 349 0, &sc->sc_memctl_ioh)) { 350 aprint_error("%s: failed to map MEMCTL\n", sc->sc_dev.dv_xname); 351 return; 352 } 353 354 /* Clear CIT (card present) and set NOS correctly. */ 355 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR, 356 (sc->sc_nslots == 2) ? MECR_NOS : 0); 357 358 if (sc->sc_flags & PPF_REVERSE_ORDER) { 359 for (i = 0; i < sc->sc_nslots; i++) { 360 s[i] = sc->sc_nslots - 1 - i; 361 } 362 } else { 363 for (i = 0; i < sc->sc_nslots; i++) { 364 s[i] = i; 365 } 366 } 367 368 for (i = 0; i < sc->sc_nslots; i++) { 369 so = &sc->sc_socket[s[i]]; 370 so->sc = sc; 371 so->socket = s[i]; 372 so->flags = 0; 373 374 (*socket_setup_hook)(so); 375 376 paa.paa_busname = "pcmcia"; 377 paa.pct = (pcmcia_chipset_tag_t)&pxapcic_pcmcia_functions; 378 paa.pch = (pcmcia_chipset_handle_t)so; 379 paa.iobase = 0; 380 paa.iosize = 0x4000000; 381 382 so->pcmcia = config_found_ia(&sc->sc_dev, "pcmciabus", &paa, 383 pxapcic_print); 384 385 pxa2x0_gpio_set_function(sc->sc_irqpin[s[i]], GPIO_IN); 386 pxa2x0_gpio_set_function(sc->sc_irqcfpin[s[i]], GPIO_IN); 387 388 /* Card slot interrupt */ 389 so->irq = pxa2x0_gpio_intr_establish(sc->sc_irqcfpin[s[i]], 390 IST_EDGE_BOTH, IPL_BIO /* XXX */, pxapcic_intr, so); 391 392 /* GPIO pin for interrupt */ 393 so->irqpin = sc->sc_irqpin[s[i]]; 394 395 /* If there's a card there, attach it. */ 396 cs = (*so->pcictag->read)(so, PXAPCIC_CARD_STATUS); 397 if (cs == PXAPCIC_CARD_VALID) 398 pxapcic_attach_card(so); 399 400 if (kthread_create(PRI_NONE, 0, NULL, pxapcic_event_thread, 401 so, &so->event_thread, "%s,%d", sc->sc_dev.dv_xname, 402 so->socket)) { 403 printf("%s: unable to create event thread for %d\n", 404 sc->sc_dev.dv_xname, so->socket); 405 } 406 } 407 } 408 409 /* 410 * Card slot interrupt handling 411 */ 412 int 413 pxapcic_intr(void *arg) 414 { 415 struct pxapcic_socket *so = (struct pxapcic_socket *)arg; 416 417 (*so->pcictag->clear_intr)(so); 418 wakeup(so); 419 420 return 1; 421 } 422 423 static void 424 pxapcic_event_thread(void *arg) 425 { 426 struct pxapcic_socket *sock = (struct pxapcic_socket *)arg; 427 u_int cs; 428 int present; 429 430 while (sock->sc->sc_shutdown == 0) { 431 (void) tsleep(sock, PWAIT, "pxapcicev", 0); 432 433 /* sleep .25s to avoid chattering interrupts */ 434 (void) tsleep((void *)sock, PWAIT, "pxapcicss", hz/4); 435 436 cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS); 437 present = sock->flags & PXAPCIC_FLAG_CARDP; 438 if ((cs == PXAPCIC_CARD_VALID) == (present == 1)) { 439 continue; /* state unchanged */ 440 } 441 442 /* XXX Do both? */ 443 pxapcic_event_process(sock); 444 } 445 sock->event_thread = NULL; 446 447 /* In case parent is waiting for us to exit. */ 448 wakeup(sock->sc); 449 kthread_exit(0); 450 } 451 452 static void 453 pxapcic_event_process(struct pxapcic_socket *sock) 454 { 455 u_int cs; 456 457 cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS); 458 if (cs == PXAPCIC_CARD_VALID) { 459 if (!(sock->flags & PXAPCIC_FLAG_CARDP)) { 460 pxapcic_attach_card(sock); 461 } 462 } else { 463 if ((sock->flags & PXAPCIC_FLAG_CARDP)) { 464 pxapcic_detach_card(sock, DETACH_FORCE); 465 } 466 } 467 } 468 469 static void 470 pxapcic_attach_card(struct pxapcic_socket *h) 471 { 472 struct pxapcic_softc *sc = h->sc; 473 uint32_t reg; 474 475 if (h->flags & PXAPCIC_FLAG_CARDP) 476 panic("pcic_attach_card: already attached"); 477 h->flags |= PXAPCIC_FLAG_CARDP; 478 479 /* Set CIT if any card is present. */ 480 reg = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR); 481 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR, 482 reg | MECR_CIT); 483 484 /* call the MI attach function */ 485 pcmcia_card_attach(h->pcmcia); 486 } 487 488 static void 489 pxapcic_detach_card(struct pxapcic_socket *h, int flags) 490 { 491 struct pxapcic_softc *sc = h->sc; 492 uint32_t reg; 493 int i; 494 495 if (h->flags & PXAPCIC_FLAG_CARDP) { 496 h->flags &= ~PXAPCIC_FLAG_CARDP; 497 498 /* call the MI detach function */ 499 pcmcia_card_detach(h->pcmcia, flags); 500 } 501 502 /* Clear CIT if no other card is present. */ 503 for (i = 0; i < sc->sc_nslots; i++) { 504 if (sc->sc_socket[i].flags & PXAPCIC_FLAG_CARDP) { 505 return; 506 } 507 } 508 509 reg = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR); 510 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR, 511 reg & ~MECR_CIT); 512 } 513