1 /* $NetBSD: zs.c,v 1.2 2008/03/29 19:15:34 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.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.2 2008/03/29 19:15:34 tsutsui Exp $");
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #include <sys/device.h>
52 #include <dev/ic/z8530reg.h>
54 #include <machine/autoconf.h>
55 #include <machine/z8530var.h>
57 #include <cobalt/cobalt/console.h>
62 * Some warts needed by z8530tty.c -
63 * The default parity REALLY needs to be the same as the PROM uses,
64 * or you can not see messages done with printf during boot-up...
66 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
68 #define ZS_DEFSPEED 115200
69 #define PCLK (115200 * 96) /* 11.0592MHz */
71 #define ZS_DELAY() delay(2)
73 /* The layout of this is hardware-dependent (padding, order). */
74 /* A/~B (Channel A/Channel B) pin is connected to DAdr0 */
75 #define ZS_CHAN_A 0x01
76 #define ZS_CHAN_B 0x00
78 /* D/~C (Data/Control) pin is connected to DAdr1 */
79 #define ZS_CSR 0x00 /* ctrl, status, and indirect access */
80 #define ZS_DATA 0x02 /* data */
83 /* Definition of the driver for autoconfig. */
84 static int zs_match(device_t
, cfdata_t
, void *);
85 static void zs_attach(device_t
, device_t
, void *);
86 static int zs_print(void *, const char *name
);
88 CFATTACH_DECL_NEW(zsc
, sizeof(struct zsc_softc
),
89 zs_match
, zs_attach
, NULL
, NULL
);
91 static int zshard(void *);
93 static int zs_get_speed(struct zs_chanstate
*);
95 static int zs_getc(void *);
96 static void zs_putc(void *, int);
98 /* console status from cninit */
99 static struct zs_chanstate zs_conschan_store
;
100 static struct zs_chanstate
*zs_conschan
;
101 static uint8_t *zs_cons
;
103 /* default speed for all channels */
104 static int zs_defspeed
= ZS_DEFSPEED
;
106 static uint8_t zs_init_reg
[16] = {
107 0, /* 0: CMD (reset, etc.) */
108 0, /* 1: No interrupts yet. */
110 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
, /* 3: RX params and ctrl */
111 ZSWR4_CLK_X16
| ZSWR4_ONESB
, /* 4: TX/RX misc params */
112 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
, /* 5: TX params and ctrl */
113 0, /* 6: TXSYNC/SYNCLO */
114 0, /* 7: RXSYNC/SYNCHI */
115 0, /* 8: alias for data port */
116 ZSWR9_MASTER_IE
, /* 9: Master interrupt ctrl */
117 0, /*10: Misc TX/RX ctrl */
118 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
, /*11: Clock Mode ctrl */
119 BPS_TO_TCONST((PCLK
/16), ZS_DEFSPEED
), /*12: BAUDLO */
121 ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
, /*14: Misc ctrl */
122 ZSWR15_BREAK_IE
, /*15: Ext/Status intr ctrl */
125 /* register address offset for each channel */
126 static const int chanoff
[] = { ZS_CHAN_A
, ZS_CHAN_B
};
130 zs_match(device_t parent
, cfdata_t cf
, void *aux
)
138 /* only Qube 2700 could have Z85C30 serial */
139 if (cobalt_id
!= COBALT_ID_QUBE2700
)
142 if (!console_present
)
153 zs_attach(device_t parent
, device_t self
, void *aux
)
155 struct zsc_softc
*zsc
= device_private(self
);
156 struct mainbus_attach_args
*maa
= aux
;
157 struct zsc_attach_args zsc_args
;
159 struct zs_chanstate
*cs
;
164 /* XXX: MI z8530 doesn't use bus_space(9) yet */
165 zs_base
= (void *)MIPS_PHYS_TO_KSEG1(maa
->ma_addr
);
167 aprint_normal(": optional Z85C30 serial port\n");
170 * Initialize software state for each channel.
172 for (channel
= 0; channel
< 2; channel
++) {
173 zsc_args
.channel
= channel
;
174 cs
= &zsc
->zsc_cs_store
[channel
];
176 zsc
->zsc_cs
[channel
] = cs
;
180 if ((zs_base
+ chanoff
[channel
]) == zs_cons
) {
181 memcpy(cs
, zs_conschan
, sizeof(struct zs_chanstate
));
183 zsc_args
.hwflags
= ZS_HWFLAG_CONSOLE
;
185 cs
->cs_reg_csr
= zs_base
+ chanoff
[channel
] + ZS_CSR
;
186 cs
->cs_reg_data
= zs_base
+ chanoff
[channel
] + ZS_DATA
;
187 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
188 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
189 cs
->cs_defspeed
= zs_defspeed
;
190 zsc_args
.hwflags
= 0;
194 cs
->cs_defcflag
= zs_def_cflag
;
196 cs
->cs_channel
= channel
;
197 cs
->cs_private
= NULL
;
198 cs
->cs_ops
= &zsops_null
;
199 cs
->cs_brg_clk
= PCLK
/ 16;
201 /* Make these correspond to cs_defcflag (-crtscts) */
202 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
204 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
208 * Clear the master interrupt enable.
209 * The INTENA is common to both channels,
210 * so just do it on the A channel.
214 zs_write_reg(cs
, 9, 0);
219 * Look for a child driver for this channel.
220 * The child attach will setup the hardware.
222 if (!config_found(self
, (void *)&zsc_args
, zs_print
)) {
223 /* No sub-driver. Just reset it. */
224 uint8_t reset
= (channel
== 0) ?
225 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
227 zs_write_reg(cs
, 9, reset
);
233 * Now safe to install interrupt handlers.
235 icu_intr_establish(maa
->ma_irq
, IST_EDGE
, IPL_SERIAL
, zshard
, zsc
);
236 zsc
->zsc_softintr_cookie
= softint_establish(SOFTINT_SERIAL
,
237 (void (*)(void *))zsc_intr_soft
, zsc
);
240 * Set the master interrupt enable and interrupt vector.
241 * (common to both channels, do it on A)
245 /* interrupt vector */
246 zs_write_reg(cs
, 2, 0);
247 /* master interrupt control (enable) */
248 zs_write_reg(cs
, 9, zs_init_reg
[9]);
253 zs_print(void *aux
, const char *name
)
255 struct zsc_attach_args
*args
= aux
;
258 aprint_normal("%s: ", name
);
260 if (args
->channel
!= -1)
261 aprint_normal(" channel %d", args
->channel
);
269 struct zsc_softc
*zsc
= arg
;
272 rval
= zsc_intr_hard(zsc
);
275 /* XXX: there is some race condition? */
277 while (zsc_intr_hard(zsc
))
281 /* We are at splzs here, so no need to lock. */
282 if (zsc
->zsc_cs
[0]->cs_softreq
|| zsc
->zsc_cs
[1]->cs_softreq
)
283 softint_schedule(zsc
->zsc_softintr_cookie
);
289 * Compute the current baud rate given a ZS channel.
293 zs_get_speed(struct zs_chanstate
*cs
)
297 tconst
= zs_read_reg(cs
, 12);
298 tconst
|= zs_read_reg(cs
, 13) << 8;
299 return TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
304 * MD functions for setting the baud rate and control modes.
307 zs_set_speed(struct zs_chanstate
*cs
, int bps
)
309 int tconst
, real_bps
;
315 if (cs
->cs_brg_clk
== 0)
316 panic("zs_set_speed");
319 tconst
= BPS_TO_TCONST(cs
->cs_brg_clk
, bps
);
323 /* Convert back to make sure we can do it. */
324 real_bps
= TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
326 /* Allow ~4% tolerance here */
327 if (abs(real_bps
- bps
) >= bps
* 4 / 100)
330 cs
->cs_preg
[12] = tconst
;
331 cs
->cs_preg
[13] = tconst
>> 8;
333 /* Caller will stuff the pending registers. */
338 zs_set_modes(struct zs_chanstate
*cs
, int cflag
)
343 * Output hardware flow control on the chip is horrendous:
344 * if carrier detect drops, the receiver is disabled, and if
345 * CTS drops, the transmitter is stoped IN MID CHARACTER!
346 * Therefore, NEVER set the HFC bit, and instead use the
347 * status interrupt to detect CTS changes.
351 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0) {
353 if ((cflag
& MDMBUF
) == 0)
354 cs
->cs_rr0_pps
= ZSRR0_DCD
;
356 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
357 if ((cflag
& CRTSCTS
) != 0) {
358 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
359 cs
->cs_wr5_rts
= ZSWR5_RTS
;
360 cs
->cs_rr0_cts
= ZSRR0_CTS
;
361 } else if ((cflag
& MDMBUF
) != 0) {
363 cs
->cs_wr5_rts
= ZSWR5_DTR
;
364 cs
->cs_rr0_cts
= ZSRR0_DCD
;
366 cs
->cs_wr5_dtr
= ZSWR5_DTR
| ZSWR5_RTS
;
372 /* Caller will stuff the pending registers. */
378 * Read or write the chip with suitable delays.
382 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
386 *cs
->cs_reg_csr
= reg
;
388 val
= *cs
->cs_reg_csr
;
394 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
397 *cs
->cs_reg_csr
= reg
;
399 *cs
->cs_reg_csr
= val
;
404 zs_read_csr(struct zs_chanstate
*cs
)
408 val
= *cs
->cs_reg_csr
;
414 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
417 *cs
->cs_reg_csr
= val
;
422 zs_read_data(struct zs_chanstate
*cs
)
426 val
= *cs
->cs_reg_data
;
432 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
435 *cs
->cs_reg_data
= val
;
440 zs_abort(struct zs_chanstate
*cs
)
454 struct zs_chanstate
*cs
= arg
;
459 /* Wait for a character to arrive. */
461 rr0
= *cs
->cs_reg_csr
;
463 } while ((rr0
& ZSRR0_RX_READY
) == 0);
465 c
= *cs
->cs_reg_data
;
473 * Polled output char.
476 zs_putc(void *arg
, int c
)
478 struct zs_chanstate
*cs
= arg
;
483 /* Wait for transmitter to become ready. */
485 rr0
= *cs
->cs_reg_csr
;
487 } while ((rr0
& ZSRR0_TX_READY
) == 0);
489 *cs
->cs_reg_data
= c
;
495 zscnprobe(struct consdev
*cn
)
498 cn
->cn_pri
= (console_present
!= 0 && cobalt_id
== COBALT_ID_QUBE2700
)
499 ? CN_NORMAL
: CN_DEAD
;
503 zscninit(struct consdev
*cn
)
505 struct zs_chanstate
*cs
;
507 extern const struct cdevsw zstty_cdevsw
;
509 cn
->cn_dev
= makedev(cdevsw_lookup_major(&zstty_cdevsw
), 0);
511 zs_cons
= (uint8_t *)MIPS_PHYS_TO_KSEG1(ZS_BASE
) + ZS_CHAN_A
; /* XXX */
513 zs_conschan
= cs
= &zs_conschan_store
;
515 /* Setup temporary chanstate. */
516 cs
->cs_reg_csr
= zs_cons
+ ZS_CSR
;
517 cs
->cs_reg_data
= zs_cons
+ ZS_DATA
;
519 /* Initialize the pending registers. */
520 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
521 cs
->cs_preg
[5] |= ZSWR5_DTR
| ZSWR5_RTS
;
523 cs
->cs_preg
[12] = BPS_TO_TCONST(PCLK
/ 16, ZS_DEFSPEED
);
525 cs
->cs_defspeed
= ZS_DEFSPEED
;
527 /* Clear the master interrupt enable. */
528 zs_write_reg(cs
, 9, 0);
530 /* Reset the whole SCC chip. */
531 zs_write_reg(cs
, 9, ZSWR9_HARD_RESET
);
533 /* Copy "pending" to "current" and H/W */
534 zs_loadchannelregs(cs
);
541 return zs_getc((void *)zs_conschan
);
545 zscnputc(dev_t dev
, int c
)
548 zs_putc((void *)zs_conschan
, c
);