diff --git a/sys/arch/hpcarm/dev/j720ssp.c b/sys/arch/hpcarm/dev/j720ssp.c index 0a41b48fa8c4..17a9df9cfd21 100644 --- a/sys/arch/hpcarm/dev/j720ssp.c +++ b/sys/arch/hpcarm/dev/j720ssp.c @@ -1,4 +1,4 @@ -/* $NetBSD: j720ssp.c,v 1.8 2002/07/22 20:55:48 manu Exp $ */ +/* $NetBSD: j720ssp.c,v 1.9 2002/09/13 22:44:58 manu Exp $ */ /*- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. @@ -77,10 +77,11 @@ #include #include #include -#include #include #include #include +#include +#include #include #include @@ -115,18 +116,27 @@ struct j720ssp_softc { void *sc_kbdsi; void *sc_tpsi; - struct callout sc_tptimeout; int sc_enabled; -}; + struct proc *sc_ssp_kthread; + int sc_ssp_status; + struct simplelock sc_ssp_status_lock; +}; +/* Values for struct softc's sc_ssp_status */ +#define J720_SSP_STATUS_NONE 0 +#define J720_SSP_STATUS_TP 1 +#define J720_SSP_STATUS_KBD 2 + +void j720ssp_create_kthread(void *); +void j720ssp_kthread(void *); int j720kbd_intr(void *); int j720tp_intr(void *); -void j720kbdsoft(void *); -void j720tpsoft(void *); -void j720tp_timeout(void *); +void j720kbd_poll(void *); +int j720tp_poll(void *); + int j720lcdparam(void *, int, long, void *); static void j720kbd_read(struct j720ssp_softc *, char *); -static int j720ssp_readwrite(struct j720ssp_softc *, int, int, int *); +static int j720ssp_readwrite(struct j720ssp_softc *, int, int, int *, int); int j720sspprobe(struct device *, struct cfdata *, void *); void j720sspattach(struct device *, struct device *, void *); @@ -221,7 +231,9 @@ j720sspattach(struct device *parent, struct device *self, void *aux) return; } - sc->sc_kbdsi = softintr_establish(IPL_SOFTCLOCK, j720kbdsoft, sc); + sc->sc_ssp_status = J720_SSP_STATUS_NONE; + simple_lock_init(&sc->sc_ssp_status_lock); + kthread_create(j720ssp_create_kthread, sc); sc->sc_enabled = 0; @@ -278,10 +290,8 @@ j720sspattach(struct device *parent, struct device *self, void *aux) } j720tp_disable(sc); - callout_init(&sc->sc_tptimeout); /* Setup touchpad interrupt */ - sc->sc_tpsi = softintr_establish(IPL_SOFTCLOCK, j720tpsoft, sc); sa11x0_intr_establish(0, 9, 1, IPL_BIO, j720tp_intr, sc); /* LCD control is on the same bus */ @@ -300,6 +310,53 @@ j720sspattach(struct device *parent, struct device *self, void *aux) CONFIG_HOOK_SHARE, j720lcdparam, sc); } +void +j720ssp_create_kthread(arg) + void *arg; +{ + struct j720ssp_softc *sc = arg; + + if (kthread_create1(j720ssp_kthread, sc, + &sc->sc_ssp_kthread, "j720ssp")) + panic("j720ssp_create_kthread"); + + return; +} + +void +j720ssp_kthread(arg) + void *arg; +{ + struct j720ssp_softc *sc = arg; + int ssp_status; + + while (1) { + if (ssp_status & J720_SSP_STATUS_TP) + tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", hz / 25); + else + tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", 0); + + simple_lock(&sc->sc_ssp_status_lock); + ssp_status = sc->sc_ssp_status; + sc->sc_ssp_status &= ~J720_SSP_STATUS_KBD; + simple_unlock(&sc->sc_ssp_status_lock); + + if (ssp_status & J720_SSP_STATUS_KBD) + j720kbd_poll(sc); + + if (ssp_status & J720_SSP_STATUS_TP) { + if (j720tp_poll(sc) == 0) { + simple_lock(&sc->sc_ssp_status_lock); + sc->sc_ssp_status &= ~J720_SSP_STATUS_TP; + simple_unlock(&sc->sc_ssp_status_lock); + } + } + } + + /* NOTREACHED */ +} + + int j720kbd_submatch(struct device *parant, struct cfdata *cf, void *aux) { @@ -361,16 +418,11 @@ j720kbd_intr(void *arg) bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1); - /* - * Schedule a soft interrupt to process at lower priority, - * as reading keycodes takes time. - * - * Interrupts are generated every 25-33ms as long as there - * are unprocessed key events. So it is not a good idea to - * use callout to call j720kbdsoft after some delay in hope - * of reducing interrupts. - */ - softintr_schedule(sc->sc_kbdsi); + simple_lock(&sc->sc_ssp_status_lock); + sc->sc_ssp_status |= J720_SSP_STATUS_KBD; + simple_unlock(&sc->sc_ssp_status_lock); + + wakeup(&sc->sc_ssp_kthread); return (1); } @@ -382,13 +434,18 @@ j720tp_intr(void *arg) bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9); - softintr_schedule(sc->sc_tpsi); + simple_lock(&sc->sc_ssp_status_lock); + sc->sc_ssp_status |= J720_SSP_STATUS_TP; + simple_unlock(&sc->sc_ssp_status_lock); + + j720tp_disable(sc); + wakeup(&sc->sc_ssp_kthread); return (1); } void -j720kbdsoft(void *arg) +j720kbd_poll(void *arg) { struct j720ssp_softc *sc = arg; int s, type, value; @@ -427,18 +484,18 @@ j720kbd_read(struct j720ssp_softc *sc, char *buf) bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); /* send scan keycode command */ - if (j720ssp_readwrite(sc, 1, 0x900, &data) < 0 || + if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 || data != 0x88) goto out; /* read numbers of scancode available */ - if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0) + if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) goto out; BIT_INVERT(data); count = data; for(; count; count--) { - if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0) + if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) goto out; BIT_INVERT(data); *buf++ = data; @@ -465,21 +522,32 @@ out: printf("j720kbd_read: error %x\n", data); } -void -j720tpsoft(void *arg) +int +j720tp_poll(void *arg) { struct j720ssp_softc *sc = arg; int buf[8], data, i, x, y; + /* + * If touch panel is not touched anymore, + * stop polling and re-enable interrupt + */ + if (bus_space_read_4(sc->sc_iot, + sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) { + wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); + j720tp_enable(sc); + return 0; + } + bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); /* send read touchpanel command */ - if (j720ssp_readwrite(sc, 1, 0x500, &data) < 0 || + if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 || data != 0x88) goto out; for(i = 0; i < 8; i++) { - if (j720ssp_readwrite(sc, 0, 0x8800, &data) < 0) + if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) goto out; BIT_INVERT(data); buf[i] = data; @@ -496,7 +564,7 @@ j720tpsoft(void *arg) buf[7] >>= 2; } #if 0 - printf("j720tpsoft: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2], + printf("j720tp_poll: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); #endif @@ -505,9 +573,7 @@ j720tpsoft(void *arg) wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); - callout_reset(&sc->sc_tptimeout, hz / 10, j720tp_timeout, sc); - - return; + return 1; out: *buf = 0; @@ -517,25 +583,9 @@ out: bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); delay(100); bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); - printf("j720tpsoft: error %x\n", data); -} + printf("j720tp_poll: error %x\n", data); -void -j720tp_timeout(void *arg) -{ - struct j720ssp_softc *sc = arg; - -#if 0 - /* XXX I don't this this is necessary (untested) */ - if (bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & - (1 << 9)) { - /* Touchpad is still pressed */ - callout_reset(&sc->sc_tptimeout, hz / 10, j720tp_timeout, sc); - return; - } -#endif - - wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); + return 0; } static int @@ -642,7 +692,7 @@ j720lcdparam(void *ctx, int type, long id, void *msg) bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); for (i = 0; i < len; i++) { - if (j720ssp_readwrite(sc, 1, data[i], &data[i]) < 0) + if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0) goto out; } bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); @@ -668,7 +718,12 @@ out: } static int -j720ssp_readwrite(struct j720ssp_softc *sc, int drainfifo, int in, int *out) +j720ssp_readwrite(sc, drainfifo, in, out, wait) + struct j720ssp_softc *sc; + int drainfifo; + int in; + int *out; + int wait; { int timo; @@ -683,13 +738,13 @@ j720ssp_readwrite(struct j720ssp_softc *sc, int drainfifo, int in, int *out) SR_RNE) bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); #if 1 - delay(5000); + delay(wait); #endif } bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in); - delay(5000); + delay(wait); timo = 100000; while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE)) if (--timo == 0) {