summaryrefslogtreecommitdiff
path: root/sys/arch/arm
diff options
context:
space:
mode:
authorMarek Vasut <marex@cvs.openbsd.org>2009-09-09 12:14:40 +0000
committerMarek Vasut <marex@cvs.openbsd.org>2009-09-09 12:14:40 +0000
commitcb686eb47fc128abf85877b7d85d88f23f43b5f4 (patch)
treead3cf41e3e161ee4efd773c40f3982bc97e6d3c8 /sys/arch/arm
parent8936a54ac6c24f8d4b7c3e15f83f90beb2481da7 (diff)
Add simple PXA27x matrix keypad controller driver
Diffstat (limited to 'sys/arch/arm')
-rw-r--r--sys/arch/arm/xscale/files.pxa2x06
-rw-r--r--sys/arch/arm/xscale/pxa27x_kpc.c224
-rw-r--r--sys/arch/arm/xscale/pxa27x_kpc.h47
-rw-r--r--sys/arch/arm/xscale/pxa2x0reg.h22
4 files changed, 297 insertions, 2 deletions
diff --git a/sys/arch/arm/xscale/files.pxa2x0 b/sys/arch/arm/xscale/files.pxa2x0
index 1439e545514..7cb2b2c4501 100644
--- a/sys/arch/arm/xscale/files.pxa2x0
+++ b/sys/arch/arm/xscale/files.pxa2x0
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pxa2x0,v 1.21 2007/05/15 05:26:44 miod Exp $
+# $OpenBSD: files.pxa2x0,v 1.22 2009/09/09 12:14:39 marex Exp $
# $NetBSD: files.pxa2x0,v 1.6 2004/05/01 19:09:14 thorpej Exp $
#
# Configuration info for Intel PXA2[51]0 CPU support
@@ -84,3 +84,7 @@ device fdc
# MMC/SD/SDIO controller
device pxammc: sdmmcbus
file arch/arm/xscale/pxa2x0_mmc.c pxammc
+
+# PXA27x keypad
+device pxa27x_kpc: wskbddev
+file arch/arm/xscale/pxa27x_kpc.c pxa27x_kpc
diff --git a/sys/arch/arm/xscale/pxa27x_kpc.c b/sys/arch/arm/xscale/pxa27x_kpc.c
new file mode 100644
index 00000000000..0d746c25385
--- /dev/null
+++ b/sys/arch/arm/xscale/pxa27x_kpc.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2009 Marek Vasut <marex@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/timeout.h>
+#include <sys/systm.h>
+
+#include <arch/arm/xscale/pxa2x0_gpio.h>
+#include <arch/arm/xscale/pxa2x0reg.h>
+#include <arch/arm/xscale/pxa2x0var.h>
+#include <arch/arm/xscale/pxa27x_kpc.h>
+
+int pxa27x_kpc_enable(void *, int);
+void pxa27x_kpc_setleds(void *, int);
+int pxa27x_kpc_ioctl(void *, u_long, caddr_t, int, struct proc *);
+
+inline void pxa27x_kpc_submit(struct pxa27x_kpc_softc *, int);
+int pxa27x_kpc_intr(void *);
+
+struct cfdriver pxa27x_kpc_cd = {
+ NULL, "pxa27x_kpc", DV_DULL,
+};
+
+struct wskbd_accessops pxa27x_kpc_accessops = {
+ pxa27x_kpc_enable,
+ pxa27x_kpc_setleds,
+ pxa27x_kpc_ioctl,
+};
+
+struct wscons_keydesc pxa27x_kpc_keydesctab[] = {
+ {KB_US, 0, 0, 0},
+ {0, 0, 0, 0},
+};
+
+struct wskbd_mapdata pxa27x_kpc_mapdata = {
+ pxa27x_kpc_keydesctab, KB_US,
+};
+
+void pxa27x_kpc_cngetc(void *, u_int *, int *);
+void pxa27x_kpc_cnpollc(void *, int);
+void pxa27x_kpc_cnbell(void *, u_int, u_int, u_int);
+
+struct wskbd_consops pxa27x_kpc_consops = {
+ pxa27x_kpc_cngetc,
+ pxa27x_kpc_cnpollc,
+ pxa27x_kpc_cnbell,
+};
+
+int
+pxa27x_kpc_match(void *aux)
+{
+ struct pxaip_attach_args *pxa = aux;
+ if (pxa->pxa_addr != PXA2X0_KPC_BASE)
+ return 0; /* Wrong device */
+
+ if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) != CPU_ID_PXA27X)
+ return 0; /* Wrong CPU */
+
+ pxa->pxa_size = PXA2X0_KPC_SIZE;
+ return 1;
+}
+
+void
+pxa27x_kpc_attach(struct pxa27x_kpc_softc *sc, void *aux)
+{
+ struct pxaip_attach_args *pxa = aux;
+ struct wskbddev_attach_args a;
+
+ sc->sc_iot = pxa->pxa_sa.sa_iot;
+ if (bus_space_map(sc->sc_iot, pxa->pxa_addr, pxa->pxa_size, 0,
+ &sc->sc_ioh) != 0) {
+ printf(": can't map regs\n");
+ goto err;
+ }
+
+ pxa2x0_clkman_config(CKEN_KEY, 1);
+
+ sc->sc_ih = pxa2x0_intr_establish(PXA2X0_INT_KPC, IPL_TTY,
+ pxa27x_kpc_intr, sc, sc->sc_dev.dv_xname);
+ if (!sc->sc_ih) {
+ printf(": can't establish interrupt\n");
+ goto err2;
+ }
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, KPC_KPC, KPC_MIE | KPC_ME |
+ KPC_MS(0xff) | KPC_IMKP | KPC_MI | KPC_MKCN(sc->sc_cols) |
+ KPC_MKRN(sc->sc_rows) | KPC_ASACT);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, KPC_KPKDI, 0x30);
+
+ pxa27x_kpc_keydesctab[0].map_size = sc->sc_ksize;
+ pxa27x_kpc_keydesctab[0].map = sc->sc_kcodes;
+
+ a.console = 1;
+ a.keymap = &pxa27x_kpc_mapdata;
+ a.accessops = &pxa27x_kpc_accessops;
+ a.accesscookie = sc;
+
+ printf("\n");
+
+ wskbd_cnattach(&pxa27x_kpc_consops, sc, &pxa27x_kpc_mapdata);
+
+ sc->sc_wskbddev = config_found((struct device *)sc, &a, wskbddevprint);
+
+ return;
+
+err2:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, PXA2X0_KPC_SIZE);
+err:
+ return;
+}
+
+inline void
+pxa27x_kpc_submit(struct pxa27x_kpc_softc *sc, int event)
+{
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+ u_char key;
+ if (sc->sc_rawkbd) {
+ key = sc->sc_key;
+ if (event == WSCONS_EVENT_KEY_DOWN)
+ key |= 0x80;
+ wskbd_rawinput(sc->sc_wskbddev, &key, 1);
+ } else
+#endif
+ wskbd_input(sc->sc_wskbddev, event, sc->sc_key);
+}
+
+int
+pxa27x_kpc_intr(void *arg)
+{
+ u_int32_t val;
+ int row = -1, col = -1;
+ int i = 0;
+ struct pxa27x_kpc_softc *sc = arg;
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, KPC_KPC);
+ if (!(val & KPC_MI)) /* interrupt didn't happen .. what ?! */
+ return 0;
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, KPC_KPAS);
+ if (val & KPAS_SO) /* bogus interrupt */
+ return 0;
+
+ if (val & KPAS_MUKP) { /* keypress */
+ col = val & KPAS_CP;
+ row = (val & KPAS_RP) >> 4;
+ for (i = 0; i < sc->sc_ksize; i++)
+ if (sc->sc_kmap[i].row == row &&
+ sc->sc_kmap[i].col == col) {
+ sc->sc_key = sc->sc_kmap[i].key;
+ pxa27x_kpc_submit(sc, WSCONS_EVENT_KEY_DOWN);
+ break;
+ }
+ } else /* no keypress aka keyrelease */
+ pxa27x_kpc_submit(sc, WSCONS_EVENT_KEY_UP);
+
+ return 1;
+}
+
+int
+pxa27x_kpc_enable(void *v, int power)
+{
+ return 0;
+}
+
+void
+pxa27x_kpc_setleds(void *v, int power)
+{
+}
+
+int
+pxa27x_kpc_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+ struct pxa27x_kpc_softc *sc = v;
+#endif
+
+ switch (cmd) {
+ case WSKBDIO_GTYPE:
+ *(int *)data = WSKBD_TYPE_KPC;
+ return 0;
+ case WSKBDIO_SETLEDS:
+ return 0;
+ case WSKBDIO_GETLEDS:
+ *(int *)data = 0;
+ return 0;
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+ case WSKBDIO_SETMODE:
+ sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
+ return 0;
+#endif
+ }
+ return -1;
+}
+
+void
+pxa27x_kpc_cnbell(void *v, u_int pitch, u_int period, u_int volume)
+{
+}
+
+void
+pxa27x_kpc_cngetc(void *v, u_int *type, int *data)
+{
+}
+
+void
+pxa27x_kpc_cnpollc(void *v, int on)
+{
+}
diff --git a/sys/arch/arm/xscale/pxa27x_kpc.h b/sys/arch/arm/xscale/pxa27x_kpc.h
new file mode 100644
index 00000000000..d3a63db8b00
--- /dev/null
+++ b/sys/arch/arm/xscale/pxa27x_kpc.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Marek Vasut <marex@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdraw.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+
+struct pxa27x_kpc_keymap {
+ int row;
+ int col;
+ keysym_t key;
+};
+
+struct pxa27x_kpc_softc {
+ struct device sc_dev;
+ struct device *sc_wskbddev;
+ void *sc_ih;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ int sc_key;
+ int sc_rawkbd;
+
+ int sc_rows;
+ int sc_cols;
+ const struct pxa27x_kpc_keymap *sc_kmap;
+ const keysym_t *sc_kcodes;
+ const keysym_t *sc_xt_kcodes;
+ int sc_ksize;
+};
+
+int pxa27x_kpc_match(void *);
+void pxa27x_kpc_attach(struct pxa27x_kpc_softc *, void *);
diff --git a/sys/arch/arm/xscale/pxa2x0reg.h b/sys/arch/arm/xscale/pxa2x0reg.h
index 421f3e727e7..9595049f156 100644
--- a/sys/arch/arm/xscale/pxa2x0reg.h
+++ b/sys/arch/arm/xscale/pxa2x0reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pxa2x0reg.h,v 1.30 2007/05/25 21:27:15 krw Exp $ */
+/* $OpenBSD: pxa2x0reg.h,v 1.31 2009/09/09 12:14:39 marex Exp $ */
/* $NetBSD: pxa2x0reg.h,v 1.4 2003/06/11 20:43:01 scw Exp $ */
/*
@@ -124,6 +124,8 @@
#define PXA2X0_MEMCTL_SIZE 0x84
#define PXA2X0_USBHC_BASE 0x4c000000 /* USB Host Controller */
#define PXA2X0_USBHC_SIZE 0x70
+#define PXA2X0_KPC_BASE 0x41500000 /* Keypad Controller */
+#define PXA2X0_KPC_SIZE 0x50
/* width of interrupt controller */
#define ICU_LEN 32 /* but some are not used */
@@ -136,6 +138,7 @@
*/
#define PXA2X0_INT_USBH2 2 /* USB host (all other events) */
#define PXA2X0_INT_USBH1 3 /* USB host (OHCI) */
+#define PXA2X0_INT_KPC 4
#define PXA2X0_INT_OST 7 /* OS timers */
#define PXA2X0_INT_GPIO0 8
#define PXA2X0_INT_GPIO1 9
@@ -872,4 +875,21 @@ struct pxa2x0_dma_desc {
#define SSSR_RNE (1<<3)
#define SSP_SSDR 0x10
+/* KPC */
+#define KPC_KPC 0x00
+#define KPC_MIE (1<<11)
+#define KPC_ME (1<<12)
+#define KPC_MS(n) ((n & 0xff) << 13)
+#define KPC_IMKP (1<<21)
+#define KPC_MI (1<<22)
+#define KPC_MKCN(n) ((n & 0x7) << 23)
+#define KPC_MKRN(n) ((n & 0x7) << 26)
+#define KPC_ASACT (1<<29)
+#define KPC_KPAS 0x20
+#define KPAS_CP (0xf<<0)
+#define KPAS_RP (0xf<<4)
+#define KPAS_MUKP (0x1f<<26)
+#define KPAS_SO (1<<31)
+#define KPC_KPKDI 0x48
+
#endif /* _ARM_XSCALE_PXA2X0REG_H_ */