[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.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