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@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 44static int pxapcic_print(void *, const char *); 45 46static void pxapcic_doattach(device_t); 47 48static void pxapcic_event_thread(void *); 49static void pxapcic_event_process(struct pxapcic_socket *); 50static void pxapcic_attach_card(struct pxapcic_socket *); 51static void pxapcic_detach_card(struct pxapcic_socket *, int); 52 53static int pxapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 54 struct pcmcia_mem_handle *); 55static void pxapcic_mem_free(pcmcia_chipset_handle_t, 56 struct pcmcia_mem_handle *); 57static int pxapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, 58 bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *); 59static void pxapcic_mem_unmap(pcmcia_chipset_handle_t, int); 60 61static int pxapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, 62 bus_size_t, bus_size_t, struct pcmcia_io_handle *); 63static void pxapcic_io_free(pcmcia_chipset_handle_t, 64 struct pcmcia_io_handle *); 65static int pxapcic_io_map(pcmcia_chipset_handle_t, int, 66 bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *); 67static void pxapcic_io_unmap(pcmcia_chipset_handle_t, int); 68 69static void *pxapcic_intr_establish(pcmcia_chipset_handle_t, 70 struct pcmcia_function *, int, int (*)(void *), void *); 71static void pxapcic_intr_disestablish(pcmcia_chipset_handle_t, void *); 72 73static void pxapcic_socket_enable(pcmcia_chipset_handle_t); 74static void pxapcic_socket_disable(pcmcia_chipset_handle_t); 75static void pxapcic_socket_settype(pcmcia_chipset_handle_t, int); 76 77/* 78 * PCMCIA chipset methods 79 */ 80static 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 */ 105static int 106pxapcic_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 118static void 119pxapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh) 120{ 121 122 /* Nothing to do */ 123} 124 125static int 126pxapcic_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 161static void 162pxapcic_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 169static int 170pxapcic_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 192static void 193pxapcic_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 200static int 201pxapcic_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 208static void 209pxapcic_io_unmap(pcmcia_chipset_handle_t pch, int window) 210{ 211 212 /* Nothing to do */ 213} 214 215static void * 216pxapcic_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 225static void 226pxapcic_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 233static void 234pxapcic_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 287static void 288pxapcic_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 301static void 302pxapcic_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 */ 325static int 326pxapcic_print(void *aux, const char *name) 327{ 328 329 return UNCONF; 330} 331 332void 333pxapcic_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 397void 398pxapcic_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 */ 439int 440pxapcic_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 450static void 451pxapcic_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 481static void 482pxapcic_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 498static void 499pxapcic_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 517static void 518pxapcic_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