1 /* $NetBSD: tc5165buf.c,v 1.17 2012/10/27 17:17:53 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Device driver for TOSHIBA TC5165BFTS, PHILIPS 74ALVC16241/245 34 * buffer chip 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: tc5165buf.c,v 1.17 2012/10/27 17:17:53 chs Exp $"); 39 40 #include "opt_use_poll.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/callout.h> 45 #include <sys/device.h> 46 47 #include <machine/bus.h> 48 #include <machine/intr.h> 49 50 #include <dev/hpc/hpckbdvar.h> 51 52 #include <hpcmips/tx/tx39var.h> 53 #include <hpcmips/tx/txcsbusvar.h> 54 #include <hpcmips/dev/tc5165bufvar.h> 55 56 #define TC5165_ROW_MAX 16 57 #define TC5165_COLUMN_MAX 8 58 59 #ifdef TC5165DEBUG 60 #define DPRINTF(arg) printf arg 61 #else 62 #define DPRINTF(arg) 63 #endif 64 65 struct tc5165buf_chip { 66 bus_space_tag_t scc_cst; 67 bus_space_handle_t scc_csh; 68 u_int16_t scc_buf[TC5165_COLUMN_MAX]; 69 int scc_enabled; 70 int scc_queued; 71 struct callout scc_soft_ch; 72 struct hpckbd_ic_if scc_if; 73 struct hpckbd_if *scc_hpckbd; 74 }; 75 76 struct tc5165buf_softc { 77 struct tc5165buf_chip *sc_chip; 78 tx_chipset_tag_t sc_tc; 79 void *sc_ih; 80 }; 81 82 int tc5165buf_match(device_t, cfdata_t, void *); 83 void tc5165buf_attach(device_t, device_t, void *); 84 int tc5165buf_intr(void *); 85 int tc5165buf_poll(void *); 86 void tc5165buf_soft(void *); 87 void tc5165buf_ifsetup(struct tc5165buf_chip *); 88 89 int tc5165buf_input_establish(void *, struct hpckbd_if *); 90 91 struct tc5165buf_chip tc5165buf_chip; 92 93 CFATTACH_DECL_NEW(tc5165buf, sizeof(struct tc5165buf_softc), 94 tc5165buf_match, tc5165buf_attach, NULL, NULL); 95 96 int 97 tc5165buf_match(device_t parent, cfdata_t cf, void *aux) 98 { 99 100 return (1); 101 } 102 103 void 104 tc5165buf_attach(device_t parent, device_t self, void *aux) 105 { 106 struct cs_attach_args *ca = aux; 107 struct tc5165buf_softc *sc = device_private(self); 108 struct hpckbd_attach_args haa; 109 110 printf(": "); 111 sc->sc_tc = ca->ca_tc; 112 sc->sc_chip = &tc5165buf_chip; 113 114 callout_init(&sc->sc_chip->scc_soft_ch, 0); 115 116 sc->sc_chip->scc_cst = ca->ca_csio.cstag; 117 118 if (bus_space_map(sc->sc_chip->scc_cst, ca->ca_csio.csbase, 119 ca->ca_csio.cssize, 0, &sc->sc_chip->scc_csh)) { 120 printf("can't map i/o space\n"); 121 return; 122 } 123 124 sc->sc_chip->scc_enabled = 0; 125 126 if (ca->ca_irq1 != -1) { 127 sc->sc_ih = tx_intr_establish(sc->sc_tc, ca->ca_irq1, 128 IST_EDGE, IPL_TTY, 129 tc5165buf_intr, sc); 130 printf("interrupt mode"); 131 } else { 132 sc->sc_ih = tx39_poll_establish(sc->sc_tc, 1, IPL_TTY, 133 tc5165buf_intr, sc); 134 printf("polling mode"); 135 } 136 137 if (!sc->sc_ih) { 138 printf(" can't establish interrupt\n"); 139 return; 140 } 141 142 printf("\n"); 143 144 /* setup upper interface */ 145 tc5165buf_ifsetup(sc->sc_chip); 146 147 haa.haa_ic = &sc->sc_chip->scc_if; 148 149 config_found(self, &haa, hpckbd_print); 150 } 151 152 void 153 tc5165buf_ifsetup(struct tc5165buf_chip *scc) 154 { 155 156 scc->scc_if.hii_ctx = scc; 157 scc->scc_if.hii_establish = tc5165buf_input_establish; 158 scc->scc_if.hii_poll = tc5165buf_poll; 159 } 160 161 int 162 tc5165buf_cnattach(paddr_t addr) 163 { 164 struct tc5165buf_chip *scc = &tc5165buf_chip; 165 166 scc->scc_csh = MIPS_PHYS_TO_KSEG1(addr); 167 168 tc5165buf_ifsetup(scc); 169 170 hpckbd_cnattach(&scc->scc_if); 171 172 return (0); 173 } 174 175 int 176 tc5165buf_input_establish(void *ic, struct hpckbd_if *kbdif) 177 { 178 struct tc5165buf_chip *scc = ic; 179 180 /* save hpckbd interface */ 181 scc->scc_hpckbd = kbdif; 182 183 scc->scc_enabled = 1; 184 185 return (0); 186 } 187 188 int 189 tc5165buf_intr(void *arg) 190 { 191 struct tc5165buf_softc *sc = arg; 192 struct tc5165buf_chip *scc = sc->sc_chip; 193 194 if (!scc->scc_enabled || scc->scc_queued) 195 return (0); 196 197 scc->scc_queued = 1; 198 callout_reset(&scc->scc_soft_ch, 1, tc5165buf_soft, scc); 199 200 return (0); 201 } 202 203 int 204 tc5165buf_poll(void *arg) 205 { 206 struct tc5165buf_chip *scc = arg; 207 208 if (!scc->scc_enabled) 209 return (POLL_CONT); 210 211 tc5165buf_soft(arg); 212 213 return (POLL_CONT); 214 } 215 216 void 217 tc5165buf_soft(void *arg) 218 { 219 struct tc5165buf_chip *scc = arg; 220 bus_space_tag_t t = scc->scc_cst; 221 bus_space_handle_t h = scc->scc_csh; 222 u_int16_t mask, rpat, edge; 223 int i, j, type, val; 224 int s; 225 226 hpckbd_input_hook(scc->scc_hpckbd); 227 228 /* clear scanlines */ 229 (void)bus_space_read_2(t, h, 0); 230 delay(3); 231 232 for (i = 0; i < TC5165_COLUMN_MAX; i++) { 233 rpat = bus_space_read_2(t, h, 2 << i); 234 delay(3); 235 (void)bus_space_read_2(t, h, 0); 236 delay(3); 237 if ((edge = (rpat ^ scc->scc_buf[i]))) { 238 scc->scc_buf[i] = rpat; 239 for (j = 0, mask = 1; j < TC5165_ROW_MAX; 240 j++, mask <<= 1) { 241 if (mask & edge) { 242 type = mask & rpat ? 1 : 0; 243 val = j * TC5165_COLUMN_MAX + i; 244 DPRINTF(("%d %d\n", j, i)); 245 hpckbd_input(scc->scc_hpckbd, 246 type, val); 247 } 248 } 249 } 250 } 251 252 s = spltty(); 253 scc->scc_queued = 0; 254 splx(s); 255 } 256