[BACK]Return to jmcu.c CVS log [TXT][DIR] Up to [local] / sys / arch / jornada / dev

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