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