1 /* $NetBSD: pxa2x0_pcic.c,v 1.15 2022/09/27 06:36:43 skrll 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 (at) 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.15 2022/09/27 06:36:43 skrll 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 29 #include <uvm/uvm.h> 30 31 #include <sys/bus.h> 32 #include <machine/intr.h> 33 34 #include <dev/pcmcia/pcmciareg.h> 35 #include <dev/pcmcia/pcmciavar.h> 36 #include <dev/pcmcia/pcmciachip.h> 37 38 #include <arm/xscale/pxa2x0cpu.h> 39 #include <arm/xscale/pxa2x0reg.h> 40 #include <arm/xscale/pxa2x0var.h> 41 #include <arm/xscale/pxa2x0_gpio.h> 42 #include <arm/xscale/pxa2x0_pcic.h> 43 44 static int pxapcic_print(void *, const char *); 45 46 static void pxapcic_doattach(device_t); 47 48 static void pxapcic_event_thread(void *); 49 static void pxapcic_event_process(struct pxapcic_socket *); 50 static void pxapcic_attach_card(struct pxapcic_socket *); 51 static void pxapcic_detach_card(struct pxapcic_socket *, int); 52 53 static int pxapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 54 struct pcmcia_mem_handle *); 55 static void pxapcic_mem_free(pcmcia_chipset_handle_t, 56 struct pcmcia_mem_handle *); 57 static int pxapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, 58 bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *); 59 static void pxapcic_mem_unmap(pcmcia_chipset_handle_t, int); 60 61 static int pxapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, 62 bus_size_t, bus_size_t, struct pcmcia_io_handle *); 63 static void pxapcic_io_free(pcmcia_chipset_handle_t, 64 struct pcmcia_io_handle *); 65 static int pxapcic_io_map(pcmcia_chipset_handle_t, int, 66 bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *); 67 static void pxapcic_io_unmap(pcmcia_chipset_handle_t, int); 68 69 static void *pxapcic_intr_establish(pcmcia_chipset_handle_t, 70 struct pcmcia_function *, int, int (*)(void *), void *); 71 static void pxapcic_intr_disestablish(pcmcia_chipset_handle_t, void *); 72 73 static void pxapcic_socket_enable(pcmcia_chipset_handle_t); 74 static void pxapcic_socket_disable(pcmcia_chipset_handle_t); 75 static void pxapcic_socket_settype(pcmcia_chipset_handle_t, int); 76 77 /* 78 * PCMCIA chipset methods 79 */ 80 static struct pcmcia_chip_functions pxapcic_pcmcia_functions = { 81 pxapcic_mem_alloc, 82 pxapcic_mem_free, 83 pxapcic_mem_map, 84 pxapcic_mem_unmap, 85 86 pxapcic_io_alloc, 87 pxapcic_io_free, 88 pxapcic_io_map, 89 pxapcic_io_unmap, 90 91 pxapcic_intr_establish, 92 pxapcic_intr_disestablish, 93 94 pxapcic_socket_enable, 95 pxapcic_socket_disable, 96 pxapcic_socket_settype, 97 }; 98 99 #define PXAPCIC_ATTR_OFFSET 0x08000000 100 #define PXAPCIC_COMMON_OFFSET 0x0C000000 101 102 /* 103 * PCMCIA Helpers 104 */ 105 static int 106 pxapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 107 struct pcmcia_mem_handle *pmh) 108 { 109 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 110 111 /* All we need is the bus space tag */ 112 memset(pmh, 0, sizeof(*pmh)); 113 pmh->memt = so->sc->sc_iot; 114 115 return 0; 116 } 117 118 static void 119 pxapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh) 120 { 121 122 /* Nothing to do */ 123 } 124 125 static int 126 pxapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr, 127 bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp, 128 int *windowp) 129 { 130 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 131 int error; 132 bus_addr_t pa; 133 134 pa = trunc_page(card_addr); 135 *offsetp = card_addr - pa; 136 size = round_page(card_addr + size) - pa; 137 pmh->realsize = size; 138 139 pa += PXA2X0_PCIC_SOCKET_BASE; 140 pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket; 141 142 switch (kind & ~PCMCIA_WIDTH_MEM_MASK) { 143 case PCMCIA_MEM_ATTR: 144 pa += PXAPCIC_ATTR_OFFSET; 145 break; 146 case PCMCIA_MEM_COMMON: 147 pa += PXAPCIC_COMMON_OFFSET; 148 break; 149 default: 150 panic("pxapcic_mem_map: bogus kind"); 151 } 152 153 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh); 154 if (error) 155 return error; 156 157 *windowp = (int)pmh->memh; 158 return 0; 159 } 160 161 static void 162 pxapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window) 163 { 164 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 165 166 bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */ 167 } 168 169 static int 170 pxapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, 171 bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih) 172 { 173 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 174 bus_addr_t pa; 175 int error; 176 177 memset(pih, 0, sizeof(*pih)); 178 pih->iot = so->sc->sc_iot; 179 pih->addr = start; 180 pih->size = size; 181 182 pa = pih->addr; 183 pa += PXA2X0_PCIC_SOCKET_BASE; 184 pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket; 185 186 /* XXX Are we ignoring alignment constraints? */ 187 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh); 188 189 return error; 190 } 191 192 static void 193 pxapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih) 194 { 195 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 196 197 bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size); 198 } 199 200 static int 201 pxapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 202 bus_size_t size, struct pcmcia_io_handle *pih, int *windowp) 203 { 204 205 return 0; 206 } 207 208 static void 209 pxapcic_io_unmap(pcmcia_chipset_handle_t pch, int window) 210 { 211 212 /* Nothing to do */ 213 } 214 215 static void * 216 pxapcic_intr_establish(pcmcia_chipset_handle_t pch, 217 struct pcmcia_function *pf, int ipl, int (*fct)(void *), void *arg) 218 { 219 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 220 /* XXX need to check if something should be done here */ 221 222 return (*so->pcictag->intr_establish)(so, ipl, fct, arg); 223 } 224 225 static void 226 pxapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih) 227 { 228 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 229 230 (*so->pcictag->intr_disestablish)(so, ih); 231 } 232 233 static void 234 pxapcic_socket_enable(pcmcia_chipset_handle_t pch) 235 { 236 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 237 int i; 238 239 /* Power down the card and socket before setting the voltage. */ 240 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF); 241 (*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF); 242 243 /* 244 * Wait 300ms until power fails (Tpf). Then, wait 100ms since 245 * we are changing Vcc (Toff). 246 */ 247 delay((300 + 100) * 1000); 248 249 /* Power up the socket and card at appropriate voltage. */ 250 if (so->power_capability & PXAPCIC_POWER_5V) { 251 (*so->pcictag->set_power)(so, PXAPCIC_POWER_5V); 252 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, 253 PXAPCIC_POWER_5V); 254 } else { 255 (*so->pcictag->set_power)(so, PXAPCIC_POWER_3V); 256 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, 257 PXAPCIC_POWER_3V); 258 } 259 260 /* 261 * Wait 100ms until power raise (Tpr) and 20ms to become 262 * stable (Tsu(Vcc)). 263 * 264 * Some machines require some more time to be settled 265 * (another 200ms is added here). 266 */ 267 delay((100 + 20 + 200) * 1000); 268 269 /* Hold RESET at least 10us. */ 270 (*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 1); 271 delay(10); 272 /* XXX wrong, but lets TE-CF100 cards work for some reason. */ 273 delay(3000); 274 (*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 0); 275 276 /* Wait 20ms as per PC Card standard (r2.01) section 4.3.6. */ 277 delay(20 * 1000); 278 279 /* Wait for the card to become ready. */ 280 for (i = 0; i < 10000; i++) { 281 if ((*so->pcictag->read)(so, PXAPCIC_CARD_READY)) 282 break; 283 delay(500); 284 } 285 } 286 287 static void 288 pxapcic_socket_disable(pcmcia_chipset_handle_t pch) 289 { 290 struct pxapcic_socket *so = (struct pxapcic_socket *)pch; 291 292 #ifdef PCICDEBUG 293 printf("pxapcic_socket_disable: socket %d\n", so->socket); 294 #endif 295 296 /* Power down the card and socket. */ 297 (*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF); 298 (*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF); 299 } 300 301 static void 302 pxapcic_socket_settype(pcmcia_chipset_handle_t pch, int type) 303 { 304 305 #ifdef PCICDEBUG 306 printf("pxapcic_socket_settype: type=%d",type); 307 308 switch (type) { 309 case PCMCIA_IFTYPE_MEMORY: 310 printf("(Memory)\n"); 311 break; 312 case PCMCIA_IFTYPE_IO: 313 printf("(I/O)\n"); 314 break; 315 default: 316 printf("(unknown)\n"); 317 break; 318 } 319 #endif 320 } 321 322 /* 323 * Attachment and initialization 324 */ 325 static int 326 pxapcic_print(void *aux, const char *name) 327 { 328 329 return UNCONF; 330 } 331 332 void 333 pxapcic_attach_common(struct pxapcic_softc *sc, 334 void (*socket_setup_hook)(struct pxapcic_socket *)) 335 { 336 struct pcmciabus_attach_args paa; 337 struct pxapcic_socket *so; 338 int s[PXAPCIC_NSLOT]; 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_dev(sc->sc_dev, "can't attach\n"); 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_dev(sc->sc_dev, "failed to map MEMCTL\n"); 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 380 so->pcmcia = 381 config_found(sc->sc_dev, &paa, pxapcic_print, CFARGS_NONE); 382 383 pxa2x0_gpio_set_function(sc->sc_irqpin[s[i]], GPIO_IN); 384 pxa2x0_gpio_set_function(sc->sc_irqcfpin[s[i]], GPIO_IN); 385 386 /* Card slot interrupt */ 387 so->irq = pxa2x0_gpio_intr_establish(sc->sc_irqcfpin[s[i]], 388 IST_EDGE_BOTH, IPL_BIO /* XXX */, pxapcic_intr, so); 389 390 /* GPIO pin for interrupt */ 391 so->irqpin = sc->sc_irqpin[s[i]]; 392 } 393 394 config_interrupts(sc->sc_dev, pxapcic_doattach); 395 } 396 397 void 398 pxapcic_doattach(device_t self) 399 { 400 struct pxapcic_softc *sc = device_private(self); 401 struct pxapcic_socket *sock; 402 int s[PXAPCIC_NSLOT]; 403 int i; 404 u_int cs; 405 406 if (sc->sc_flags & PPF_REVERSE_ORDER) { 407 for (i = 0; i < sc->sc_nslots; i++) { 408 s[i] = sc->sc_nslots - 1 - i; 409 } 410 } else { 411 for (i = 0; i < sc->sc_nslots; i++) { 412 s[i] = i; 413 } 414 } 415 416 for (i = 0; i < sc->sc_nslots; i++) { 417 sock = &sc->sc_socket[s[i]]; 418 419 config_pending_incr(self); 420 421 /* If there's a card there, attach it. */ 422 cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS); 423 if (cs == PXAPCIC_CARD_VALID) 424 pxapcic_attach_card(sock); 425 426 if (kthread_create(PRI_NONE, 0, NULL, pxapcic_event_thread, 427 sock, &sock->event_thread, "%s,%d", 428 device_xname(sc->sc_dev), sock->socket)) { 429 aprint_error_dev(sc->sc_dev, 430 "unable to create event thread for %d\n", 431 sock->socket); 432 } 433 } 434 } 435 436 /* 437 * Card slot interrupt handling 438 */ 439 int 440 pxapcic_intr(void *arg) 441 { 442 struct pxapcic_socket *so = (struct pxapcic_socket *)arg; 443 444 (*so->pcictag->clear_intr)(so); 445 wakeup(so); 446 447 return 1; 448 } 449 450 static void 451 pxapcic_event_thread(void *arg) 452 { 453 struct pxapcic_socket *sock = (struct pxapcic_socket *)arg; 454 u_int cs; 455 int present; 456 457 config_pending_decr(sock->sc->sc_dev); 458 459 while (sock->sc->sc_shutdown == 0) { 460 (void) tsleep(sock, PWAIT, "pxapcicev", 0); 461 462 /* sleep .25s to avoid chattering interrupts */ 463 (void) tsleep((void *)sock, PWAIT, "pxapcicss", hz/4); 464 465 cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS); 466 present = sock->flags & PXAPCIC_FLAG_CARDP; 467 if ((cs == PXAPCIC_CARD_VALID) == (present == 1)) { 468 continue; /* state unchanged */ 469 } 470 471 /* XXX Do both? */ 472 pxapcic_event_process(sock); 473 } 474 sock->event_thread = NULL; 475 476 /* In case parent is waiting for us to exit. */ 477 wakeup(sock->sc); 478 kthread_exit(0); 479 } 480 481 static void 482 pxapcic_event_process(struct pxapcic_socket *sock) 483 { 484 u_int cs; 485 486 cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS); 487 if (cs == PXAPCIC_CARD_VALID) { 488 if (!(sock->flags & PXAPCIC_FLAG_CARDP)) { 489 pxapcic_attach_card(sock); 490 } 491 } else { 492 if ((sock->flags & PXAPCIC_FLAG_CARDP)) { 493 pxapcic_detach_card(sock, DETACH_FORCE); 494 } 495 } 496 } 497 498 static void 499 pxapcic_attach_card(struct pxapcic_socket *h) 500 { 501 struct pxapcic_softc *sc = h->sc; 502 uint32_t reg; 503 504 if (h->flags & PXAPCIC_FLAG_CARDP) 505 panic("pcic_attach_card: already attached"); 506 h->flags |= PXAPCIC_FLAG_CARDP; 507 508 /* Set CIT if any card is present. */ 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 /* call the MI attach function */ 514 pcmcia_card_attach(h->pcmcia); 515 } 516 517 static void 518 pxapcic_detach_card(struct pxapcic_socket *h, int flags) 519 { 520 struct pxapcic_softc *sc = h->sc; 521 uint32_t reg; 522 int i; 523 524 if (h->flags & PXAPCIC_FLAG_CARDP) { 525 h->flags &= ~PXAPCIC_FLAG_CARDP; 526 527 /* call the MI detach function */ 528 pcmcia_card_detach(h->pcmcia, flags); 529 } 530 531 /* Clear CIT if no other card is present. */ 532 for (i = 0; i < sc->sc_nslots; i++) { 533 if (sc->sc_socket[i].flags & PXAPCIC_FLAG_CARDP) { 534 return; 535 } 536 } 537 538 reg = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR); 539 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR, 540 reg & ~MECR_CIT); 541 } 542