Annotation of sys/arch/jornada/dev/jmcu.c, Revision 1.4
1.4 ! nbrk 1: /* $Id: jmcu.c,v 1.3 2008/05/11 09:26:11 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.4 ! nbrk 128: /* jmcubatt_getstatus(sc); */
1.3 nbrk 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