zs_ap.c revision 1.29 1 /* $NetBSD: zs_ap.c,v 1.29 2018/10/14 00:10:11 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gordon W. Ross.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
18 *
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.
30 */
31
32 /*
33 * Zilog Z8530 Dual UART driver (machine-dependent part)
34 *
35 * Runs two serial lines per chip using slave drivers.
36 * Plain tty/async lines use the zs_async slave.
37 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.29 2018/10/14 00:10:11 tsutsui Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/tty.h>
47 #include <sys/conf.h>
48 #include <sys/cpu.h>
49 #include <sys/intr.h>
50 #ifdef NEWS4000_ZS_AP_POLLING
51 #include <sys/callout.h>
52 #endif
53
54 #include <machine/adrsmap.h>
55 #include <machine/z8530var.h>
56
57 #include <dev/cons.h>
58 #include <dev/ic/z8530reg.h>
59
60 #include <newsmips/apbus/apbusvar.h>
61
62 #include "zsc.h" /* NZSC */
63 #define NZS NZSC
64
65 /* Make life easier for the initialized arrays here. */
66 #if NZS < 2
67 #undef NZS
68 #define NZS 2
69 #endif
70
71 #define NEWS5000_PORTB_TXPORT 0x00000000
72 #define NEWS5000_PORTB_RXPORT 0x00010000
73 #define NEWS5000_PORTA_TXPORT 0x00020000
74 #define NEWS5000_PORTA_RXPORT 0x00030000
75 #define NEWS5000_DMA_MODE_REG 3
76 #define NEWS5000_DMA_ENABLE 0x01 /* DMA enable */
77 #define NEWS5000_DMA_DIR_DM 0x00 /* device to memory */
78 #define NEWS5000_DMA_DIR_MD 0x02 /* memory to device */
79 #define NEWS5000_DMA_EXTRDY 0x08 /* DMA external ready */
80 #define NEWS5000_PORTB_OFFSET 0x00040000
81 #define NEWS5000_PORTA_OFFSET 0x00050000
82 #define NEWS5000_PORT_CTL 2
83 #define NEWS5000_PORTCTL_RI 0x01
84 #define NEWS5000_PORTCTL_DSR 0x02
85 #define NEWS5000_PORTCTL_DTR 0x04
86 #define NEWS5000_PORT_SEL 3
87 #define NEWS5000_PORTSEL_LOCALTALK 0x01
88 #define NEWS5000_PORTSEL_RS232C 0x02
89 #define NEWS5000_ESCC_REG 0x00060000
90 #define NEWS5000_ESCCREG_INTSTAT 0
91 #define NEWS5000_INTSTAT_SCC 0x01
92 #define NEWS5000_ESCCREG_INTMASK 1
93 #define NEWS5000_INTMASK_SCC 0x01
94
95 #define NEWS4000_PORTB_TXPORT 0x00000000 /* XXX: not confirmed */
96 #define NEWS4000_PORTB_RXPORT 0x00010000 /* XXX: not confirmed */
97 #define NEWS4000_PORTA_TXPORT 0x00040000 /* XXX: not confirmed */
98 #define NEWS4000_PORTA_RXPORT 0x00050000 /* XXX: not confirmed */
99 #define NEWS4000_DMA_MODE_REG 3
100 #define NEWS4000_DMA_ENABLE 0x01 /* DMA enable */
101 #define NEWS4000_DMA_DIR_DM 0x00 /* device to memory */
102 #define NEWS4000_DMA_DIR_MD 0x02 /* memory to device */
103 #define NEWS4000_DMA_EXTRDY 0x08 /* DMA external ready */
104 #define NEWS4000_PORTB_CTL 0x00020000 /* XXX: not confirmed */
105 #define NEWS4000_PORTA_CTL 0x00060000 /* XXX: not confirmed */
106 #define NEWS4000_PORT_CTL 4
107 #define NEWS4000_PORTCTL_RI 0x01
108 #define NEWS4000_PORTCTL_DSR 0x02
109 #define NEWS4000_PORTCTL_DTR 0x04
110 #define NEWS4000_PORT_SEL 5
111 #define NEWS4000_PORTSEL_LOCALTALK 0x01
112 #define NEWS4000_PORTSEL_RS232C 0x02
113 #define NEWS4000_ESCC_REG 0x00060000 /* XXX: not confirmed */
114 #define NEWS4000_ESCCREG_INTSTAT 0
115 #define NEWS4000_INTSTAT_SCC 0x01
116 #define NEWS4000_ESCCREG_INTMASK 1
117 #define NEWS4000_INTMASK_SCC 0x01
118 #define NEWS4000_PORTB_OFFSET 0x00080000
119 #define NEWS4000_PORTA_OFFSET 0x00080008
120
121 extern int zs_def_cflag;
122 extern void (*zs_delay)(void);
123
124 /*
125 * The news5000 provides a 9.8304 MHz clock to the ZS chips.
126 */
127 #define PCLK (9600 * 1024) /* PCLK pin input clock rate */
128
129 #define ZS_DELAY() DELAY(2)
130
131 /* The layout of this is hardware-dependent (padding, order). */
132 struct zschan {
133 volatile uint8_t pad1[3];
134 volatile uint8_t zc_csr; /* ctrl,status, and indirect access */
135 volatile uint8_t pad2[3];
136 volatile uint8_t zc_data; /* data */
137 };
138
139 static void *zsaddr[NZS];
140
141 /* Flags from cninit() */
142 static int zs_hwflags[NZS][2];
143
144 /* Default speed for all channels */
145 static int zs_defspeed = 9600;
146
147 static uint8_t zs_init_reg[16] = {
148 0, /* 0: CMD (reset, etc.) */
149 0, /* 1: No interrupts yet. */
150 0, /* IVECT */
151 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
152 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
153 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
154 0, /* 6: TXSYNC/SYNCLO */
155 0, /* 7: RXSYNC/SYNCHI */
156 0, /* 8: alias for data port */
157 ZSWR9_MASTER_IE,
158 0, /*10: Misc. TX/RX control bits */
159 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
160 ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */
161 0, /*13: BAUDHI (default=9600) */
162 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
163 ZSWR15_BREAK_IE,
164 };
165
166 #ifdef NEWS4000_ZS_AP_POLLING
167 static struct callout zscallout;
168 #endif
169
170 static struct zschan * zs_get_chan_addr(int, int);
171 static void zs_ap_delay(void);
172 static int zshard_ap(void *);
173 static int zs_getc(void *);
174 static void zs_putc(void *, int);
175
176 struct zschan *
177 zs_get_chan_addr(int zs_unit, int channel)
178 {
179 void *addr;
180 struct zschan *zc = NULL;
181
182 if (zs_unit >= NZS)
183 return NULL;
184 addr = zsaddr[zs_unit];
185 if (addr == NULL)
186 return NULL;
187 if (systype == NEWS5000) {
188 if (channel == 0) {
189 zc = (void *)((uint8_t *)addr + NEWS5000_PORTA_OFFSET);
190 } else {
191 zc = (void *)((uint8_t *)addr + NEWS5000_PORTB_OFFSET);
192 }
193 }
194 if (systype == NEWS4000) {
195 if (channel == 0) {
196 zc = (void *)((uint8_t *)addr + NEWS4000_PORTA_OFFSET);
197 } else {
198 zc = (void *)((uint8_t *)addr + NEWS4000_PORTB_OFFSET);
199 }
200 }
201 return zc;
202 }
203
204 void
205 zs_ap_delay(void)
206 {
207
208 ZS_DELAY();
209 }
210
211 /****************************************************************
212 * Autoconfig
213 ****************************************************************/
214
215 /* Definition of the driver for autoconfig. */
216 int zs_ap_match(device_t, cfdata_t, void *);
217 void zs_ap_attach(device_t, device_t, void *);
218
219 CFATTACH_DECL_NEW(zsc_ap, sizeof(struct zsc_softc),
220 zs_ap_match, zs_ap_attach, NULL, NULL);
221
222 /*
223 * Is the zs chip present?
224 */
225 int
226 zs_ap_match(device_t parent, cfdata_t cf, void *aux)
227 {
228 struct apbus_attach_args *apa = aux;
229
230 if (strcmp("esccf", apa->apa_name) == 0 ||
231 strcmp("esccg", apa->apa_name) == 0)
232 return 1;
233
234 return 0;
235 }
236
237 /*
238 * Attach a found zs.
239 *
240 * Match slave number to zs unit number, so that misconfiguration will
241 * not set up the keyboard as ttya, etc.
242 */
243 void
244 zs_ap_attach(device_t parent, device_t self, void *aux)
245 {
246 struct zsc_softc *zsc = device_private(self);
247 struct apbus_attach_args *apa = aux;
248 struct zsc_attach_args zsc_args;
249 volatile struct zschan *zc;
250 struct zs_chanstate *cs;
251 int s, zs_unit, channel;
252 volatile uint32_t *txBfifo;
253 volatile uint32_t *rxBfifo;
254 volatile uint32_t *txAfifo;
255 volatile uint32_t *rxAfifo;
256 volatile uint32_t *portBctl;
257 volatile uint32_t *portActl;
258 volatile uint32_t *esccregs;
259
260 zsc->zsc_dev = self;
261 zs_unit = device_unit(self);
262 zsaddr[zs_unit] = (void *)apa->apa_hwbase;
263
264 aprint_normal(" slot%d addr 0x%lx\n", apa->apa_slotno, apa->apa_hwbase);
265
266 /* XXX: appease gcc -Wuninitialized */
267 txBfifo = (void *)(apa->apa_hwbase);
268 rxBfifo = (void *)(apa->apa_hwbase);
269 txAfifo = (void *)(apa->apa_hwbase);
270 rxAfifo = (void *)(apa->apa_hwbase);
271 portBctl = (void *)(apa->apa_hwbase);
272 portActl = (void *)(apa->apa_hwbase);
273 esccregs = (void *)(apa->apa_hwbase);
274
275 if (systype == NEWS5000) {
276 txBfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTB_TXPORT);
277 rxBfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTB_RXPORT);
278 txAfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTA_TXPORT);
279 rxAfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTA_RXPORT);
280 portBctl = (void *)(apa->apa_hwbase + NEWS5000_PORTB_OFFSET);
281 portActl = (void *)(apa->apa_hwbase + NEWS5000_PORTA_OFFSET);
282 esccregs = (void *)(apa->apa_hwbase + NEWS5000_ESCC_REG);
283 }
284 if (systype == NEWS4000) {
285 txBfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTB_TXPORT);
286 rxBfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTB_RXPORT);
287 txAfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTA_TXPORT);
288 rxAfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTA_RXPORT);
289 portBctl = (void *)(apa->apa_hwbase + NEWS4000_PORTB_CTL);
290 portActl = (void *)(apa->apa_hwbase + NEWS4000_PORTA_CTL);
291 esccregs = (void *)(apa->apa_hwbase + NEWS4000_ESCC_REG);
292 }
293
294 if (systype == NEWS5000) {
295 txAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
296 rxAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
297 txBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
298 rxBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
299
300 /* assert DTR */ /* XXX */
301 portBctl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
302 portActl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
303
304 /* select RS-232C (ch1 only) */
305 portActl[NEWS5000_PORT_SEL] = NEWS5000_PORTSEL_RS232C;
306
307 /* enable SCC interrupts */
308 esccregs[NEWS5000_ESCCREG_INTMASK] = NEWS5000_INTMASK_SCC;
309 }
310
311 if (systype == NEWS4000) {
312 txAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
313 rxAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
314 txBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
315 rxBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
316
317 #if 1 /* XXX: zsc on news4000 seems mangled by these ops */
318 /* assert DTR */ /* XXX */
319 portBctl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
320 portActl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
321
322 /* select RS-232C (ch1 only) */
323 portActl[NEWS4000_PORT_SEL] = NEWS4000_PORTSEL_RS232C;
324 #endif
325
326 /* enable SCC interrupts */
327 esccregs[NEWS4000_ESCCREG_INTMASK] = NEWS4000_INTMASK_SCC;
328 }
329
330 zs_delay = zs_ap_delay;
331
332 /*
333 * Initialize software state for each channel.
334 */
335 for (channel = 0; channel < 2; channel++) {
336 zsc_args.channel = channel;
337 zsc_args.hwflags = zs_hwflags[zs_unit][channel];
338 cs = &zsc->zsc_cs_store[channel];
339 zsc->zsc_cs[channel] = cs;
340
341 zs_lock_init(cs);
342 cs->cs_channel = channel;
343 cs->cs_private = NULL;
344 cs->cs_ops = &zsops_null;
345 cs->cs_brg_clk = PCLK / 16;
346
347 zc = zs_get_chan_addr(zs_unit, channel);
348 cs->cs_reg_csr = &zc->zc_csr;
349 cs->cs_reg_data = &zc->zc_data;
350
351 memcpy(cs->cs_creg, zs_init_reg, 16);
352 memcpy(cs->cs_preg, zs_init_reg, 16);
353
354 /* XXX: Get these from the EEPROM instead? */
355 /* XXX: See the mvme167 code. Better. */
356 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
357 cs->cs_defspeed = zs_get_speed(cs);
358 else
359 cs->cs_defspeed = zs_defspeed;
360 cs->cs_defcflag = zs_def_cflag;
361
362 /* Make these correspond to cs_defcflag (-crtscts) */
363 cs->cs_rr0_dcd = ZSRR0_DCD;
364 cs->cs_rr0_cts = 0;
365 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
366 cs->cs_wr5_rts = 0;
367
368 /*
369 * Clear the master interrupt enable.
370 * The INTENA is common to both channels,
371 * so just do it on the A channel.
372 */
373 if (channel == 0) {
374 zs_write_reg(cs, 9, 0);
375 }
376
377 /*
378 * Look for a child driver for this channel.
379 * The child attach will setup the hardware.
380 */
381 if (!config_found(self, (void *)&zsc_args, zs_print)) {
382 /* No sub-driver. Just reset it. */
383 uint8_t reset = (channel == 0) ?
384 ZSWR9_A_RESET : ZSWR9_B_RESET;
385 s = splhigh();
386 zs_write_reg(cs, 9, reset);
387 splx(s);
388 }
389 }
390
391 /*
392 * Now safe to install interrupt handlers.
393 */
394 zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
395 (void (*)(void *))zsc_intr_soft, zsc);
396 if (systype == NEWS5000) {
397 apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
398 NEWS5000_INT1_SCC,
399 0, /* priority */
400 zshard_ap, zsc,
401 device_xname(self), apa->apa_ctlnum);
402 }
403 if (systype == NEWS4000) {
404 apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
405 0x0200,
406 0, /* priority */
407 zshard_ap, zsc,
408 device_xname(self), apa->apa_ctlnum);
409 #ifdef NEWS4000_ZS_AP_POLLING
410 /* XXX: no info how to enable zs ap interrupt for now */
411 callout_init(&zscallout, 0);
412 callout_reset(&zscallout, 1,
413 (void (*)(void *))zshard_ap, (void *)zsc);
414 #endif
415 }
416 /* XXX; evcnt_attach() ? */
417
418 #if 0
419 {
420 u_int x;
421
422 /* determine SCC/ESCC type */
423 x = zs_read_reg(cs, 15);
424 zs_write_reg(cs, 15, x | ZSWR15_ENABLE_ENHANCED);
425
426 if (zs_read_reg(cs, 15) & ZSWR15_ENABLE_ENHANCED) { /* ESCC Z85230 */
427 zs_write_reg(cs, 7, ZSWR7P_EXTEND_READ | ZSWR7P_TX_FIFO);
428 }
429 }
430 #endif
431
432 /*
433 * Set the master interrupt enable and interrupt vector.
434 * (common to both channels, do it on A)
435 */
436 cs = zsc->zsc_cs[0];
437 s = splhigh();
438 /* interrupt vector */
439 zs_write_reg(cs, 2, zs_init_reg[2]);
440 /* master interrupt control (enable) */
441 zs_write_reg(cs, 9, zs_init_reg[9]);
442 splx(s);
443 }
444
445 static int
446 zshard_ap(void *arg)
447 {
448
449 zshard(arg);
450 #ifdef NEWS4000_ZS_AP_POLLING
451 if (systype == NEWS4000) {
452 callout_schedule(&zscallout, 1);
453 }
454 #endif
455 return 1;
456 }
457
458 /*
459 * Polled input char.
460 */
461 int
462 zs_getc(void *arg)
463 {
464 volatile struct zschan *zc = arg;
465 int s, c;
466 uint8_t rr0;
467
468 s = splhigh();
469 /* Wait for a character to arrive. */
470 do {
471 rr0 = zc->zc_csr;
472 ZS_DELAY();
473 } while ((rr0 & ZSRR0_RX_READY) == 0);
474
475 c = zc->zc_data;
476 ZS_DELAY();
477 splx(s);
478
479 /*
480 * This is used by the kd driver to read scan codes,
481 * so don't translate '\r' ==> '\n' here...
482 */
483 return c;
484 }
485
486 /*
487 * Polled output char.
488 */
489 void
490 zs_putc(void *arg, int c)
491 {
492 volatile struct zschan *zc = arg;
493 int s;
494 uint8_t rr0;
495
496 s = splhigh();
497 /* Wait for transmitter to become ready. */
498 do {
499 rr0 = zc->zc_csr;
500 ZS_DELAY();
501 } while ((rr0 & ZSRR0_TX_READY) == 0);
502
503 zc->zc_data = c;
504 ZS_DELAY();
505 splx(s);
506 }
507
508 /*****************************************************************/
509
510 static void zscnprobe(struct consdev *);
511 static void zscninit(struct consdev *);
512 static int zscngetc(dev_t);
513 static void zscnputc(dev_t, int);
514
515 struct consdev consdev_zs_ap = {
516 zscnprobe,
517 zscninit,
518 zscngetc,
519 zscnputc,
520 nullcnpollc,
521 NULL,
522 NULL,
523 NULL,
524 NODEV,
525 CN_DEAD
526 };
527
528 static void
529 zscnprobe(struct consdev *cn)
530 {
531 }
532
533 static void
534 zscninit(struct consdev *cn)
535 {
536 extern const struct cdevsw zstty_cdevsw;
537
538 cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
539 cn->cn_pri = CN_REMOTE;
540 zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE;
541 }
542
543 static int
544 zscngetc(dev_t dev)
545 {
546 void *sccport0a;
547
548 if (systype == NEWS5000)
549 sccport0a = (void *)NEWS5000_SCCPORT0A;
550 if (systype == NEWS4000)
551 sccport0a = (void *)NEWS4000_SCCPORT0A;
552
553 return zs_getc(sccport0a);
554 }
555
556 static void
557 zscnputc(dev_t dev, int c)
558 {
559 void *sccport0a;
560
561 if (systype == NEWS5000)
562 sccport0a = (void *)NEWS5000_SCCPORT0A;
563 if (systype == NEWS4000)
564 sccport0a = (void *)NEWS4000_SCCPORT0A;
565
566 zs_putc(sccport0a, c);
567 }
568