1 /* $NetBSD: zs.c,v 1.29 2008/03/29 19:15:35 tsutsui 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.
40 * news68k/dev/zs.c - based on {newsmips,x68k,mvme68k}/dev/zs.c
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.29 2008/03/29 19:15:35 tsutsui Exp $");
48 #include <sys/param.h>
49 #include <sys/systm.h>
51 #include <sys/device.h>
56 #include <machine/z8530var.h>
59 #include <dev/ic/z8530reg.h>
61 #include <news68k/dev/hbvar.h>
66 void zs_putc(void *, int);
69 * Some warts needed by z8530tty.c -
70 * The default parity REALLY needs to be the same as the PROM uses,
71 * or you can not see messages done with printf during boot-up...
73 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
76 * The news68k machines use three different clocks for the ZS chips.
79 #define PCLK0 (9600 * 416) /* news1700: 3.9936MHz */
80 #define PCLK1 (9600 * 512) /* news1200: 4.9152MHz */
81 #define PCLK2 (9600 * 384) /* external: 3.6864MHz */
83 static const u_int pclk
[NPCLK
] = {
90 * Define interrupt levels.
95 #define ZS_DELAY() /* delay(2) */
97 /* The layout of this is hardware-dependent (padding, order). */
99 volatile uint8_t zc_csr
; /* ctrl,status, and indirect access */
100 volatile uint8_t zc_data
; /* data */
103 /* Yes, they are backwards. */
104 struct zschan zs_chan_b
;
105 struct zschan zs_chan_a
;
108 /* Default speed for all channels */
109 static int zs_defspeed
= 9600;
111 /* console status from cninit */
112 static struct zs_chanstate zs_conschan_store
;
113 static struct zs_chanstate
*zs_conschan
;
114 static struct zschan
*zc_cons
;
116 static uint8_t zs_init_reg
[16] = {
117 0, /* 0: CMD (reset, etc.) */
118 0, /* 1: No interrupts yet. */
119 ZS_IVECT
, /* IVECT */
120 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
,
121 ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_EVENP
,
122 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
,
123 0, /* 6: TXSYNC/SYNCLO */
124 0, /* 7: RXSYNC/SYNCHI */
125 0, /* 8: alias for data port */
127 0, /*10: Misc. TX/RX control bits */
128 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
,
129 BPS_TO_TCONST((PCLK0
/16), 9600), /*12: BAUDLO (default=9600) */
130 0, /*13: BAUDHI (default=9600) */
131 ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
,
136 /****************************************************************
138 ****************************************************************/
140 /* Definition of the driver for autoconfig. */
141 static int zs_match(device_t
, cfdata_t
, void *);
142 static void zs_attach(device_t
, device_t
, void *);
143 static int zs_print(void *, const char *name
);
145 CFATTACH_DECL_NEW(zsc
, sizeof(struct zsc_softc
),
146 zs_match
, zs_attach
, NULL
, NULL
);
148 static int zshard(void *);
150 static int zs_get_speed(struct zs_chanstate
*);
154 * Is the zs chip present?
157 zs_match(device_t parent
, cfdata_t cf
, void *aux
)
159 struct hb_attach_args
*ha
= aux
;
162 if (strcmp(ha
->ha_name
, "zsc"))
165 /* XXX no default address */
166 if (ha
->ha_address
== (u_int
)-1)
169 addr
= IIOV(ha
->ha_address
);
170 /* This returns -1 on a fault (bus error). */
171 if (badaddr((void *)addr
, 1))
181 zs_attach(device_t parent
, device_t self
, void *aux
)
183 struct zsc_softc
*zsc
= device_private(self
);
184 struct cfdata
*cf
= device_cfdata(self
);
185 struct hb_attach_args
*ha
= aux
;
186 struct zsc_attach_args zsc_args
;
189 struct zs_chanstate
*cs
;
194 zs
= (void *)IIOV(ha
->ha_address
);
197 if (clk
< 0 || clk
>= NPCLK
)
203 * Initialize software state for each channel.
205 for (channel
= 0; channel
< 2; channel
++) {
206 zsc_args
.channel
= channel
;
207 cs
= &zsc
->zsc_cs_store
[channel
];
209 zsc
->zsc_cs
[channel
] = cs
;
210 zc
= (channel
== 0) ? &zs
->zs_chan_a
: &zs
->zs_chan_b
;
212 if (ha
->ha_vect
!= -1)
213 zs_init_reg
[2] = ha
->ha_vect
;
216 memcpy(cs
, zs_conschan
, sizeof(struct zs_chanstate
));
218 zsc_args
.hwflags
= ZS_HWFLAG_CONSOLE
;
220 cs
->cs_reg_csr
= &zc
->zc_csr
;
221 cs
->cs_reg_data
= &zc
->zc_data
;
222 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
223 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
224 cs
->cs_defspeed
= zs_defspeed
;
225 zsc_args
.hwflags
= 0;
229 cs
->cs_defcflag
= zs_def_cflag
;
231 cs
->cs_channel
= channel
;
232 cs
->cs_private
= NULL
;
233 cs
->cs_ops
= &zsops_null
;
234 cs
->cs_brg_clk
= pclk
[clk
] / 16;
236 /* Make these correspond to cs_defcflag (-crtscts) */
237 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
239 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
243 * Clear the master interrupt enable.
244 * The INTENA is common to both channels,
245 * so just do it on the A channel.
249 zs_write_reg(cs
, 9, 0);
254 * Look for a child driver for this channel.
255 * The child attach will setup the hardware.
257 if (!config_found(self
, (void *)&zsc_args
, zs_print
)) {
258 /* No sub-driver. Just reset it. */
259 uint8_t reset
= (channel
== 0) ?
260 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
262 zs_write_reg(cs
, 9, reset
);
268 * Now safe to install interrupt handlers.
270 hb_intr_establish(zs_init_reg
[2], zshard
, ZSHARD_PRI
, zsc
);
271 zsc
->zsc_softintr_cookie
= softint_establish(SOFTINT_SERIAL
,
272 (void (*)(void *))zsc_intr_soft
, zsc
);
275 * Set the master interrupt enable and interrupt vector.
276 * (common to both channels, do it on A)
280 /* interrupt vector */
281 zs_write_reg(cs
, 2, zs_init_reg
[2]);
282 /* master interrupt control (enable) */
283 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
);
303 * For news68k-port, we don't use autovectored interrupt.
304 * We do not need to look at all of the zs chips.
309 struct zsc_softc
*zsc
= arg
;
312 rval
= zsc_intr_hard(zsc
);
314 /* We are at splzs here, so no need to lock. */
315 if (zsc
->zsc_cs
[0]->cs_softreq
|| zsc
->zsc_cs
[1]->cs_softreq
) {
316 softint_schedule(zsc
->zsc_softintr_cookie
);
323 * Compute the current baud rate given a ZS channel.
327 zs_get_speed(struct zs_chanstate
*cs
)
331 tconst
= zs_read_reg(cs
, 12);
332 tconst
|= zs_read_reg(cs
, 13) << 8;
333 return TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
338 * MD functions for setting the baud rate and control modes.
341 zs_set_speed(struct zs_chanstate
*cs
, int bps
)
343 int tconst
, real_bps
;
349 if (cs
->cs_brg_clk
== 0)
350 panic("zs_set_speed");
353 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, bps
);
357 /* Convert back to make sure we can do it. */
358 real_bps
= TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
360 /* XXX - Allow some tolerance here? */
364 cs
->cs_preg
[12] = tconst
;
365 cs
->cs_preg
[13] = tconst
>> 8;
367 /* Caller will stuff the pending registers. */
372 zs_set_modes(struct zs_chanstate
*cs
, int cflag
)
377 * Output hardware flow control on the chip is horrendous:
378 * if carrier detect drops, the receiver is disabled, and if
379 * CTS drops, the transmitter is stoped IN MID CHARACTER!
380 * Therefore, NEVER set the HFC bit, and instead use the
381 * status interrupt to detect CTS changes.
385 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0) {
387 if ((cflag
& MDMBUF
) == 0)
388 cs
->cs_rr0_pps
= ZSRR0_DCD
;
390 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
391 if ((cflag
& CRTSCTS
) != 0) {
392 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
393 cs
->cs_wr5_rts
= ZSWR5_RTS
;
394 cs
->cs_rr0_cts
= ZSRR0_CTS
;
395 } else if ((cflag
& MDMBUF
) != 0) {
397 cs
->cs_wr5_rts
= ZSWR5_DTR
;
398 cs
->cs_rr0_cts
= ZSRR0_DCD
;
400 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
406 /* Caller will stuff the pending registers. */
412 * Read or write the chip with suitable delays.
416 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
420 *cs
->cs_reg_csr
= reg
;
422 val
= *cs
->cs_reg_csr
;
428 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
431 *cs
->cs_reg_csr
= reg
;
433 *cs
->cs_reg_csr
= val
;
438 zs_read_csr(struct zs_chanstate
*cs
)
442 val
= *cs
->cs_reg_csr
;
448 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
451 *cs
->cs_reg_csr
= val
;
456 zs_read_data(struct zs_chanstate
*cs
)
460 val
= *cs
->cs_reg_data
;
466 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
469 *cs
->cs_reg_data
= val
;
474 zs_abort(struct zs_chanstate
*cs
)
488 struct zs_chanstate
*cs
= arg
;
492 /* Wait for a character to arrive. */
494 rr0
= *cs
->cs_reg_csr
;
496 } while ((rr0
& ZSRR0_RX_READY
) == 0);
498 c
= *cs
->cs_reg_data
;
506 * Polled output char.
509 zs_putc(void *arg
, int c
)
511 struct zs_chanstate
*cs
= arg
;
515 /* Wait for transmitter to become ready. */
517 rr0
= *cs
->cs_reg_csr
;
519 } while ((rr0
& ZSRR0_TX_READY
) == 0);
521 *cs
->cs_reg_data
= c
;
526 /*****************************************************************/
528 static void zscnprobe(struct consdev
*);
529 static void zscninit(struct consdev
*);
530 static int zscngetc(dev_t
);
531 static void zscnputc(dev_t
, int);
533 struct consdev consdev_zs
= {
547 zscnprobe(struct consdev
*cn
)
552 zscninit(struct consdev
*cn
)
554 struct zs_chanstate
*cs
;
556 extern const struct cdevsw zstty_cdevsw
;
557 extern int tty00_is_console
;
558 extern uint32_t sccport0a
;
560 cn
->cn_dev
= makedev(cdevsw_lookup_major(&zstty_cdevsw
), 0);
561 if (tty00_is_console
)
562 cn
->cn_pri
= CN_REMOTE
;
564 cn
->cn_pri
= CN_NORMAL
;
566 zc_cons
= (struct zschan
*)sccport0a
; /* XXX */
568 zs_conschan
= cs
= &zs_conschan_store
;
570 /* Setup temporary chanstate. */
571 cs
->cs_reg_csr
= &zc_cons
->zc_csr
;
572 cs
->cs_reg_data
= &zc_cons
->zc_data
;
574 /* Initialize the pending registers. */
575 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
576 cs
->cs_preg
[5] |= ZSWR5_DTR
| ZSWR5_RTS
;
578 cs
->cs_preg
[12] = BPS_TO_TCONST(pclk
[systype
] / 16, 9600); /* XXX */
580 cs
->cs_defspeed
= 9600;
582 /* Clear the master interrupt enable. */
583 zs_write_reg(cs
, 9, 0);
585 /* Reset the whole SCC chip. */
586 zs_write_reg(cs
, 9, ZSWR9_HARD_RESET
);
588 /* Copy "pending" to "current" and H/W */
589 zs_loadchannelregs(cs
);
596 return zs_getc((void *)zs_conschan
);
600 zscnputc(dev_t dev
, int c
)
603 zs_putc((void *)zs_conschan
, c
);