1 /* $Id: at91cf.c,v 1.4 2011/07/26 22:52:47 dyoung Exp $ */ 2 /* $NetBSD: at91cf.c,v 1.4 2011/07/26 22:52:47 dyoung 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.4 2011/07/26 22:52:47 dyoung 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 <sys/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 ph->ph_card = config_found_ia(sc->sc_dev, "pcmciabus", &paa, 232 at91cf_print); 233 234 (*cscf->intr_establish)(sc, CD_IRQ, IPL_BIO, at91cf_intr_carddetect, ph); 235 wait = (*cscf->power_ctl)(sc, POWER_OFF); 236 delay(wait); 237 238 kthread_create(PRI_NONE, 0, NULL, at91cf_create_event_thread, ph, 239 &ph->ph_event_thread, "%s", device_xname(sc->sc_dev)); 240 } 241 242 static int 243 at91cf_print(void *arg, const char *pnp) 244 { 245 return (UNCONF); 246 } 247 248 static void 249 at91cf_create_event_thread(void *arg) 250 { 251 struct at91cf_handle *ph = arg; 252 struct at91cf_softc *sc = ph->ph_sc; 253 at91cf_chipset_tag_t cscf = sc->sc_cscf; 254 255 ph->ph_status = (*cscf->card_detect)(sc); 256 257 DPRINTFN(1, ("at91cf_create_event_thread: status=%d\n", ph->ph_status)); 258 259 if (ph->ph_status) 260 pcmcia_card_attach(ph->ph_card); 261 262 ph->ph_run = 1; 263 kthread_create(PRI_NONE, 0, NULL, at91cf_event_thread, ph, 264 &ph->ph_event_thread, "%s", device_xname(sc->sc_dev)); 265 } 266 267 static void 268 at91cf_event_thread(void *arg) 269 { 270 struct at91cf_handle *ph = arg; 271 int status; 272 273 for (;;) { 274 status = ph->ph_status; 275 tsleep(ph, PWAIT, "CSC wait", 0); 276 if (!ph->ph_run) 277 break; 278 279 DPRINTFN(1, ("at91cf_event_thread: old status=%d, new status=%d\n", status, ph->ph_status)); 280 281 if (!status && ph->ph_status) 282 pcmcia_card_attach(ph->ph_card); 283 else if (status && !ph->ph_status) 284 pcmcia_card_detach(ph->ph_card, DETACH_FORCE); 285 } 286 287 DPRINTFN(1, ("at91cf_event_thread: run=%d\n",ph->ph_run)); 288 ph->ph_event_thread = NULL; 289 kthread_exit(0); 290 } 291 292 void 293 at91cf_shutdown(void *arg) 294 { 295 struct at91cf_handle *ph = arg; 296 297 DPRINTFN(1, ("at91cf_shutdown\n")); 298 ph->ph_run = 0; 299 wakeup(ph); 300 } 301 302 static int 303 at91cf_intr_carddetect(void *arg) 304 { 305 struct at91cf_handle *ph = arg; 306 struct at91cf_softc *sc = ph->ph_sc; 307 at91cf_chipset_tag_t cscf = sc->sc_cscf; 308 int nstatus; 309 310 nstatus = (*cscf->card_detect)(sc); 311 312 DPRINTFN(1, ("at91cf_intr: nstatus=%#x, ostatus=%#x\n", nstatus, ph->ph_status)); 313 314 if (nstatus != ph->ph_status) { 315 ph->ph_status = nstatus; 316 wakeup(ph); 317 } 318 319 return 0; 320 } 321 322 static int 323 at91cf_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 324 struct pcmcia_mem_handle *pmh) 325 { 326 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 327 struct at91cf_softc *sc = ph->ph_sc; 328 329 DPRINTFN(1, ("at91cf_mem_alloc: size=%#x\n",(unsigned)size)); 330 331 pmh->memt = sc->sc_iot; 332 return 0; 333 } 334 335 static void 336 at91cf_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh) 337 { 338 DPRINTFN(1, ("at91cf_mem_free\n")); 339 } 340 341 static int 342 at91cf_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr, 343 bus_size_t size, struct pcmcia_mem_handle *pmh, 344 bus_size_t *offsetp, int *windowp) 345 { 346 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 347 struct at91cf_softc *sc = ph->ph_sc; 348 bus_addr_t pa; 349 int err; 350 351 DPRINTFN(1, ("at91cf_mem_map: kind=%d, addr=%#x, size=%#x\n",kind,(unsigned)addr,(unsigned)size)); 352 353 pa = addr; 354 *offsetp = 0; 355 size = round_page(size); 356 pmh->realsize = size; 357 if (kind & PCMCIA_WIDTH_MEM8) 358 ph->ph_width = 8; 359 else 360 ph->ph_width = 16; 361 switch (kind & ~PCMCIA_WIDTH_MEM_MASK) { 362 case PCMCIA_MEM_ATTR: 363 pa += ph->ph_space[ATTRIBUTE].base; 364 break; 365 case PCMCIA_MEM_COMMON: 366 pa += ph->ph_space[COMMON].base; 367 break; 368 default: 369 return -1; 370 } 371 372 DPRINTFN(1, ("at91cf_mem_map: pa=%#x, *offsetp=%#x, size=%#x\n",(unsigned)pa,(unsigned)addr,(unsigned)size)); 373 374 if (!(err = bus_space_map(sc->sc_iot, pa, size, 0, &pmh->memh))) 375 *windowp = (int)pmh->memh; 376 return err; 377 } 378 379 static void 380 at91cf_mem_unmap(pcmcia_chipset_handle_t pch, int window) 381 { 382 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 383 struct at91cf_softc *sc = ph->ph_sc; 384 385 DPRINTFN(1, ("at91cf_mem_unmap: window=%#x\n",window)); 386 387 bus_space_unmap(sc->sc_iot, (bus_addr_t)window, 0x1000); 388 } 389 390 static int 391 at91cf_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size, 392 bus_size_t align, struct pcmcia_io_handle *pih) 393 { 394 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 395 struct at91cf_softc *sc = ph->ph_sc; 396 bus_addr_t pa; 397 398 DPRINTFN(1, ("at91cf_io_alloc: start=%#x, size=%#x, align=%#x\n",(unsigned)start,(unsigned)size,(unsigned)align)); 399 400 pih->iot = sc->sc_iot; 401 pih->addr = start; 402 pih->size = size; 403 pa = pih->addr + ph->ph_space[IO].base; 404 return bus_space_map(sc->sc_iot, pa, size, 0, &pih->ioh); 405 } 406 407 static void 408 at91cf_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih) 409 { 410 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 411 struct at91cf_softc *sc = ph->ph_sc; 412 413 DPRINTFN(1, ("at91cf_io_free\n")); 414 415 bus_space_unmap(sc->sc_iot, pih->ioh, pih->size); 416 } 417 418 static int 419 at91cf_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 420 bus_size_t size, struct pcmcia_io_handle *pih, int *windowp) 421 { 422 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 423 424 DPRINTFN(1, ("at91cf_io_map: offset=%#x, size=%#x, width=%d",(unsigned)offset,(unsigned)size,width)); 425 426 switch (width) { 427 case PCMCIA_WIDTH_IO8: 428 DPRINTFN(1, ("(8bit)\n")); 429 ph->ph_width = 8; 430 break; 431 case PCMCIA_WIDTH_IO16: 432 case PCMCIA_WIDTH_AUTO: /* I don't understand how I check it */ 433 DPRINTFN(1, ("(16bit)\n")); 434 ph->ph_width = 16; 435 break; 436 default: 437 DPRINTFN(1, ("(unknown)\n")); 438 return -1; 439 } 440 *windowp = 0; /* unused */ 441 return 0; 442 } 443 444 static void 445 at91cf_io_unmap(pcmcia_chipset_handle_t pch, int window) 446 { 447 DPRINTFN(1, ("at91cf_io_unmap: window=%#x\n",window)); 448 } 449 450 static void * 451 at91cf_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf, 452 int ipl, int (*ih_func)(void *), void *ih_arg) 453 { 454 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 455 struct at91cf_softc *sc = ph->ph_sc; 456 at91cf_chipset_tag_t cscf = sc->sc_cscf; 457 458 DPRINTFN(1, ("at91cf_intr_establish\n")); 459 460 if (ph->ph_ih_func) 461 return 0; 462 463 ph->ph_ih_func = ih_func; 464 ph->ph_ih_arg = ih_arg; 465 466 return (*cscf->intr_establish)(sc, CF_IRQ, ipl, at91cf_intr_socket, ph); 467 // return (*cscf->intr_establish)(sc, CF_IRQ, ipl, ih_func, ih_arg); 468 } 469 470 static void 471 at91cf_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih) 472 { 473 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 474 struct at91cf_softc *sc = ph->ph_sc; 475 at91cf_chipset_tag_t cscf = sc->sc_cscf; 476 477 DPRINTFN(1, ("at91cf_intr_disestablish\n")); 478 479 ph->ph_ih_func = NULL; 480 ph->ph_ih_arg = NULL; 481 482 (*cscf->intr_disestablish)(sc, CF_IRQ, ih); 483 } 484 485 static int 486 at91cf_intr_socket(void *arg) 487 { 488 struct at91cf_handle *ph = arg; 489 struct at91cf_softc *sc = ph->ph_sc; 490 at91cf_chipset_tag_t cscf = sc->sc_cscf; 491 int err = 0, irq; 492 493 if (ph->ph_ih_func) { 494 irq = (*cscf->irq_line)(sc); 495 if (ph->ph_type == PCMCIA_IFTYPE_IO) 496 irq = !irq; 497 if (irq) 498 err = (*ph->ph_ih_func)(ph->ph_ih_arg); 499 else 500 DPRINTFN(2,("%s: other edge ignored\n", __FUNCTION__)); 501 } 502 503 return err; 504 } 505 506 static void 507 at91cf_socket_enable(pcmcia_chipset_handle_t pch) 508 { 509 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 510 struct at91cf_softc *sc = ph->ph_sc; 511 at91cf_chipset_tag_t cscf = sc->sc_cscf; 512 int wait; 513 514 DPRINTFN(1, ("at91cf_socket_enable\n")); 515 516 wait = (cscf->power_ctl)(sc, POWER_ON); 517 delay(wait); 518 } 519 520 static void 521 at91cf_socket_disable(pcmcia_chipset_handle_t pch) 522 { 523 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 524 struct at91cf_softc *sc = ph->ph_sc; 525 at91cf_chipset_tag_t cscf = sc->sc_cscf; 526 int wait; 527 528 DPRINTFN(1, ("at91cf_socket_disable\n")); 529 530 wait = (cscf->power_ctl)(sc, POWER_OFF); 531 delay(wait); 532 } 533 534 static void 535 at91cf_socket_settype(pcmcia_chipset_handle_t pch, int type) 536 { 537 struct at91cf_handle *ph = (struct at91cf_handle *)pch; 538 539 DPRINTFN(1, ("at91cf_socket_settype: type=%d",type)); 540 541 ph->ph_type = type; 542 543 switch (type) { 544 case PCMCIA_IFTYPE_MEMORY: 545 DPRINTFN(1, ("(Memory)\n")); 546 break; 547 case PCMCIA_IFTYPE_IO: 548 DPRINTFN(1, ("(I/O)\n")); 549 break; 550 default: 551 DPRINTFN(1, ("(unknown)\n")); 552 return; 553 } 554 } 555 556 #if 0 557 static int 558 at91cf_get_voltage(struct at91cf_handle *ph) 559 { 560 struct at91cf_softc *sc = ph->ph_sc; 561 at91cf_chipset_tag_t cscf = sc->sc_cscf; 562 int cap, vcc = 0; 563 564 cap = (cscf->power_capability)(sc); 565 if (eppio_read(sc->sc_pio, ph->ph_port, ph->ph_vs[0])) { 566 if (cap | VCC_5V) 567 vcc = 5; 568 else 569 printf("%s: unsupported Vcc 5 Volts", 570 device_xname(sc->sc_dev)); 571 } else { 572 if (cap | VCC_3V) 573 vcc = 3; 574 else 575 printf("%s: unsupported Vcc 3.3 Volts", 576 device_xname(sc->sc_dev)); 577 } 578 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)); 579 return vcc; 580 } 581 582 #endif 583