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