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