Annotation of sys/arch/jornada/dev/jmcu.c, Revision 1.3
1.3 ! nbrk 1: /* $Id: jmcu.c,v 1.2 2008/03/05 20:31:27 nbrk Exp $ */
1.1 nbrk 2: #include <sys/param.h>
3: #include <sys/systm.h>
4: #include <sys/device.h>
5: #include <sys/proc.h>
6: #include <sys/conf.h>
7: #include <sys/endian.h>
8:
9: #include <machine/intr.h>
10: #include <machine/bus.h>
11:
12: #include <dev/wscons/wsconsio.h>
13: #include <dev/wscons/wskbdvar.h>
14: #include <dev/wscons/wsksymdef.h>
15: #include <dev/wscons/wsksymvar.h>
16:
17: #include <dev/spivar.h>
18:
19: #include <jornada/dev/jmcu_cmd.h>
20:
21: #include <arm/sa11x0/sa11x0_var.h>
22: #include <arm/sa11x0/sa11x0_reg.h>
23: #include <arm/sa11x0/sa11x0_gpiovar.h>
24:
25: #include <jornada/dev/jmcu_kbdmap.h>
1.3 ! nbrk 26: #include "wskbd.h"
1.1 nbrk 27:
28: #define JMCU_KBD_GPIOINTR 0
29: #define JMCU_TS_GPIOINTR 15
30:
31: #define JMCU_KBD_NEVENTS 8
32:
33: struct jmcu_softc {
34: struct device sc_dev;
35:
1.3 ! nbrk 36: /* parent SPI stuff */
1.1 nbrk 37: struct spi_bus *sc_bus;
38: void *sc_spisc;
39:
1.3 ! nbrk 40: /* keyboard stuff */
! 41: struct device *sc_wskbddev;
! 42: int sc_polling; /* if in 'poll' mode now */
! 43: u_int sc_kbdqtypes[JMCU_KBD_NEVENTS];
! 44: uint8_t sc_kbdqkeys[JMCU_KBD_NEVENTS];
! 45: uint8_t sc_kbdnevents;
! 46:
! 47: /* battery charge */
! 48: uint16_t sc_batmain;
! 49: uint16_t sc_batback;
1.1 nbrk 50: };
51:
52: struct jmcu_softc *jmcu_sc;
1.3 ! nbrk 53:
1.1 nbrk 54: struct wskbd_mapdata jmcukbd_keymapdata = {
55: jmcukbd_keydesctab,
56: KB_US,
57: };
58:
59: /*
60: * Prototypes.
61: */
62: int jmcu_match(struct device *parent, void *cf, void *aux);
63: void jmcu_attach(struct device *parent, struct device *self, void *aux);
64: int jmcu_kbdintr(void *arg);
65: int jmcu_touchintr(void *arg);
66: void jmcukbd_cngetc(void *v, u_int *type, int *data);
1.3 ! nbrk 67: void jmcukbd_cnpollc(void *v, int on);
! 68: void jmcukbd_poll(void *v);
! 69: void jmcukbd_enqueue(struct jmcu_softc *sc, u_int type, uint8_t key);
! 70: void jmcukbd_dequeue(struct jmcu_softc *sc, u_int *type, int *data);
! 71: void jmcubatt_getstatus(struct jmcu_softc *sc);
! 72: void jmcukbd_readcodes(struct jmcu_softc *sc, char *buf);
! 73: /* accessops */
! 74: int jmcukbd_enable(void *, int);
! 75: void jmcukbd_set_leds(void *, int);
! 76: int jmcukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 77:
1.1 nbrk 78:
79: /*
80: * Autoconf glue.
81: */
82: struct cfattach jmcu_ca = {
83: sizeof(struct jmcu_softc), jmcu_match, jmcu_attach, NULL, NULL
84: };
85:
86: struct cfdriver jmcu_cd = {
87: NULL,
88: "jmcu",
89: DV_DULL
90: };
91:
92: /*
93: * Console ops.
94: */
95: struct wskbd_consops jmcukbd_consops = {
96: jmcukbd_cngetc,
1.3 ! nbrk 97: jmcukbd_cnpollc,
1.1 nbrk 98: NULL /* bell */
99: };
100:
1.3 ! nbrk 101: struct wskbd_accessops jmcukbd_accessops = {
! 102: jmcukbd_enable,
! 103: jmcukbd_set_leds,
! 104: jmcukbd_ioctl,
! 105: };
! 106:
1.1 nbrk 107:
108: int
109: jmcu_match(struct device *parent, void *cf, void *aux)
110: {
111: return (1);
112: }
113:
114: void
115: jmcu_attach(struct device *parent, struct device *self, void *aux)
116: {
117: struct jmcu_softc *sc = (struct jmcu_softc *)self;
118: struct spibus_attach_args *sba = aux;
1.3 ! nbrk 119: #if NWSKBD > 0
1.1 nbrk 120: struct wskbddev_attach_args wda;
1.3 ! nbrk 121: #endif
! 122: /* leap to parent */
1.1 nbrk 123: sc->sc_bus = sba->sba_bus;
124: sc->sc_spisc = sba->sba_spisc;
125:
1.3 ! nbrk 126: jmcu_sc = sc;
1.1 nbrk 127:
1.3 ! nbrk 128: jmcubatt_getstatus(sc);
! 129:
! 130: printf(": Jornada MCU (battery charge: main=%d backup=%d)\n", sc->sc_batmain, sc->sc_batback);
! 131:
! 132: #if 0
! 133: sa11x0_gpio_intr_establish(JMCU_KBD_GPIOINTR, IST_EDGE_FALLING, IPL_TTY, jmcu_kbdintr, sc, "jmcukbd_intr");
! 134: #endif /* 0 */
1.1 nbrk 135:
1.3 ! nbrk 136: #if NWSKBD > 0
! 137: /* empty event queue */
! 138: sc->sc_kbdnevents = 0;
1.1 nbrk 139:
140: wskbd_cnattach(&jmcukbd_consops, sc, &jmcukbd_keymapdata);
141:
142: wda.console = 1;
143: wda.keymap = &jmcukbd_keymapdata;
1.3 ! nbrk 144: wda.accessops = &jmcukbd_accessops;
1.1 nbrk 145: wda.accesscookie = sc;
146:
1.3 ! nbrk 147: sc->sc_wskbddev = config_found(self, &wda, wskbddevprint);
! 148: #endif
1.1 nbrk 149: return;
150: }
151:
1.3 ! nbrk 152: #if 0
1.1 nbrk 153: int
154: jmcu_kbdintr(void *arg)
155: {
1.3 ! nbrk 156: jmcukbd_poll(arg);
1.1 nbrk 157:
158: return(0);
159: }
1.3 ! nbrk 160: #endif
1.1 nbrk 161:
1.3 ! nbrk 162: #if 0
1.1 nbrk 163: int
164: jmcu_touchintr(void *arg)
165: {
166: struct jmcu_softc *sc = arg;
167: printf("%s: jmcu_touchintr\n", sc->sc_dev.dv_xname);
168:
169: return(0);
170: }
1.3 ! nbrk 171: #endif
1.1 nbrk 172:
173: void
174: jmcukbd_cngetc(void *v, u_int *type, int *data)
175: {
176: struct jmcu_softc *sc = v;
177:
1.3 ! nbrk 178: /* XXX we should block until new keycode has been obtained */
1.1 nbrk 179:
1.3 ! nbrk 180: sc->sc_polling = 1;
! 181: while (sc->sc_kbdnevents == 0) {
! 182: /* enqueue events */
! 183: jmcukbd_poll(v);
! 184: }
! 185: sc->sc_polling = 0;
! 186:
! 187: jmcukbd_dequeue(sc, type, data);
! 188: }
! 189:
! 190: void
! 191: jmcukbd_cnpollc(void *v, int on)
! 192: {
1.1 nbrk 193:
1.3 ! nbrk 194: }
! 195:
! 196: void
! 197: jmcukbd_poll(void *v)
! 198: {
! 199: struct jmcu_softc *sc = v;
! 200: u_int type;
! 201: int key, s;
! 202: char buf[JMCU_KBD_NEVENTS + 1], *p;
! 203:
! 204: s = spltty();
! 205:
! 206: jmcukbd_readcodes(sc, buf);
! 207:
! 208: for (p = buf; *p; p++) {
! 209: type = *p & 0x80 ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
! 210: key = *p & 0x7f;
! 211:
! 212: /* XXX */
! 213: if (sc->sc_polling == 0)
! 214: wskbd_input(sc->sc_wskbddev, type, key);
! 215: else {
! 216: /* enqueue event */
! 217: jmcukbd_enqueue(sc, type, key);
! 218: }
! 219: }
1.1 nbrk 220:
1.3 ! nbrk 221: splx(s);
1.1 nbrk 222: }
223:
224: void
1.3 ! nbrk 225: jmcukbd_readcodes(struct jmcu_softc *sc, char *buf)
1.1 nbrk 226: {
227: int nkeys;
228:
229: /* wake up the MCU */
230: sa11x0_gpio_clear_bit(25);
231:
232: spi_acquire(sc->sc_spisc);
233:
1.3 ! nbrk 234: /* ask mcu about how many keypress events are there; should get TXDUMMY here */
! 235: if (spi_shift_1(sc->sc_spisc, JMCU_CMD_GETKEYCODES) != JMCU_CMD_TXDUMMY) {
1.1 nbrk 236: printf("%s: WARNING, no txdummy received\n", sc->sc_dev.dv_xname);
237:
1.3 ! nbrk 238: goto out;
! 239: }
! 240:
! 241: nkeys = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY);
1.1 nbrk 242:
243: while (nkeys) {
1.3 ! nbrk 244: *buf = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY);
1.1 nbrk 245:
246: nkeys--;
1.3 ! nbrk 247: buf++;
1.1 nbrk 248: }
1.3 ! nbrk 249:
! 250: out:
! 251: /* terminate buffer */
! 252: *buf = 0;
! 253:
1.1 nbrk 254: spi_release(sc->sc_spisc);
255:
256: /* park off the MCU */
257: sa11x0_gpio_set_bit(25);
258: }
259:
1.3 ! nbrk 260:
1.1 nbrk 261: void
1.3 ! nbrk 262: jmcukbd_enqueue(struct jmcu_softc *sc, u_int type, uint8_t key)
1.1 nbrk 263: {
1.3 ! nbrk 264:
! 265: if (sc->sc_kbdnevents > JMCU_KBD_NEVENTS) {
! 266: printf("%s: WARNING, event queue is full; keycode 0x%x will be discarded\n", sc->sc_dev.dv_xname, key);
1.1 nbrk 267: return;
268: }
269:
1.3 ! nbrk 270: sc->sc_kbdqtypes[sc->sc_kbdnevents] = type;
! 271: sc->sc_kbdqkeys[sc->sc_kbdnevents] = key;
! 272: sc->sc_kbdnevents++;
1.1 nbrk 273: }
274:
275: void
1.3 ! nbrk 276: jmcukbd_dequeue(struct jmcu_softc *sc, u_int *type, int *data)
1.1 nbrk 277: {
1.3 ! nbrk 278: #if 0
1.1 nbrk 279: if (sc->sc_kbdeventsnum < 1) {
280: printf("%s: WARNING, event queue is empty\n", sc->sc_dev.dv_xname);
281: return;
282: }
1.3 ! nbrk 283: #endif
! 284: sc->sc_kbdnevents--;
! 285: *type = sc->sc_kbdqtypes[sc->sc_kbdnevents];
! 286: *data = sc->sc_kbdqkeys[sc->sc_kbdnevents];
! 287: }
1.1 nbrk 288:
289:
290: void
1.3 ! nbrk 291: jmcubatt_getstatus(struct jmcu_softc *sc)
1.1 nbrk 292: {
293: uint8_t fraction;
294:
295: /* wake up the MCU */
296: sa11x0_gpio_clear_bit(25);
297:
298: spi_acquire(sc->sc_spisc);
299: spi_shift_1(sc->sc_spisc, JMCU_CMD_GETBATTERYDATA);
1.3 ! nbrk 300: sc->sc_batmain = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY);
! 301: sc->sc_batback = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY);
1.1 nbrk 302: fraction = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY);
303: spi_release(sc->sc_spisc);
304:
305: /* park off the MCU */
306: sa11x0_gpio_set_bit(25);
307:
308: /* fraction[0:1] is mainbatt[8:9]; fraction[2:3] is backbatt[8:9] */
1.3 ! nbrk 309: sc->sc_batmain |= (uint16_t)((fraction & 0x03) << 8);
! 310: sc->sc_batback |= (uint16_t)((fraction & 0x0c) << 6);
! 311: }
! 312:
! 313: int
! 314: jmcukbd_enable(void *v, int on)
! 315: {
! 316: return 0;
! 317: }
! 318:
! 319: void
! 320: jmcukbd_set_leds(void *v, int on)
! 321: {
! 322: }
1.1 nbrk 323:
1.3 ! nbrk 324: int
! 325: jmcukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
! 326: {
! 327: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 328: struct jmcukbd_softc *sc = v;
! 329: #endif
! 330:
! 331: switch (cmd) {
! 332:
! 333: case WSKBDIO_GTYPE:
! 334: *(int *)data = WSKBD_TYPE_ZAURUS /* XXX WSKBD_TYPE_JORNADA */;
! 335: return 0;
! 336: case WSKBDIO_SETLEDS:
! 337: return 0;
! 338: case WSKBDIO_GETLEDS:
! 339: *(int *)data = 0;
! 340: return 0;
! 341: #ifdef WSDISPLAY_COMPAT_RAWKBD
! 342: case WSKBDIO_SETMODE:
! 343: sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
! 344: timeout_del(&sc->sc_rawrepeat_ch);
! 345: return (0);
! 346: #endif
! 347:
! 348: }
! 349: /* kbdioctl(...); */
! 350:
! 351: return -1;
1.1 nbrk 352: }
1.3 ! nbrk 353:
1.1 nbrk 354:
CVSweb