1 /* $NetBSD: zs.c,v 1.32 2008/04/28 20:23:30 martin Exp $ */
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
37 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
40 /* This was snarfed from the netbsd sparc/dev/zs.c at version 1.56
41 * and then updated to reflect changes in 1.59
42 * by Darrin B Jewell <jewell@mit.edu> Mon Mar 30 20:24:46 1998
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.32 2008/04/28 20:23:30 martin Exp $");
50 #include "opt_serial.h"
52 #include <sys/param.h>
53 #include <sys/systm.h>
55 #include <sys/device.h>
57 #include <sys/ioctl.h>
58 #include <sys/kernel.h>
62 #include <sys/syslog.h>
66 #include <machine/autoconf.h>
67 #include <machine/psl.h>
71 #include <dev/ic/z8530reg.h>
72 #include <machine/z8530var.h>
74 #include <next68k/next68k/isr.h>
76 #include <next68k/dev/intiovar.h>
77 #include <next68k/dev/zs_cons.h>
80 #include "zsc.h" /* NZSC */
83 #error "No serial controllers?"
87 * Some warts needed by z8530tty.c -
88 * The default parity REALLY needs to be the same as the PROM uses,
89 * or you can not see messages done with printf during boot-up...
91 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
94 * The NeXT provides a 3.686400 MHz clock to the ZS chips.
96 #define PCLK (9600 * 384) /* PCLK pin input clock rate */
98 #define ZS_DELAY() delay(2)
100 /* The layout of this is hardware-dependent (padding, order). */
102 volatile uint8_t zc_csr
; /* ctrl,status, and indirect access */
104 volatile uint8_t zc_data
; /* data */
108 /* Flags from cninit() */
109 static int zs_hwflags
[2];
111 /* Default speed for each channel */
112 static int zs_defspeed
[2] = {
117 static uint8_t zs_init_reg
[16] = {
118 0, /* 0: CMD (reset, etc.) */
119 0, /* 1: No interrupts yet. */
120 0x18 + NEXT_I_IPL(NEXT_I_SCC
), /* 2: IVECT */
121 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
,
122 ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_EVENP
,
123 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
,
124 0, /* 6: TXSYNC/SYNCLO */
125 0, /* 7: RXSYNC/SYNCHI */
126 0, /* 8: alias for data port */
128 0, /*10: Misc. TX/RX control bits */
129 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
,
130 ((PCLK
/32)/9600)-2, /*12: BAUDLO (default=9600) */
131 0, /*13: BAUDHI (default=9600) */
132 ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
,
137 zs_get_chan_addr(int channel
)
142 addr
= (void *)IIOV(NEXT_P_SCC
);
144 /* handle the fact the ports are intertwined. */
145 zc
= (struct zschan
*)(addr
+ 1);
147 zc
= (struct zschan
*)(addr
);
153 /****************************************************************
155 ****************************************************************/
157 /* Definition of the driver for autoconfig. */
158 static int zs_match(device_t
, cfdata_t
, void *);
159 static void zs_attach(device_t
, device_t
, void *);
160 static int zs_print(void *, const char *);
162 extern int zs_getc(void *);
163 extern void zs_putc(void *, int);
165 CFATTACH_DECL_NEW(zsc
, sizeof(struct zsc_softc
),
166 zs_match
, zs_attach
, NULL
, NULL
);
168 static int zs_attached
;
170 /* Interrupt handlers. */
171 static int zshard(void *);
173 static int zs_get_speed(struct zs_chanstate
*);
176 * Is the zs chip present?
179 zs_match(device_t parent
, cfdata_t cf
, void *aux
)
181 struct intio_attach_args
*ia
= aux
;
186 ia
->ia_addr
= (void *)IIOV(NEXT_P_SCC
);
194 * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR
195 * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE?
198 zs_attach(device_t parent
, device_t self
, void *aux
)
200 struct zsc_softc
*zsc
= device_private(self
);
201 struct zsc_attach_args zsc_args
;
202 volatile struct zschan
*zc
;
203 struct zs_chanstate
*cs
;
212 * Initialize software state for each channel.
214 for (channel
= 0; channel
< 2; channel
++) {
215 zsc_args
.channel
= channel
;
216 zsc_args
.hwflags
= zs_hwflags
[channel
];
217 cs
= &zsc
->zsc_cs_store
[channel
];
218 zsc
->zsc_cs
[channel
] = cs
;
221 cs
->cs_channel
= channel
;
222 cs
->cs_private
= NULL
;
223 cs
->cs_ops
= &zsops_null
;
224 cs
->cs_brg_clk
= PCLK
/ 16;
226 zc
= zs_get_chan_addr(channel
);
227 cs
->cs_reg_csr
= &zc
->zc_csr
;
228 cs
->cs_reg_data
= &zc
->zc_data
;
230 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
231 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
233 /* XXX: Get these from the PROM properties! */
234 /* XXX: See the mvme167 code. Better. */
235 if (zsc_args
.hwflags
& ZS_HWFLAG_CONSOLE
)
236 cs
->cs_defspeed
= zs_get_speed(cs
);
238 cs
->cs_defspeed
= zs_defspeed
[channel
];
239 cs
->cs_defcflag
= zs_def_cflag
;
241 /* Make these correspond to cs_defcflag (-crtscts) */
242 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
244 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
248 * Clear the master interrupt enable.
249 * The INTENA is common to both channels,
250 * so just do it on the A channel.
253 zs_write_reg(cs
, 9, 0);
257 * Look for a child driver for this channel.
258 * The child attach will setup the hardware.
260 if (!config_found(self
, (void *)&zsc_args
, zs_print
)) {
261 /* No sub-driver. Just reset it. */
262 uint8_t reset
= (channel
== 0) ?
263 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
265 zs_write_reg(cs
, 9, reset
);
270 isrlink_autovec(zshard
, NULL
, NEXT_I_IPL(NEXT_I_SCC
), 0, NULL
);
271 zsc
->zsc_softintr_cookie
= softint_establish(SOFTINT_SERIAL
,
272 (void (*)(void *))zsc_intr_soft
, zsc
);
273 INTR_ENABLE(NEXT_I_SCC
);
276 * Set the master interrupt enable and interrupt vector.
277 * (common to both channels, do it on A)
281 /* interrupt vector */
282 zs_write_reg(cs
, 2, zs_init_reg
[2]);
283 /* master interrupt control (enable) */
284 zs_write_reg(cs
, 9, zs_init_reg
[9]);
289 zs_print(void *aux
, const char *name
)
291 struct zsc_attach_args
*args
= aux
;
294 aprint_normal("%s: ", name
);
296 if (args
->channel
!= -1)
297 aprint_normal(" channel %d", args
->channel
);
302 static volatile int zssoftpending
;
305 * Our ZS chips all share a common, autovectored interrupt,
306 * so we have to look at all of them on each interrupt.
311 struct zsc_softc
*zsc
;
314 if (!INTR_OCCURRED(NEXT_I_SCC
))
318 for (unit
= 0; unit
< zsc_cd
.cd_ndevs
; unit
++) {
319 zsc
= device_lookup_private(&zsc_cd
, unit
);
322 rr3
= zsc_intr_hard(zsc
);
323 /* Count up the interrupts. */
326 zsc
->zsc_intrcnt
.ev_count
++;
328 /* We are at splzs here, so no need to lock. */
329 if (zsc
->zsc_cs
[0]->cs_softreq
|| zsc
->zsc_cs
[1]->cs_softreq
)
330 softint_schedule(zsc
->zsc_softintr_cookie
);
337 * Compute the current baud rate given a ZS channel.
340 zs_get_speed(struct zs_chanstate
*cs
)
344 tconst
= zs_read_reg(cs
, 12);
345 tconst
|= zs_read_reg(cs
, 13) << 8;
346 return (TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
));
350 * MD functions for setting the baud rate and control modes.
353 zs_set_speed(struct zs_chanstate
*cs
, int bps
)
355 int tconst
, real_bps
;
361 if (cs
->cs_brg_clk
== 0)
362 panic("zs_set_speed");
365 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, bps
);
369 /* Convert back to make sure we can do it. */
370 real_bps
= TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
372 /* XXX - Allow some tolerance here? */
376 cs
->cs_preg
[12] = tconst
;
377 cs
->cs_preg
[13] = tconst
>> 8;
379 /* Caller will stuff the pending registers. */
384 zs_set_modes(struct zs_chanstate
*cs
, int cflag
)
389 * Output hardware flow control on the chip is horrendous:
390 * if carrier detect drops, the receiver is disabled, and if
391 * CTS drops, the transmitter is stoped IN MID CHARACTER!
392 * Therefore, NEVER set the HFC bit, and instead use the
393 * status interrupt to detect CTS changes.
397 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0) {
399 if ((cflag
& MDMBUF
) == 0)
400 cs
->cs_rr0_pps
= ZSRR0_DCD
;
402 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
403 if ((cflag
& CRTSCTS
) != 0) {
404 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
405 cs
->cs_wr5_rts
= ZSWR5_RTS
;
406 cs
->cs_rr0_cts
= ZSRR0_CTS
;
407 } else if ((cflag
& CDTRCTS
) != 0) {
409 cs
->cs_wr5_rts
= ZSWR5_DTR
;
410 cs
->cs_rr0_cts
= ZSRR0_CTS
;
411 } else if ((cflag
& MDMBUF
) != 0) {
413 cs
->cs_wr5_rts
= ZSWR5_DTR
;
414 cs
->cs_rr0_cts
= ZSRR0_DCD
;
416 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
422 /* Caller will stuff the pending registers. */
427 * Read or write the chip with suitable delays.
431 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
435 *cs
->cs_reg_csr
= reg
;
437 val
= *cs
->cs_reg_csr
;
443 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
445 *cs
->cs_reg_csr
= reg
;
447 *cs
->cs_reg_csr
= val
;
452 zs_read_csr(struct zs_chanstate
*cs
)
456 val
= *cs
->cs_reg_csr
;
462 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
464 *cs
->cs_reg_csr
= val
;
469 zs_read_data(struct zs_chanstate
*cs
)
473 val
= *cs
->cs_reg_data
;
479 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
481 *cs
->cs_reg_data
= val
;
485 /****************************************************************
486 * Console support functions (Sun specific!)
487 * Note: this code is allowed to know about the layout of
488 * the chip registers, and uses that to keep things simple.
489 * XXX - I think I like the mvme167 code better. -gwr
490 ****************************************************************/
492 extern void Debugger(void);
497 * Handle user request to enter kernel debugger.
500 zs_abort(struct zs_chanstate
*cs
)
502 #if defined(ZS_CONSOLE_ABORT)
503 volatile struct zschan
*zc
= zs_conschan
;
506 /* Wait for end of break to avoid PROM abort. */
507 /* XXX - Limit the wait? */
511 } while (rr0
& ZSRR0_BREAK
);
518 /* XXX eventually, drop into next rom monitor here */
519 printf("stopping on keyboard abort not supported without DDB or KGDB\n");
521 #else /* !ZS_CONSOLE_ABORT */
532 volatile struct zschan
*zc
= arg
;
536 /* Wait for a character to arrive. */
540 } while ((rr0
& ZSRR0_RX_READY
) == 0);
547 * This is used by the kd driver to read scan codes,
548 * so don't translate '\r' ==> '\n' here...
554 * Polled output char.
557 zs_putc(void *arg
, int c
)
559 volatile struct zschan
*zc
= arg
;
563 /* Wait for transmitter to become ready. */
567 } while ((rr0
& ZSRR0_TX_READY
) == 0);
576 /*****************************************************************/
578 void zscninit(struct consdev
*);
580 void zscnputc(dev_t
, int);
581 void zscnprobe(struct consdev
*);
584 zscnprobe(struct consdev
*cp
)
586 extern const struct cdevsw zstty_cdevsw
;
589 maj
= cdevsw_lookup_major(&zstty_cdevsw
);
592 cp
->cn_pri
= CN_REMOTE
;
594 cp
->cn_pri
= CN_NORMAL
; /* Lower than CN_INTERNAL */
597 cp
->cn_dev
= makedev(maj
, zs_consunit
);
598 zs_conschan
= zs_get_chan_addr(zs_consunit
);
600 cp
->cn_pri
= CN_DEAD
;
605 zscninit(struct consdev
*cn
)
607 struct zs_chanstate xcs
;
608 struct zs_chanstate
*cs
;
609 volatile struct zschan
*zc
;
612 zs_hwflags
[zs_consunit
] = ZS_HWFLAG_CONSOLE
;
614 /* Setup temporary chanstate. */
615 memset(&xcs
, 0, sizeof(xcs
));
618 cs
->cs_reg_csr
= &zc
->zc_csr
;
619 cs
->cs_reg_data
= &zc
->zc_data
;
620 cs
->cs_channel
= zs_consunit
;
621 cs
->cs_brg_clk
= PCLK
/ 16;
623 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
624 cs
->cs_preg
[5] |= ZSWR5_DTR
| ZSWR5_RTS
;
625 cs
->cs_preg
[15] = ZSWR15_BREAK_IE
;
627 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, zs_defspeed
[zs_consunit
]);
628 cs
->cs_preg
[12] = tconst
;
629 cs
->cs_preg
[13] = tconst
>> 8;
632 * can't use zs_set_speed as we haven't set up the
633 * signal sources, and it's not worth it for now
636 cs
->cs_preg
[9] &= ~ZSWR9_MASTER_IE
;
637 /* no interrupts until later, after attach. */
640 zs_loadchannelregs(cs
);
643 printf("\nNetBSD/next68k console\n");
647 * Polled console input putchar.
652 return (zs_getc(zs_conschan
));
656 * Polled console output putchar.
659 zscnputc(dev_t dev
, int c
)
661 zs_putc(zs_conschan
, c
);
664 /*****************************************************************/