Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / cesfic / dev / zs.c
blob93794543f4cb2a91195ef7d500ae21138a12d48d
1 /* $NetBSD: zs.c,v 1.17 2009/03/18 17:06:43 cegger Exp $ */
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gordon W. Ross.
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.
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.
33 * Zilog Z8530 Dual UART driver (machine-dependent part)
35 * Runs two serial lines per chip using slave drivers.
36 * Plain tty/async lines use the zs_async slave.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.17 2009/03/18 17:06:43 cegger Exp $");
42 #include "opt_ddb.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/conf.h>
47 #include <sys/device.h>
48 #include <sys/file.h>
49 #include <sys/ioctl.h>
50 #include <sys/kernel.h>
51 #include <sys/malloc.h>
52 #include <sys/proc.h>
53 #include <sys/tty.h>
54 #include <sys/time.h>
55 #include <sys/syslog.h>
57 #include <dev/cons.h>
58 #include <dev/ic/z8530reg.h>
60 #include <machine/cpu.h>
62 #include <machine/z8530var.h>
63 #include <cesfic/dev/zsvar.h>
65 #include "ioconf.h"
67 int zs_getc(void *);
68 void zs_putc(void*, int);
70 static struct zs_chanstate zs_conschan_store;
71 static int zs_hwflags[2][2];
73 static uint8_t zs_init_reg[16] = {
74 0, /* 0: CMD (reset, etc.) */
75 0, /* 1: No interrupts yet. */
76 0x18 + ZSHARD_PRI, /* IVECT */
77 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
78 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
79 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
80 0, /* 6: TXSYNC/SYNCLO */
81 0, /* 7: RXSYNC/SYNCHI */
82 0, /* 8: alias for data port */
83 ZSWR9_MASTER_IE,
84 0, /*10: Misc. TX/RX control bits */
85 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
86 11, /*12: BAUDLO (default=9600) */
87 0, /*13: BAUDHI (default=9600) */
88 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
89 ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
92 static int zsc_print(void *, const char *);
93 int zscngetc(dev_t);
94 void zscnputc(dev_t, int);
96 static struct consdev zscons = {
97 NULL, NULL,
98 zscngetc, zscnputc, nullcnpollc, NULL, NULL, NULL,
99 NODEV, 1
102 void
103 zs_config(struct zsc_softc *zsc, char *base)
105 struct zsc_attach_args zsc_args;
106 struct zs_chanstate *cs;
107 int zsc_unit, channel, s;
109 zsc_unit = device_unit(zsc->zsc_dev);
110 aprint_normal(": Zilog 8530 SCC\n");
113 * Initialize software state for each channel.
115 for (channel = 0; channel < 2; channel++) {
116 zsc_args.channel = channel;
117 zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
120 * If we're the console, copy the channel state, and
121 * adjust the console channel pointer.
123 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) {
124 cs = &zs_conschan_store;
125 } else {
126 cs = malloc(sizeof(struct zs_chanstate),
127 M_DEVBUF, M_NOWAIT | M_ZERO);
128 if(channel==0){
129 cs->cs_reg_csr = base + 7;
130 cs->cs_reg_data = base + 15;
131 } else {
132 cs->cs_reg_csr = base + 3;
133 cs->cs_reg_data = base + 11;
135 memcpy(cs->cs_creg, zs_init_reg, 16);
136 memcpy(cs->cs_preg, zs_init_reg, 16);
137 cs->cs_defspeed = 9600;
139 zsc->zsc_cs[channel] = cs;
140 zs_lock_init(cs);
142 cs->cs_defcflag = CREAD | CS8 | HUPCL;
144 /* Make these correspond to cs_defcflag (-crtscts) */
145 cs->cs_rr0_dcd = ZSRR0_DCD;
146 cs->cs_rr0_cts = 0;
147 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
148 cs->cs_wr5_rts = 0;
150 cs->cs_channel = channel;
151 cs->cs_private = NULL;
152 cs->cs_ops = &zsops_null;
153 cs->cs_brg_clk = 4000000 / 16;
156 * Clear the master interrupt enable.
157 * The INTENA is common to both channels,
158 * so just do it on the A channel.
160 if (channel == 0) {
161 zs_write_reg(cs, 9, 0);
165 * Look for a child driver for this channel.
166 * The child attach will setup the hardware.
168 if (!config_found(zsc->zsc_dev, (void *)&zsc_args,
169 zsc_print)) {
170 /* No sub-driver. Just reset it. */
171 uint8_t reset = (channel == 0) ?
172 ZSWR9_A_RESET : ZSWR9_B_RESET;
173 s = splzs();
174 zs_write_reg(cs, 9, reset);
175 splx(s);
180 static int
181 zsc_print(void *aux, const char *name)
183 struct zsc_attach_args *args = aux;
185 if (name != NULL)
186 aprint_normal("%s: ", name);
188 if (args->channel != -1)
189 aprint_normal(" channel %d", args->channel);
191 return UNCONF;
195 zshard(void *arg)
197 struct zsc_softc *zsc;
198 int unit, rval;
200 rval = 0;
201 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
202 zsc = device_lookup_private(&zsc_cd, unit);
203 if (zsc == NULL)
204 continue;
205 rval |= zsc_intr_hard(zsc);
206 if ((zsc->zsc_cs[0]->cs_softreq) ||
207 (zsc->zsc_cs[1]->cs_softreq)) {
208 softint_schedule(zsc->zsc_softintr_cookie);
211 return (rval);
214 uint8_t
215 zs_read_reg(struct zs_chanstate *cs, uint8_t reg)
217 uint8_t val;
219 *cs->cs_reg_csr = reg;
220 ZS_DELAY();
221 val = *cs->cs_reg_csr;
222 ZS_DELAY();
223 return val;
226 void
227 zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val)
229 *cs->cs_reg_csr = reg;
230 ZS_DELAY();
231 *cs->cs_reg_csr = val;
232 ZS_DELAY();
235 uint8_t
236 zs_read_csr(struct zs_chanstate *cs)
238 uint8_t val;
240 val = *cs->cs_reg_csr;
241 ZS_DELAY();
242 return val;
245 void
246 zs_write_csr(struct zs_chanstate *cs, uint8_t val)
249 *cs->cs_reg_csr = val;
250 ZS_DELAY();
253 uint8_t
254 zs_read_data(struct zs_chanstate *cs)
256 uint8_t val;
258 val = *cs->cs_reg_data;
259 ZS_DELAY();
260 return val;
263 void
264 zs_write_data(struct zs_chanstate *cs, uint8_t val)
267 *cs->cs_reg_data = val;
268 ZS_DELAY();
272 zs_set_speed(struct zs_chanstate *cs, int bps)
274 int tconst, real_bps;
276 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
278 if (tconst < 0)
279 return (EINVAL);
281 /* Convert back to make sure we can do it. */
282 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
283 #if 0
284 /* XXX - Allow some tolerance here? */
285 if (real_bps != bps)
286 return (EINVAL);
287 #endif
288 cs->cs_preg[12] = tconst;
289 cs->cs_preg[13] = tconst >> 8;
291 return (0);
295 zs_set_modes(struct zs_chanstate *cs, int cflag)
297 int s;
300 * Output hardware flow control on the chip is horrendous:
301 * if carrier detect drops, the receiver is disabled, and if
302 * CTS drops, the transmitter is stoped IN MID CHARACTER!
303 * Therefore, NEVER set the HFC bit, and instead use the
304 * status interrupt to detect CTS changes.
306 s = splzs();
307 #if 0 /* XXX - See below. */
308 if (cflag & CLOCAL) {
309 cs->cs_rr0_dcd = 0;
310 cs->cs_preg[15] &= ~ZSWR15_DCD_IE;
311 } else {
312 /* XXX - Need to notice DCD change here... */
313 cs->cs_rr0_dcd = ZSRR0_DCD;
314 cs->cs_preg[15] |= ZSWR15_DCD_IE;
316 #endif /* XXX */
317 if (cflag & CRTSCTS) {
318 cs->cs_wr5_dtr = ZSWR5_DTR;
319 cs->cs_wr5_rts = ZSWR5_RTS;
320 cs->cs_rr0_cts = ZSRR0_CTS;
321 cs->cs_preg[15] |= ZSWR15_CTS_IE;
322 } else {
323 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
324 cs->cs_wr5_rts = 0;
325 cs->cs_rr0_cts = 0;
326 cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
328 splx(s);
330 /* Caller will stuff the pending registers. */
331 return (0);
335 * Handle user request to enter kernel debugger.
337 void
338 zs_abort(struct zs_chanstate *cs)
340 int rr0;
342 /* Wait for end of break to avoid PROM abort. */
343 /* XXX - Limit the wait? */
344 do {
345 rr0 = *cs->cs_reg_csr;
346 ZS_DELAY();
347 } while (rr0 & ZSRR0_BREAK);
348 #ifdef DDB
349 console_debugger();
350 #endif
354 * Polled input char.
357 zs_getc(void *arg)
359 struct zs_chanstate *cs = arg;
360 int s, c;
361 uint8_t rr0, stat;
363 s = splhigh();
364 top:
365 /* Wait for a character to arrive. */
366 do {
367 rr0 = *cs->cs_reg_csr;
368 ZS_DELAY();
369 } while ((rr0 & ZSRR0_RX_READY) == 0);
371 /* Read error register. */
372 stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE);
373 if (stat) {
374 zs_write_csr(cs, ZSM_RESET_ERR);
375 goto top;
378 /* Read character. */
379 c = *cs->cs_reg_data;
380 ZS_DELAY();
381 splx(s);
383 return (c);
387 * Polled output char.
389 void
390 zs_putc(void *arg, int c)
392 struct zs_chanstate *cs = arg;
393 int s;
394 uint8_t rr0;
396 s = splhigh();
397 /* Wait for transmitter to become ready. */
398 do {
399 rr0 = *cs->cs_reg_csr;
400 ZS_DELAY();
401 } while ((rr0 & ZSRR0_TX_READY) == 0);
403 *cs->cs_reg_data = c;
404 ZS_DELAY();
405 splx(s);
409 zscngetc(dev_t dev)
411 struct zs_chanstate *cs = &zs_conschan_store;
412 int c;
414 c = zs_getc(cs);
415 return (c);
418 void
419 zscnputc(dev_t dev, int c)
421 struct zs_chanstate *cs = &zs_conschan_store;
423 zs_putc(cs, c);
427 * Common parts of console init.
429 void
430 zs_cninit(void *base)
432 struct zs_chanstate *cs;
434 * Pointer to channel state. Later, the console channel
435 * state is copied into the softc, and the console channel
436 * pointer adjusted to point to the new copy.
438 cs = &zs_conschan_store;
439 zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE;
441 /* Setup temporary chanstate. */
442 cs->cs_reg_csr = (uint8_t *)base + 7;
443 cs->cs_reg_data = (uint8_t *)base + 15;
445 /* Initialize the pending registers. */
446 memcpy(cs->cs_preg, zs_init_reg, 16);
447 cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
449 /* XXX: Preserve BAUD rate from boot loader. */
450 /* XXX: Also, why reset the chip here? -gwr */
451 /* cs->cs_defspeed = zs_get_speed(cs); */
452 cs->cs_defspeed = 9600; /* XXX */
454 /* Clear the master interrupt enable. */
455 zs_write_reg(cs, 9, 0);
457 /* Reset the whole SCC chip. */
458 zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
460 /* Copy "pending" to "current" and H/W. */
461 zs_loadchannelregs(cs);
463 /* Point the console at the SCC. */
464 cn_tab = &zscons;