stp4020.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /* $OpenBSD: stp4020.c,v 1.18 2013/11/19 01:23:51 deraadt Exp $ */
  2. /* $NetBSD: stp4020.c,v 1.23 2002/06/01 23:51:03 lukem Exp $ */
  3. /*-
  4. * Copyright (c) 1998 The NetBSD Foundation, Inc.
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to The NetBSD Foundation
  8. * by Paul Kranenburg.
  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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  21. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  23. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /*
  32. * STP4020: SBus/PCMCIA bridge supporting one Type-3 PCMCIA card, or up to
  33. * two Type-1 and Type-2 PCMCIA cards..
  34. */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/errno.h>
  38. #include <sys/extent.h>
  39. #include <sys/proc.h>
  40. #include <sys/kernel.h>
  41. #include <sys/kthread.h>
  42. #include <sys/device.h>
  43. #include <dev/pcmcia/pcmciareg.h>
  44. #include <dev/pcmcia/pcmciavar.h>
  45. #include <dev/pcmcia/pcmciachip.h>
  46. #include <machine/bus.h>
  47. #include <machine/intr.h>
  48. #include <dev/sbus/stp4020reg.h>
  49. #include <dev/sbus/stp4020var.h>
  50. /*
  51. * We use the three available windows per socket in a simple, fixed
  52. * arrangement. Each window maps (at full 1 MB size) one of the pcmcia
  53. * spaces into sbus space.
  54. */
  55. #define STP_WIN_ATTR 0 /* index of the attribute memory space window */
  56. #define STP_WIN_MEM 1 /* index of the common memory space window */
  57. #define STP_WIN_IO 2 /* index of the io space window */
  58. #ifdef STP4020_DEBUG
  59. int stp4020_debug = 0;
  60. #define DPRINTF(x) do { if (stp4020_debug) printf x; } while(0)
  61. #else
  62. #define DPRINTF(x)
  63. #endif
  64. int stp4020print(void *, const char *);
  65. void stp4020_map_window(struct stp4020_socket *, int, int);
  66. void stp4020_calc_speed(int, int, int *, int *);
  67. void stp4020_intr_dispatch(void *);
  68. struct cfdriver stp_cd = {
  69. NULL, "stp", DV_DULL
  70. };
  71. #ifdef STP4020_DEBUG
  72. static void stp4020_dump_regs(struct stp4020_socket *);
  73. #endif
  74. static u_int16_t stp4020_rd_sockctl(struct stp4020_socket *, int);
  75. static void stp4020_wr_sockctl(struct stp4020_socket *, int, u_int16_t);
  76. static u_int16_t stp4020_rd_winctl(struct stp4020_socket *, int, int);
  77. static void stp4020_wr_winctl(struct stp4020_socket *, int, int, u_int16_t);
  78. void stp4020_delay(unsigned int);
  79. void stp4020_attach_socket(struct stp4020_socket *, int);
  80. void stp4020_create_event_thread(void *);
  81. void stp4020_event_thread(void *);
  82. void stp4020_queue_event(struct stp4020_softc *, int);
  83. int stp4020_chip_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
  84. struct pcmcia_mem_handle *);
  85. void stp4020_chip_mem_free(pcmcia_chipset_handle_t,
  86. struct pcmcia_mem_handle *);
  87. int stp4020_chip_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
  88. bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
  89. void stp4020_chip_mem_unmap(pcmcia_chipset_handle_t, int);
  90. int stp4020_chip_io_alloc(pcmcia_chipset_handle_t,
  91. bus_addr_t, bus_size_t, bus_size_t, struct pcmcia_io_handle *);
  92. void stp4020_chip_io_free(pcmcia_chipset_handle_t,
  93. struct pcmcia_io_handle *);
  94. int stp4020_chip_io_map(pcmcia_chipset_handle_t, int, bus_addr_t,
  95. bus_size_t, struct pcmcia_io_handle *, int *);
  96. void stp4020_chip_io_unmap(pcmcia_chipset_handle_t, int);
  97. void stp4020_chip_socket_enable(pcmcia_chipset_handle_t);
  98. void stp4020_chip_socket_disable(pcmcia_chipset_handle_t);
  99. void *stp4020_chip_intr_establish(pcmcia_chipset_handle_t,
  100. struct pcmcia_function *, int, int (*) (void *), void *, char *);
  101. void stp4020_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
  102. const char *stp4020_chip_intr_string(pcmcia_chipset_handle_t, void *);
  103. /* Our PCMCIA chipset methods */
  104. static struct pcmcia_chip_functions stp4020_functions = {
  105. stp4020_chip_mem_alloc,
  106. stp4020_chip_mem_free,
  107. stp4020_chip_mem_map,
  108. stp4020_chip_mem_unmap,
  109. stp4020_chip_io_alloc,
  110. stp4020_chip_io_free,
  111. stp4020_chip_io_map,
  112. stp4020_chip_io_unmap,
  113. stp4020_chip_intr_establish,
  114. stp4020_chip_intr_disestablish,
  115. stp4020_chip_intr_string,
  116. stp4020_chip_socket_enable,
  117. stp4020_chip_socket_disable
  118. };
  119. static __inline__ u_int16_t
  120. stp4020_rd_sockctl(h, idx)
  121. struct stp4020_socket *h;
  122. int idx;
  123. {
  124. int o = ((STP4020_SOCKREGS_SIZE * (h->sock)) + idx);
  125. return (bus_space_read_2(h->tag, h->regs, o));
  126. }
  127. static __inline__ void
  128. stp4020_wr_sockctl(h, idx, v)
  129. struct stp4020_socket *h;
  130. int idx;
  131. u_int16_t v;
  132. {
  133. int o = (STP4020_SOCKREGS_SIZE * (h->sock)) + idx;
  134. bus_space_write_2(h->tag, h->regs, o, v);
  135. }
  136. static __inline__ u_int16_t
  137. stp4020_rd_winctl(h, win, idx)
  138. struct stp4020_socket *h;
  139. int win;
  140. int idx;
  141. {
  142. int o = (STP4020_SOCKREGS_SIZE * (h->sock)) +
  143. (STP4020_WINREGS_SIZE * win) + idx;
  144. return (bus_space_read_2(h->tag, h->regs, o));
  145. }
  146. static __inline__ void
  147. stp4020_wr_winctl(h, win, idx, v)
  148. struct stp4020_socket *h;
  149. int win;
  150. int idx;
  151. u_int16_t v;
  152. {
  153. int o = (STP4020_SOCKREGS_SIZE * (h->sock)) +
  154. (STP4020_WINREGS_SIZE * win) + idx;
  155. bus_space_write_2(h->tag, h->regs, o, v);
  156. }
  157. int
  158. stp4020print(aux, busname)
  159. void *aux;
  160. const char *busname;
  161. {
  162. struct pcmciabus_attach_args *paa = aux;
  163. struct stp4020_socket *h = paa->pch;
  164. printf(" socket %d", h->sock);
  165. return (UNCONF);
  166. }
  167. /*
  168. * Attach all the sub-devices we can find
  169. */
  170. void
  171. stpattach_common(struct stp4020_softc *sc, int clockfreq)
  172. {
  173. int i, rev;
  174. rev = stp4020_rd_sockctl(&sc->sc_socks[0], STP4020_ISR1_IDX) &
  175. STP4020_ISR1_REV_M;
  176. printf(": rev %x\n", rev);
  177. sc->sc_pct = (pcmcia_chipset_tag_t)&stp4020_functions;
  178. /*
  179. * Arrange that a kernel thread be created to handle
  180. * insert/removal events.
  181. */
  182. sc->events = 0;
  183. kthread_create_deferred(stp4020_create_event_thread, sc);
  184. for (i = 0; i < STP4020_NSOCK; i++) {
  185. struct stp4020_socket *h = &sc->sc_socks[i];
  186. h->sock = i;
  187. h->sc = sc;
  188. #ifdef STP4020_DEBUG
  189. if (stp4020_debug)
  190. stp4020_dump_regs(h);
  191. #endif
  192. stp4020_attach_socket(h, clockfreq);
  193. }
  194. }
  195. void
  196. stp4020_attach_socket(h, speed)
  197. struct stp4020_socket *h;
  198. int speed;
  199. {
  200. struct pcmciabus_attach_args paa;
  201. int v;
  202. /* no interrupt handlers yet */
  203. h->intrhandler = NULL;
  204. h->intrarg = NULL;
  205. h->softint = NULL;
  206. h->int_enable = h->int_disable = 0;
  207. /* Map all three windows */
  208. stp4020_map_window(h, STP_WIN_ATTR, speed);
  209. stp4020_map_window(h, STP_WIN_MEM, speed);
  210. stp4020_map_window(h, STP_WIN_IO, speed);
  211. /* Configure one pcmcia device per socket */
  212. paa.paa_busname = "pcmcia";
  213. paa.pct = (pcmcia_chipset_tag_t)h->sc->sc_pct;
  214. paa.pch = (pcmcia_chipset_handle_t)h;
  215. paa.iobase = 0;
  216. paa.iosize = STP4020_WINDOW_SIZE;
  217. h->pcmcia = config_found(&h->sc->sc_dev, &paa, stp4020print);
  218. if (h->pcmcia == NULL)
  219. return;
  220. /*
  221. * There's actually a pcmcia bus attached; initialize the slot.
  222. */
  223. /*
  224. * Clear things up before we enable status change interrupts.
  225. * This seems to not be fully initialized by the PROM.
  226. */
  227. stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0);
  228. stp4020_wr_sockctl(h, STP4020_ICR0_IDX, 0);
  229. stp4020_wr_sockctl(h, STP4020_ISR1_IDX, 0x3fff);
  230. stp4020_wr_sockctl(h, STP4020_ISR0_IDX, 0x3fff);
  231. /*
  232. * Enable socket status change interrupts.
  233. * We use SB_INT[1] for status change interrupts.
  234. */
  235. v = STP4020_ICR0_ALL_STATUS_IE | STP4020_ICR0_SCILVL_SB1;
  236. stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v);
  237. /* Get live status bits from ISR0 */
  238. v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX);
  239. h->sense = v & (STP4020_ISR0_CD1ST | STP4020_ISR0_CD2ST);
  240. if (h->sense != 0) {
  241. h->flags |= STP4020_SOCKET_BUSY;
  242. pcmcia_card_attach(h->pcmcia);
  243. }
  244. }
  245. /*
  246. * Deferred thread creation callback.
  247. */
  248. void
  249. stp4020_create_event_thread(arg)
  250. void *arg;
  251. {
  252. struct stp4020_softc *sc = arg;
  253. if (kthread_create(stp4020_event_thread, sc, &sc->event_thread,
  254. sc->sc_dev.dv_xname)) {
  255. panic("%s: unable to create event thread", sc->sc_dev.dv_xname);
  256. }
  257. }
  258. /*
  259. * The actual event handling thread.
  260. */
  261. void
  262. stp4020_event_thread(arg)
  263. void *arg;
  264. {
  265. struct stp4020_softc *sc = arg;
  266. int s, sense;
  267. unsigned int socket;
  268. for (;;) {
  269. struct stp4020_socket *h;
  270. s = splhigh();
  271. if ((socket = ffs(sc->events)) == 0) {
  272. splx(s);
  273. (void)tsleep(&sc->events, PWAIT, "stp4020_ev", 0);
  274. continue;
  275. }
  276. socket--;
  277. sc->events &= ~(1 << socket);
  278. splx(s);
  279. if (socket >= STP4020_NSOCK) {
  280. #ifdef DEBUG
  281. printf("stp4020_event_thread: wayward socket number %d\n",
  282. socket);
  283. #endif
  284. continue;
  285. }
  286. h = &sc->sc_socks[socket];
  287. /* Read socket's ISR0 for the interrupt status bits */
  288. sense = stp4020_rd_sockctl(h, STP4020_ISR0_IDX) &
  289. (STP4020_ISR0_CD1ST | STP4020_ISR0_CD2ST);
  290. if (sense > h->sense) {
  291. /*
  292. * If at least one more sensor is asserted, this is
  293. * a card insertion.
  294. */
  295. h->sense = sense;
  296. if ((h->flags & STP4020_SOCKET_BUSY) == 0) {
  297. h->flags |= STP4020_SOCKET_BUSY;
  298. pcmcia_card_attach(h->pcmcia);
  299. }
  300. } else if (sense < h->sense) {
  301. /*
  302. * If at least one less sensor is asserted, this is
  303. * a card removal.
  304. */
  305. h->sense = sense;
  306. if (h->flags & STP4020_SOCKET_BUSY) {
  307. h->flags &= ~STP4020_SOCKET_BUSY;
  308. pcmcia_card_detach(h->pcmcia, DETACH_FORCE);
  309. }
  310. }
  311. }
  312. }
  313. void
  314. stp4020_queue_event(sc, sock)
  315. struct stp4020_softc *sc;
  316. int sock;
  317. {
  318. int s;
  319. s = splhigh();
  320. sc->events |= (1 << sock);
  321. splx(s);
  322. wakeup(&sc->events);
  323. }
  324. /*
  325. * Software interrupt called to invoke the real driver interrupt handler.
  326. */
  327. void
  328. stp4020_intr_dispatch(void *arg)
  329. {
  330. struct stp4020_socket *h = (struct stp4020_socket *)arg;
  331. int s;
  332. /* invoke driver handler */
  333. h->intrhandler(h->intrarg);
  334. /* enable SBUS interrupts for PCMCIA interrupts again */
  335. s = splhigh();
  336. stp4020_wr_sockctl(h, STP4020_ICR0_IDX, h->int_enable);
  337. splx(s);
  338. }
  339. int
  340. stp4020_statintr(arg)
  341. void *arg;
  342. {
  343. struct stp4020_softc *sc = arg;
  344. int i, sense, r = 0;
  345. int s;
  346. /* protect hardware access against soft interrupts */
  347. s = splhigh();
  348. /*
  349. * Check each socket for pending requests.
  350. */
  351. for (i = 0 ; i < STP4020_NSOCK; i++) {
  352. struct stp4020_socket *h;
  353. int v;
  354. h = &sc->sc_socks[i];
  355. /* Read socket's ISR0 for the interrupt status bits */
  356. v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX);
  357. sense = v & (STP4020_ISR0_CD1ST | STP4020_ISR0_CD2ST);
  358. #ifdef STP4020_DEBUG
  359. if (stp4020_debug != 0)
  360. printf("stp4020_statintr: ISR0=%b\n",
  361. v, STP4020_ISR0_IOBITS);
  362. #endif
  363. /* Ack all interrupts at once */
  364. stp4020_wr_sockctl(h, STP4020_ISR0_IDX,
  365. STP4020_ISR0_ALL_STATUS_IRQ);
  366. if ((v & STP4020_ISR0_CDCHG) != 0) {
  367. r = 1;
  368. /*
  369. * Card detect status changed. In an ideal world,
  370. * both card detect sensors should be set if a card
  371. * is in the slot, and clear if it is not.
  372. *
  373. * Unfortunately, it turns out that we can get the
  374. * notification before both sensors are set (or
  375. * clear).
  376. *
  377. * This can be very funny if only one sensor is set.
  378. * Is this a removal or an insertion operation?
  379. * Defer appropriate action to the worker thread.
  380. */
  381. if (sense != h->sense)
  382. stp4020_queue_event(sc, i);
  383. }
  384. /* informational messages */
  385. if ((v & STP4020_ISR0_BVD1CHG) != 0) {
  386. DPRINTF(("stp4020[%d]: Battery change 1\n",
  387. h->sock));
  388. r = 1;
  389. }
  390. if ((v & STP4020_ISR0_BVD2CHG) != 0) {
  391. DPRINTF(("stp4020[%d]: Battery change 2\n",
  392. h->sock));
  393. r = 1;
  394. }
  395. if ((v & STP4020_ISR0_RDYCHG) != 0) {
  396. DPRINTF(("stp4020[%d]: Ready/Busy change\n",
  397. h->sock));
  398. r = 1;
  399. }
  400. if ((v & STP4020_ISR0_WPCHG) != 0) {
  401. DPRINTF(("stp4020[%d]: Write protect change\n",
  402. h->sock));
  403. r = 1;
  404. }
  405. if ((v & STP4020_ISR0_PCTO) != 0) {
  406. DPRINTF(("stp4020[%d]: Card access timeout\n",
  407. h->sock));
  408. r = 1;
  409. }
  410. if ((v & STP4020_ISR0_SCINT) != 0) {
  411. DPRINTF(("stp4020[%d]: Status change\n",
  412. h->sock));
  413. r = 1;
  414. }
  415. /*
  416. * Not interrupts flag per se, but interrupts can occur when
  417. * they are asserted, at least during our slot enable routine.
  418. */
  419. if ((h->flags & STP4020_SOCKET_ENABLING) &&
  420. (v & (STP4020_ISR0_WAITST | STP4020_ISR0_PWRON)))
  421. r = 1;
  422. }
  423. splx(s);
  424. return (r);
  425. }
  426. int
  427. stp4020_iointr(arg)
  428. void *arg;
  429. {
  430. struct stp4020_softc *sc = arg;
  431. int i, r = 0;
  432. int s;
  433. /* protect hardware access against soft interrupts */
  434. s = splhigh();
  435. /*
  436. * Check each socket for pending requests.
  437. */
  438. for (i = 0 ; i < STP4020_NSOCK; i++) {
  439. struct stp4020_socket *h;
  440. int v;
  441. h = &sc->sc_socks[i];
  442. v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX);
  443. if ((v & STP4020_ISR0_IOINT) != 0) {
  444. /* we can not deny this is ours, no matter what the
  445. card driver says. */
  446. r = 1;
  447. /* ack interrupt */
  448. stp4020_wr_sockctl(h, STP4020_ISR0_IDX, v);
  449. /* It's a card interrupt */
  450. if ((h->flags & STP4020_SOCKET_BUSY) == 0) {
  451. printf("stp4020[%d]: spurious interrupt?\n",
  452. h->sock);
  453. continue;
  454. }
  455. /* Call card handler, if any */
  456. if (h->softint != NULL) {
  457. softintr_schedule(h->softint);
  458. /*
  459. * Disable this sbus interrupt, until the
  460. * softintr handler had a chance to run.
  461. */
  462. stp4020_wr_sockctl(h, STP4020_ICR0_IDX,
  463. h->int_disable);
  464. }
  465. }
  466. }
  467. splx(s);
  468. return (r);
  469. }
  470. /*
  471. * The function gets the sbus speed and a access time and calculates
  472. * values for the CMDLNG and CMDDLAY registers.
  473. */
  474. void
  475. stp4020_calc_speed(int bus_speed, int ns, int *length, int *delay)
  476. {
  477. int result;
  478. if (ns < STP4020_MEM_SPEED_MIN)
  479. ns = STP4020_MEM_SPEED_MIN;
  480. else if (ns > STP4020_MEM_SPEED_MAX)
  481. ns = STP4020_MEM_SPEED_MAX;
  482. result = ns * (bus_speed / 1000);
  483. if (result % 1000000)
  484. result = result / 1000000 + 1;
  485. else
  486. result /= 1000000;
  487. *length = result;
  488. /* the sbus frequency range is limited, so we can keep this simple */
  489. *delay = ns <= STP4020_MEM_SPEED_MIN ? 1 : 2;
  490. }
  491. void
  492. stp4020_map_window(struct stp4020_socket *h, int win, int speed)
  493. {
  494. int v, length, delay;
  495. /*
  496. * According to the PC Card standard 300ns access timing should be
  497. * used for attribute memory access. Our pcmcia framework does not
  498. * seem to propagate timing information, so we use that
  499. * everywhere.
  500. */
  501. stp4020_calc_speed(speed, 300, &length, &delay);
  502. /*
  503. * Fill in the Address Space Select and Base Address
  504. * fields of this windows control register 0.
  505. */
  506. v = ((delay << STP4020_WCR0_CMDDLY_S) & STP4020_WCR0_CMDDLY_M) |
  507. ((length << STP4020_WCR0_CMDLNG_S) & STP4020_WCR0_CMDLNG_M);
  508. switch (win) {
  509. case STP_WIN_ATTR:
  510. v |= STP4020_WCR0_ASPSEL_AM;
  511. break;
  512. case STP_WIN_MEM:
  513. v |= STP4020_WCR0_ASPSEL_CM;
  514. break;
  515. case STP_WIN_IO:
  516. v |= STP4020_WCR0_ASPSEL_IO;
  517. break;
  518. }
  519. v |= (STP4020_ADDR2PAGE(0) & STP4020_WCR0_BASE_M);
  520. stp4020_wr_winctl(h, win, STP4020_WCR0_IDX, v);
  521. stp4020_wr_winctl(h, win, STP4020_WCR1_IDX,
  522. 1 << STP4020_WCR1_WAITREQ_S);
  523. }
  524. int
  525. stp4020_chip_mem_alloc(pch, size, pcmhp)
  526. pcmcia_chipset_handle_t pch;
  527. bus_size_t size;
  528. struct pcmcia_mem_handle *pcmhp;
  529. {
  530. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  531. /* we can not do much here, defere work to _mem_map */
  532. pcmhp->memt = h->wintag;
  533. pcmhp->size = size;
  534. pcmhp->addr = 0;
  535. pcmhp->mhandle = 0;
  536. pcmhp->realsize = size;
  537. return (0);
  538. }
  539. void
  540. stp4020_chip_mem_free(pch, pcmhp)
  541. pcmcia_chipset_handle_t pch;
  542. struct pcmcia_mem_handle *pcmhp;
  543. {
  544. }
  545. int
  546. stp4020_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
  547. pcmcia_chipset_handle_t pch;
  548. int kind;
  549. bus_addr_t card_addr;
  550. bus_size_t size;
  551. struct pcmcia_mem_handle *pcmhp;
  552. bus_size_t *offsetp;
  553. int *windowp;
  554. {
  555. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  556. int win = (kind & PCMCIA_MEM_ATTR) ? STP_WIN_ATTR : STP_WIN_MEM;
  557. pcmhp->memt = h->wintag;
  558. bus_space_subregion(h->wintag, h->windows[win].winaddr,
  559. card_addr, size, &pcmhp->memh);
  560. pcmhp->size = size;
  561. pcmhp->realsize = STP4020_WINDOW_SIZE - card_addr;
  562. *offsetp = 0;
  563. *windowp = win;
  564. return (0);
  565. }
  566. void
  567. stp4020_chip_mem_unmap(pch, win)
  568. pcmcia_chipset_handle_t pch;
  569. int win;
  570. {
  571. }
  572. int
  573. stp4020_chip_io_alloc(pch, start, size, align, pcihp)
  574. pcmcia_chipset_handle_t pch;
  575. bus_addr_t start;
  576. bus_size_t size;
  577. bus_size_t align;
  578. struct pcmcia_io_handle *pcihp;
  579. {
  580. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  581. pcihp->iot = h->wintag;
  582. pcihp->ioh = h->windows[STP_WIN_IO].winaddr;
  583. pcihp->size = size;
  584. return (0);
  585. }
  586. void
  587. stp4020_chip_io_free(pch, pcihp)
  588. pcmcia_chipset_handle_t pch;
  589. struct pcmcia_io_handle *pcihp;
  590. {
  591. }
  592. int
  593. stp4020_chip_io_map(pch, width, offset, size, pcihp, windowp)
  594. pcmcia_chipset_handle_t pch;
  595. int width;
  596. bus_addr_t offset;
  597. bus_size_t size;
  598. struct pcmcia_io_handle *pcihp;
  599. int *windowp;
  600. {
  601. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  602. pcihp->iot = h->wintag;
  603. bus_space_subregion(h->wintag, h->windows[STP_WIN_IO].winaddr,
  604. offset, size, &pcihp->ioh);
  605. *windowp = 0;
  606. return (0);
  607. }
  608. void
  609. stp4020_chip_io_unmap(pch, win)
  610. pcmcia_chipset_handle_t pch;
  611. int win;
  612. {
  613. }
  614. void
  615. stp4020_chip_socket_enable(pch)
  616. pcmcia_chipset_handle_t pch;
  617. {
  618. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  619. int i, v;
  620. h->flags |= STP4020_SOCKET_ENABLING;
  621. /* this bit is mostly stolen from pcic_attach_card */
  622. /* Power down the socket to reset it, clear the card reset pin */
  623. stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0);
  624. /*
  625. * wait 300ms until power fails (Tpf). Then, wait 100ms since
  626. * we are changing Vcc (Toff).
  627. */
  628. stp4020_delay((300 + 100) * 1000);
  629. /* Power up the socket */
  630. v = STP4020_ICR1_MSTPWR;
  631. stp4020_wr_sockctl(h, STP4020_ICR1_IDX, v);
  632. /*
  633. * wait 100ms until power raise (Tpr) and 20ms to become
  634. * stable (Tsu(Vcc)).
  635. *
  636. * some machines require some more time to be settled
  637. * (another 200ms is added here).
  638. */
  639. stp4020_delay((100 + 20 + 200) * 1000);
  640. v |= STP4020_ICR1_PCIFOE | STP4020_ICR1_VPP1_VCC;
  641. stp4020_wr_sockctl(h, STP4020_ICR1_IDX, v);
  642. /*
  643. * hold RESET at least 20us.
  644. */
  645. stp4020_wr_sockctl(h, STP4020_ICR0_IDX,
  646. stp4020_rd_sockctl(h, STP4020_ICR0_IDX) | STP4020_ICR0_RESET);
  647. delay(20);
  648. stp4020_wr_sockctl(h, STP4020_ICR0_IDX,
  649. stp4020_rd_sockctl(h, STP4020_ICR0_IDX) & ~STP4020_ICR0_RESET);
  650. /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
  651. stp4020_delay(20000);
  652. /* Wait for the chip to finish initializing (5 seconds max) */
  653. for (i = 10000; i > 0; i--) {
  654. v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX);
  655. /* If the card has been removed, abort */
  656. if ((v & (STP4020_ISR0_CD1ST | STP4020_ISR0_CD2ST)) == 0) {
  657. h->flags &= ~STP4020_SOCKET_ENABLING;
  658. return;
  659. }
  660. if ((v & STP4020_ISR0_RDYST) != 0)
  661. break;
  662. delay(500);
  663. }
  664. if (i <= 0) {
  665. #ifdef STP4020_DEBUG
  666. printf("stp4020_chip_socket_enable: not ready: status %b\n",
  667. v, STP4020_ISR0_IOBITS);
  668. #endif
  669. h->flags &= ~STP4020_SOCKET_ENABLING;
  670. return;
  671. }
  672. v = stp4020_rd_sockctl(h, STP4020_ICR0_IDX);
  673. /*
  674. * Check the card type.
  675. * Enable socket I/O interrupts for IO cards.
  676. * We use level SB_INT[0] for I/O interrupts.
  677. */
  678. if (pcmcia_card_gettype(h->pcmcia) == PCMCIA_IFTYPE_IO) {
  679. v &= ~(STP4020_ICR0_IOILVL | STP4020_ICR0_IFTYPE);
  680. v |= STP4020_ICR0_IFTYPE_IO | STP4020_ICR0_IOIE |
  681. STP4020_ICR0_IOILVL_SB0 | STP4020_ICR0_SPKREN;
  682. h->int_enable = v;
  683. h->int_disable = v & ~STP4020_ICR0_IOIE;
  684. DPRINTF(("%s: configuring card for IO usage\n",
  685. h->sc->sc_dev.dv_xname));
  686. } else {
  687. v &= ~(STP4020_ICR0_IOILVL | STP4020_ICR0_IFTYPE |
  688. STP4020_ICR0_SPKREN | STP4020_ICR0_IOIE);
  689. v |= STP4020_ICR0_IFTYPE_MEM;
  690. h->int_enable = h->int_disable = v;
  691. DPRINTF(("%s: configuring card for MEM ONLY usage\n",
  692. h->sc->sc_dev.dv_xname));
  693. }
  694. stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v);
  695. h->flags &= ~STP4020_SOCKET_ENABLING;
  696. }
  697. void
  698. stp4020_chip_socket_disable(pch)
  699. pcmcia_chipset_handle_t pch;
  700. {
  701. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  702. int v;
  703. /*
  704. * Disable socket I/O interrupts.
  705. */
  706. v = stp4020_rd_sockctl(h, STP4020_ICR0_IDX);
  707. v &= ~(STP4020_ICR0_IOILVL | STP4020_ICR0_IFTYPE |
  708. STP4020_ICR0_SPKREN | STP4020_ICR0_IOIE);
  709. stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v);
  710. /* Power down the socket */
  711. stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0);
  712. /*
  713. * wait 300ms until power fails (Tpf).
  714. */
  715. stp4020_delay(300 * 1000);
  716. }
  717. void *
  718. stp4020_chip_intr_establish(pch, pf, ipl, handler, arg, xname)
  719. pcmcia_chipset_handle_t pch;
  720. struct pcmcia_function *pf;
  721. int ipl;
  722. int (*handler) (void *);
  723. void *arg;
  724. char *xname;
  725. {
  726. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  727. /*
  728. * Note that this code relies on softintr_establish() to be
  729. * used with real, hardware ipl values. All platforms with
  730. * SBus support support this.
  731. */
  732. h->intrhandler = handler;
  733. h->intrarg = arg;
  734. h->softint = softintr_establish(ipl, stp4020_intr_dispatch, h);
  735. return h->softint != NULL ? h : NULL;
  736. }
  737. void
  738. stp4020_chip_intr_disestablish(pch, ih)
  739. pcmcia_chipset_handle_t pch;
  740. void *ih;
  741. {
  742. struct stp4020_socket *h = (struct stp4020_socket *)pch;
  743. if (h->softint != NULL) {
  744. softintr_disestablish(h->softint);
  745. h->softint = NULL;
  746. }
  747. h->intrhandler = NULL;
  748. h->intrarg = NULL;
  749. }
  750. const char *
  751. stp4020_chip_intr_string(pch, ih)
  752. pcmcia_chipset_handle_t pch;
  753. void *ih;
  754. {
  755. if (ih == NULL)
  756. return ("couldn't establish interrupt");
  757. else
  758. return (""); /* nothing for now */
  759. }
  760. /*
  761. * Delay and possibly yield CPU.
  762. * XXX - assumes a context
  763. */
  764. void
  765. stp4020_delay(ms)
  766. unsigned int ms;
  767. {
  768. unsigned int ticks;
  769. /* Convert to ticks */
  770. ticks = (ms * hz) / 1000000;
  771. if (cold || ticks == 0) {
  772. delay(ms);
  773. return;
  774. }
  775. #ifdef DEBUG
  776. if (ticks > 60 * hz)
  777. panic("stp4020: preposterous delay: %u", ticks);
  778. #endif
  779. tsleep(&ticks, 0, "stp4020_delay", ticks);
  780. }
  781. #ifdef STP4020_DEBUG
  782. void
  783. stp4020_dump_regs(h)
  784. struct stp4020_socket *h;
  785. {
  786. /*
  787. * Dump control and status registers.
  788. */
  789. printf("socket[%d] registers:\n"
  790. "\tICR0=%b\n\tICR1=%b\n\tISR0=%b\n\tISR1=%x\n", h->sock,
  791. stp4020_rd_sockctl(h, STP4020_ICR0_IDX), STP4020_ICR0_BITS,
  792. stp4020_rd_sockctl(h, STP4020_ICR1_IDX), STP4020_ICR1_BITS,
  793. stp4020_rd_sockctl(h, STP4020_ISR0_IDX), STP4020_ISR0_IOBITS,
  794. stp4020_rd_sockctl(h, STP4020_ISR1_IDX));
  795. }
  796. #endif /* STP4020_DEBUG */