1*beecddb6Sthorpej /* $NetBSD: wzero3_kbd.c,v 1.12 2021/08/07 16:18:53 thorpej Exp $ */
2b62fc9e2Snonaka
30a5ccc74Snonaka /*-
40a5ccc74Snonaka * Copyright (C) 2008, 2009, 2010 NONAKA Kimihiro <nonaka@netbsd.org>
5b62fc9e2Snonaka * All rights reserved.
6b62fc9e2Snonaka *
7b62fc9e2Snonaka * Redistribution and use in source and binary forms, with or without
8b62fc9e2Snonaka * modification, are permitted provided that the following conditions
9b62fc9e2Snonaka * are met:
10b62fc9e2Snonaka * 1. Redistributions of source code must retain the above copyright
11b62fc9e2Snonaka * notice, this list of conditions and the following disclaimer.
12b62fc9e2Snonaka * 2. Redistributions in binary form must reproduce the above copyright
13b62fc9e2Snonaka * notice, this list of conditions and the following disclaimer in the
14b62fc9e2Snonaka * documentation and/or other materials provided with the distribution.
15b62fc9e2Snonaka *
160a5ccc74Snonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
170a5ccc74Snonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
180a5ccc74Snonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
190a5ccc74Snonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
200a5ccc74Snonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
210a5ccc74Snonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
220a5ccc74Snonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
230a5ccc74Snonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
240a5ccc74Snonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
250a5ccc74Snonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b62fc9e2Snonaka */
27b62fc9e2Snonaka
28b62fc9e2Snonaka #include <sys/cdefs.h>
29*beecddb6Sthorpej __KERNEL_RCSID(0, "$NetBSD: wzero3_kbd.c,v 1.12 2021/08/07 16:18:53 thorpej Exp $");
30b62fc9e2Snonaka
31b62fc9e2Snonaka #include <sys/param.h>
32b62fc9e2Snonaka #include <sys/systm.h>
33b62fc9e2Snonaka #include <sys/device.h>
34b62fc9e2Snonaka #include <sys/kernel.h>
3543acb194Sthorpej #include <sys/kmem.h>
36b62fc9e2Snonaka #include <sys/callout.h>
37d8e81853Sdyoung #include <sys/bus.h>
38b62fc9e2Snonaka
39b62fc9e2Snonaka #include <dev/sysmon/sysmonvar.h>
40b62fc9e2Snonaka #include <dev/sysmon/sysmon_taskq.h>
41b62fc9e2Snonaka
42b62fc9e2Snonaka #include <arm/xscale/pxa2x0cpu.h>
43b62fc9e2Snonaka #include <arm/xscale/pxa2x0var.h>
44b62fc9e2Snonaka #include <arm/xscale/pxa2x0_gpio.h>
45b62fc9e2Snonaka
46b62fc9e2Snonaka #include <machine/bootinfo.h>
47b62fc9e2Snonaka #include <machine/config_hook.h>
48b62fc9e2Snonaka #include <machine/platid.h>
49b62fc9e2Snonaka #include <machine/platid_mask.h>
50b62fc9e2Snonaka
51b62fc9e2Snonaka #include <dev/hpc/hpckbdvar.h>
52b62fc9e2Snonaka
53b62fc9e2Snonaka #include <arch/hpcarm/dev/wzero3_reg.h>
54b62fc9e2Snonaka
55b62fc9e2Snonaka #ifdef DEBUG
56b62fc9e2Snonaka #define DPRINTF(arg) printf arg
57b62fc9e2Snonaka #else
58b62fc9e2Snonaka #define DPRINTF(arg) /* nothing */
59b62fc9e2Snonaka #endif
60b62fc9e2Snonaka
61b62fc9e2Snonaka #define CSR_READ1(r) bus_space_read_1(sc->sc_iot, sc->sc_ioh, (r))
62b62fc9e2Snonaka #define CSR_WRITE1(r,v) bus_space_write_1(sc->sc_iot, sc->sc_ioh, (r), (v))
63b62fc9e2Snonaka #define CSR_READ2(r) bus_space_read_2(sc->sc_iot, sc->sc_ioh, (r))
64b62fc9e2Snonaka #define CSR_WRITE2(r,v) bus_space_write_2(sc->sc_iot, sc->sc_ioh, (r), (v))
65b62fc9e2Snonaka #define CSR_READ4(r) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (r))
66b62fc9e2Snonaka #define CSR_WRITE4(r,v) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (r), (v))
67b62fc9e2Snonaka
68b62fc9e2Snonaka /* register */
69b62fc9e2Snonaka #define KBDCOL_L (0x00) /* Write */
70b62fc9e2Snonaka #define KBDCOL_U (0x04) /* Write */
71b62fc9e2Snonaka #define KBDCHARGE (0x08) /* Write */
72b62fc9e2Snonaka #define KBDDATA (0x08) /* Read */
73b62fc9e2Snonaka #define REGMAPSIZE 0x0c
74b62fc9e2Snonaka
75b62fc9e2Snonaka #define KEYWAIT 20 /* us */
76b62fc9e2Snonaka
77b62fc9e2Snonaka #define WS003SH_NCOLUMN 12
78b62fc9e2Snonaka #define WS003SH_NROW 7
79b62fc9e2Snonaka
80b62fc9e2Snonaka struct wzero3kbd_softc {
81b62fc9e2Snonaka device_t sc_dev;
82b62fc9e2Snonaka
83b62fc9e2Snonaka bus_space_tag_t sc_iot;
84b62fc9e2Snonaka bus_space_handle_t sc_ioh;
85b62fc9e2Snonaka
86b62fc9e2Snonaka int sc_ncolumn;
87b62fc9e2Snonaka int sc_nrow;
88b62fc9e2Snonaka uint8_t *sc_okeystat;
89b62fc9e2Snonaka uint8_t *sc_keystat;
90b62fc9e2Snonaka
91b62fc9e2Snonaka void *sc_key_ih;
92b62fc9e2Snonaka void *sc_power_ih;
93b62fc9e2Snonaka void *sc_reset_ih;
94b62fc9e2Snonaka
95b62fc9e2Snonaka int sc_key_pin;
96b62fc9e2Snonaka int sc_power_pin;
97b62fc9e2Snonaka int sc_reset_pin;
98b62fc9e2Snonaka
99b62fc9e2Snonaka struct hpckbd_ic_if sc_if;
100b62fc9e2Snonaka struct hpckbd_if *sc_hpckbd;
101b62fc9e2Snonaka
102b62fc9e2Snonaka struct sysmon_pswitch sc_smpsw; /* for reset key */
103b62fc9e2Snonaka
104b62fc9e2Snonaka int sc_enabled;
105b62fc9e2Snonaka
106b62fc9e2Snonaka /* polling stuff */
107b62fc9e2Snonaka struct callout sc_keyscan_ch;
108b62fc9e2Snonaka int sc_interval;
109b62fc9e2Snonaka #define KEY_INTERVAL 50 /* ms */
110b62fc9e2Snonaka
111b62fc9e2Snonaka #if defined(KEYTEST) || defined(KEYTEST2) || defined(KEYTEST3) || defined(KEYTEST4) || defined(KEYTEST5)
112b62fc9e2Snonaka void *sc_test_ih;
113b62fc9e2Snonaka int sc_test_pin;
114b62fc9e2Snonaka int sc_nouse_pin;
115b62fc9e2Snonaka int sc_nouse_pin2;
116b62fc9e2Snonaka int sc_nouse_pin3;
117b62fc9e2Snonaka int sc_bit;
118b62fc9e2Snonaka #endif
119b62fc9e2Snonaka };
120b62fc9e2Snonaka
121b62fc9e2Snonaka static int wzero3kbd_match(device_t, cfdata_t, void *);
122b62fc9e2Snonaka static void wzero3kbd_attach(device_t, device_t, void *);
123b62fc9e2Snonaka
124b62fc9e2Snonaka CFATTACH_DECL_NEW(wzero3kbd, sizeof(struct wzero3kbd_softc),
125b62fc9e2Snonaka wzero3kbd_match, wzero3kbd_attach, NULL, NULL);
126b62fc9e2Snonaka
127b62fc9e2Snonaka static int wzero3kbd_intr(void *arg);
128b62fc9e2Snonaka #if defined(KEYTEST)
129b62fc9e2Snonaka static int wzero3kbd_intr2(void *arg);
130b62fc9e2Snonaka #endif
131b62fc9e2Snonaka #if defined(KEYTEST3)
132b62fc9e2Snonaka static int wzero3kbd_intr3(void *arg);
133b62fc9e2Snonaka #endif
134b62fc9e2Snonaka static void wzero3kbd_tick(void *arg);
135b62fc9e2Snonaka static int wzero3kbd_power_intr(void *arg);
136b62fc9e2Snonaka static int wzero3kbd_reset_intr(void *arg);
137b62fc9e2Snonaka static int wzero3kbd_input_establish(void *arg, struct hpckbd_if *kbdif);
138b62fc9e2Snonaka static void wzero3kbd_sysmon_reset_event(void *arg);
139b62fc9e2Snonaka static int wzero3kbd_poll(void *arg);
140b62fc9e2Snonaka static int wzero3kbd_poll1(void *arg);
141b62fc9e2Snonaka
142b62fc9e2Snonaka /*
143250a759eSnonaka * WS003SH/WS004SH/WS007SH keyscan map
144b62fc9e2Snonaka col#0 col#1 col#2 col#3 col#4 col#5 col#6 col#7 col#8 col#9 col#10 col#11
145b62fc9e2Snonaka row#0: CTRL 1 3 5 6 7 9 0 BS (none) ROTATE CAMERA
146b62fc9e2Snonaka row#1: (none) 2 4 r y 8 i o p (none) VOL- VOL+
147b62fc9e2Snonaka row#2: TAB q e t g u j k (none) (none) (none) (none)
148b62fc9e2Snonaka row#3: (none) w s f v h m l (none) (none) SHIFT (none)
149b62fc9e2Snonaka row#4: CALL a d c b n . (none) ENTER (none) WIN (none)
150b62fc9e2Snonaka row#5: MAIL z x - SPACE / (none) UP (none) (none) LSOFT FN
151b62fc9e2Snonaka row#6: IE MOJI (none) OK ACTION , LEFT DOWN RIGHT (none) RSOFT (none)
152b62fc9e2Snonaka */
153b62fc9e2Snonaka
154b62fc9e2Snonaka /*
155b62fc9e2Snonaka * WS011SH keyscan map
156b62fc9e2Snonaka col#0 col#1 col#2 col#3 col#4 col#5 col#6 col#7 col#8 col#9 col#10 col#11
157b62fc9e2Snonaka row#0 Ctrl (none) (none) (none) (none) (none) (none) (none) Del (none) ROTATE (none)
158250a759eSnonaka row#1 (none) (none) (none) R Y (none) I O P (none) (none) (none)
159b62fc9e2Snonaka row#2 Tab Q E T G U J K (none) (none) (none) (none)
160b62fc9e2Snonaka row#3 (none) W S F V H M L (none) (none) Shift (none)
161b62fc9e2Snonaka row#4 (none) A D C B N . (none) Enter (none) (none) (none)
162250a759eSnonaka row#5 (none) Z X - Space / (none) UP (none) (none) (none) Fn
163250a759eSnonaka row#6 (none) MOJI HAN/ZEN OK (none) , LEFT DOWN RIGHT (none) (none) (none)
164250a759eSnonaka */
165250a759eSnonaka
166250a759eSnonaka /*
167250a759eSnonaka * WS020SH keyscan map
168250a759eSnonaka col#0 col#1 col#2 col#3 col#4 col#5 col#6 col#7 col#8 col#9 col#10 col#11
169250a759eSnonaka row#0 Ctrl (none) (none) (none) (none) (none) (none) (none) Del (none) ROTATE (none)
170250a759eSnonaka row#1 (none) (none) (none) R Y (none) I O P (none) MEDIA (none)
171250a759eSnonaka row#2 Tab Q E T G U J K (none) (none) (none) (none)
172250a759eSnonaka row#3 (none) W S F V H M L (none) (none) LShift (none)
173250a759eSnonaka row#4 (none) A D C B N . (none) Enter (none) RShift (none)
174250a759eSnonaka row#5 (none) Z X - Space / (none) UP (none) DOWN (none) Fn
175250a759eSnonaka row#6 (none) MOJI HAN/ZEN OK (none) , LEFT (none) RIGHT (none) (none) (none)
176b62fc9e2Snonaka */
177b62fc9e2Snonaka
178b62fc9e2Snonaka static const struct wzero3kbd_model {
179b62fc9e2Snonaka platid_mask_t *platid;
180b62fc9e2Snonaka int key_pin;
181b62fc9e2Snonaka int power_pin;
182b62fc9e2Snonaka int reset_pin;
183b62fc9e2Snonaka int ncolumn;
184b62fc9e2Snonaka int nrow;
185b62fc9e2Snonaka } wzero3kbd_table[] = {
186b62fc9e2Snonaka /* WS003SH */
187b62fc9e2Snonaka {
188b62fc9e2Snonaka &platid_mask_MACH_SHARP_WZERO3_WS003SH,
189b62fc9e2Snonaka -1, /* XXX */
190b62fc9e2Snonaka GPIO_WS003SH_POWER_BUTTON,
191b62fc9e2Snonaka -1, /* None */
192b62fc9e2Snonaka WS003SH_NCOLUMN,
193b62fc9e2Snonaka WS003SH_NROW,
194b62fc9e2Snonaka },
195b62fc9e2Snonaka /* WS004SH */
196b62fc9e2Snonaka {
197b62fc9e2Snonaka &platid_mask_MACH_SHARP_WZERO3_WS004SH,
198b62fc9e2Snonaka -1, /* XXX */
199b62fc9e2Snonaka GPIO_WS003SH_POWER_BUTTON,
200b62fc9e2Snonaka -1, /* None */
201b62fc9e2Snonaka WS003SH_NCOLUMN,
202b62fc9e2Snonaka WS003SH_NROW,
203b62fc9e2Snonaka },
204b62fc9e2Snonaka /* WS007SH */
205b62fc9e2Snonaka {
206b62fc9e2Snonaka &platid_mask_MACH_SHARP_WZERO3_WS007SH,
207b62fc9e2Snonaka -1, /* XXX */
208b62fc9e2Snonaka GPIO_WS007SH_POWER_BUTTON,
209b62fc9e2Snonaka GPIO_WS007SH_RESET_BUTTON,
210b62fc9e2Snonaka WS003SH_NCOLUMN,
211b62fc9e2Snonaka WS003SH_NROW,
212b62fc9e2Snonaka },
213b62fc9e2Snonaka /* WS011SH */
214b62fc9e2Snonaka {
215b62fc9e2Snonaka &platid_mask_MACH_SHARP_WZERO3_WS011SH,
216b62fc9e2Snonaka -1, /* XXX */
217b62fc9e2Snonaka GPIO_WS011SH_POWER_BUTTON,
218b62fc9e2Snonaka GPIO_WS011SH_RESET_BUTTON,
219b62fc9e2Snonaka WS003SH_NCOLUMN,
220b62fc9e2Snonaka WS003SH_NROW,
221b62fc9e2Snonaka },
222b62fc9e2Snonaka /* WS020SH */
223b62fc9e2Snonaka {
224b62fc9e2Snonaka &platid_mask_MACH_SHARP_WZERO3_WS020SH,
225b62fc9e2Snonaka -1, /* XXX */
226250a759eSnonaka GPIO_WS020SH_POWER_BUTTON,
227250a759eSnonaka GPIO_WS020SH_RESET_BUTTON,
228b62fc9e2Snonaka WS003SH_NCOLUMN,
229b62fc9e2Snonaka WS003SH_NROW,
230b62fc9e2Snonaka },
231b62fc9e2Snonaka
232b62fc9e2Snonaka { NULL, -1, -1, -1, 0, 0, }
233b62fc9e2Snonaka };
234b62fc9e2Snonaka
235b62fc9e2Snonaka static const struct wzero3kbd_model *
wzero3kbd_lookup(void)236b62fc9e2Snonaka wzero3kbd_lookup(void)
237b62fc9e2Snonaka {
238b62fc9e2Snonaka const struct wzero3kbd_model *model;
239b62fc9e2Snonaka
240b62fc9e2Snonaka for (model = wzero3kbd_table; model->platid != NULL; model++) {
241b62fc9e2Snonaka if (platid_match(&platid, model->platid)) {
242b62fc9e2Snonaka return model;
243b62fc9e2Snonaka }
244b62fc9e2Snonaka }
245b62fc9e2Snonaka return NULL;
246b62fc9e2Snonaka }
247b62fc9e2Snonaka
248b62fc9e2Snonaka static int
wzero3kbd_match(device_t parent,cfdata_t cf,void * aux)2495f819ca3Schs wzero3kbd_match(device_t parent, cfdata_t cf, void *aux)
250b62fc9e2Snonaka {
251b62fc9e2Snonaka
252b62fc9e2Snonaka if (strcmp(cf->cf_name, "wzero3kbd") != 0)
253b62fc9e2Snonaka return 0;
254b62fc9e2Snonaka if (wzero3kbd_lookup() == NULL)
255b62fc9e2Snonaka return 0;
256b62fc9e2Snonaka return 1;
257b62fc9e2Snonaka }
258b62fc9e2Snonaka
259b62fc9e2Snonaka static void
wzero3kbd_attach(device_t parent,device_t self,void * aux)2605f819ca3Schs wzero3kbd_attach(device_t parent, device_t self, void *aux)
261b62fc9e2Snonaka {
262b62fc9e2Snonaka struct wzero3kbd_softc *sc = device_private(self);
263b62fc9e2Snonaka struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux;
264b62fc9e2Snonaka struct hpckbd_attach_args haa;
265b62fc9e2Snonaka const struct wzero3kbd_model *model;
266b62fc9e2Snonaka
267b62fc9e2Snonaka sc->sc_dev = self;
268b62fc9e2Snonaka
269b62fc9e2Snonaka model = wzero3kbd_lookup();
270b62fc9e2Snonaka if (model == NULL) {
271b62fc9e2Snonaka aprint_error(": unknown model\n");
272b62fc9e2Snonaka return;
273b62fc9e2Snonaka }
274b62fc9e2Snonaka
275b62fc9e2Snonaka aprint_normal(": keyboard\n");
276b62fc9e2Snonaka aprint_naive("\n");
277b62fc9e2Snonaka
278b62fc9e2Snonaka sc->sc_key_pin = model->key_pin;
279b62fc9e2Snonaka sc->sc_power_pin = model->power_pin;
280b62fc9e2Snonaka sc->sc_reset_pin = model->reset_pin;
281b62fc9e2Snonaka sc->sc_ncolumn = model->ncolumn;
282b62fc9e2Snonaka sc->sc_nrow = model->nrow;
283b62fc9e2Snonaka
284b62fc9e2Snonaka sc->sc_iot = pxa->pxa_iot;
285b62fc9e2Snonaka if (bus_space_map(sc->sc_iot, PXA2X0_CS2_START, REGMAPSIZE, 0,
286b62fc9e2Snonaka &sc->sc_ioh)) {
287b62fc9e2Snonaka aprint_error_dev(self, "couldn't map registers.\n");
288b62fc9e2Snonaka return;
289b62fc9e2Snonaka }
290b62fc9e2Snonaka
29143acb194Sthorpej sc->sc_okeystat = kmem_zalloc(sc->sc_nrow * sc->sc_ncolumn, KM_SLEEP);
29243acb194Sthorpej sc->sc_keystat = kmem_zalloc(sc->sc_nrow * sc->sc_ncolumn, KM_SLEEP);
293b62fc9e2Snonaka
294b62fc9e2Snonaka sc->sc_if.hii_ctx = sc;
295b62fc9e2Snonaka sc->sc_if.hii_establish = wzero3kbd_input_establish;
296b62fc9e2Snonaka sc->sc_if.hii_poll = wzero3kbd_poll;
297b62fc9e2Snonaka
298b62fc9e2Snonaka /* Attach console if not using serial. */
299b62fc9e2Snonaka if (!(bootinfo->bi_cnuse & BI_CNUSE_SERIAL))
300b62fc9e2Snonaka hpckbd_cnattach(&sc->sc_if);
301b62fc9e2Snonaka
302b62fc9e2Snonaka /* Install interrupt handler. */
303b62fc9e2Snonaka if (sc->sc_key_pin >= 0) {
304b62fc9e2Snonaka pxa2x0_gpio_set_function(sc->sc_key_pin, GPIO_IN);
305b62fc9e2Snonaka sc->sc_key_ih = pxa2x0_gpio_intr_establish(sc->sc_key_pin,
306b62fc9e2Snonaka IST_EDGE_BOTH, IPL_TTY, wzero3kbd_intr, sc);
307b62fc9e2Snonaka if (sc->sc_key_ih == NULL) {
308b62fc9e2Snonaka aprint_error_dev(sc->sc_dev,
309b62fc9e2Snonaka "couldn't establish key interrupt\n");
310b62fc9e2Snonaka }
311b62fc9e2Snonaka } else {
312b62fc9e2Snonaka sc->sc_interval = KEY_INTERVAL / (1000 / hz);
313b62fc9e2Snonaka if (sc->sc_interval < 1)
314b62fc9e2Snonaka sc->sc_interval = 1;
315b62fc9e2Snonaka callout_init(&sc->sc_keyscan_ch, 0);
316b62fc9e2Snonaka callout_reset(&sc->sc_keyscan_ch, sc->sc_interval,
317b62fc9e2Snonaka wzero3kbd_tick, sc);
318b62fc9e2Snonaka }
319b62fc9e2Snonaka
320b62fc9e2Snonaka /* power key */
321b62fc9e2Snonaka if (sc->sc_power_pin >= 0) {
322b62fc9e2Snonaka pxa2x0_gpio_set_function(sc->sc_power_pin, GPIO_IN);
323b62fc9e2Snonaka sc->sc_power_ih = pxa2x0_gpio_intr_establish(
324b62fc9e2Snonaka sc->sc_power_pin, IST_EDGE_BOTH, IPL_TTY,
325b62fc9e2Snonaka wzero3kbd_power_intr, sc);
326b62fc9e2Snonaka if (sc->sc_power_ih == NULL) {
327b62fc9e2Snonaka aprint_error_dev(sc->sc_dev,
328b62fc9e2Snonaka "couldn't establish power key interrupt\n");
329b62fc9e2Snonaka }
330b62fc9e2Snonaka }
331b62fc9e2Snonaka
332b62fc9e2Snonaka /* reset button */
333b62fc9e2Snonaka if (sc->sc_reset_pin >= 0) {
334b62fc9e2Snonaka pxa2x0_gpio_set_function(sc->sc_reset_pin, GPIO_IN);
335b62fc9e2Snonaka sc->sc_reset_ih = pxa2x0_gpio_intr_establish(
336b62fc9e2Snonaka sc->sc_reset_pin, IST_EDGE_BOTH, IPL_TTY,
337b62fc9e2Snonaka wzero3kbd_reset_intr, sc);
338b62fc9e2Snonaka if (sc->sc_reset_ih == NULL) {
339b62fc9e2Snonaka aprint_error_dev(sc->sc_dev,
340b62fc9e2Snonaka "couldn't establish reset key interrupt\n");
341b62fc9e2Snonaka }
342b62fc9e2Snonaka
343b62fc9e2Snonaka sc->sc_smpsw.smpsw_name = device_xname(self);
344b62fc9e2Snonaka sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_RESET;
345b62fc9e2Snonaka if (sysmon_pswitch_register(&sc->sc_smpsw) != 0) {
346b62fc9e2Snonaka aprint_error_dev(sc->sc_dev,
347b62fc9e2Snonaka "unable to register reset event handler\n");
348b62fc9e2Snonaka }
349b62fc9e2Snonaka }
350b62fc9e2Snonaka
351b62fc9e2Snonaka /* Attach hpckbd. */
352b62fc9e2Snonaka haa.haa_ic = &sc->sc_if;
353*beecddb6Sthorpej config_found(self, &haa, hpckbd_print, CFARGS_NONE);
354b62fc9e2Snonaka
355b62fc9e2Snonaka #if defined(KEYTEST) || defined(KEYTEST2) || defined(KEYTEST3) || defined(KEYTEST4) || defined(KEYTEST5)
356b62fc9e2Snonaka sc->sc_test_ih = NULL;
357b62fc9e2Snonaka sc->sc_test_pin = -1;
358b62fc9e2Snonaka sc->sc_nouse_pin = -1;
359b62fc9e2Snonaka sc->sc_nouse_pin2 = -1;
360b62fc9e2Snonaka sc->sc_nouse_pin3 = -1;
361b62fc9e2Snonaka sc->sc_bit = 0x01;
362b62fc9e2Snonaka if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS003SH)
363b62fc9e2Snonaka || platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS004SH)) {
364b62fc9e2Snonaka sc->sc_nouse_pin = GPIO_WS003SH_SD_DETECT; /* SD_DETECT */
365b62fc9e2Snonaka sc->sc_nouse_pin2 = 86; /* Vsync? */
366b62fc9e2Snonaka sc->sc_nouse_pin3 = 89; /* RESET? */
367b62fc9e2Snonaka }
368b62fc9e2Snonaka if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS007SH)) {
369b62fc9e2Snonaka sc->sc_nouse_pin = GPIO_WS007SH_SD_DETECT; /* SD_DETECT */
370b62fc9e2Snonaka sc->sc_nouse_pin2 = 77; /* Vsync? */
371b62fc9e2Snonaka }
372b62fc9e2Snonaka if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) {
373b62fc9e2Snonaka sc->sc_nouse_pin = GPIO_WS011SH_SD_DETECT; /* SD_DETECT */
374b62fc9e2Snonaka sc->sc_nouse_pin2 = 77; /* Vsync? */
375b62fc9e2Snonaka }
376250a759eSnonaka if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS020SH)) {
377250a759eSnonaka sc->sc_nouse_pin = GPIO_WS020SH_SD_DETECT; /* SD_DETECT */
378250a759eSnonaka sc->sc_nouse_pin2 = 77; /* Vsync? */
379250a759eSnonaka }
380b62fc9e2Snonaka
381b62fc9e2Snonaka #ifdef KEYTEST
382b62fc9e2Snonaka for (sc->sc_test_pin = 2; sc->sc_test_pin < PXA270_GPIO_NPINS; sc->sc_test_pin++) {
383b62fc9e2Snonaka if (sc->sc_test_pin != sc->sc_nouse_pin
384b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin2
385b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin3
386b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_key_pin
387b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_power_pin
388b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_reset_pin
389b62fc9e2Snonaka && GPIO_IS_GPIO_IN(pxa2x0_gpio_get_function(sc->sc_test_pin)))
390b62fc9e2Snonaka break;
391b62fc9e2Snonaka }
392b62fc9e2Snonaka if (sc->sc_test_pin < PXA270_GPIO_NPINS) {
393b62fc9e2Snonaka printf("GPIO_IN: GPIO pin #%d\n", sc->sc_test_pin);
394b62fc9e2Snonaka sc->sc_test_ih = pxa2x0_gpio_intr_establish(sc->sc_test_pin,
395b62fc9e2Snonaka IST_EDGE_BOTH, IPL_TTY, wzero3kbd_intr2, sc);
396b62fc9e2Snonaka } else {
397b62fc9e2Snonaka sc->sc_test_pin = -1;
398b62fc9e2Snonaka }
399b62fc9e2Snonaka #endif
400b62fc9e2Snonaka
401b62fc9e2Snonaka #ifdef KEYTEST3
402b62fc9e2Snonaka {
403b62fc9e2Snonaka int i;
404b62fc9e2Snonaka printf("pin: ");
405b62fc9e2Snonaka for (i = 0; i < PXA270_GPIO_NPINS; i++) {
406b62fc9e2Snonaka if (i == sc->sc_nouse_pin
407b62fc9e2Snonaka || i == sc->sc_nouse_pin2
408b62fc9e2Snonaka || i == sc->sc_nouse_pin3
409b62fc9e2Snonaka || i == sc->sc_key_pin
410b62fc9e2Snonaka || i == sc->sc_power_pin
411b62fc9e2Snonaka || i == sc->sc_reset_pin)
412b62fc9e2Snonaka continue;
413b62fc9e2Snonaka
414b62fc9e2Snonaka printf("%d, ", i);
415b62fc9e2Snonaka if (GPIO_IS_GPIO_IN(pxa2x0_gpio_get_function(i))) {
416b62fc9e2Snonaka pxa2x0_gpio_intr_establish(i, IST_EDGE_BOTH,
417b62fc9e2Snonaka IPL_TTY, wzero3kbd_intr3, (void *)(long)i);
418b62fc9e2Snonaka }
419b62fc9e2Snonaka }
420b62fc9e2Snonaka }
421b62fc9e2Snonaka #endif
422b62fc9e2Snonaka
423b62fc9e2Snonaka #ifdef KEYTEST4
424b62fc9e2Snonaka for (sc->sc_test_pin = 2; sc->sc_test_pin < PXA270_GPIO_NPINS; sc->sc_test_pin++) {
425b62fc9e2Snonaka if (sc->sc_test_pin != sc->sc_nouse_pin
426b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin2
427b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin3
428b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_key_pin
429b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_power_pin
430b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_reset_pin
431b62fc9e2Snonaka && GPIO_IS_GPIO_OUT(pxa2x0_gpio_get_function(sc->sc_test_pin)))
432b62fc9e2Snonaka break;
433b62fc9e2Snonaka }
434b62fc9e2Snonaka if (sc->sc_test_pin < PXA270_GPIO_NPINS) {
435b62fc9e2Snonaka printf("GPIO_OUT: GPIO pin #%d\n", sc->sc_test_pin);
436b62fc9e2Snonaka } else {
437b62fc9e2Snonaka sc->sc_test_pin = -1;
438b62fc9e2Snonaka }
439b62fc9e2Snonaka #endif
440b62fc9e2Snonaka #ifdef KEYTEST5
441b62fc9e2Snonaka sc->sc_test_pin = 0x00;
442b62fc9e2Snonaka sc->sc_bit = 0x01;
443b62fc9e2Snonaka #endif
444b62fc9e2Snonaka #endif
445b62fc9e2Snonaka }
446b62fc9e2Snonaka
447b62fc9e2Snonaka static int
wzero3kbd_intr(void * arg)448b62fc9e2Snonaka wzero3kbd_intr(void *arg)
449b62fc9e2Snonaka {
450b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
451b62fc9e2Snonaka
452b62fc9e2Snonaka #if defined(KEYTEST) || defined(KEYTEST2) || defined(KEYTEST3) || defined(KEYTEST4) || defined(KEYTEST5)
453b62fc9e2Snonaka printf("wzero3kbd_intr: GPIO pin #%d = %s\n", sc->sc_key_pin,
454b62fc9e2Snonaka pxa2x0_gpio_get_bit(sc->sc_key_pin) ? "on" : "off");
455b62fc9e2Snonaka #endif
456b62fc9e2Snonaka
457b62fc9e2Snonaka #if defined(KEYTEST4)
458b62fc9e2Snonaka if (sc->sc_test_pin >= 0) {
459b62fc9e2Snonaka if (pxa2x0_gpio_get_bit(sc->sc_test_pin)) {
460b62fc9e2Snonaka printf("GPIO_OUT: GPIO pin #%d: L\n",sc->sc_test_pin);
461b62fc9e2Snonaka pxa2x0_gpio_clear_bit(sc->sc_test_pin);
462b62fc9e2Snonaka } else {
463b62fc9e2Snonaka printf("GPIO_OUT: GPIO pin #%d: H\n", sc->sc_test_pin);
464b62fc9e2Snonaka pxa2x0_gpio_set_bit(sc->sc_test_pin);
465b62fc9e2Snonaka }
466b62fc9e2Snonaka }
467b62fc9e2Snonaka #endif
468b62fc9e2Snonaka #if defined(KEYTEST5)
469b62fc9e2Snonaka printf("CPLD(%#x): value=%#x, mask=%#x\n",
470b62fc9e2Snonaka sc->sc_test_pin, CSR_READ4(sc->sc_test_pin), sc->sc_bit);
471b62fc9e2Snonaka if (CSR_READ4(sc->sc_test_pin) & sc->sc_bit) {
472b62fc9e2Snonaka printf("CPLD_OUT: CPLD: L\n");
473b62fc9e2Snonaka CSR_WRITE4(sc->sc_test_pin,
474b62fc9e2Snonaka CSR_READ4(sc->sc_test_pin) & ~sc->sc_bit);
475b62fc9e2Snonaka } else {
476b62fc9e2Snonaka printf("CPLD_OUT: CPLD: H\n");
477b62fc9e2Snonaka CSR_WRITE4(sc->sc_test_pin,
478b62fc9e2Snonaka CSR_READ4(sc->sc_test_pin) | sc->sc_bit);
479b62fc9e2Snonaka }
480b62fc9e2Snonaka #endif
481b62fc9e2Snonaka
482b62fc9e2Snonaka (void) wzero3kbd_poll1(sc);
483b62fc9e2Snonaka
484b62fc9e2Snonaka pxa2x0_gpio_clear_intr(sc->sc_key_pin);
485b62fc9e2Snonaka
486b62fc9e2Snonaka return 1;
487b62fc9e2Snonaka }
488b62fc9e2Snonaka
489b62fc9e2Snonaka #if defined(KEYTEST)
490b62fc9e2Snonaka static int
wzero3kbd_intr2(void * arg)491b62fc9e2Snonaka wzero3kbd_intr2(void *arg)
492b62fc9e2Snonaka {
493b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
494b62fc9e2Snonaka
495b62fc9e2Snonaka printf("wzero3kbd_intr2: GPIO_IN: GPIO pin #%d = %s\n", sc->sc_test_pin,
496b62fc9e2Snonaka pxa2x0_gpio_get_bit(sc->sc_test_pin) ? "on" : "off");
497b62fc9e2Snonaka
498b62fc9e2Snonaka return 1;
499b62fc9e2Snonaka }
500b62fc9e2Snonaka #endif
501b62fc9e2Snonaka
502b62fc9e2Snonaka #if defined(KEYTEST3)
503b62fc9e2Snonaka static int
wzero3kbd_intr3(void * arg)504b62fc9e2Snonaka wzero3kbd_intr3(void *arg)
505b62fc9e2Snonaka {
506b62fc9e2Snonaka int pin = (int)arg;
507b62fc9e2Snonaka
508b62fc9e2Snonaka printf("wzero3kbd_intr3: GPIO pin #%d = %s\n", pin,
509b62fc9e2Snonaka pxa2x0_gpio_get_bit(pin) ? "on" : "off");
510b62fc9e2Snonaka
511b62fc9e2Snonaka return 1;
512b62fc9e2Snonaka }
513b62fc9e2Snonaka #endif
514b62fc9e2Snonaka
515b62fc9e2Snonaka
516b62fc9e2Snonaka static void
wzero3kbd_tick(void * arg)517b62fc9e2Snonaka wzero3kbd_tick(void *arg)
518b62fc9e2Snonaka {
519b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
520b62fc9e2Snonaka
521b62fc9e2Snonaka (void) wzero3kbd_poll1(sc);
522b62fc9e2Snonaka
52357e70595Snonaka callout_schedule(&sc->sc_keyscan_ch, sc->sc_interval);
524b62fc9e2Snonaka }
525b62fc9e2Snonaka
526b62fc9e2Snonaka static int
wzero3kbd_power_intr(void * arg)527b62fc9e2Snonaka wzero3kbd_power_intr(void *arg)
528b62fc9e2Snonaka {
529b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
530b62fc9e2Snonaka
531b62fc9e2Snonaka #if defined(KEYTEST) || defined(KEYTEST2) || defined(KEYTEST3) || defined(KEYTEST4)
532b62fc9e2Snonaka printf("wzero3kbd_power_intr: status = %s\n",
533b62fc9e2Snonaka pxa2x0_gpio_get_bit(sc->sc_power_pin) ? "on" : "off");
534b62fc9e2Snonaka #endif
535b62fc9e2Snonaka
536b62fc9e2Snonaka #if defined(KEYTEST)
537b62fc9e2Snonaka if (pxa2x0_gpio_get_bit(sc->sc_power_pin)) {
538b62fc9e2Snonaka if (sc->sc_test_pin >= 0) {
539b62fc9e2Snonaka int orig_pin = sc->sc_test_pin;
540b62fc9e2Snonaka pxa2x0_gpio_intr_disestablish(sc->sc_test_ih);
541b62fc9e2Snonaka sc->sc_test_ih = NULL;
542b62fc9e2Snonaka
543b62fc9e2Snonaka for (;;) {
544b62fc9e2Snonaka if (++sc->sc_test_pin >= PXA270_GPIO_NPINS)
545b62fc9e2Snonaka sc->sc_test_pin = 2;
546b62fc9e2Snonaka if (sc->sc_test_pin == orig_pin)
547b62fc9e2Snonaka break;
548b62fc9e2Snonaka if (sc->sc_test_pin != sc->sc_nouse_pin
549b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin2
550b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin3
551b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_key_pin
552b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_power_pin
553b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_reset_pin
554b62fc9e2Snonaka && GPIO_IS_GPIO_IN(pxa2x0_gpio_get_function(sc->sc_test_pin)))
555b62fc9e2Snonaka break;
556b62fc9e2Snonaka }
557b62fc9e2Snonaka if (sc->sc_test_pin != orig_pin) {
558b62fc9e2Snonaka printf("GPIO_IN: GPIO pin #%d\n",
559b62fc9e2Snonaka sc->sc_test_pin);
560b62fc9e2Snonaka sc->sc_test_ih =
561b62fc9e2Snonaka pxa2x0_gpio_intr_establish(sc->sc_test_pin,
562b62fc9e2Snonaka IST_EDGE_BOTH, IPL_TTY, wzero3kbd_intr2,sc);
563b62fc9e2Snonaka } else {
564b62fc9e2Snonaka sc->sc_test_pin = -1;
565b62fc9e2Snonaka }
566b62fc9e2Snonaka }
567b62fc9e2Snonaka }
568b62fc9e2Snonaka #endif
569b62fc9e2Snonaka
570b62fc9e2Snonaka #if defined(KEYTEST2)
571b62fc9e2Snonaka if (pxa2x0_gpio_get_bit(sc->sc_power_pin)) {
572b62fc9e2Snonaka sc->sc_enabled ^= 2;
573b62fc9e2Snonaka if (sc->sc_enabled & 2) {
574b62fc9e2Snonaka printf("print col/row\n");
575b62fc9e2Snonaka } else {
576b62fc9e2Snonaka printf("keyscan\n");
577b62fc9e2Snonaka }
578b62fc9e2Snonaka }
579b62fc9e2Snonaka #endif
580b62fc9e2Snonaka #if defined(KEYTEST4)
581b62fc9e2Snonaka if (pxa2x0_gpio_get_bit(sc->sc_power_pin)) {
582b62fc9e2Snonaka if (sc->sc_test_pin >= 0) {
583b62fc9e2Snonaka int orig_pin = sc->sc_test_pin;
584b62fc9e2Snonaka for (;;) {
585b62fc9e2Snonaka if (++sc->sc_test_pin >= PXA270_GPIO_NPINS)
586b62fc9e2Snonaka sc->sc_test_pin = 2;
587b62fc9e2Snonaka if (sc->sc_test_pin == orig_pin)
588b62fc9e2Snonaka break;
589b62fc9e2Snonaka if (sc->sc_test_pin != sc->sc_nouse_pin
590b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin2
591b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_nouse_pin3
592b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_key_pin
593b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_power_pin
594b62fc9e2Snonaka && sc->sc_test_pin != sc->sc_reset_pin
595b62fc9e2Snonaka && GPIO_IS_GPIO_OUT(pxa2x0_gpio_get_function(sc->sc_test_pin)))
596b62fc9e2Snonaka break;
597b62fc9e2Snonaka }
598b62fc9e2Snonaka if (sc->sc_test_pin != orig_pin) {
599b62fc9e2Snonaka printf("GPIO_OUT: GPIO pin #%d\n", sc->sc_test_pin);
600b62fc9e2Snonaka } else {
601b62fc9e2Snonaka sc->sc_test_pin = -1;
602b62fc9e2Snonaka }
603b62fc9e2Snonaka }
604b62fc9e2Snonaka }
605b62fc9e2Snonaka #endif
606b62fc9e2Snonaka #if defined(KEYTEST5)
607b62fc9e2Snonaka if (pxa2x0_gpio_get_bit(sc->sc_power_pin)) {
608b62fc9e2Snonaka sc->sc_bit <<= 1;
609b62fc9e2Snonaka if (sc->sc_bit & ~0xff) {
610b62fc9e2Snonaka sc->sc_bit = 0x01;
611b62fc9e2Snonaka sc->sc_test_pin += 0x4;
612b62fc9e2Snonaka if (sc->sc_test_pin >= 0x20) {
613b62fc9e2Snonaka sc->sc_test_pin = 0x00;
614b62fc9e2Snonaka }
615b62fc9e2Snonaka }
616b62fc9e2Snonaka printf("CPLD(%#x), mask=%#x\n", sc->sc_test_pin, sc->sc_bit);
617b62fc9e2Snonaka }
618b62fc9e2Snonaka #endif
619b62fc9e2Snonaka
620b62fc9e2Snonaka pxa2x0_gpio_clear_intr(sc->sc_power_pin);
621b62fc9e2Snonaka
622b62fc9e2Snonaka return 1;
623b62fc9e2Snonaka }
624b62fc9e2Snonaka
625b62fc9e2Snonaka static int
wzero3kbd_reset_intr(void * arg)626b62fc9e2Snonaka wzero3kbd_reset_intr(void *arg)
627b62fc9e2Snonaka {
628b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
629b62fc9e2Snonaka
630b62fc9e2Snonaka sysmon_task_queue_sched(0, wzero3kbd_sysmon_reset_event, sc);
631b62fc9e2Snonaka
632b62fc9e2Snonaka pxa2x0_gpio_clear_intr(sc->sc_reset_pin);
633b62fc9e2Snonaka
634b62fc9e2Snonaka return 1;
635b62fc9e2Snonaka }
636b62fc9e2Snonaka
637b62fc9e2Snonaka static int
wzero3kbd_input_establish(void * arg,struct hpckbd_if * kbdif)638b62fc9e2Snonaka wzero3kbd_input_establish(void *arg, struct hpckbd_if *kbdif)
639b62fc9e2Snonaka {
640b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
641b62fc9e2Snonaka
642b62fc9e2Snonaka /* Save hpckbd interface. */
643b62fc9e2Snonaka sc->sc_hpckbd = kbdif;
644b62fc9e2Snonaka sc->sc_enabled = 1;
645b62fc9e2Snonaka
646b62fc9e2Snonaka return 0;
647b62fc9e2Snonaka }
648b62fc9e2Snonaka
649b62fc9e2Snonaka static void
wzero3kbd_sysmon_reset_event(void * arg)650b62fc9e2Snonaka wzero3kbd_sysmon_reset_event(void *arg)
651b62fc9e2Snonaka {
652b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
653b62fc9e2Snonaka
654b62fc9e2Snonaka sysmon_pswitch_event(&sc->sc_smpsw, PSWITCH_EVENT_PRESSED);
655b62fc9e2Snonaka }
656b62fc9e2Snonaka
657b62fc9e2Snonaka static int
wzero3kbd_poll(void * arg)658b62fc9e2Snonaka wzero3kbd_poll(void *arg)
659b62fc9e2Snonaka {
660b62fc9e2Snonaka int keydown;
661b62fc9e2Snonaka
662b62fc9e2Snonaka keydown = wzero3kbd_poll1(arg);
663b62fc9e2Snonaka
664b62fc9e2Snonaka return keydown;
665b62fc9e2Snonaka }
666b62fc9e2Snonaka
667b62fc9e2Snonaka static int
wzero3kbd_poll1(void * arg)668b62fc9e2Snonaka wzero3kbd_poll1(void *arg)
669b62fc9e2Snonaka {
670b62fc9e2Snonaka struct wzero3kbd_softc *sc = (struct wzero3kbd_softc *)arg;
671b62fc9e2Snonaka int row, col, data;
67256de8227Snonaka int keycol;
673b62fc9e2Snonaka int keydown;
674b62fc9e2Snonaka int i;
675b62fc9e2Snonaka int s;
676b62fc9e2Snonaka
677b62fc9e2Snonaka if (!sc->sc_enabled) {
678b62fc9e2Snonaka DPRINTF(("wzero3kbd_poll: disabled\n"));
679b62fc9e2Snonaka return 0;
680b62fc9e2Snonaka }
681b62fc9e2Snonaka
682b62fc9e2Snonaka s = spltty();
683b62fc9e2Snonaka
684b62fc9e2Snonaka for (col = 0; col < sc->sc_ncolumn; col++) {
685b62fc9e2Snonaka /* deselect column# and charge */
686b62fc9e2Snonaka CSR_WRITE1(KBDCOL_L, 0);
687b62fc9e2Snonaka CSR_WRITE1(KBDCOL_U, 0);
688b62fc9e2Snonaka CSR_WRITE1(KBDCHARGE, 1);
689b62fc9e2Snonaka delay(KEYWAIT);
690b62fc9e2Snonaka CSR_WRITE1(KBDCHARGE, 0);
691b62fc9e2Snonaka
692b62fc9e2Snonaka /* select scan column# */
693e8fe64adSnonaka keycol = 1 << col;
69456de8227Snonaka CSR_WRITE1(KBDCOL_L, keycol & 0xff);
69556de8227Snonaka CSR_WRITE1(KBDCOL_U, keycol >> 8);
696b62fc9e2Snonaka delay(KEYWAIT);
697b62fc9e2Snonaka CSR_WRITE1(KBDCHARGE, 0);
698b62fc9e2Snonaka
699b62fc9e2Snonaka /* read key data */
700b62fc9e2Snonaka data = CSR_READ1(KBDDATA);
701b62fc9e2Snonaka for (row = 0; row < sc->sc_nrow; row++) {
702b62fc9e2Snonaka #ifdef KEYTEST2
703b62fc9e2Snonaka if (!(sc->sc_enabled & 2)) {
704b62fc9e2Snonaka #endif
705b62fc9e2Snonaka sc->sc_keystat[row + col * sc->sc_nrow] =
706b62fc9e2Snonaka (data >> row) & 1;
707b62fc9e2Snonaka #ifdef KEYTEST2
708b62fc9e2Snonaka } else if (data & (1 << row)) {
709b62fc9e2Snonaka printf("col = %d, row = %d, idx = %d, data = 0x%02x\n", col, row, row + col * sc->sc_nrow, data);
710b62fc9e2Snonaka }
711b62fc9e2Snonaka #endif
712b62fc9e2Snonaka }
713b62fc9e2Snonaka }
714b62fc9e2Snonaka
715b62fc9e2Snonaka /* deselect column# and charge */
716b62fc9e2Snonaka CSR_WRITE1(KBDCOL_L, 0);
717b62fc9e2Snonaka CSR_WRITE1(KBDCOL_U, 0);
718b62fc9e2Snonaka CSR_WRITE1(KBDCHARGE, 1);
719b62fc9e2Snonaka delay(KEYWAIT);
720b62fc9e2Snonaka CSR_WRITE1(KBDCHARGE, 0);
721b62fc9e2Snonaka
722b62fc9e2Snonaka /* send key scan code */
723b62fc9e2Snonaka keydown = 0;
724b62fc9e2Snonaka for (i = 0; i < sc->sc_nrow * sc->sc_ncolumn; i++) {
72556de8227Snonaka if (sc->sc_keystat[i] == sc->sc_okeystat[i])
72656de8227Snonaka continue;
72756de8227Snonaka
72856de8227Snonaka keydown |= sc->sc_keystat[i];
72956de8227Snonaka hpckbd_input(sc->sc_hpckbd, sc->sc_keystat[i], i);
73056de8227Snonaka sc->sc_okeystat[i] = sc->sc_keystat[i];
731b62fc9e2Snonaka }
732b62fc9e2Snonaka
733b62fc9e2Snonaka splx(s);
734b62fc9e2Snonaka
735b62fc9e2Snonaka return keydown;
736b62fc9e2Snonaka }
737