xref: /netbsd-src/sys/arch/evbarm/tsarm/tskp.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
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