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