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