1 1.8 thorpej /* $NetBSD: j720kbd.c,v 1.8 2021/08/07 16:18:53 thorpej Exp $ */ 2 1.1 peter 3 1.1 peter /*- 4 1.1 peter * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 1.1 peter * All rights reserved. 6 1.1 peter * 7 1.1 peter * This code is derived from software contributed to The NetBSD Foundation 8 1.1 peter * by IWAMOTO Toshihiro and Peter Postma. 9 1.1 peter * 10 1.1 peter * Redistribution and use in source and binary forms, with or without 11 1.1 peter * modification, are permitted provided that the following conditions 12 1.1 peter * are met: 13 1.1 peter * 1. Redistributions of source code must retain the above copyright 14 1.1 peter * notice, this list of conditions and the following disclaimer. 15 1.1 peter * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 peter * notice, this list of conditions and the following disclaimer in the 17 1.1 peter * documentation and/or other materials provided with the distribution. 18 1.1 peter * 19 1.1 peter * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 peter * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 peter * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 peter * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 peter * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 peter * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 peter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 peter * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 peter * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 peter * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 peter * POSSIBILITY OF SUCH DAMAGE. 30 1.1 peter */ 31 1.1 peter 32 1.1 peter /* Jornada 720 keyboard driver. */ 33 1.1 peter 34 1.1 peter #include <sys/cdefs.h> 35 1.8 thorpej __KERNEL_RCSID(0, "$NetBSD: j720kbd.c,v 1.8 2021/08/07 16:18:53 thorpej Exp $"); 36 1.1 peter 37 1.1 peter #include <sys/param.h> 38 1.1 peter #include <sys/systm.h> 39 1.1 peter #include <sys/device.h> 40 1.1 peter #include <sys/kernel.h> 41 1.1 peter 42 1.1 peter #include <machine/bootinfo.h> 43 1.1 peter #include <machine/config_hook.h> 44 1.1 peter #include <machine/platid.h> 45 1.1 peter #include <machine/platid_mask.h> 46 1.1 peter 47 1.1 peter #include <arm/sa11x0/sa11x0_var.h> 48 1.1 peter #include <arm/sa11x0/sa11x0_gpioreg.h> 49 1.1 peter #include <arm/sa11x0/sa11x0_ppcreg.h> 50 1.1 peter #include <arm/sa11x0/sa11x0_sspreg.h> 51 1.1 peter 52 1.1 peter #include <dev/hpc/hpckbdvar.h> 53 1.1 peter 54 1.1 peter #include <hpcarm/dev/j720sspvar.h> 55 1.1 peter 56 1.1 peter #ifdef DEBUG 57 1.6 rjs #define DPRINTF(arg) aprint_normal arg 58 1.1 peter #else 59 1.1 peter #define DPRINTF(arg) /* nothing */ 60 1.1 peter #endif 61 1.1 peter 62 1.1 peter struct j720kbd_chip { 63 1.1 peter int scc_enabled; 64 1.1 peter 65 1.1 peter struct j720ssp_softc *scc_ssp; 66 1.1 peter 67 1.1 peter struct hpckbd_ic_if scc_if; 68 1.1 peter struct hpckbd_if *scc_hpckbd; 69 1.1 peter }; 70 1.1 peter 71 1.1 peter struct j720kbd_softc { 72 1.6 rjs device_t sc_dev; 73 1.1 peter 74 1.1 peter struct j720kbd_chip *sc_chip; 75 1.1 peter }; 76 1.1 peter 77 1.1 peter static struct j720kbd_chip j720kbd_chip; 78 1.1 peter 79 1.6 rjs static int j720kbd_match(device_t, cfdata_t, void *); 80 1.6 rjs static void j720kbd_attach(device_t, device_t, void *); 81 1.1 peter 82 1.1 peter static void j720kbd_cnattach(void); 83 1.1 peter static void j720kbd_ifsetup(struct j720kbd_chip *); 84 1.1 peter static int j720kbd_input_establish(void *, struct hpckbd_if *); 85 1.1 peter static int j720kbd_intr(void *); 86 1.1 peter static int j720kbd_poll(void *); 87 1.1 peter static void j720kbd_read(struct j720kbd_chip *, char *); 88 1.1 peter 89 1.6 rjs CFATTACH_DECL_NEW(j720kbd, sizeof(struct j720kbd_softc), 90 1.1 peter j720kbd_match, j720kbd_attach, NULL, NULL); 91 1.1 peter 92 1.1 peter 93 1.1 peter static int 94 1.6 rjs j720kbd_match(device_t parent, cfdata_t cf, void *aux) 95 1.1 peter { 96 1.1 peter 97 1.1 peter if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX)) 98 1.1 peter return 0; 99 1.1 peter if (strcmp(cf->cf_name, "j720kbd") != 0) 100 1.1 peter return 0; 101 1.1 peter 102 1.1 peter return 1; 103 1.1 peter } 104 1.1 peter 105 1.1 peter static void 106 1.6 rjs j720kbd_attach(device_t parent, device_t self, void *aux) 107 1.1 peter { 108 1.6 rjs struct j720kbd_softc *sc = device_private(self); 109 1.1 peter struct hpckbd_attach_args haa; 110 1.1 peter 111 1.6 rjs aprint_normal("\n"); 112 1.2 peter 113 1.6 rjs sc->sc_dev = self; 114 1.1 peter sc->sc_chip = &j720kbd_chip; 115 1.6 rjs sc->sc_chip->scc_ssp = device_private(parent); 116 1.1 peter sc->sc_chip->scc_enabled = 0; 117 1.1 peter 118 1.1 peter /* Attach console if not using serial. */ 119 1.1 peter if (!(bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) 120 1.1 peter j720kbd_cnattach(); 121 1.1 peter 122 1.1 peter j720kbd_ifsetup(sc->sc_chip); 123 1.1 peter 124 1.1 peter /* Install interrupt handler. */ 125 1.2 peter sa11x0_intr_establish(0, 0, 1, IPL_TTY, j720kbd_intr, sc); 126 1.1 peter 127 1.1 peter /* Attach hpckbd. */ 128 1.1 peter haa.haa_ic = &sc->sc_chip->scc_if; 129 1.8 thorpej config_found(self, &haa, hpckbd_print, CFARGS_NONE); 130 1.1 peter } 131 1.1 peter 132 1.1 peter static void 133 1.1 peter j720kbd_cnattach(void) 134 1.1 peter { 135 1.1 peter struct j720kbd_chip *scc = &j720kbd_chip; 136 1.1 peter 137 1.1 peter /* Initialize interface. */ 138 1.1 peter j720kbd_ifsetup(scc); 139 1.1 peter 140 1.1 peter /* Attach console. */ 141 1.1 peter hpckbd_cnattach(&scc->scc_if); 142 1.1 peter } 143 1.1 peter 144 1.1 peter static void 145 1.1 peter j720kbd_ifsetup(struct j720kbd_chip *scc) 146 1.1 peter { 147 1.1 peter 148 1.1 peter scc->scc_if.hii_ctx = scc; 149 1.1 peter scc->scc_if.hii_establish = j720kbd_input_establish; 150 1.1 peter scc->scc_if.hii_poll = j720kbd_poll; 151 1.1 peter } 152 1.1 peter 153 1.1 peter static int 154 1.1 peter j720kbd_input_establish(void *ic, struct hpckbd_if *kbdif) 155 1.1 peter { 156 1.1 peter struct j720kbd_chip *scc = ic; 157 1.1 peter 158 1.1 peter /* Save hpckbd interface. */ 159 1.1 peter scc->scc_hpckbd = kbdif; 160 1.1 peter 161 1.1 peter scc->scc_enabled = 1; 162 1.1 peter 163 1.1 peter return 0; 164 1.1 peter } 165 1.1 peter 166 1.1 peter static int 167 1.1 peter j720kbd_intr(void *arg) 168 1.1 peter { 169 1.1 peter struct j720kbd_softc *sc = arg; 170 1.1 peter struct j720ssp_softc *ssp = sc->sc_chip->scc_ssp; 171 1.1 peter 172 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1); 173 1.1 peter 174 1.1 peter return j720kbd_poll(sc->sc_chip); 175 1.1 peter } 176 1.1 peter 177 1.1 peter static int 178 1.1 peter j720kbd_poll(void *arg) 179 1.1 peter { 180 1.1 peter struct j720kbd_chip *scc = arg; 181 1.1 peter int type, key; 182 1.1 peter char buf[9], *p; 183 1.1 peter 184 1.1 peter if (!scc->scc_enabled) { 185 1.1 peter DPRINTF(("j720kbd_poll: !scc_enabled\n")); 186 1.1 peter return 0; 187 1.1 peter } 188 1.1 peter 189 1.1 peter j720kbd_read(scc, buf); 190 1.1 peter 191 1.1 peter for (p = buf; *p; p++) { 192 1.1 peter type = *p & 0x80 ? 0 : 1; 193 1.1 peter key = *p & 0x7f; 194 1.1 peter 195 1.1 peter hpckbd_input(scc->scc_hpckbd, type, key); 196 1.1 peter } 197 1.1 peter 198 1.1 peter return 1; 199 1.1 peter } 200 1.1 peter 201 1.1 peter static void 202 1.1 peter j720kbd_read(struct j720kbd_chip *scc, char *buf) 203 1.1 peter { 204 1.1 peter struct j720ssp_softc *ssp = scc->scc_ssp; 205 1.1 peter int data, count; 206 1.1 peter 207 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 208 1.1 peter 209 1.1 peter /* Send scan keycode command. */ 210 1.3 peter if (j720ssp_readwrite(ssp, 1, 0x90, &data, 500) < 0 || data != 0x11) { 211 1.1 peter DPRINTF(("j720kbd_read: no dummy received\n")); 212 1.1 peter goto out; 213 1.1 peter } 214 1.1 peter 215 1.1 peter /* Read number of scancodes available. */ 216 1.3 peter if (j720ssp_readwrite(ssp, 0, 0x11, &data, 500) < 0) { 217 1.1 peter DPRINTF(("j720kbd_read: unable to read number of scancodes\n")); 218 1.1 peter goto out; 219 1.1 peter } 220 1.1 peter count = data; 221 1.1 peter 222 1.1 peter for (; count; count--) { 223 1.3 peter if (j720ssp_readwrite(ssp, 0, 0x11, &data, 100) < 0) 224 1.1 peter goto out; 225 1.1 peter *buf++ = data; 226 1.1 peter } 227 1.1 peter *buf = 0; 228 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 229 1.1 peter 230 1.1 peter return; 231 1.1 peter 232 1.1 peter out: 233 1.1 peter *buf = 0; 234 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 235 1.1 peter 236 1.1 peter /* reset SSP */ 237 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 238 1.1 peter delay(100); 239 1.1 peter bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 240 1.1 peter 241 1.1 peter DPRINTF(("j720kbd_read: error %x\n", data)); 242 1.1 peter } 243