1*c7fb772bSthorpej /* $NetBSD: tskp.c,v 1.12 2021/08/07 16:18:50 thorpej Exp $ */
2564073f0Sjoff
3564073f0Sjoff /*-
4564073f0Sjoff * Copyright (c) 2005 The NetBSD Foundation, Inc.
5564073f0Sjoff * All rights reserved.
6564073f0Sjoff *
7564073f0Sjoff * This code is from software contributed to The NetBSD Foundation
8564073f0Sjoff * by Jesse Off.
9564073f0Sjoff *
10564073f0Sjoff * Redistribution and use in source and binary forms, with or without
11564073f0Sjoff * modification, are permitted provided that the following conditions
12564073f0Sjoff * are met:
13564073f0Sjoff * 1. Redistributions of source code must retain the above copyright
14564073f0Sjoff * notice, this list of conditions and the following disclaimer.
15564073f0Sjoff * 2. Redistributions in binary form must reproduce the above copyright
16564073f0Sjoff * notice, this list of conditions and the following disclaimer in the
17564073f0Sjoff * documentation and/or other materials provided with the distribution.
18564073f0Sjoff *
19564073f0Sjoff * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20564073f0Sjoff * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21564073f0Sjoff * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22564073f0Sjoff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23564073f0Sjoff * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24564073f0Sjoff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25564073f0Sjoff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26564073f0Sjoff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27564073f0Sjoff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28564073f0Sjoff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29564073f0Sjoff * POSSIBILITY OF SUCH DAMAGE.
30564073f0Sjoff */
31564073f0Sjoff #include <sys/cdefs.h>
32*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: tskp.c,v 1.12 2021/08/07 16:18:50 thorpej Exp $");
33564073f0Sjoff
34564073f0Sjoff #include <sys/param.h>
35564073f0Sjoff #include <sys/systm.h>
36564073f0Sjoff #include <sys/proc.h>
37564073f0Sjoff #include <sys/poll.h>
38564073f0Sjoff #include <sys/conf.h>
39564073f0Sjoff #include <sys/uio.h>
40564073f0Sjoff #include <sys/types.h>
41564073f0Sjoff #include <sys/kernel.h>
42564073f0Sjoff #include <sys/device.h>
43564073f0Sjoff #include <sys/callout.h>
44564073f0Sjoff #include <sys/select.h>
45564073f0Sjoff
46cf10107dSdyoung #include <sys/bus.h>
47564073f0Sjoff #include <machine/autoconf.h>
48564073f0Sjoff
49564073f0Sjoff #include <dev/wscons/wsconsio.h>
50564073f0Sjoff #include <dev/wscons/wskbdvar.h>
51564073f0Sjoff #include <dev/wscons/wsksymdef.h>
52564073f0Sjoff #include <dev/wscons/wsksymvar.h>
53564073f0Sjoff
54564073f0Sjoff #include <arm/ep93xx/ep93xxreg.h>
5500185e02Smatt #include <arm/ep93xx/epgpioreg.h>
56564073f0Sjoff #include <dev/ic/matrixkpvar.h>
57564073f0Sjoff #include <evbarm/tsarm/tspldvar.h>
58564073f0Sjoff #include <evbarm/tsarm/tsarmreg.h>
59564073f0Sjoff
60564073f0Sjoff struct tskp_softc {
61564073f0Sjoff struct matrixkp_softc sc_mxkp;
62564073f0Sjoff bus_space_tag_t sc_iot;
63564073f0Sjoff bus_space_handle_t sc_gpioh;
64564073f0Sjoff };
65564073f0Sjoff
66564073f0Sjoff #define KC(n) KS_KEYCODE(n)
67564073f0Sjoff static const keysym_t mxkp_keydesc_default[] = {
68564073f0Sjoff /* pos normal shifted */
6993f6c1c2Sjoff KC(0), KS_1,
7093f6c1c2Sjoff KC(1), KS_2,
7193f6c1c2Sjoff KC(2), KS_3,
7293f6c1c2Sjoff KC(3), KS_A,
7393f6c1c2Sjoff KC(4), KS_4,
7493f6c1c2Sjoff KC(5), KS_5,
7593f6c1c2Sjoff KC(6), KS_6,
7693f6c1c2Sjoff KC(7), KS_B,
7793f6c1c2Sjoff KC(8), KS_7,
7893f6c1c2Sjoff KC(9), KS_8,
7993f6c1c2Sjoff KC(10), KS_9,
8093f6c1c2Sjoff KC(11), KS_C,
8193f6c1c2Sjoff KC(12), KS_asterisk,
8293f6c1c2Sjoff KC(13), KS_0,
8393f6c1c2Sjoff KC(14), KS_numbersign,
8493f6c1c2Sjoff KC(15), KS_D,
85564073f0Sjoff };
86564073f0Sjoff #undef KC
87564073f0Sjoff #define KBD_MAP(name, base, map) \
88564073f0Sjoff { name, base, sizeof(map)/sizeof(keysym_t), map }
89564073f0Sjoff const struct wscons_keydesc mxkp_keydesctab[] = {
90564073f0Sjoff KBD_MAP(KB_US, 0, mxkp_keydesc_default),
91564073f0Sjoff {0, 0, 0, 0}
92564073f0Sjoff };
93564073f0Sjoff #undef KBD_MAP
94564073f0Sjoff
95564073f0Sjoff struct wskbd_mapdata mxkp_keymapdata = {
96564073f0Sjoff mxkp_keydesctab,
97564073f0Sjoff KB_US,
98564073f0Sjoff };
99564073f0Sjoff
100cbab9cadSchs static int tskp_match(device_t, cfdata_t, void *);
101cbab9cadSchs static void tskp_attach(device_t, device_t, void *);
10208a4aba7Sskrll static void tskp_scankeys(struct matrixkp_softc *, uint32_t *);
103564073f0Sjoff
104cbab9cadSchs CFATTACH_DECL_NEW(tskp, sizeof(struct tskp_softc),
105564073f0Sjoff tskp_match, tskp_attach, NULL, NULL);
106564073f0Sjoff
107564073f0Sjoff static int
tskp_match(device_t parent,cfdata_t match,void * aux)108cbab9cadSchs tskp_match(device_t parent, cfdata_t match, void *aux)
109564073f0Sjoff {
110564073f0Sjoff return 1;
111564073f0Sjoff }
112564073f0Sjoff
113564073f0Sjoff #define GPIO_GET(x) bus_space_read_1(sc->sc_iot, sc->sc_gpioh, \
114564073f0Sjoff (EP93XX_GPIO_ ## x))
115564073f0Sjoff
116564073f0Sjoff #define GPIO_SET(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
117564073f0Sjoff (EP93XX_GPIO_ ## x), (y))
118564073f0Sjoff
119564073f0Sjoff #define GPIO_SETBITS(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
120564073f0Sjoff (EP93XX_GPIO_ ## x), GPIO_GET(x) | (y))
121564073f0Sjoff
122564073f0Sjoff #define GPIO_CLEARBITS(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
123564073f0Sjoff (EP93XX_GPIO_ ## x), GPIO_GET(x) & (~(y)))
124564073f0Sjoff
125564073f0Sjoff static void
tskp_attach(device_t parent,device_t self,void * aux)126cbab9cadSchs tskp_attach(device_t parent, device_t self, void *aux)
127564073f0Sjoff {
128cbab9cadSchs struct tskp_softc *sc = device_private(self);
129564073f0Sjoff struct tspld_attach_args *taa = aux;
130564073f0Sjoff struct wskbddev_attach_args wa;
131564073f0Sjoff
132564073f0Sjoff sc->sc_iot = taa->ta_iot;
133564073f0Sjoff if (bus_space_map(sc->sc_iot, EP93XX_APB_HWBASE + EP93XX_APB_GPIO,
134564073f0Sjoff EP93XX_APB_GPIO_SIZE, 0, &sc->sc_gpioh))
135564073f0Sjoff panic("tskp_attach: couldn't map GPIO registers");
136564073f0Sjoff
137564073f0Sjoff sc->sc_mxkp.mxkp_scankeys = tskp_scankeys;
138564073f0Sjoff sc->sc_mxkp.mxkp_event = mxkp_wskbd_event;
139564073f0Sjoff sc->sc_mxkp.mxkp_nkeys = 16; /* 4 x 4 matrix keypad */
140564073f0Sjoff sc->sc_mxkp.debounce_stable_ms = 3;
141564073f0Sjoff sc->sc_mxkp.sc_dev = self;
142564073f0Sjoff sc->sc_mxkp.poll_freq = hz;
143564073f0Sjoff
144564073f0Sjoff GPIO_SET(PBDDR, 0xff); /* tristate all lines */
145564073f0Sjoff
146564073f0Sjoff printf(": 4x4 matrix keypad, polling at %d hz\n", hz);
147564073f0Sjoff
148564073f0Sjoff mxkp_attach(&sc->sc_mxkp);
149564073f0Sjoff wa.console = 0;
150564073f0Sjoff wa.keymap = &mxkp_keymapdata;
151564073f0Sjoff wa.accessops = &mxkp_accessops;
152564073f0Sjoff wa.accesscookie = &sc->sc_mxkp;
1532685996bSthorpej sc->sc_mxkp.sc_wskbddev = config_found(self, &wa, wskbddevprint,
154*c7fb772bSthorpej CFARGS_NONE);
155564073f0Sjoff }
156564073f0Sjoff
157564073f0Sjoff static void
tskp_scankeys(struct matrixkp_softc * mxkp_sc,uint32_t * keys)15808a4aba7Sskrll tskp_scankeys(struct matrixkp_softc *mxkp_sc, uint32_t *keys)
159564073f0Sjoff {
160cbab9cadSchs struct tskp_softc *sc = device_private(mxkp_sc->sc_dev);
16108a4aba7Sskrll uint32_t pos;
162564073f0Sjoff
163564073f0Sjoff for(pos = 0; pos < 4; pos++) {
164564073f0Sjoff GPIO_SET(PBDDR, (1 << pos));
165564073f0Sjoff GPIO_SET(PBDR, ~(1 << pos));
166564073f0Sjoff delay(1);
167564073f0Sjoff keys[0] |= (~(GPIO_GET(PBDR) >> 4) & 0xf) << (4 * pos);
168564073f0Sjoff }
169564073f0Sjoff }
170