zs_hb.c revision 1.23.14.2 1 1.23.14.1 mjf /* $NetBSD: zs_hb.c,v 1.23.14.2 2008/06/02 13:22:29 mjf Exp $ */
2 1.1 tsubai
3 1.1 tsubai /*-
4 1.1 tsubai * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 1.1 tsubai * All rights reserved.
6 1.1 tsubai *
7 1.1 tsubai * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsubai * by Gordon W. Ross.
9 1.1 tsubai *
10 1.1 tsubai * Redistribution and use in source and binary forms, with or without
11 1.1 tsubai * modification, are permitted provided that the following conditions
12 1.1 tsubai * are met:
13 1.1 tsubai * 1. Redistributions of source code must retain the above copyright
14 1.1 tsubai * notice, this list of conditions and the following disclaimer.
15 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsubai * notice, this list of conditions and the following disclaimer in the
17 1.1 tsubai * documentation and/or other materials provided with the distribution.
18 1.1 tsubai *
19 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 tsubai * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 tsubai * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 tsubai * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 tsubai * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 tsubai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 tsubai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 tsubai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 tsubai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 tsubai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 tsubai * POSSIBILITY OF SUCH DAMAGE.
30 1.1 tsubai */
31 1.1 tsubai
32 1.1 tsubai /*
33 1.1 tsubai * Zilog Z8530 Dual UART driver (machine-dependent part)
34 1.1 tsubai *
35 1.1 tsubai * Runs two serial lines per chip using slave drivers.
36 1.1 tsubai * Plain tty/async lines use the zs_async slave.
37 1.1 tsubai * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
38 1.1 tsubai */
39 1.17 lukem
40 1.17 lukem #include <sys/cdefs.h>
41 1.23.14.1 mjf __KERNEL_RCSID(0, "$NetBSD: zs_hb.c,v 1.23.14.2 2008/06/02 13:22:29 mjf Exp $");
42 1.1 tsubai
43 1.1 tsubai #include <sys/param.h>
44 1.1 tsubai #include <sys/systm.h>
45 1.1 tsubai #include <sys/device.h>
46 1.1 tsubai #include <sys/tty.h>
47 1.5 gehenna #include <sys/conf.h>
48 1.23 ad #include <sys/cpu.h>
49 1.23 ad #include <sys/intr.h>
50 1.1 tsubai
51 1.1 tsubai #include <machine/adrsmap.h>
52 1.1 tsubai #include <machine/z8530var.h>
53 1.1 tsubai
54 1.1 tsubai #include <dev/cons.h>
55 1.1 tsubai #include <dev/ic/z8530reg.h>
56 1.1 tsubai
57 1.12 tsutsui #include <newsmips/dev/hbvar.h>
58 1.12 tsutsui
59 1.1 tsubai #include "zsc.h" /* NZSC */
60 1.1 tsubai #define NZS NZSC
61 1.1 tsubai
62 1.1 tsubai /* Make life easier for the initialized arrays here. */
63 1.1 tsubai #if NZS < 2
64 1.1 tsubai #undef NZS
65 1.1 tsubai #define NZS 2
66 1.1 tsubai #endif
67 1.1 tsubai
68 1.3 tsubai #define ZSCFLAG_EX 0x01 /* expansion board */
69 1.3 tsubai
70 1.1 tsubai /*
71 1.1 tsubai * The news3400 provides a 4.9152 MHz clock to the ZS chips.
72 1.1 tsubai */
73 1.3 tsubai #define PCLK (9600 * 512) /* PCLK pin input clock rate */
74 1.3 tsubai #define PCLK_EX (9600 * 384)
75 1.1 tsubai
76 1.1 tsubai /*
77 1.1 tsubai * Define interrupt levels.
78 1.1 tsubai */
79 1.1 tsubai #define ZSHARD_PRI 64
80 1.1 tsubai
81 1.1 tsubai #define ZS_DELAY() {(void)*(volatile char *)INTEN1; delay(2);}
82 1.1 tsubai
83 1.1 tsubai /* The layout of this is hardware-dependent (padding, order). */
84 1.1 tsubai struct zschan {
85 1.23.14.1 mjf volatile uint8_t zc_csr; /* ctrl,status, and indirect access */
86 1.23.14.1 mjf volatile uint8_t zc_data; /* data */
87 1.1 tsubai };
88 1.1 tsubai struct zsdevice {
89 1.1 tsubai /* Yes, they are backwards. */
90 1.1 tsubai struct zschan zs_chan_b;
91 1.1 tsubai struct zschan zs_chan_a;
92 1.1 tsubai };
93 1.1 tsubai
94 1.1 tsubai extern int zs_def_cflag;
95 1.1 tsubai
96 1.1 tsubai static struct zsdevice *zsaddr[NZS];
97 1.1 tsubai
98 1.1 tsubai /* Flags from cninit() */
99 1.1 tsubai static int zs_hwflags[NZS][2];
100 1.1 tsubai
101 1.1 tsubai /* Default speed for all channels */
102 1.1 tsubai static int zs_defspeed = 9600;
103 1.1 tsubai
104 1.23.14.1 mjf static uint8_t zs_init_reg[16] = {
105 1.1 tsubai 0, /* 0: CMD (reset, etc.) */
106 1.1 tsubai 0, /* 1: No interrupts yet. */
107 1.1 tsubai ZSHARD_PRI, /* IVECT */
108 1.1 tsubai ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
109 1.1 tsubai ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
110 1.1 tsubai ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
111 1.1 tsubai 0, /* 6: TXSYNC/SYNCLO */
112 1.1 tsubai 0, /* 7: RXSYNC/SYNCHI */
113 1.1 tsubai 0, /* 8: alias for data port */
114 1.1 tsubai ZSWR9_MASTER_IE,
115 1.1 tsubai 0, /*10: Misc. TX/RX control bits */
116 1.1 tsubai ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
117 1.3 tsubai ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */
118 1.1 tsubai 0, /*13: BAUDHI (default=9600) */
119 1.1 tsubai ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
120 1.1 tsubai ZSWR15_BREAK_IE,
121 1.1 tsubai };
122 1.1 tsubai
123 1.18 tsutsui static struct zschan * zs_get_chan_addr(int, int);
124 1.18 tsutsui static void zs_hb_delay(void);
125 1.18 tsutsui static int zshard_hb(void *);
126 1.18 tsutsui static int zs_getc(void *);
127 1.18 tsutsui static void zs_putc(void *, int);
128 1.1 tsubai
129 1.2 tsubai struct zschan *
130 1.18 tsutsui zs_get_chan_addr(int zs_unit, int channel)
131 1.1 tsubai {
132 1.1 tsubai struct zsdevice *addr;
133 1.1 tsubai struct zschan *zc;
134 1.1 tsubai
135 1.1 tsubai if (zs_unit >= NZS)
136 1.1 tsubai return NULL;
137 1.1 tsubai addr = zsaddr[zs_unit];
138 1.1 tsubai if (addr == NULL)
139 1.1 tsubai return NULL;
140 1.1 tsubai if (channel == 0) {
141 1.1 tsubai zc = &addr->zs_chan_a;
142 1.1 tsubai } else {
143 1.1 tsubai zc = &addr->zs_chan_b;
144 1.1 tsubai }
145 1.18 tsutsui return zc;
146 1.1 tsubai }
147 1.1 tsubai
148 1.11 tsutsui static void
149 1.18 tsutsui zs_hb_delay(void)
150 1.1 tsubai {
151 1.11 tsutsui
152 1.1 tsubai ZS_DELAY();
153 1.1 tsubai }
154 1.1 tsubai
155 1.1 tsubai /****************************************************************
156 1.1 tsubai * Autoconfig
157 1.1 tsubai ****************************************************************/
158 1.1 tsubai
159 1.1 tsubai /* Definition of the driver for autoconfig. */
160 1.23.14.1 mjf int zs_hb_match(device_t, cfdata_t, void *);
161 1.23.14.1 mjf void zs_hb_attach(device_t, device_t, void *);
162 1.1 tsubai
163 1.23.14.1 mjf CFATTACH_DECL_NEW(zsc_hb, sizeof(struct zsc_softc),
164 1.7 thorpej zs_hb_match, zs_hb_attach, NULL, NULL);
165 1.1 tsubai
166 1.1 tsubai /*
167 1.1 tsubai * Is the zs chip present?
168 1.1 tsubai */
169 1.1 tsubai int
170 1.23.14.1 mjf zs_hb_match(device_t parent, cfdata_t cf, void *aux)
171 1.1 tsubai {
172 1.12 tsutsui struct hb_attach_args *ha = aux;
173 1.1 tsubai
174 1.12 tsutsui if (strcmp(ha->ha_name, "zsc"))
175 1.1 tsubai return 0;
176 1.1 tsubai
177 1.1 tsubai /* This returns -1 on a fault (bus error). */
178 1.12 tsutsui if (hb_badaddr((char *)ha->ha_addr, 1))
179 1.1 tsubai return 0;
180 1.1 tsubai
181 1.1 tsubai return 1;
182 1.1 tsubai }
183 1.1 tsubai
184 1.1 tsubai /*
185 1.1 tsubai * Attach a found zs.
186 1.1 tsubai *
187 1.1 tsubai * Match slave number to zs unit number, so that misconfiguration will
188 1.1 tsubai * not set up the keyboard as ttya, etc.
189 1.1 tsubai */
190 1.1 tsubai void
191 1.23.14.1 mjf zs_hb_attach(device_t parent, device_t self, void *aux)
192 1.1 tsubai {
193 1.23.14.1 mjf struct zsc_softc *zsc = device_private(self);
194 1.12 tsutsui struct hb_attach_args *ha = aux;
195 1.1 tsubai struct zsc_attach_args zsc_args;
196 1.1 tsubai volatile struct zschan *zc;
197 1.1 tsubai struct zs_chanstate *cs;
198 1.1 tsubai int s, zs_unit, channel, intlevel;
199 1.1 tsubai static int didintr;
200 1.1 tsubai
201 1.23.14.1 mjf zsc->zsc_dev = self;
202 1.23.14.1 mjf zs_unit = device_unit(self);
203 1.12 tsutsui intlevel = ha->ha_level;
204 1.12 tsutsui zsaddr[zs_unit] = (void *)ha->ha_addr;
205 1.1 tsubai
206 1.1 tsubai if (intlevel == -1) {
207 1.1 tsubai #if 0
208 1.23.14.1 mjf aprint_error(": interrupt level not configured\n");
209 1.1 tsubai return;
210 1.1 tsubai #else
211 1.23.14.1 mjf aprint_error(": interrupt level not configured; using");
212 1.1 tsubai intlevel = 1;
213 1.1 tsubai #endif
214 1.1 tsubai }
215 1.1 tsubai
216 1.23.14.1 mjf aprint_error(" level %d\n", intlevel);
217 1.1 tsubai
218 1.1 tsubai zs_delay = zs_hb_delay;
219 1.1 tsubai
220 1.1 tsubai /*
221 1.1 tsubai * Initialize software state for each channel.
222 1.1 tsubai */
223 1.1 tsubai for (channel = 0; channel < 2; channel++) {
224 1.1 tsubai zsc_args.channel = channel;
225 1.1 tsubai zsc_args.hwflags = zs_hwflags[zs_unit][channel];
226 1.1 tsubai cs = &zsc->zsc_cs_store[channel];
227 1.1 tsubai zsc->zsc_cs[channel] = cs;
228 1.1 tsubai
229 1.22 ad zs_lock_init(cs);
230 1.1 tsubai cs->cs_channel = channel;
231 1.1 tsubai cs->cs_private = NULL;
232 1.1 tsubai cs->cs_ops = &zsops_null;
233 1.23.14.1 mjf if ((device_cfdata(self)->cf_flags & ZSCFLAG_EX) == 0)
234 1.3 tsubai cs->cs_brg_clk = PCLK / 16;
235 1.1 tsubai else
236 1.3 tsubai cs->cs_brg_clk = PCLK_EX / 16;
237 1.1 tsubai
238 1.1 tsubai zc = zs_get_chan_addr(zs_unit, channel);
239 1.1 tsubai cs->cs_reg_csr = &zc->zc_csr;
240 1.1 tsubai cs->cs_reg_data = &zc->zc_data;
241 1.1 tsubai
242 1.18 tsutsui memcpy(cs->cs_creg, zs_init_reg, 16);
243 1.18 tsutsui memcpy(cs->cs_preg, zs_init_reg, 16);
244 1.1 tsubai
245 1.1 tsubai /* XXX: Get these from the EEPROM instead? */
246 1.1 tsubai /* XXX: See the mvme167 code. Better. */
247 1.1 tsubai if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
248 1.1 tsubai cs->cs_defspeed = zs_get_speed(cs);
249 1.1 tsubai else
250 1.1 tsubai cs->cs_defspeed = zs_defspeed;
251 1.1 tsubai cs->cs_defcflag = zs_def_cflag;
252 1.1 tsubai
253 1.1 tsubai /* Make these correspond to cs_defcflag (-crtscts) */
254 1.1 tsubai cs->cs_rr0_dcd = ZSRR0_DCD;
255 1.1 tsubai cs->cs_rr0_cts = 0;
256 1.1 tsubai cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
257 1.1 tsubai cs->cs_wr5_rts = 0;
258 1.1 tsubai
259 1.1 tsubai /*
260 1.1 tsubai * Clear the master interrupt enable.
261 1.1 tsubai * The INTENA is common to both channels,
262 1.1 tsubai * so just do it on the A channel.
263 1.1 tsubai */
264 1.1 tsubai if (channel == 0) {
265 1.1 tsubai zs_write_reg(cs, 9, 0);
266 1.1 tsubai }
267 1.1 tsubai
268 1.1 tsubai /*
269 1.1 tsubai * Look for a child driver for this channel.
270 1.1 tsubai * The child attach will setup the hardware.
271 1.1 tsubai */
272 1.1 tsubai if (!config_found(self, (void *)&zsc_args, zs_print)) {
273 1.1 tsubai /* No sub-driver. Just reset it. */
274 1.23.14.1 mjf uint8_t reset = (channel == 0) ?
275 1.23.14.1 mjf ZSWR9_A_RESET : ZSWR9_B_RESET;
276 1.1 tsubai s = splhigh();
277 1.1 tsubai zs_write_reg(cs, 9, reset);
278 1.1 tsubai splx(s);
279 1.1 tsubai }
280 1.1 tsubai }
281 1.1 tsubai
282 1.1 tsubai /*
283 1.1 tsubai * Now safe to install interrupt handlers. Note the arguments
284 1.1 tsubai * to the interrupt handlers aren't used. Note, we only do this
285 1.1 tsubai * once since both SCCs interrupt at the same level and vector.
286 1.1 tsubai */
287 1.1 tsubai if (!didintr) {
288 1.1 tsubai didintr = 1;
289 1.1 tsubai
290 1.23 ad zsc->zsc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc);
291 1.15 tsutsui hb_intr_establish(intlevel, INTST1_SCC, IPL_SERIAL,
292 1.15 tsutsui zshard_hb, NULL);
293 1.1 tsubai }
294 1.1 tsubai /* XXX; evcnt_attach() ? */
295 1.1 tsubai
296 1.1 tsubai /*
297 1.1 tsubai * Set the master interrupt enable and interrupt vector.
298 1.1 tsubai * (common to both channels, do it on A)
299 1.1 tsubai */
300 1.1 tsubai cs = zsc->zsc_cs[0];
301 1.1 tsubai s = splhigh();
302 1.1 tsubai /* interrupt vector */
303 1.1 tsubai zs_write_reg(cs, 2, zs_init_reg[2]);
304 1.1 tsubai /* master interrupt control (enable) */
305 1.1 tsubai zs_write_reg(cs, 9, zs_init_reg[9]);
306 1.1 tsubai splx(s);
307 1.1 tsubai }
308 1.1 tsubai
309 1.1 tsubai static int
310 1.18 tsutsui zshard_hb(void *arg)
311 1.1 tsubai {
312 1.14 tsutsui int rv;
313 1.14 tsutsui
314 1.1 tsubai (void) *(volatile u_char *)SCCVECT;
315 1.14 tsutsui rv = zshard(arg);
316 1.14 tsutsui
317 1.14 tsutsui /* XXX news3400 sometimes losts zs interrupt */
318 1.14 tsutsui if (rv)
319 1.14 tsutsui zshard(arg);
320 1.1 tsubai
321 1.14 tsutsui return rv;
322 1.1 tsubai }
323 1.1 tsubai
324 1.1 tsubai /*
325 1.1 tsubai * Polled input char.
326 1.1 tsubai */
327 1.1 tsubai int
328 1.18 tsutsui zs_getc(void *arg)
329 1.1 tsubai {
330 1.11 tsutsui volatile struct zschan *zc = arg;
331 1.11 tsutsui int s, c, rr0;
332 1.1 tsubai
333 1.1 tsubai s = splhigh();
334 1.1 tsubai /* Wait for a character to arrive. */
335 1.1 tsubai do {
336 1.1 tsubai rr0 = zc->zc_csr;
337 1.1 tsubai ZS_DELAY();
338 1.1 tsubai } while ((rr0 & ZSRR0_RX_READY) == 0);
339 1.1 tsubai
340 1.1 tsubai c = zc->zc_data;
341 1.1 tsubai ZS_DELAY();
342 1.1 tsubai splx(s);
343 1.1 tsubai
344 1.1 tsubai /*
345 1.1 tsubai * This is used by the kd driver to read scan codes,
346 1.1 tsubai * so don't translate '\r' ==> '\n' here...
347 1.1 tsubai */
348 1.18 tsutsui return c;
349 1.1 tsubai }
350 1.1 tsubai
351 1.1 tsubai /*
352 1.1 tsubai * Polled output char.
353 1.1 tsubai */
354 1.1 tsubai void
355 1.18 tsutsui zs_putc(void *arg, int c)
356 1.1 tsubai {
357 1.11 tsutsui volatile struct zschan *zc = arg;
358 1.11 tsutsui int s, rr0;
359 1.1 tsubai
360 1.1 tsubai s = splhigh();
361 1.1 tsubai /* Wait for transmitter to become ready. */
362 1.1 tsubai do {
363 1.1 tsubai rr0 = zc->zc_csr;
364 1.1 tsubai ZS_DELAY();
365 1.1 tsubai } while ((rr0 & ZSRR0_TX_READY) == 0);
366 1.1 tsubai
367 1.1 tsubai zc->zc_data = c;
368 1.1 tsubai ZS_DELAY();
369 1.1 tsubai splx(s);
370 1.1 tsubai }
371 1.1 tsubai
372 1.1 tsubai /*****************************************************************/
373 1.1 tsubai
374 1.18 tsutsui static void zscnprobe(struct consdev *);
375 1.18 tsutsui static void zscninit(struct consdev *);
376 1.18 tsutsui static int zscngetc(dev_t);
377 1.18 tsutsui static void zscnputc(dev_t, int);
378 1.1 tsubai
379 1.1 tsubai struct consdev consdev_zs = {
380 1.1 tsubai zscnprobe,
381 1.1 tsubai zscninit,
382 1.1 tsubai zscngetc,
383 1.1 tsubai zscnputc,
384 1.11 tsutsui nullcnpollc,
385 1.11 tsutsui NULL,
386 1.11 tsutsui NULL,
387 1.4 thorpej NULL,
388 1.11 tsutsui NODEV,
389 1.11 tsutsui CN_DEAD
390 1.1 tsubai };
391 1.1 tsubai
392 1.11 tsutsui static void
393 1.18 tsutsui zscnprobe(struct consdev *cn)
394 1.1 tsubai {
395 1.1 tsubai }
396 1.1 tsubai
397 1.11 tsutsui static void
398 1.18 tsutsui zscninit(struct consdev *cn)
399 1.1 tsubai {
400 1.5 gehenna extern const struct cdevsw zstty_cdevsw;
401 1.5 gehenna
402 1.5 gehenna cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
403 1.1 tsubai cn->cn_pri = CN_REMOTE;
404 1.1 tsubai zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE;
405 1.1 tsubai }
406 1.1 tsubai
407 1.11 tsutsui static int
408 1.18 tsutsui zscngetc(dev_t dev)
409 1.1 tsubai {
410 1.11 tsutsui
411 1.1 tsubai return zs_getc((void *)SCCPORT0A);
412 1.1 tsubai }
413 1.1 tsubai
414 1.11 tsutsui static void
415 1.18 tsutsui zscnputc(dev_t dev, int c)
416 1.1 tsubai {
417 1.11 tsutsui
418 1.1 tsubai zs_putc((void *)SCCPORT0A, c);
419 1.1 tsubai }
420