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