/* $Id: jmcu.c,v 1.2 2008/03/05 20:31:27 nbrk Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define JMCU_KBD_GPIOINTR 0 #define JMCU_TS_GPIOINTR 15 #define JMCU_KBD_NEVENTS 8 struct jmcu_softc { struct device sc_dev; struct spi_bus *sc_bus; void *sc_spisc; uint8_t sc_kbdeventsbuf[JMCU_KBD_NEVENTS]; uint8_t sc_kbdeventsnum; }; struct jmcu_softc *jmcu_sc; struct wskbd_mapdata jmcukbd_keymapdata = { jmcukbd_keydesctab, KB_US, }; /* * Prototypes. */ int jmcu_match(struct device *parent, void *cf, void *aux); void jmcu_attach(struct device *parent, struct device *self, void *aux); int jmcu_kbdintr(void *arg); int jmcu_touchintr(void *arg); void jmcukbd_cngetc(void *v, u_int *type, int *data); void jmcukbd_enqueue(struct jmcu_softc *sc, uint8_t keycode); void jmcukbd_dequeue(struct jmcu_softc *sc, uint8_t *keycodep); void jmcukbd_getcodes(struct jmcu_softc *sc, int block); void jmcubatt_status(struct jmcu_softc *sc); /* * Autoconf glue. */ struct cfattach jmcu_ca = { sizeof(struct jmcu_softc), jmcu_match, jmcu_attach, NULL, NULL }; struct cfdriver jmcu_cd = { NULL, "jmcu", DV_DULL }; /* * Console ops. */ struct wskbd_consops jmcukbd_consops = { jmcukbd_cngetc, NULL, /* pollc */ NULL /* bell */ }; int jmcu_match(struct device *parent, void *cf, void *aux) { return (1); } void jmcu_attach(struct device *parent, struct device *self, void *aux) { struct jmcu_softc *sc = (struct jmcu_softc *)self; struct spibus_attach_args *sba = aux; struct wskbddev_attach_args wda; sc->sc_bus = sba->sba_bus; sc->sc_spisc = sba->sba_spisc; printf(": Jornada MCU\n"); jmcu_sc = sc; /* XXX */ jmcubatt_status(sc); wskbd_cnattach(&jmcukbd_consops, sc, &jmcukbd_keymapdata); wda.console = 1; wda.keymap = &jmcukbd_keymapdata; wda.accessops = NULL; //jmcukbd_accessops; wda.accesscookie = sc; config_found(self, &wda, wskbddevprint); return; } int jmcu_kbdintr(void *arg) { struct jmcu_softc *sc = arg; printf("%s: jmcu_kbdintr\n", sc->sc_dev.dv_xname); return(0); } int jmcu_touchintr(void *arg) { struct jmcu_softc *sc = arg; printf("%s: jmcu_touchintr\n", sc->sc_dev.dv_xname); return(0); } void jmcukbd_cngetc(void *v, u_int *type, int *data) { struct jmcu_softc *sc = v; uint8_t ourdata; printf("jmcukbd_cngetc:\n"); if (sc->sc_kbdeventsnum == 0) jmcukbd_getcodes(sc, 1); /* note that we've passed blocking flag */ jmcukbd_dequeue(sc, &ourdata); *data = ourdata & 0x7f; *type = ourdata & 0x80 ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; } void jmcukbd_getcodes(struct jmcu_softc *sc, int block) { int nkeys; uint8_t keycode; /* wake up the MCU */ sa11x0_gpio_clear_bit(25); spi_acquire(sc->sc_spisc); do { /* ask mcu about how many keypress events are there; should get TXDUMMY here */ if (spi_shift_1(sc->sc_spisc, JMCU_CMD_GETKEYCODES) != JMCU_CMD_TXDUMMY) printf("%s: WARNING, no txdummy received\n", sc->sc_dev.dv_xname); nkeys = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); } while(nkeys == 0 && block); while (nkeys) { keycode = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); jmcukbd_enqueue(sc, keycode); nkeys--; } spi_release(sc->sc_spisc); /* park off the MCU */ sa11x0_gpio_set_bit(25); } void jmcukbd_enqueue(struct jmcu_softc *sc, uint8_t keycode) { if (sc->sc_kbdeventsnum >= JMCU_KBD_NEVENTS) { printf("%s: WARNING, event queue is full; keycode 0x%x will be discarded\n", sc->sc_dev.dv_xname, keycode); return; } sc->sc_kbdeventsbuf[sc->sc_kbdeventsnum] = keycode; sc->sc_kbdeventsnum++; } void jmcukbd_dequeue(struct jmcu_softc *sc, uint8_t *keycodep) { if (sc->sc_kbdeventsnum < 1) { printf("%s: WARNING, event queue is empty\n", sc->sc_dev.dv_xname); return; } sc->sc_kbdeventsnum--; *keycodep = sc->sc_kbdeventsbuf[sc->sc_kbdeventsnum]; } void jmcubatt_status(struct jmcu_softc *sc) { uint16_t mainbatt; uint16_t backbatt; uint8_t fraction; /* wake up the MCU */ sa11x0_gpio_clear_bit(25); spi_acquire(sc->sc_spisc); spi_shift_1(sc->sc_spisc, JMCU_CMD_GETBATTERYDATA); mainbatt = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); backbatt = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); fraction = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); spi_release(sc->sc_spisc); /* park off the MCU */ sa11x0_gpio_set_bit(25); /* fraction[0:1] is mainbatt[8:9]; fraction[2:3] is backbatt[8:9] */ mainbatt |= (uint16_t)((fraction & 0x03) << 8); backbatt |= (uint16_t)((fraction & 0xc0) << 6); printf("%s: battery status: main %d, backup %d\n", sc->sc_dev.dv_xname, mainbatt, backbatt); }