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