zs_sbdio.c revision 1.2.6.4 1 1.2.6.4 yamt /* $NetBSD: zs_sbdio.c,v 1.2.6.4 2007/09/03 14:24:55 yamt Exp $ */
2 1.2.6.2 yamt
3 1.2.6.2 yamt /*-
4 1.2.6.2 yamt * Copyright (c) 1996, 2005 The NetBSD Foundation, Inc.
5 1.2.6.2 yamt * All rights reserved.
6 1.2.6.2 yamt *
7 1.2.6.2 yamt * This code is derived from software contributed to The NetBSD Foundation
8 1.2.6.2 yamt * by Gordon W. Ross.
9 1.2.6.2 yamt *
10 1.2.6.2 yamt * Redistribution and use in source and binary forms, with or without
11 1.2.6.2 yamt * modification, are permitted provided that the following conditions
12 1.2.6.2 yamt * are met:
13 1.2.6.2 yamt * 1. Redistributions of source code must retain the above copyright
14 1.2.6.2 yamt * notice, this list of conditions and the following disclaimer.
15 1.2.6.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
16 1.2.6.2 yamt * notice, this list of conditions and the following disclaimer in the
17 1.2.6.2 yamt * documentation and/or other materials provided with the distribution.
18 1.2.6.2 yamt * 3. All advertising materials mentioning features or use of this software
19 1.2.6.2 yamt * must display the following acknowledgement:
20 1.2.6.2 yamt * This product includes software developed by the NetBSD
21 1.2.6.2 yamt * Foundation, Inc. and its contributors.
22 1.2.6.2 yamt * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.2.6.2 yamt * contributors may be used to endorse or promote products derived
24 1.2.6.2 yamt * from this software without specific prior written permission.
25 1.2.6.2 yamt *
26 1.2.6.2 yamt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.2.6.2 yamt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.2.6.2 yamt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.2.6.2 yamt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.2.6.2 yamt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.2.6.2 yamt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.2.6.2 yamt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.2.6.2 yamt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.2.6.2 yamt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.2.6.2 yamt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.2.6.2 yamt * POSSIBILITY OF SUCH DAMAGE.
37 1.2.6.2 yamt */
38 1.2.6.2 yamt
39 1.2.6.2 yamt /*
40 1.2.6.2 yamt * Zilog Z8530 Dual UART driver (machine-dependent part)
41 1.2.6.2 yamt *
42 1.2.6.2 yamt * Runs two serial lines per chip using slave drivers.
43 1.2.6.2 yamt * Plain tty/async lines use the zs_async slave.
44 1.2.6.2 yamt */
45 1.2.6.2 yamt
46 1.2.6.2 yamt #include <sys/cdefs.h>
47 1.2.6.4 yamt __KERNEL_RCSID(0, "$NetBSD: zs_sbdio.c,v 1.2.6.4 2007/09/03 14:24:55 yamt Exp $");
48 1.2.6.2 yamt
49 1.2.6.2 yamt #include <sys/param.h>
50 1.2.6.2 yamt #include <sys/systm.h>
51 1.2.6.2 yamt #include <sys/device.h>
52 1.2.6.2 yamt #include <sys/tty.h>
53 1.2.6.2 yamt #include <sys/conf.h>
54 1.2.6.2 yamt
55 1.2.6.2 yamt #include <dev/cons.h>
56 1.2.6.2 yamt #include <dev/ic/z8530reg.h>
57 1.2.6.2 yamt
58 1.2.6.2 yamt #include <machine/sbdiovar.h>
59 1.2.6.2 yamt #include <machine/z8530var.h>
60 1.2.6.2 yamt
61 1.2.6.2 yamt #define ZS_DEFSPEED 9600
62 1.2.6.2 yamt #define PCLK (9600 * 512) /* 4.915200MHz */
63 1.2.6.2 yamt
64 1.2.6.2 yamt /* The layout of this is hardware-dependent (padding, order). */
65 1.2.6.2 yamt struct zschan {
66 1.2.6.2 yamt volatile uint8_t zc_csr; /* ctrl, status, and indirect access */
67 1.2.6.2 yamt uint8_t padding1[3];
68 1.2.6.2 yamt volatile uint8_t zc_data; /* data */
69 1.2.6.2 yamt uint8_t padding2[3];
70 1.2.6.2 yamt } __attribute__((__packed__));
71 1.2.6.2 yamt
72 1.2.6.2 yamt struct zsdevice {
73 1.2.6.2 yamt /* Yes, they are backwards. */
74 1.2.6.2 yamt struct zschan zs_chan_b;
75 1.2.6.2 yamt struct zschan zs_chan_a;
76 1.2.6.2 yamt } __attribute__((__packed__));
77 1.2.6.2 yamt
78 1.2.6.2 yamt static uint8_t zs_init_reg[16] = {
79 1.2.6.2 yamt 0, /* 0: CMD (reset, etc.) */
80 1.2.6.2 yamt 0, /* 1: No interrupts yet. */
81 1.2.6.2 yamt 0, /* 2: IVECT EWS-UX don't set this. */
82 1.2.6.2 yamt ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
83 1.2.6.2 yamt ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
84 1.2.6.2 yamt ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
85 1.2.6.2 yamt 0, /* 6: TXSYNC/SYNCLO */
86 1.2.6.2 yamt 0, /* 7: RXSYNC/SYNCHI */
87 1.2.6.2 yamt 0, /* 8: alias for data port */
88 1.2.6.2 yamt ZSWR9_MASTER_IE,
89 1.2.6.2 yamt 0, /* 10: Misc. TX/RX control bits */
90 1.2.6.2 yamt ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
91 1.2.6.2 yamt BPS_TO_TCONST((PCLK/16), ZS_DEFSPEED), /* 12: BAUDLO (default=9600) */
92 1.2.6.2 yamt 0, /*13: BAUDHI (default=9600) */
93 1.2.6.2 yamt ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
94 1.2.6.2 yamt ZSWR15_BREAK_IE,
95 1.2.6.2 yamt };
96 1.2.6.2 yamt
97 1.2.6.2 yamt int zs_sbdio_match(struct device *, struct cfdata *, void *);
98 1.2.6.2 yamt void zs_sbdio_attach(struct device *, struct device *, void *);
99 1.2.6.2 yamt
100 1.2.6.2 yamt CFATTACH_DECL(zsc_sbdio, sizeof(struct zsc_softc),
101 1.2.6.2 yamt zs_sbdio_match, zs_sbdio_attach, NULL, NULL);
102 1.2.6.2 yamt
103 1.2.6.2 yamt int
104 1.2.6.2 yamt zs_sbdio_match(struct device *parent, struct cfdata *cf, void *aux)
105 1.2.6.2 yamt {
106 1.2.6.2 yamt struct sbdio_attach_args *sa = aux;
107 1.2.6.2 yamt
108 1.2.6.2 yamt return strcmp(sa->sa_name, "zsc") ? 0 : 1;
109 1.2.6.2 yamt }
110 1.2.6.2 yamt
111 1.2.6.2 yamt void
112 1.2.6.2 yamt zs_sbdio_attach(struct device *parent, struct device *self, void *aux)
113 1.2.6.2 yamt {
114 1.2.6.2 yamt struct sbdio_attach_args *sa = aux;
115 1.2.6.2 yamt struct zsc_softc *zsc = (void *)self;
116 1.2.6.2 yamt struct zsc_attach_args zsc_args;
117 1.2.6.2 yamt struct zschan *zc;
118 1.2.6.2 yamt struct zs_chanstate *cs;
119 1.2.6.2 yamt struct zsdevice *zs_addr;
120 1.2.6.2 yamt int s, zs_unit, channel;
121 1.2.6.2 yamt
122 1.2.6.2 yamt printf(" at %p irq %d\n", (void *)sa->sa_addr1, sa->sa_irq);
123 1.2.6.2 yamt
124 1.2.6.2 yamt zs_unit = device_unit(&zsc->zsc_dev);
125 1.2.6.2 yamt zs_addr = (void *)MIPS_PHYS_TO_KSEG1(sa->sa_addr1);
126 1.2.6.2 yamt zsc->zsc_flags = sa->sa_flags;
127 1.2.6.2 yamt
128 1.2.6.2 yamt /*
129 1.2.6.2 yamt * Initialize software state for each channel.
130 1.2.6.2 yamt */
131 1.2.6.2 yamt for (channel = 0; channel < 2; channel++) {
132 1.2.6.2 yamt zsc_args.channel = channel;
133 1.2.6.2 yamt zsc_args.hwflags = 0;
134 1.2.6.2 yamt cs = &zsc->zsc_cs_store[channel];
135 1.2.6.2 yamt zsc->zsc_cs[channel] = cs;
136 1.2.6.2 yamt
137 1.2.6.2 yamt cs->cs_channel = channel;
138 1.2.6.2 yamt cs->cs_private = NULL;
139 1.2.6.2 yamt cs->cs_ops = &zsops_null;
140 1.2.6.2 yamt
141 1.2.6.2 yamt if (channel == 0)
142 1.2.6.2 yamt zc = &zs_addr->zs_chan_a;
143 1.2.6.2 yamt else
144 1.2.6.2 yamt zc = &zs_addr->zs_chan_b;
145 1.2.6.2 yamt
146 1.2.6.2 yamt if (zc == zs_consaddr) {
147 1.2.6.2 yamt memcpy(cs, zs_conscs, sizeof(struct zs_chanstate));
148 1.2.6.2 yamt zs_conscs = cs;
149 1.2.6.2 yamt zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
150 1.2.6.2 yamt } else {
151 1.2.6.2 yamt cs->cs_reg_csr = &zc->zc_csr;
152 1.2.6.2 yamt cs->cs_reg_data = &zc->zc_data;
153 1.2.6.2 yamt memcpy(cs->cs_creg, zs_init_reg, 16);
154 1.2.6.2 yamt memcpy(cs->cs_preg, zs_init_reg, 16);
155 1.2.6.2 yamt cs->cs_defspeed = ZS_DEFSPEED;
156 1.2.6.2 yamt zsc_args.hwflags = 0;
157 1.2.6.2 yamt }
158 1.2.6.2 yamt
159 1.2.6.4 yamt simple_lock_init(&cs->cs_lock);
160 1.2.6.2 yamt cs->cs_brg_clk = PCLK / 16;
161 1.2.6.2 yamt cs->cs_defcflag = zs_def_cflag;
162 1.2.6.2 yamt
163 1.2.6.2 yamt /* Make these correspond to cs_defcflag (-crtscts) */
164 1.2.6.2 yamt cs->cs_rr0_dcd = ZSRR0_DCD;
165 1.2.6.2 yamt cs->cs_rr0_cts = 0;
166 1.2.6.2 yamt cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
167 1.2.6.2 yamt cs->cs_wr5_rts = 0;
168 1.2.6.2 yamt
169 1.2.6.2 yamt /*
170 1.2.6.2 yamt * Clear the master interrupt enable.
171 1.2.6.2 yamt * The INTENA is common to both channels,
172 1.2.6.2 yamt * so just do it on the A channel.
173 1.2.6.2 yamt */
174 1.2.6.2 yamt if (channel == 0) {
175 1.2.6.2 yamt zs_write_reg(cs, 9, 0);
176 1.2.6.2 yamt }
177 1.2.6.2 yamt
178 1.2.6.2 yamt /*
179 1.2.6.2 yamt * Look for a child driver for this channel.
180 1.2.6.2 yamt * The child attach will setup the hardware.
181 1.2.6.2 yamt */
182 1.2.6.2 yamt if (!config_found(self, (void *)&zsc_args, zs_print)) {
183 1.2.6.2 yamt /* No sub-driver. Just reset it. */
184 1.2.6.2 yamt uint8_t reset = (channel == 0) ?
185 1.2.6.2 yamt ZSWR9_A_RESET : ZSWR9_B_RESET;
186 1.2.6.2 yamt s = splhigh();
187 1.2.6.2 yamt zs_write_reg(cs, 9, reset);
188 1.2.6.2 yamt splx(s);
189 1.2.6.2 yamt }
190 1.2.6.2 yamt }
191 1.2.6.2 yamt
192 1.2.6.3 yamt zsc->zsc_si = softintr_establish(IPL_SOFTSERIAL,
193 1.2.6.3 yamt (void (*)(void *))zsc_intr_soft, zsc);
194 1.2.6.3 yamt intr_establish(sa->sa_irq, zshard, zsc);
195 1.2.6.2 yamt
196 1.2.6.2 yamt /*
197 1.2.6.2 yamt * Set the master interrupt enable and interrupt vector.
198 1.2.6.2 yamt * (common to both channels, do it on A)
199 1.2.6.2 yamt */
200 1.2.6.2 yamt cs = zsc->zsc_cs[0];
201 1.2.6.2 yamt s = splhigh();
202 1.2.6.2 yamt /* interrupt vector */
203 1.2.6.2 yamt zs_write_reg(cs, 2, zs_init_reg[2]);
204 1.2.6.2 yamt /* master interrupt control (enable) */
205 1.2.6.2 yamt zs_write_reg(cs, 9, zs_init_reg[9]);
206 1.2.6.2 yamt splx(s);
207 1.2.6.2 yamt }
208 1.2.6.2 yamt
209 1.2.6.2 yamt /*
210 1.2.6.2 yamt * console stuff
211 1.2.6.2 yamt */
212 1.2.6.2 yamt
213 1.2.6.2 yamt static void zs_sbdio_cnprobe(struct consdev *);
214 1.2.6.2 yamt static void zs_sbdio_cninit(struct consdev *);
215 1.2.6.2 yamt
216 1.2.6.2 yamt struct consdev consdev_zs_sbdio = {
217 1.2.6.2 yamt zs_sbdio_cnprobe,
218 1.2.6.2 yamt zs_sbdio_cninit,
219 1.2.6.2 yamt zscngetc,
220 1.2.6.2 yamt zscnputc,
221 1.2.6.2 yamt nullcnpollc,
222 1.2.6.2 yamt NULL,
223 1.2.6.2 yamt NULL,
224 1.2.6.2 yamt NULL,
225 1.2.6.2 yamt NODEV,
226 1.2.6.2 yamt CN_DEAD
227 1.2.6.2 yamt };
228 1.2.6.2 yamt
229 1.2.6.2 yamt static void
230 1.2.6.2 yamt zs_sbdio_cnprobe(struct consdev *cn)
231 1.2.6.2 yamt {
232 1.2.6.2 yamt
233 1.2.6.2 yamt /* not used */
234 1.2.6.2 yamt }
235 1.2.6.2 yamt
236 1.2.6.2 yamt static void
237 1.2.6.2 yamt zs_sbdio_cninit(struct consdev *cn)
238 1.2.6.2 yamt {
239 1.2.6.2 yamt struct zs_chanstate *cs;
240 1.2.6.2 yamt struct zschan *zc;
241 1.2.6.2 yamt
242 1.2.6.2 yamt zc = zs_consaddr;
243 1.2.6.2 yamt cs = zs_conscs;
244 1.2.6.2 yamt
245 1.2.6.2 yamt /* Setup temporary chanstate. */
246 1.2.6.2 yamt cs->cs_reg_csr = &zc->zc_csr;
247 1.2.6.2 yamt cs->cs_reg_data = &zc->zc_data;
248 1.2.6.2 yamt
249 1.2.6.2 yamt /* Initialize the pending registers. */
250 1.2.6.2 yamt memcpy(cs->cs_preg, zs_init_reg, 16);
251 1.2.6.2 yamt cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
252 1.2.6.2 yamt
253 1.2.6.2 yamt cs->cs_brg_clk = PCLK / 16;
254 1.2.6.2 yamt cs->cs_defspeed = ZS_DEFSPEED;
255 1.2.6.2 yamt zs_set_speed(cs, ZS_DEFSPEED);
256 1.2.6.2 yamt
257 1.2.6.2 yamt /* Clear the master interrupt enable. */
258 1.2.6.2 yamt zs_write_reg(cs, 9, 0);
259 1.2.6.2 yamt
260 1.2.6.2 yamt /* Reset the whole SCC chip. */
261 1.2.6.2 yamt zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
262 1.2.6.2 yamt
263 1.2.6.2 yamt /* Copy "pending" to "current" and H/W */
264 1.2.6.2 yamt zs_loadchannelregs(cs);
265 1.2.6.2 yamt }
266