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