1 /* $Id: at91cf.c,v 1.2 2008/07/03 01:15:38 matt Exp $ */ 2 /* $NetBSD: at91cf.c,v 1.2 2008/07/03 01:15:38 matt Exp $ */ 3 4 /* 5 * Copyright (c) 2007 Embedtronics Oy. All rights reserved. 6 * 7 * Based on arch/evbarm/ep93xx/eppcic.c, 8 * Copyright (c) 2005 HAMAJIMA Katsuomi. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: at91cf.c,v 1.2 2008/07/03 01:15:38 matt Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/device.h> 40 #include <sys/kthread.h> 41 #include <uvm/uvm_param.h> 42 #include <machine/bus.h> 43 #include <dev/pcmcia/pcmciareg.h> 44 #include <dev/pcmcia/pcmciavar.h> 45 #include <dev/pcmcia/pcmciachip.h> 46 #include <arm/at91/at91reg.h> 47 #include <arm/at91/at91var.h> 48 #include <arm/at91/at91cfvar.h> 49 50 #include "at91pio.h" 51 #if NAT91PIO == 0 52 #error "at91cf requires at91pio" 53 #endif 54 55 #ifdef AT91CF_DEBUG 56 int at91cf_debug = AT91CF_DEBUG; 57 #define DPRINTFN(n,x) if (at91cf_debug>(n)) printf x; 58 #else 59 #define DPRINTFN(n,x) 60 #endif 61 62 struct at91cf_handle { 63 struct at91cf_softc *ph_sc; 64 device_t ph_card; 65 int (*ph_ih_func)(void *); 66 void *ph_ih_arg; 67 lwp_t *ph_event_thread; 68 int ph_type; /* current access type */ 69 int ph_run; /* kthread running */ 70 int ph_width; /* 8 or 16 */ 71 int ph_vcc; /* 3 or 5 */ 72 int ph_status; /* combined cd1 and cd2 */ 73 struct { 74 bus_size_t reg; 75 bus_addr_t base; 76 bus_size_t size; 77 } ph_space[3]; 78 #define IO 0 79 #define COMMON 1 80 #define ATTRIBUTE 2 81 }; 82 83 static int at91cf_intr_carddetect(void *); 84 static int at91cf_intr_socket(void *); 85 static int at91cf_print(void *, const char *); 86 static void at91cf_create_event_thread(void *); 87 static void at91cf_event_thread(void *); 88 void at91cf_shutdown(void *); 89 90 static int at91cf_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 91 struct pcmcia_mem_handle *); 92 static void at91cf_mem_free(pcmcia_chipset_handle_t, 93 struct pcmcia_mem_handle *); 94 static int at91cf_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t, 95 struct pcmcia_mem_handle *, bus_size_t *, int *); 96 static void at91cf_mem_unmap(pcmcia_chipset_handle_t, int); 97 static int at91cf_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t, 98 bus_size_t, struct pcmcia_io_handle *); 99 static void at91cf_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *); 100 static int at91cf_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t, 101 struct pcmcia_io_handle *, int *); 102 static void at91cf_io_unmap(pcmcia_chipset_handle_t, int); 103 static void *at91cf_intr_establish(pcmcia_chipset_handle_t, 104 struct pcmcia_function *, 105 int, int (*)(void *), void *); 106 static void at91cf_intr_disestablish(pcmcia_chipset_handle_t, void *); 107 static void at91cf_socket_enable(pcmcia_chipset_handle_t); 108 static void at91cf_socket_disable(pcmcia_chipset_handle_t); 109 static void at91cf_socket_settype(pcmcia_chipset_handle_t, int); 110 111 static void at91cf_attach_socket(struct at91cf_handle *); 112 static void at91cf_config_socket(struct at91cf_handle *); 113 //static int at91cf_get_voltage(struct at91cf_handle *); 114 115 static struct pcmcia_chip_functions at91cf_functions = { 116 at91cf_mem_alloc, at91cf_mem_free, 117 at91cf_mem_map, at91cf_mem_unmap, 118 at91cf_io_alloc, at91cf_io_free, 119 at91cf_io_map, at91cf_io_unmap, 120 at91cf_intr_establish, at91cf_intr_disestablish, 121 at91cf_socket_enable, at91cf_socket_disable, 122 at91cf_socket_settype 123 }; 124 125 #define MEMORY_BASE 0 126 #define MEMORY_SIZE 0x1000 127 #define COMMON_BASE 0x400000 128 #define COMMON_SIZE 0x1000 129 #define IO_BASE 0x800000 130 #define IO_SIZE 0x1000 131 #define MIN_SIZE (IO_BASE + IO_SIZE) 132 133 void 134 at91cf_attach_common(device_t parent, device_t self, void *aux, 135 at91cf_chipset_tag_t cscf) 136 { 137 struct at91cf_softc *sc = device_private(self); 138 struct at91bus_attach_args *sa = aux; 139 struct at91cf_handle *ph; 140 141 if (sa->sa_size < MIN_SIZE) { 142 printf("%s: it's not possible to map registers\n", 143 device_xname(self)); 144 return; 145 } 146 147 sc->sc_dev = self; 148 sc->sc_iot = sa->sa_iot; 149 sc->sc_cscf = cscf; 150 sc->sc_enable = 0; 151 152 if (bus_space_map(sa->sa_iot, sa->sa_addr + MEMORY_BASE, 153 MEMORY_SIZE, 0, &sc->sc_memory_ioh)){ 154 printf("%s: Cannot map memory space\n", device_xname(self)); 155 return; 156 } 157 158 if (bus_space_map(sa->sa_iot, sa->sa_addr + COMMON_BASE, 159 COMMON_SIZE, 0, &sc->sc_common_ioh)){ 160 printf("%s: Cannot map common memory space\n", 161 device_xname(self)); 162 bus_space_unmap(sa->sa_iot, sc->sc_memory_ioh, MEMORY_SIZE); 163 return; 164 } 165 166 if (bus_space_map(sa->sa_iot, sa->sa_addr + IO_BASE, 167 IO_SIZE, 0, &sc->sc_io_ioh)){ 168 printf("%s: Cannot map I/O space\n", device_xname(self)); 169 bus_space_unmap(sa->sa_iot, sc->sc_memory_ioh, MEMORY_SIZE); 170 bus_space_unmap(sa->sa_iot, sc->sc_common_ioh, COMMON_SIZE); 171 return; 172 } 173 174 printf("\n"); 175 176 /* socket 0 */ 177 ph = malloc(sizeof(struct at91cf_handle), M_DEVBUF, M_NOWAIT|M_ZERO); 178 if (ph == NULL) { 179 printf("%s: Cannot allocate memory\n", device_xname(self)); 180 // @@@@ unmap? @@@@ 181 return; /* ENOMEM */ 182 } 183 sc->sc_ph = ph; 184 ph->ph_sc = sc; 185 ph->ph_space[IO].base = sa->sa_addr + IO_BASE; 186 ph->ph_space[IO].size = IO_SIZE; 187 ph->ph_space[COMMON].base = sa->sa_addr + COMMON_BASE; 188 ph->ph_space[COMMON].size = COMMON_SIZE; 189 ph->ph_space[ATTRIBUTE].base = sa->sa_addr + MEMORY_BASE; 190 ph->ph_space[ATTRIBUTE].size = MEMORY_SIZE; 191 at91cf_attach_socket(ph); 192 193 // @@@ reset CF now? @@@@ 194 195 at91cf_config_socket(sc->sc_ph); 196 } 197 198 static void 199 at91cf_attach_socket(struct at91cf_handle *ph) 200 { 201 struct at91cf_softc *sc = ph->ph_sc; 202 at91cf_chipset_tag_t cscf = sc->sc_cscf; 203 int wait; 204 205 ph->ph_width = 16; 206 ph->ph_vcc = 3; 207 ph->ph_event_thread = NULL; 208 ph->ph_run = 0; 209 ph->ph_ih_func = NULL; 210 ph->ph_ih_arg = NULL; 211 212 ph->ph_status = (*cscf->card_detect)(sc); 213 214 wait = (cscf->power_ctl)(sc, POWER_OFF); 215 delay(wait); 216 wait = (cscf->power_ctl)(sc, POWER_ON); 217 delay(wait); 218 } 219 220 static void 221 at91cf_config_socket(struct at91cf_handle *ph) 222 { 223 struct at91cf_softc *sc = ph->ph_sc; 224 at91cf_chipset_tag_t cscf = sc->sc_cscf; 225 struct pcmciabus_attach_args paa; 226 int wait; 227 228 paa.paa_busname = "pcmcia"; 229 paa.pct = (pcmcia_chipset_tag_t)&at91cf_functions; 230 paa.pch = (pcmcia_chipset_handle_t)ph; 231 paa.iobase = ph->ph_space[IO].base; 232 paa.iosize = ph->ph_space[IO].size; 233 ph->ph_card = config_found_ia(sc->sc_dev, "pcmciabus", &paa, 234 at91cf_print); 235 236 (*cscf->intr_establish)(sc, CD_IRQ, IPL_BIO, at91cf_intr_carddetect, ph); 237 wait = (*cscf->power_ctl)(sc, POWER_OFF); 238 delay(wait); 239 240 kthread_create(PRI_NONE, 0, NULL, at91cf_create_event_thread, ph, 241 &ph->ph_event_thread, "%s", device_xname(sc->sc_dev)); 242 } 243 244 static int 245 at91cf_print(void *arg, const char *pnp) 246 { 247 return (UNCONF); 248 } 249 250 static void 251 at91cf_create_event_thread(void *arg) 252 { 253 struct at91cf_handle *ph = arg; 254 struct at91cf_softc *sc = ph->ph_sc; 255 at91cf_chipset_tag_t cscf = sc->sc_cscf; 256 257 ph->ph_status = (*cscf->card_detect)(sc); 258 259 DPRINTFN(1, ("at91cf_create_event_thread: status=%d\n", ph->ph_status)); 260 261 if (ph->ph_status) 262 pcmcia_card_attach(ph->ph_card); 263 264 ph->ph_run = 1; 265 kthread_create(PRI_NONE, 0, NULL, at91cf_event_thread, ph, 266 &ph->ph_event_thread, "%s", device_xname(sc->sc_dev)); 267 } 268 269 static void 270 at91cf_event_thread(void *arg) 271 { 272 struct at91cf_handle *ph = arg; 273 int status; 274 275 for (;;) { 276 status = ph->ph_status; 277 tsleep(ph, PWAIT, "CSC wait", 0); 278 if (!ph->ph_run) 279 break; 280 281 DPRINTFN(1, ("at91cf_event_thread: old status=%d, new status=%d\n", status, ph->ph_status)); 282 283 if (!status && ph->ph_status) 284 pcmcia_card_attach(ph->ph_card); 285 else if (status && !ph->ph_status) 286 pcmcia_card_detach(ph->ph_card, DETACH_FORCE); 287 } 288 289 DPRINTFN(1, ("at91cf_event_thread: run=%d\n",ph->ph_run)); 290 ph->ph_event_thread = NULL; 291 kthread_exit(0); 292 } 293 294 void 295 at91cf_shutdown(void *arg) 296 { 297 struct at91cf_handle *ph = arg; 298 299 DPRINTFN(1, ("at91cf_shutdown\n")); 300 ph->ph_run = 0; 301 wakeup(ph); 302 } 303 304 static int 305 at91cf_intr_carddetect(void *arg) 306 { 307 struct at91cf_handle *ph = arg; 308 struct at91cf_softc *sc = ph->ph_sc; 309 at91cf_chipset_tag_t cscf = sc->sc_cscf; 310 int nstatus; 311 312 nstatus = (*cscf->card_detect)(sc); 313 314 DPRINTFN(1, ("at91cf_intr: nstatus=%#x, ostatus=%#x\n", nstatus, ph->ph_status)); 315 316 if (nstatus != ph->ph_status) { 317 ph->ph_status = nstatus; 318 wakeup(ph); 319 } 320 321 return 0; 322 } 323 324 static int 325 at91cf_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 326 struct pcmcia_mem_handle *pmh) 327 { 328 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 329 struct at91cf_softc *sc = ph->ph_sc; 330 331 DPRINTFN(1, ("at91cf_mem_alloc: size=%#x\n",(unsigned)size)); 332 333 pmh->memt = sc->sc_iot; 334 return 0; 335 } 336 337 static void 338 at91cf_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh) 339 { 340 DPRINTFN(1, ("at91cf_mem_free\n")); 341 } 342 343 static int 344 at91cf_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr, 345 bus_size_t size, struct pcmcia_mem_handle *pmh, 346 bus_size_t *offsetp, int *windowp) 347 { 348 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 349 struct at91cf_softc *sc = ph->ph_sc; 350 bus_addr_t pa; 351 int err; 352 353 DPRINTFN(1, ("at91cf_mem_map: kind=%d, addr=%#x, size=%#x\n",kind,(unsigned)addr,(unsigned)size)); 354 355 pa = addr; 356 *offsetp = 0; 357 size = round_page(size); 358 pmh->realsize = size; 359 if (kind & PCMCIA_WIDTH_MEM8) 360 ph->ph_width = 8; 361 else 362 ph->ph_width = 16; 363 switch (kind & ~PCMCIA_WIDTH_MEM_MASK) { 364 case PCMCIA_MEM_ATTR: 365 pa += ph->ph_space[ATTRIBUTE].base; 366 break; 367 case PCMCIA_MEM_COMMON: 368 pa += ph->ph_space[COMMON].base; 369 break; 370 default: 371 return -1; 372 } 373 374 DPRINTFN(1, ("at91cf_mem_map: pa=%#x, *offsetp=%#x, size=%#x\n",(unsigned)pa,(unsigned)addr,(unsigned)size)); 375 376 if (!(err = bus_space_map(sc->sc_iot, pa, size, 0, &pmh->memh))) 377 *windowp = (int)pmh->memh; 378 return err; 379 } 380 381 static void 382 at91cf_mem_unmap(pcmcia_chipset_handle_t pch, int window) 383 { 384 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 385 struct at91cf_softc *sc = ph->ph_sc; 386 387 DPRINTFN(1, ("at91cf_mem_unmap: window=%#x\n",window)); 388 389 bus_space_unmap(sc->sc_iot, (bus_addr_t)window, 0x1000); 390 } 391 392 static int 393 at91cf_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size, 394 bus_size_t align, struct pcmcia_io_handle *pih) 395 { 396 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 397 struct at91cf_softc *sc = ph->ph_sc; 398 bus_addr_t pa; 399 400 DPRINTFN(1, ("at91cf_io_alloc: start=%#x, size=%#x, align=%#x\n",(unsigned)start,(unsigned)size,(unsigned)align)); 401 402 pih->iot = sc->sc_iot; 403 pih->addr = start; 404 pih->size = size; 405 pa = pih->addr + ph->ph_space[IO].base; 406 return bus_space_map(sc->sc_iot, pa, size, 0, &pih->ioh); 407 } 408 409 static void 410 at91cf_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih) 411 { 412 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 413 struct at91cf_softc *sc = ph->ph_sc; 414 415 DPRINTFN(1, ("at91cf_io_free\n")); 416 417 bus_space_unmap(sc->sc_iot, pih->ioh, pih->size); 418 } 419 420 static int 421 at91cf_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 422 bus_size_t size, struct pcmcia_io_handle *pih, int *windowp) 423 { 424 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 425 426 DPRINTFN(1, ("at91cf_io_map: offset=%#x, size=%#x, width=%d",(unsigned)offset,(unsigned)size,width)); 427 428 switch (width) { 429 case PCMCIA_WIDTH_IO8: 430 DPRINTFN(1, ("(8bit)\n")); 431 ph->ph_width = 8; 432 break; 433 case PCMCIA_WIDTH_IO16: 434 case PCMCIA_WIDTH_AUTO: /* I don't understand how I check it */ 435 DPRINTFN(1, ("(16bit)\n")); 436 ph->ph_width = 16; 437 break; 438 default: 439 DPRINTFN(1, ("(unknown)\n")); 440 return -1; 441 } 442 *windowp = 0; /* unused */ 443 return 0; 444 } 445 446 static void 447 at91cf_io_unmap(pcmcia_chipset_handle_t pch, int window) 448 { 449 DPRINTFN(1, ("at91cf_io_unmap: window=%#x\n",window)); 450 } 451 452 static void * 453 at91cf_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf, 454 int ipl, int (*ih_func)(void *), void *ih_arg) 455 { 456 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 457 struct at91cf_softc *sc = ph->ph_sc; 458 at91cf_chipset_tag_t cscf = sc->sc_cscf; 459 460 DPRINTFN(1, ("at91cf_intr_establish\n")); 461 462 if (ph->ph_ih_func) 463 return 0; 464 465 ph->ph_ih_func = ih_func; 466 ph->ph_ih_arg = ih_arg; 467 468 return (*cscf->intr_establish)(sc, CF_IRQ, ipl, at91cf_intr_socket, ph); 469 // return (*cscf->intr_establish)(sc, CF_IRQ, ipl, ih_func, ih_arg); 470 } 471 472 static void 473 at91cf_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih) 474 { 475 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 476 struct at91cf_softc *sc = ph->ph_sc; 477 at91cf_chipset_tag_t cscf = sc->sc_cscf; 478 479 DPRINTFN(1, ("at91cf_intr_disestablish\n")); 480 481 ph->ph_ih_func = NULL; 482 ph->ph_ih_arg = NULL; 483 484 (*cscf->intr_disestablish)(sc, CF_IRQ, ih); 485 } 486 487 static int 488 at91cf_intr_socket(void *arg) 489 { 490 struct at91cf_handle *ph = arg; 491 struct at91cf_softc *sc = ph->ph_sc; 492 at91cf_chipset_tag_t cscf = sc->sc_cscf; 493 int err = 0, irq; 494 495 if (ph->ph_ih_func) { 496 irq = (*cscf->irq_line)(sc); 497 if (ph->ph_type == PCMCIA_IFTYPE_IO) 498 irq = !irq; 499 if (irq) 500 err = (*ph->ph_ih_func)(ph->ph_ih_arg); 501 else 502 DPRINTFN(2,("%s: other edge ignored\n", __FUNCTION__)); 503 } 504 505 return err; 506 } 507 508 static void 509 at91cf_socket_enable(pcmcia_chipset_handle_t pch) 510 { 511 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 512 struct at91cf_softc *sc = ph->ph_sc; 513 at91cf_chipset_tag_t cscf = sc->sc_cscf; 514 int wait; 515 516 DPRINTFN(1, ("at91cf_socket_enable\n")); 517 518 wait = (cscf->power_ctl)(sc, POWER_ON); 519 delay(wait); 520 } 521 522 static void 523 at91cf_socket_disable(pcmcia_chipset_handle_t pch) 524 { 525 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 526 struct at91cf_softc *sc = ph->ph_sc; 527 at91cf_chipset_tag_t cscf = sc->sc_cscf; 528 int wait; 529 530 DPRINTFN(1, ("at91cf_socket_disable\n")); 531 532 wait = (cscf->power_ctl)(sc, POWER_OFF); 533 delay(wait); 534 } 535 536 static void 537 at91cf_socket_settype(pcmcia_chipset_handle_t pch, int type) 538 { 539 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 540 541 DPRINTFN(1, ("at91cf_socket_settype: type=%d",type)); 542 543 ph->ph_type = type; 544 545 switch (type) { 546 case PCMCIA_IFTYPE_MEMORY: 547 DPRINTFN(1, ("(Memory)\n")); 548 break; 549 case PCMCIA_IFTYPE_IO: 550 DPRINTFN(1, ("(I/O)\n")); 551 break; 552 default: 553 DPRINTFN(1, ("(unknown)\n")); 554 return; 555 } 556 } 557 558 #if 0 559 static int 560 at91cf_get_voltage(struct at91cf_handle *ph) 561 { 562 struct at91cf_softc *sc = ph->ph_sc; 563 at91cf_chipset_tag_t cscf = sc->sc_cscf; 564 int cap, vcc = 0; 565 566 cap = (cscf->power_capability)(sc); 567 if (eppio_read(sc->sc_pio, ph->ph_port, ph->ph_vs[0])) { 568 if (cap | VCC_5V) 569 vcc = 5; 570 else 571 printf("%s: unsupported Vcc 5 Volts", 572 device_xname(sc->sc_dev)); 573 } else { 574 if (cap | VCC_3V) 575 vcc = 3; 576 else 577 printf("%s: unsupported Vcc 3.3 Volts", 578 device_xname(sc->sc_dev)); 579 } 580 DPRINTFN(1, ("at91cf_get_voltage: vs1=%d, vs2=%d (%dV)\n",eppio_read_bit(sc->sc_pio, ph->ph_port, ph->ph_vs[0]),eppio_read_bit(sc->sc_pio, ph->ph_port, ph->ph_vs[1]),vcc)); 581 return vcc; 582 } 583 584 #endif 585