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