1 /* $NetBSD: zs.c,v 1.39 2008/12/18 05:56:42 isaki Exp $ */
4 * Copyright (c) 1998 Minoura Makoto
5 * Copyright (c) 1996 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Zilog Z8530 Dual UART driver (machine-dependent part)
36 * X68k uses one Z8530 built-in. Channel A is for RS-232C serial port;
37 * while channel B is dedicated to the mouse.
38 * Extra Z8530's can be installed for serial ports. This driver
39 * supports up to 5 chips including the built-in one.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.39 2008/12/18 05:56:42 isaki Exp $");
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/device.h>
50 #include <sys/ioctl.h>
51 #include <sys/kernel.h>
55 #include <sys/syslog.h>
60 #include <arch/x68k/dev/intiovar.h>
61 #include <machine/z8530var.h>
63 #include <dev/ic/z8530reg.h>
66 #include "zsc.h" /* NZSC */
69 #define ZSCN_SPEED 9600
74 extern void Debugger(void);
77 * Some warts needed by z8530tty.c -
78 * The default parity REALLY needs to be the same as the PROM uses,
79 * or you can not see messages done with printf during boot-up...
81 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
82 int zscn_def_cflag
= (CREAD
| CS8
| HUPCL
);
85 * X68k provides a 5.0 MHz clock to the ZS chips.
87 #define PCLK (5 * 1000 * 1000) /* PCLK pin input clock rate */
90 /* Default physical addresses. */
92 static bus_addr_t zs_physaddr
[ZS_MAXDEV
] = {
100 static uint8_t zs_init_reg
[16] = {
101 0, /* 0: CMD (reset, etc.) */
102 0, /* 1: No interrupts yet. */
103 0x70, /* 2: XXX: IVECT */
104 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
,
105 ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_EVENP
,
106 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
,
107 0, /* 6: TXSYNC/SYNCLO */
108 0, /* 7: RXSYNC/SYNCHI */
109 0, /* 8: alias for data port */
111 ZSWR10_NRZ
, /*10: Misc. TX/RX control bits */
112 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
,
113 ((PCLK
/32)/9600)-2, /*12: BAUDLO (default=9600) */
114 0, /*13: BAUDHI (default=9600) */
115 ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
,
119 static volatile struct zschan
*conschan
= 0;
122 /****************************************************************
124 ****************************************************************/
126 /* Definition of the driver for autoconfig. */
127 static int zs_match(device_t
, cfdata_t
, void *);
128 static void zs_attach(device_t
, device_t
, void *);
129 static int zs_print(void *, const char *name
);
131 CFATTACH_DECL_NEW(zsc
, sizeof(struct zsc_softc
),
132 zs_match
, zs_attach
, NULL
, NULL
);
134 static int zshard(void *);
135 static int zs_get_speed(struct zs_chanstate
*);
139 * Is the zs chip present?
142 zs_match(device_t parent
, cfdata_t cf
, void *aux
)
144 struct intio_attach_args
*ia
= aux
;
145 struct zsdevice
*zsaddr
= (void *)ia
->ia_addr
;
148 if (strcmp(ia
->ia_name
, "zsc") != 0)
151 for (i
= 0; i
< ZS_MAXDEV
; i
++)
152 if (zsaddr
== (void *)zs_physaddr
[i
]) /* XXX */
156 if (intio_map_allocate_region(parent
, ia
, INTIO_MAP_TESTONLY
))
159 if (zsaddr
!= (void *)zs_physaddr
[i
])
161 if (badaddr((void *)IIOV(zsaddr
)))
171 zs_attach(device_t parent
, device_t self
, void *aux
)
173 struct zsc_softc
*zsc
= device_private(self
);
174 struct intio_attach_args
*ia
= aux
;
175 struct zsc_attach_args zsc_args
;
176 volatile struct zschan
*zc
;
177 struct zs_chanstate
*cs
;
178 int r
, s
, zs_unit
, channel
;
183 zs_unit
= device_unit(self
);
184 zsc
->zsc_addr
= (void *)ia
->ia_addr
;
187 r
= intio_map_allocate_region(parent
, ia
, INTIO_MAP_ALLOCATE
);
190 panic("zs: intio IO map corruption");
194 * Initialize software state for each channel.
196 for (channel
= 0; channel
< 2; channel
++) {
199 zsc_args
.channel
= channel
;
200 zsc_args
.hwflags
= 0;
201 cs
= &zsc
->zsc_cs_store
[channel
];
202 zsc
->zsc_cs
[channel
] = cs
;
205 cs
->cs_channel
= channel
;
206 cs
->cs_private
= NULL
;
207 cs
->cs_ops
= &zsops_null
;
208 cs
->cs_brg_clk
= PCLK
/ 16;
211 zc
= (volatile void *)IIOV(&zsc
->zsc_addr
->zs_chan_a
);
213 zc
= (volatile void *)IIOV(&zsc
->zsc_addr
->zs_chan_b
);
214 cs
->cs_reg_csr
= &zc
->zc_csr
;
215 cs
->cs_reg_data
= &zc
->zc_data
;
217 zs_init_reg
[2] = ia
->ia_intr
;
218 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
219 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
221 if (zc
== conschan
) {
222 zsc_args
.hwflags
|= ZS_HWFLAG_CONSOLE
;
223 cs
->cs_defspeed
= zs_get_speed(cs
);
224 cs
->cs_defcflag
= zscn_def_cflag
;
226 cs
->cs_defspeed
= 9600;
227 cs
->cs_defcflag
= zs_def_cflag
;
230 /* Make these correspond to cs_defcflag (-crtscts) */
231 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
233 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
237 * Clear the master interrupt enable.
238 * The INTENA is common to both channels,
239 * so just do it on the A channel.
243 zs_write_reg(cs
, 9, 0);
248 * Look for a child driver for this channel.
249 * The child attach will setup the hardware.
251 child
= config_found(self
, (void *)&zsc_args
, zs_print
);
253 if (zc
== conschan
&&
254 ((child
&& strcmp(device_xname(child
), "zstty0")) ||
255 child
== NULL
)) /* XXX */
256 panic("%s: console device mismatch", __func__
);
259 /* No sub-driver. Just reset it. */
260 uint8_t reset
= (channel
== 0) ?
261 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
263 zs_write_reg(cs
, 9, reset
);
269 * Now safe to install interrupt handlers.
271 if (intio_intr_establish(ia
->ia_intr
, "zs", zshard
, zsc
))
272 panic("%s: interrupt vector busy", __func__
);
273 zsc
->zsc_softintr_cookie
= softint_establish(SOFTINT_SERIAL
,
274 (void (*)(void *))zsc_intr_soft
, zsc
);
275 /* XXX; evcnt_attach() ? */
278 * Set the master interrupt enable and interrupt vector.
279 * (common to both channels, do it on A)
283 /* interrupt vector */
284 zs_write_reg(cs
, 2, ia
->ia_intr
);
285 /* master interrupt control (enable) */
286 zs_write_reg(cs
, 9, zs_init_reg
[9]);
291 zs_print(void *aux
, const char *name
)
293 struct zsc_attach_args
*args
= aux
;
296 aprint_normal("%s: ", name
);
298 if (args
->channel
!= -1)
299 aprint_normal(" channel %d", args
->channel
);
306 * For x68k-port, we don't use autovectored interrupt.
307 * We do not need to look at all of the zs chips.
312 struct zsc_softc
*zsc
= arg
;
317 * Actually, zs hardware ipl is 5.
318 * Here we disable all interrupts to shorten the zshard
319 * handling time. Otherwise, too many characters are
323 rval
= zsc_intr_hard(zsc
);
325 /* We are at splzs here, so no need to lock. */
326 if (zsc
->zsc_cs
[0]->cs_softreq
|| zsc
->zsc_cs
[1]->cs_softreq
)
327 softint_schedule(zsc
->zsc_softintr_cookie
);
333 * Compute the current baud rate given a ZS channel.
336 zs_get_speed(struct zs_chanstate
*cs
)
340 tconst
= zs_read_reg(cs
, 12);
341 tconst
|= zs_read_reg(cs
, 13) << 8;
342 return (TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
));
346 * MD functions for setting the baud rate and control modes.
349 zs_set_speed(struct zs_chanstate
*cs
, int bps
/* bits per second */)
351 int tconst
, real_bps
;
357 if (cs
->cs_brg_clk
== 0)
358 panic("zs_set_speed");
361 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, bps
);
365 /* Convert back to make sure we can do it. */
366 real_bps
= TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
369 /* XXX - Allow some tolerance here? */
374 * Since our PCLK has somewhat strange value,
375 * we have to allow tolerance here.
377 if (BPS_TO_TCONST(cs
->cs_brg_clk
, real_bps
) != tconst
)
381 cs
->cs_preg
[12] = tconst
;
382 cs
->cs_preg
[13] = tconst
>> 8;
384 /* Caller will stuff the pending registers. */
389 zs_set_modes(struct zs_chanstate
*cs
, int cflag
/* bits per second */)
394 * Output hardware flow control on the chip is horrendous:
395 * if carrier detect drops, the receiver is disabled, and if
396 * CTS drops, the transmitter is stoped IN MID CHARACTER!
397 * Therefore, NEVER set the HFC bit, and instead use the
398 * status interrupt to detect CTS changes.
402 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0) {
404 if ((cflag
& MDMBUF
) == 0)
405 cs
->cs_rr0_pps
= ZSRR0_DCD
;
407 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
408 if ((cflag
& CRTSCTS
) != 0) {
409 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
410 cs
->cs_wr5_rts
= ZSWR5_RTS
;
411 cs
->cs_rr0_cts
= ZSRR0_CTS
;
412 } else if ((cflag
& MDMBUF
) != 0) {
414 cs
->cs_wr5_rts
= ZSWR5_DTR
;
415 cs
->cs_rr0_cts
= ZSRR0_DCD
;
417 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
423 /* Caller will stuff the pending registers. */
429 * Read or write the chip with suitable delays.
433 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
437 *cs
->cs_reg_csr
= reg
;
439 val
= *cs
->cs_reg_csr
;
445 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
447 *cs
->cs_reg_csr
= reg
;
449 *cs
->cs_reg_csr
= val
;
454 zs_read_csr(struct zs_chanstate
*cs
)
458 val
= *cs
->cs_reg_csr
;
464 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
466 *cs
->cs_reg_csr
= val
;
471 zs_read_data(struct zs_chanstate
*cs
)
475 val
= *cs
->cs_reg_data
;
481 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
483 *cs
->cs_reg_data
= val
;
488 /****************************************************************
489 * Console support functions (x68k specific!)
490 * Note: this code is allowed to know about the layout of
491 * the chip registers, and uses that to keep things simple.
492 * XXX - I think I like the mvme167 code better. -gwr
493 ****************************************************************/
496 * Handle user request to enter kernel debugger.
499 zs_abort(struct zs_chanstate
*cs
)
503 /* Wait for end of break to avoid PROM abort. */
504 /* XXX - Limit the wait? */
506 rr0
= *cs
->cs_reg_csr
;
508 } while (rr0
& ZSRR0_BREAK
);
520 #include <dev/cons.h>
523 static int zs_getc(void);
524 static void zs_putc(int);
526 static struct zs_chanstate zscn_cs
;
537 /* Wait for a character to arrive. */
539 rr0
= zs_read_csr(&zscn_cs
);
540 } while ((rr0
& ZSRR0_RX_READY
) == 0);
542 c
= zs_read_data(&zscn_cs
);
546 * This is used by the kd driver to read scan codes,
547 * so don't translate '\r' ==> '\n' here...
553 * Polled output char.
561 /* Wait for transmitter to become ready. */
563 rr0
= zs_read_csr(&zscn_cs
);
564 } while ((rr0
& ZSRR0_TX_READY
) == 0);
566 zs_write_data(&zscn_cs
, c
);
571 zscninit(struct consdev
*cn
)
573 volatile struct zschan
*cnchan
= (volatile void *)IIOV(ZSCN_PHYSADDR
);
576 memset(&zscn_cs
, 0, sizeof(struct zs_chanstate
));
577 zscn_cs
.cs_reg_csr
= &cnchan
->zc_csr
;
578 zscn_cs
.cs_reg_data
= &cnchan
->zc_data
;
579 zscn_cs
.cs_channel
= 0;
580 zscn_cs
.cs_brg_clk
= PCLK
/ 16;
581 memcpy(zscn_cs
.cs_preg
, zs_init_reg
, 16);
582 zscn_cs
.cs_preg
[4] = ZSWR4_CLK_X16
| ZSWR4_ONESB
; /* XXX */
583 zscn_cs
.cs_preg
[9] = 0;
584 zs_set_speed(&zscn_cs
, ZSCN_SPEED
);
586 zs_loadchannelregs(&zscn_cs
);
592 * Polled console input putchar.
601 * Polled console output putchar.
604 zscnputc(dev_t dev
, int c
)
610 zscnprobe(struct consdev
*cd
)
613 extern const struct cdevsw zstty_cdevsw
;
615 /* locate the major number */
616 maj
= cdevsw_lookup_major(&zstty_cdevsw
);
617 /* XXX: minor number is 0 */
620 cd
->cn_pri
= CN_DEAD
;
623 cd
->cn_pri
= CN_REMOTE
; /* higher than ITE (CN_INTERNAL) */
625 cd
->cn_pri
= CN_NORMAL
;
627 cd
->cn_dev
= makedev(maj
, 0);
632 zscnpollc(dev_t dev
, int on
)