Subject: kthreaded ssp access: today's patch
To: None <port-hpcarm@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: port-hpcarm
Date: 09/11/2002 23:33:40
Please find below my last patch proposal about the touchpanel problems. If
nobody complains, I will commit it shortly.
I think I addressed the re-entrency problem pointed out by Toshihiro. We now
have only one kernel thread, called j720ssp. I use a status flag to communicate
between interrupt handlers and the kernel thread.
It is possible to use the keyboard while the stylus is moving the X cursor, this
works, I checked it.
Somewhat related:
During my checks, I found some weird behaviors: if you hit d continously, the
machine displays a lot of d, then while d is still pressed, hit k quickly, the
machine display a k and then carry on displaying d
Try the same think with l and x, you don't get the same behavior. Any idea why?
One more weird thing: in windowmaker, while moving a window with the stylus, I
type a a dozen of times. Nothing is displayed, which is normal since the window
does not have the focus. When I stop moving it, even if I released it, the
system believes the a key is hold, and I get a appearing in my shell forever
until I hit another key. Is it a windowmaker bug or a jornada bug? Anyone can
reproduce it?
Index: j720ssp.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/hpcarm/dev/j720ssp.c,v
retrieving revision 1.8
diff -U4 -r1.8 j720ssp.c
--- j720ssp.c 2002/07/22 20:55:48 1.8
+++ j720ssp.c 2002/09/11 21:04:23
@@ -76,12 +76,13 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
-#include <sys/callout.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/ioctl.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
#include <machine/bus.h>
#include <machine/config_hook.h>
#include <machine/bootinfo.h>
@@ -114,17 +115,26 @@
struct tpcalib_softc sc_tpcalib;
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 *);
@@ -220,9 +230,11 @@
sc->sc_dev.dv_xname);
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;
a.console = 0;
@@ -277,12 +289,10 @@
(caddr_t)&j720_default_calib, 0, 0);
}
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 */
config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS,
@@ -299,8 +309,55 @@
config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX,
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) {
if (strcmp(cf->cf_driver->cd_name, "wskbd") == 0)
@@ -360,19 +417,14 @@
struct j720ssp_softc *sc = 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);
}
int
@@ -380,16 +432,21 @@
{
struct j720ssp_softc *sc = arg;
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9);
+
+ simple_lock(&sc->sc_ssp_status_lock);
+ sc->sc_ssp_status |= J720_SSP_STATUS_TP;
+ simple_unlock(&sc->sc_ssp_status_lock);
- softintr_schedule(sc->sc_tpsi);
+ 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;
char buf[9], *p;
@@ -464,14 +521,25 @@
bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
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 ||
@@ -495,20 +563,18 @@
buf[i + 3] |= buf[7] & 0x300;
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
/* XXX buf[1], buf[2], ... should also be used */
tpcalib_trans(&sc->sc_tpcalib, buf[1], buf[4], &x, &y);
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;
bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
@@ -516,27 +582,11 @@
/* reset SSP */
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);
-}
-
-void
-j720tp_timeout(void *arg)
-{
- struct j720ssp_softc *sc = arg;
+ printf("j720tp_poll: error %x\n", data);
-#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
j720tp_enable(void *arg) {
@@ -670,8 +720,9 @@
static int
j720ssp_readwrite(struct j720ssp_softc *sc, int drainfifo, int in, int *out)
{
int timo;
+ int dontcare;
timo = 100000;
while(bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & 0x400)
if (--timo == 0) {
@@ -682,15 +733,15 @@
while(bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) &
SR_RNE)
bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR);
#if 1
- delay(5000);
+ tsleep(&dontcare, PRIBIO, "j720ssp_readwrite", 1);
#endif
}
bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in);
- delay(5000);
+ tsleep(&dontcare, PRIBIO, "j720ssp_readwrite", 1);
timo = 100000;
while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE))
if (--timo == 0) {
printf("timo1\n");
--
Emmanuel Dreyfus.
NetBSD, parceque je le vaux bien.
manu@netbsd.org