1 /* $NetBSD: zs.c,v 1.41 2008/06/13 12:26:02 cegger 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.
38 * Modified for NetBSD/mvme68k by Jason R. Thorpe <thorpej@NetBSD.org>
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.41 2008/06/13 12:26:02 cegger Exp $");
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #include <sys/device.h>
49 #include <sys/ioctl.h>
50 #include <sys/kernel.h>
54 #include <sys/syslog.h>
60 #include <dev/ic/z8530reg.h>
61 #include <machine/z8530var.h>
63 #include <mvme68k/dev/zsvar.h>
68 * Some warts needed by z8530tty.c -
69 * The default parity REALLY needs to be the same as the PROM uses,
70 * or you can not see messages done with printf during boot-up...
72 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
74 /* Flags from zscnprobe() */
75 static int zs_hwflags
[NZSC
][2];
77 /* Default speed for each channel */
78 static int zs_defspeed
[NZSC
][2] = {
85 static struct zs_chanstate zs_conschan_store
;
86 static struct zs_chanstate
*zs_conschan
;
88 uint8_t zs_init_reg
[16] = {
89 0, /* 0: CMD (reset, etc.) */
90 0, /* 1: No interrupts yet. */
91 0x18 + ZSHARD_PRI
, /* IVECT */
92 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
,
93 ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_EVENP
,
94 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
,
95 0, /* 6: TXSYNC/SYNCLO */
96 0, /* 7: RXSYNC/SYNCHI */
97 0, /* 8: alias for data port */
99 0, /*10: Misc. TX/RX control bits */
100 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
,
101 0, /*12: BAUDLO (default=9600) */
102 0, /*13: BAUDHI (default=9600) */
103 ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
,
108 /****************************************************************
110 ****************************************************************/
112 /* Definition of the driver for autoconfig. */
113 static int zsc_print(void *, const char *name
);
115 void zs_putc(void *, int);
118 static int zs_get_speed(struct zs_chanstate
*);
125 * Configure children of an SCC.
128 zs_config(struct zsc_softc
*zsc
, struct zsdevice
*zs
, int vector
, int pclk
)
130 struct zsc_attach_args zsc_args
;
131 volatile struct zschan
*zc
;
132 struct zs_chanstate
*cs
;
133 int zsc_unit
, channel
, s
;
135 zsc_unit
= device_unit(zsc
->zsc_dev
);
136 printf(": Zilog 8530 SCC at vector 0x%x\n", vector
);
139 * Initialize software state for each channel.
141 for (channel
= 0; channel
< 2; channel
++) {
142 zsc_args
.channel
= channel
;
143 zsc_args
.hwflags
= zs_hwflags
[zsc_unit
][channel
];
144 cs
= &zsc
->zsc_cs_store
[channel
];
145 zsc
->zsc_cs
[channel
] = cs
;
148 * If we're the console, copy the channel state, and
149 * adjust the console channel pointer.
151 if (zsc_args
.hwflags
& ZS_HWFLAG_CONSOLE
) {
152 memcpy(cs
, zs_conschan
, sizeof(struct zs_chanstate
));
155 zc
= (channel
== 0) ? &zs
->zs_chan_a
: &zs
->zs_chan_b
;
156 cs
->cs_reg_csr
= zc
->zc_csr
;
157 cs
->cs_reg_data
= zc
->zc_data
;
158 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
159 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
160 cs
->cs_defspeed
= zs_defspeed
[zsc_unit
][channel
];
164 cs
->cs_brg_clk
= pclk
/ 16;
165 cs
->cs_creg
[2] = cs
->cs_preg
[2] = vector
;
166 zs_set_speed(cs
, cs
->cs_defspeed
);
167 cs
->cs_creg
[12] = cs
->cs_preg
[12];
168 cs
->cs_creg
[13] = cs
->cs_preg
[13];
169 cs
->cs_defcflag
= zs_def_cflag
;
171 /* Make these correspond to cs_defcflag (-crtscts) */
172 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
174 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
177 cs
->cs_channel
= channel
;
178 cs
->cs_private
= NULL
;
179 cs
->cs_ops
= &zsops_null
;
182 * Clear the master interrupt enable.
183 * The INTENA is common to both channels,
184 * so just do it on the A channel.
185 * Write the interrupt vector while we're at it.
188 zs_write_reg(cs
, 9, 0);
189 zs_write_reg(cs
, 2, vector
);
193 * Look for a child driver for this channel.
194 * The child attach will setup the hardware.
196 if (!config_found(zsc
->zsc_dev
, (void *)&zsc_args
,
198 /* No sub-driver. Just reset it. */
199 uint8_t reset
= (channel
== 0) ?
200 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
202 zs_write_reg(cs
, 9, reset
);
208 * Allocate a software interrupt cookie.
210 zsc
->zsc_softintr_cookie
= softint_establish(SOFTINT_SERIAL
,
211 (void (*)(void *)) zsc_intr_soft
, zsc
);
213 assert(zsc
->zsc_softintr_cookie
);
218 zsc_print(void *aux
, const char *name
)
220 struct zsc_attach_args
*args
= aux
;
223 aprint_normal("%s: ", name
);
225 if (args
->channel
!= -1)
226 aprint_normal(" channel %d", args
->channel
);
231 #if defined(MVME162) || defined(MVME172)
233 * Our ZS chips each have their own interrupt vector.
236 zshard_unshared(void *arg
)
238 struct zsc_softc
*zsc
= arg
;
241 rval
= zsc_intr_hard(zsc
);
244 if ((zsc
->zsc_cs
[0]->cs_softreq
) ||
245 (zsc
->zsc_cs
[1]->cs_softreq
))
246 softint_schedule(zsc
->zsc_softintr_cookie
);
247 zsc
->zsc_evcnt
.ev_count
++;
256 * Our ZS chips all share a common, PCC-vectored interrupt,
257 * so we have to look at all of them on each interrupt.
260 zshard_shared(void *arg
)
262 struct zsc_softc
*zsc
;
266 for (unit
= 0; unit
< zsc_cd
.cd_ndevs
; unit
++) {
267 zsc
= device_lookup_private(&zsc_cd
, unit
);
268 if (zsc
!= NULL
&& zsc_intr_hard(zsc
)) {
269 if ((zsc
->zsc_cs
[0]->cs_softreq
) ||
270 (zsc
->zsc_cs
[1]->cs_softreq
))
271 softint_schedule(zsc
->zsc_softintr_cookie
);
272 zsc
->zsc_evcnt
.ev_count
++;
283 * Compute the current baud rate given a ZSCC channel.
286 zs_get_speed(struct zs_chanstate
*cs
)
290 tconst
= zs_read_reg(cs
, 12);
291 tconst
|= zs_read_reg(cs
, 13) << 8;
292 return TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
297 * MD functions for setting the baud rate and control modes.
300 zs_set_speed(struct zs_chanstate
*cs
, int bps
)
302 int tconst
, real_bps
;
308 if (cs
->cs_brg_clk
== 0)
309 panic("zs_set_speed");
312 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, bps
);
316 /* Convert back to make sure we can do it. */
317 real_bps
= TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
319 /* Allow 2% tolerance WRT the required bps */
320 if (((abs(real_bps
- bps
) * 1000) / bps
) > 20)
323 cs
->cs_preg
[12] = tconst
;
324 cs
->cs_preg
[13] = tconst
>> 8;
326 /* Caller will stuff the pending registers. */
331 zs_set_modes(struct zs_chanstate
*cs
, int cflag
)
336 * Output hardware flow control on the chip is horrendous:
337 * if carrier detect drops, the receiver is disabled, and if
338 * CTS drops, the transmitter is stoped IN MID CHARACTER!
339 * Therefore, NEVER set the HFC bit, and instead use the
340 * status interrupt to detect CTS changes.
344 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0) {
346 if ((cflag
& MDMBUF
) == 0)
347 cs
->cs_rr0_pps
= ZSRR0_DCD
;
349 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
350 if ((cflag
& CRTSCTS
) != 0) {
351 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
352 cs
->cs_wr5_rts
= ZSWR5_RTS
;
353 cs
->cs_rr0_cts
= ZSRR0_CTS
;
354 } else if ((cflag
& MDMBUF
) != 0) {
356 cs
->cs_wr5_rts
= ZSWR5_DTR
;
357 cs
->cs_rr0_cts
= ZSRR0_DCD
;
359 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
365 /* Caller will stuff the pending registers. */
371 * Read or write the chip with suitable delays.
375 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
379 *cs
->cs_reg_csr
= reg
;
381 val
= *cs
->cs_reg_csr
;
387 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
390 *cs
->cs_reg_csr
= reg
;
392 *cs
->cs_reg_csr
= val
;
397 zs_read_csr(struct zs_chanstate
*cs
)
401 val
= *cs
->cs_reg_csr
;
407 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
410 *cs
->cs_reg_csr
= val
;
415 zs_read_data(struct zs_chanstate
*cs
)
419 val
= *cs
->cs_reg_data
;
425 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
428 *cs
->cs_reg_data
= val
;
432 /****************************************************************
433 * Console support functions (MVME specific!)
434 ****************************************************************/
442 struct zs_chanstate
*cs
= arg
;
447 /* Wait for a character to arrive. */
449 rr0
= *cs
->cs_reg_csr
;
451 } while ((rr0
& ZSRR0_RX_READY
) == 0);
453 /* Read error register. */
454 stat
= zs_read_reg(cs
, 1) & (ZSRR1_FE
| ZSRR1_DO
| ZSRR1_PE
);
456 zs_write_csr(cs
, ZSM_RESET_ERR
);
460 /* Read character. */
461 c
= *cs
->cs_reg_data
;
469 * Polled output char.
472 zs_putc(void *arg
, int c
)
474 struct zs_chanstate
*cs
= arg
;
478 /* Wait for transmitter to become ready. */
480 rr0
= *cs
->cs_reg_csr
;
482 } while ((rr0
& ZSRR0_TX_READY
) == 0);
484 *cs
->cs_reg_data
= c
;
490 * Common parts of console init.
493 zs_cnconfig(int zsc_unit
, int channel
, struct zsdevice
*zs
, int pclk
)
495 struct zs_chanstate
*cs
;
498 zc
= (channel
== 0) ? &zs
->zs_chan_a
: &zs
->zs_chan_b
;
501 * Pointer to channel state. Later, the console channel
502 * state is copied into the softc, and the console channel
503 * pointer adjusted to point to the new copy.
505 zs_conschan
= cs
= &zs_conschan_store
;
506 zs_hwflags
[zsc_unit
][channel
] = ZS_HWFLAG_CONSOLE
;
508 /* Setup temporary chanstate. */
509 cs
->cs_brg_clk
= pclk
/ 16;
510 cs
->cs_reg_csr
= zc
->zc_csr
;
511 cs
->cs_reg_data
= zc
->zc_data
;
513 /* Initialize the pending registers. */
514 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
515 cs
->cs_preg
[5] |= (ZSWR5_DTR
| ZSWR5_RTS
);
518 /* XXX: Preserve BAUD rate from boot loader. */
519 /* XXX: Also, why reset the chip here? -gwr */
520 cs
->cs_defspeed
= zs_get_speed(cs
);
522 cs
->cs_defspeed
= 9600; /* XXX */
524 zs_set_speed(cs
, cs
->cs_defspeed
);
525 cs
->cs_creg
[12] = cs
->cs_preg
[12];
526 cs
->cs_creg
[13] = cs
->cs_preg
[13];
528 /* Clear the master interrupt enable. */
529 zs_write_reg(cs
, 9, 0);
531 /* Reset the whole SCC chip. */
532 zs_write_reg(cs
, 9, ZSWR9_HARD_RESET
);
534 /* Copy "pending" to "current" and H/W. */
535 zs_loadchannelregs(cs
);
539 * Polled console input putchar.
542 zsc_pcccngetc(dev_t dev
)
544 struct zs_chanstate
*cs
= zs_conschan
;
552 * Polled console output putchar.
555 zsc_pcccnputc(dev_t dev
, int c
)
557 struct zs_chanstate
*cs
= zs_conschan
;
563 * Handle user request to enter kernel debugger.
566 zs_abort(struct zs_chanstate
*cs
)
570 /* Wait for end of break to avoid PROM abort. */
571 /* XXX - Limit the wait? */
573 rr0
= *cs
->cs_reg_csr
;
575 } while (rr0
& ZSRR0_BREAK
);
577 mvme68k_abort("SERIAL LINE ABORT");