1 /* $NetBSD: sa11xx_pcic.c,v 1.6 2005/12/11 12:16:51 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2001 IWAMOTO Toshihiro. All rights reserved. 5 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Common code for SA11x0 based PCMCIA modules 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: sa11xx_pcic.c,v 1.6 2005/12/11 12:16:51 christos Exp $"); 39 40 #include <sys/types.h> 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/device.h> 44 #include <sys/callout.h> 45 #include <sys/kernel.h> 46 #include <sys/kthread.h> 47 #include <sys/malloc.h> 48 #include <uvm/uvm.h> 49 50 #include <machine/bus.h> 51 #include <machine/intr.h> 52 53 #include <dev/pcmcia/pcmciareg.h> 54 #include <dev/pcmcia/pcmciavar.h> 55 #include <dev/pcmcia/pcmciachip.h> 56 57 #include <arm/sa11x0/sa11x0_reg.h> 58 #include <arm/sa11x0/sa11x0_var.h> 59 #include <arm/sa11x0/sa11xx_pcicreg.h> 60 #include <arm/sa11x0/sa11xx_pcicvar.h> 61 62 static int sapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 63 struct pcmcia_mem_handle *); 64 static void sapcic_mem_free(pcmcia_chipset_handle_t, 65 struct pcmcia_mem_handle *); 66 static int sapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, 67 bus_size_t, struct pcmcia_mem_handle *, 68 bus_addr_t *, int *); 69 static void sapcic_mem_unmap(pcmcia_chipset_handle_t, int); 70 static int sapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, 71 bus_size_t, bus_size_t, 72 struct pcmcia_io_handle *); 73 static void sapcic_io_free(pcmcia_chipset_handle_t, 74 struct pcmcia_io_handle *); 75 static int sapcic_io_map(pcmcia_chipset_handle_t, int, 76 bus_addr_t, bus_size_t, 77 struct pcmcia_io_handle *, int *); 78 static void sapcic_io_unmap(pcmcia_chipset_handle_t, int); 79 static void *sapcic_intr_establish(pcmcia_chipset_handle_t, 80 struct pcmcia_function *, int, 81 int (*)(void *), void *); 82 static void sapcic_intr_disestablish(pcmcia_chipset_handle_t, 83 void *); 84 static void sapcic_socket_enable(pcmcia_chipset_handle_t); 85 static void sapcic_socket_disable(pcmcia_chipset_handle_t); 86 static void sapcic_socket_settype(pcmcia_chipset_handle_t, int); 87 88 static void sapcic_event_thread(void *); 89 90 static void sapcic_delay(int, const char *); 91 92 #ifdef DEBUG 93 #define DPRINTF(arg) printf arg 94 #else 95 #define DPRINTF(arg) 96 #endif 97 98 struct pcmcia_chip_functions sa11x0_pcmcia_functions = { 99 sapcic_mem_alloc, 100 sapcic_mem_free, 101 sapcic_mem_map, 102 sapcic_mem_unmap, 103 104 sapcic_io_alloc, 105 sapcic_io_free, 106 sapcic_io_map, 107 sapcic_io_unmap, 108 109 sapcic_intr_establish, 110 sapcic_intr_disestablish, 111 112 sapcic_socket_enable, 113 sapcic_socket_disable, 114 sapcic_socket_settype, 115 }; 116 117 118 void 119 sapcic_kthread_create(arg) 120 void *arg; 121 { 122 struct sapcic_socket *so = arg; 123 124 /* XXX attach card if already present */ 125 126 so->laststatus =(so->pcictag->read)(so, SAPCIC_STATUS_CARD); 127 if (so->laststatus == SAPCIC_CARD_VALID) { 128 printf("%s: card present\n", 129 so->sc->sc_dev.dv_xname); 130 131 pcmcia_card_attach(so->pcmcia); 132 } 133 134 if (kthread_create1(sapcic_event_thread, so, &so->event_thread, 135 "%s,%d", so->sc->sc_dev.dv_xname, so->socket)) { 136 printf("%s: unable to create event thread for socket %d\n", 137 so->sc->sc_dev.dv_xname, so->socket); 138 panic("sapcic_kthread_create"); 139 } 140 } 141 142 static void 143 sapcic_event_thread(arg) 144 void *arg; 145 { 146 struct sapcic_socket *so = arg; 147 int newstatus, s; 148 149 while (so->shutdown == 0) { 150 /* 151 * Serialize event processing on the PCIC. We may 152 * sleep while we hold this lock. 153 */ 154 (void) lockmgr(&so->sc->sc_lock, LK_EXCLUSIVE, NULL); 155 156 /* sleep .25s to be enqueued chatterling interrupts */ 157 (void) tsleep((caddr_t)sapcic_event_thread, PWAIT, 158 "pcicss", hz/4); 159 160 s = splhigh(); 161 so->event = 0; 162 163 /* we don't rely on interrupt type */ 164 newstatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD); 165 splx(s); 166 167 if (so->laststatus == newstatus) { 168 /* 169 * No events to process; release the PCIC lock. 170 */ 171 (void) lockmgr(&so->sc->sc_lock, LK_RELEASE, NULL); 172 (void) tsleep(&so->event, PWAIT, "pcicev", hz); 173 continue; 174 } 175 176 so->laststatus = newstatus; 177 switch (newstatus) { 178 case SAPCIC_CARD_VALID: 179 printf("%s: insertion event\n", 180 so->sc->sc_dev.dv_xname); 181 182 pcmcia_card_attach(so->pcmcia); 183 break; 184 185 case SAPCIC_CARD_INVALID: 186 printf("%s: removal event\n", 187 so->sc->sc_dev.dv_xname); 188 189 pcmcia_card_detach(so->pcmcia, DETACH_FORCE); 190 break; 191 192 default: 193 panic("sapcic_event_thread: unknown status %d", 194 newstatus); 195 } 196 197 (void) lockmgr(&so->sc->sc_lock, LK_RELEASE, NULL); 198 } 199 200 so->event_thread = NULL; 201 202 /* In case parent is waiting for us to exit. */ 203 wakeup(so->sc); 204 205 kthread_exit(0); 206 } 207 208 static void 209 sapcic_delay(timo, wmesg) 210 int timo; /* in milliseconds */ 211 const char *wmesg; 212 { 213 #ifdef DIAGNOSTIC 214 if (curlwp == NULL) 215 panic("sapcic_delay: called in interrupt context"); 216 #endif 217 218 tsleep(sapcic_delay, PWAIT, wmesg, roundup(timo * hz, 1000) / 1000); 219 } 220 221 int 222 sapcic_intr(arg) 223 void *arg; 224 { 225 struct sapcic_socket *so = arg; 226 227 so->event++; 228 (so->pcictag->clear_intr)(so->socket); 229 wakeup(&so->event); 230 return 1; 231 } 232 233 static int 234 sapcic_mem_alloc(pch, size, pmh) 235 pcmcia_chipset_handle_t pch; 236 bus_size_t size; 237 struct pcmcia_mem_handle *pmh; 238 { 239 struct sapcic_socket *so = pch; 240 241 /* All we need is bus space tag */ 242 memset(pmh, 0, sizeof(*pmh)); 243 pmh->memt = so->sc->sc_iot; 244 return (0); 245 } 246 247 248 static void 249 sapcic_mem_free(pch, pmh) 250 pcmcia_chipset_handle_t pch; 251 struct pcmcia_mem_handle *pmh; 252 { 253 } 254 255 static int 256 sapcic_mem_map(pch, kind, card_addr, size, pmh, offsetp, windowp) 257 pcmcia_chipset_handle_t pch; 258 int kind; 259 bus_addr_t card_addr; 260 bus_size_t size; 261 struct pcmcia_mem_handle *pmh; 262 bus_addr_t *offsetp; 263 int *windowp; 264 { 265 struct sapcic_socket *so = pch; 266 int error; 267 bus_addr_t pa; 268 269 pa = trunc_page(card_addr); 270 *offsetp = card_addr - pa; 271 size = round_page(card_addr + size) - pa; 272 pmh->realsize = size; 273 274 pa += SAPCIC_BASE_OFFSET; 275 pa += SAPCIC_SOCKET_OFFSET * so->socket; 276 277 switch (kind & ~PCMCIA_WIDTH_MEM_MASK) { 278 case PCMCIA_MEM_ATTR: 279 pa += SAPCIC_ATTR_OFFSET; 280 break; 281 case PCMCIA_MEM_COMMON: 282 pa += SAPCIC_COMMON_OFFSET; 283 break; 284 default: 285 panic("sapcic_mem_map: bogus kind"); 286 } 287 288 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh); 289 if (! error) 290 *windowp = (int)pmh->memh; 291 return (error); 292 } 293 294 static void 295 sapcic_mem_unmap(pch, window) 296 pcmcia_chipset_handle_t pch; 297 int window; 298 { 299 struct sapcic_socket *so = pch; 300 301 bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */ 302 } 303 304 static int 305 sapcic_io_alloc(pch, start, size, align, pih) 306 pcmcia_chipset_handle_t pch; 307 bus_addr_t start; 308 bus_size_t size; 309 bus_size_t align; 310 struct pcmcia_io_handle *pih; 311 { 312 struct sapcic_socket *so = pch; 313 int error; 314 bus_addr_t pa; 315 316 memset(pih, 0, sizeof(*pih)); 317 pih->iot = so->sc->sc_iot; 318 pih->addr = start; 319 pih->size = size; 320 321 pa = pih->addr; 322 pa += SAPCIC_BASE_OFFSET; 323 pa += SAPCIC_SOCKET_OFFSET * so->socket; 324 325 DPRINTF(("sapcic_io_alloc: %x %x\n", (unsigned int)pa, 326 (unsigned int)size)); 327 /* XXX Are we ignoring alignment constraints? */ 328 error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh); 329 330 return (error); 331 } 332 333 static void 334 sapcic_io_free(pch, pih) 335 pcmcia_chipset_handle_t pch; 336 struct pcmcia_io_handle *pih; 337 { 338 struct sapcic_socket *so = pch; 339 340 bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size); 341 } 342 343 static int 344 sapcic_io_map(pch, width, offset, size, pih, windowp) 345 pcmcia_chipset_handle_t pch; 346 int width; 347 bus_addr_t offset; 348 bus_size_t size; 349 struct pcmcia_io_handle *pih; 350 int *windowp; 351 { 352 return (0); 353 } 354 355 static void sapcic_io_unmap(pch, window) 356 pcmcia_chipset_handle_t pch; 357 int window; 358 { 359 } 360 361 static void * 362 sapcic_intr_establish(pch, pf, ipl, fct, arg) 363 pcmcia_chipset_handle_t pch; 364 struct pcmcia_function *pf; 365 int ipl; 366 int (*fct)(void *); 367 void *arg; 368 { 369 struct sapcic_socket *so = pch; 370 371 /* XXX need to check if something should be done here */ 372 373 return ((so->pcictag->intr_establish)(so, ipl, fct, arg)); 374 } 375 376 static void 377 sapcic_intr_disestablish(pch, ih) 378 pcmcia_chipset_handle_t pch; 379 void *ih; 380 { 381 struct sapcic_socket *so = pch; 382 383 ((so->pcictag->intr_disestablish)(so, ih)); 384 } 385 386 static void 387 sapcic_socket_enable(pch) 388 pcmcia_chipset_handle_t pch; 389 { 390 struct sapcic_socket *so = pch; 391 int i; 392 393 #if defined(DIAGNOSTIC) && defined(notyet) 394 if (so->flags & PCIC_FLAG_ENABLED) 395 printf("sapcic_socket_enable: enabling twice\n"); 396 #endif 397 398 /* disable interrupts */ 399 400 /* power down the socket to reset it, clear the card reset pin */ 401 (so->pcictag->set_power)(so, SAPCIC_POWER_OFF); 402 403 /* 404 * wait 300ms until power fails (Tpf). Then, wait 100ms since 405 * we are changing Vcc (Toff). 406 */ 407 sapcic_delay(300 + 100, "pccen0"); 408 409 /* power up the socket */ 410 /* XXX voltage selection should be done in PCMCIA code */ 411 if (so->power_capability & SAPCIC_POWER_5V) { 412 (so->pcictag->set_power)(so, SAPCIC_POWER_5V); 413 (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT, 414 SAPCIC_POWER_5V); 415 } else { 416 (so->pcictag->set_power)(so, SAPCIC_POWER_3V); 417 (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT, 418 SAPCIC_POWER_3V); 419 } 420 421 /* enable PCMCIA control lines */ 422 (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 1); 423 424 /* 425 * wait 100ms until power raise (Tpr) and 20ms to become 426 * stable (Tsu(Vcc)). 427 * 428 * some machines require some more time to be settled 429 * (300ms is added here). 430 */ 431 sapcic_delay(100 + 20 + 300, "pccen1"); 432 433 /* honor nWAIT signal */ 434 (so->pcictag->write)(so, SAPCIC_CONTROL_WAITENABLE, 1); 435 /* now make sure we have reset# active */ 436 (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 1); 437 438 /* 439 * hold RESET at least 10us, this is a min allow for slop in 440 * delay routine. 441 */ 442 delay(20); 443 444 /* clear the reset flag */ 445 (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 0); 446 447 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ 448 sapcic_delay(20, "pccen2"); 449 450 /* wait for the chip to finish initializing */ 451 sapcic_delay(10, "pccen3"); 452 for(i = 100; i; i--) { 453 if ((so->pcictag->read)(so, SAPCIC_STATUS_READY)) 454 break; 455 sapcic_delay(100, "pccen4"); 456 } 457 DPRINTF(("sapcic_socket_enable: wait ready %d\n", 100 - i)); 458 459 /* finally enable the interrupt */ 460 461 } 462 463 static void 464 sapcic_socket_disable(pch) 465 pcmcia_chipset_handle_t pch; 466 { 467 struct sapcic_socket *so = pch; 468 469 /* XXX mask card interrupts */ 470 471 /* power down the card */ 472 (so->pcictag->set_power)(so, SAPCIC_POWER_OFF); 473 474 /* float controller lines */ 475 (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 0); 476 } 477 478 static void 479 sapcic_socket_settype(pch, type) 480 pcmcia_chipset_handle_t pch; 481 int type; 482 { 483 484 /* XXX nothing to do */ 485 } 486