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