1 /*        $NetBSD: zs.c,v 1.34 2021/09/11 20:28:04 andvar 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  */
38 
39 /*
40  * news68k/dev/zs.c - based on {newsmips,x68k,mvme68k}/dev/zs.c
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.34 2021/09/11 20:28:04 andvar Exp $");
45 
46 #include "opt_ddb.h"
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/conf.h>
51 #include <sys/device.h>
52 #include <sys/tty.h>
53 #include <sys/cpu.h>
54 #include <sys/intr.h>
55 
56 #include <machine/z8530var.h>
57 
58 #include <dev/cons.h>
59 #include <dev/ic/z8530reg.h>
60 
61 #include <news68k/dev/hbvar.h>
62 
63 #include "ioconf.h"
64 
65 int  zs_getc(void *);
66 void zs_putc(void *, int);
67 
68 /*
69  * Some warts needed by z8530tty.c -
70  * The default parity REALLY needs to be the same as the PROM uses,
71  * or you can not see messages done with printf during boot-up...
72  */
73 int zs_def_cflag = (CREAD | CS8 | HUPCL);
74 
75 /*
76  * The news68k machines use three different clocks for the ZS chips.
77  */
78 #define NPCLK       3
79 #define PCLK0       (9600 * 416)        /*  news1700: 3.9936MHz */
80 #define PCLK1       (9600 * 512)        /*  news1200: 4.9152MHz */
81 #define PCLK2       (9600 * 384)        /*  external: 3.6864MHz */
82 
83 static const u_int pclk[NPCLK] = {
84           PCLK0,
85           PCLK1,
86           PCLK2,
87 };
88 
89 /*
90  * Define interrupt levels.
91  */
92 #define ZSHARD_PRI 5
93 #define ZS_IVECT 64
94 
95 #define ZS_DELAY() /* delay(2) */
96 
97 /* The layout of this is hardware-dependent (padding, order). */
98 struct zschan {
99           volatile uint8_t zc_csr;      /* ctrl,status, and indirect access */
100           volatile uint8_t zc_data;     /* data */
101 };
102 struct zsdevice {
103           /* Yes, they are backwards. */
104           struct    zschan zs_chan_b;
105           struct    zschan zs_chan_a;
106 };
107 
108 /* Default speed for all channels */
109 static int zs_defspeed = 9600;
110 
111 /* console status from cninit */
112 static struct zs_chanstate zs_conschan_store;
113 static struct zs_chanstate *zs_conschan;
114 static struct zschan *zc_cons;
115 
116 static uint8_t zs_init_reg[16] = {
117           0,        /* 0: CMD (reset, etc.) */
118           0,        /* 1: No interrupts yet. */
119           ZS_IVECT, /* IVECT */
120           ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
121           ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
122           ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
123           0,        /* 6: TXSYNC/SYNCLO */
124           0,        /* 7: RXSYNC/SYNCHI */
125           0,        /* 8: alias for data port */
126           ZSWR9_MASTER_IE,
127           0,        /*10: Misc. TX/RX control bits */
128           ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
129           BPS_TO_TCONST((PCLK0/16), 9600), /*12: BAUDLO (default=9600) */
130           0,                            /*13: BAUDHI (default=9600) */
131           ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
132           ZSWR15_BREAK_IE,
133 };
134 
135 
136 /****************************************************************
137  * Autoconfig
138  ****************************************************************/
139 
140 /* Definition of the driver for autoconfig. */
141 static int  zs_match(device_t, cfdata_t, void *);
142 static void zs_attach(device_t, device_t, void *);
143 static int  zs_print(void *, const char *name);
144 
145 CFATTACH_DECL_NEW(zsc, sizeof(struct zsc_softc),
146     zs_match, zs_attach, NULL, NULL);
147 
148 static int zshard(void *);
149 #if 0
150 static int zs_get_speed(struct zs_chanstate *);
151 #endif
152 
153 /*
154  * Is the zs chip present?
155  */
156 static int
zs_match(device_t parent,cfdata_t cf,void * aux)157 zs_match(device_t parent, cfdata_t cf, void *aux)
158 {
159           struct hb_attach_args *ha = aux;
160           u_int addr;
161 
162           if (strcmp(ha->ha_name, "zsc"))
163                     return 0;
164 
165           /* XXX no default address */
166           if (ha->ha_address == (u_int)-1)
167                     return 0;
168 
169           addr = (ha->ha_address);
170           /* This returns -1 on a fault (bus error). */
171           if (badaddr((void *)addr, 1))
172                     return 0;
173 
174           return 1;
175 }
176 
177 /*
178  * Attach a found zs.
179  */
180 static void
zs_attach(device_t parent,device_t self,void * aux)181 zs_attach(device_t parent, device_t self, void *aux)
182 {
183           struct zsc_softc *zsc = device_private(self);
184           struct cfdata *cf = device_cfdata(self);
185           struct hb_attach_args *ha = aux;
186           struct zsc_attach_args zsc_args;
187           struct zsdevice *zs;
188           struct zschan *zc;
189           struct zs_chanstate *cs;
190           int s, channel, clk;
191 
192           zsc->zsc_dev = self;
193 
194           zs = (void *)(ha->ha_address);
195 
196           clk = cf->cf_flags;
197           if (clk < 0 || clk >= NPCLK)
198                     clk = 0;
199 
200           aprint_normal("\n");
201 
202           /*
203            * Initialize software state for each channel.
204            */
205           for (channel = 0; channel < 2; channel++) {
206                     zsc_args.channel = channel;
207                     cs = &zsc->zsc_cs_store[channel];
208 
209                     zsc->zsc_cs[channel] = cs;
210                     zc = (channel == 0) ? &zs->zs_chan_a : &zs->zs_chan_b;
211 
212                     if (ha->ha_vect != -1)
213                               zs_init_reg[2] = ha->ha_vect;
214 
215                     if (zc == zc_cons) {
216                               memcpy(cs, zs_conschan, sizeof(struct zs_chanstate));
217                               zs_conschan = cs;
218                               zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
219                     } else {
220                               cs->cs_reg_csr  = &zc->zc_csr;
221                               cs->cs_reg_data = &zc->zc_data;
222                               memcpy(cs->cs_creg, zs_init_reg, 16);
223                               memcpy(cs->cs_preg, zs_init_reg, 16);
224                               cs->cs_defspeed = zs_defspeed;
225                               zsc_args.hwflags = 0;
226                     }
227 
228                     zs_lock_init(cs);
229                     cs->cs_defcflag = zs_def_cflag;
230 
231                     cs->cs_channel = channel;
232                     cs->cs_private = NULL;
233                     cs->cs_ops = &zsops_null;
234                     cs->cs_brg_clk = pclk[clk] / 16;
235 
236                     /* Make these correspond to cs_defcflag (-crtscts) */
237                     cs->cs_rr0_dcd = ZSRR0_DCD;
238                     cs->cs_rr0_cts = 0;
239                     cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
240                     cs->cs_wr5_rts = 0;
241 
242                     /*
243                      * Clear the master interrupt enable.
244                      * The INTENA is common to both channels,
245                      * so just do it on the A channel.
246                      */
247                     if (channel == 0) {
248                               s = splhigh();
249                               zs_write_reg(cs, 9, 0);
250                               splx(s);
251                     }
252 
253                     /*
254                      * Look for a child driver for this channel.
255                      * The child attach will setup the hardware.
256                      */
257                     if (!config_found(self, (void *)&zsc_args, zs_print,
258                         CFARGS_NONE)) {
259                               /* No sub-driver.  Just reset it. */
260                               uint8_t reset = (channel == 0) ?
261                                         ZSWR9_A_RESET : ZSWR9_B_RESET;
262                               s = splhigh();
263                               zs_write_reg(cs,  9, reset);
264                               splx(s);
265                     }
266           }
267 
268           /*
269            * Now safe to install interrupt handlers.
270            */
271           hb_intr_establish(zs_init_reg[2], zshard, ZSHARD_PRI, zsc);
272           zsc->zsc_softintr_cookie = softint_establish(SOFTINT_SERIAL,
273               (void (*)(void *))zsc_intr_soft, zsc);
274 
275           /*
276            * Set the master interrupt enable and interrupt vector.
277            * (common to both channels, do it on A)
278            */
279           cs = zsc->zsc_cs[0];
280           s = splhigh();
281           /* interrupt vector */
282           zs_write_reg(cs, 2, zs_init_reg[2]);
283           /* master interrupt control (enable) */
284           zs_write_reg(cs, 9, zs_init_reg[9]);
285           splx(s);
286 
287 }
288 
289 static int
zs_print(void * aux,const char * name)290 zs_print(void *aux, const char *name)
291 {
292           struct zsc_attach_args *args = aux;
293 
294           if (name != NULL)
295                     aprint_normal("%s: ", name);
296 
297           if (args->channel != -1)
298                     aprint_normal(" channel %d", args->channel);
299 
300           return UNCONF;
301 }
302 
303 /*
304  * For news68k-port, we don't use autovectored interrupt.
305  * We do not need to look at all of the zs chips.
306  */
307 static int
zshard(void * arg)308 zshard(void *arg)
309 {
310           struct zsc_softc *zsc = arg;
311           int rval;
312 
313           rval = zsc_intr_hard(zsc);
314 
315           /* We are at splzs here, so no need to lock. */
316           if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) {
317                     softint_schedule(zsc->zsc_softintr_cookie);
318           }
319 
320           return rval;
321 }
322 
323 /*
324  * Compute the current baud rate given a ZS channel.
325  */
326 #if 0
327 static int
328 zs_get_speed(struct zs_chanstate *cs)
329 {
330           int tconst;
331 
332           tconst = zs_read_reg(cs, 12);
333           tconst |= zs_read_reg(cs, 13) << 8;
334           return TCONST_TO_BPS(cs->cs_brg_clk, tconst);
335 }
336 #endif
337 
338 /*
339  * MD functions for setting the baud rate and control modes.
340  */
341 int
zs_set_speed(struct zs_chanstate * cs,int bps)342 zs_set_speed(struct zs_chanstate *cs, int bps)
343 {
344           int tconst, real_bps;
345 
346           if (bps == 0)
347                     return 0;
348 
349 #ifdef    DIAGNOSTIC
350           if (cs->cs_brg_clk == 0)
351                     panic("zs_set_speed");
352 #endif
353 
354           tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
355           if (tconst < 0)
356                     return EINVAL;
357 
358           /* Convert back to make sure we can do it. */
359           real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
360 
361           /* XXX - Allow some tolerance here? */
362           if (real_bps != bps)
363                     return EINVAL;
364 
365           cs->cs_preg[12] = tconst;
366           cs->cs_preg[13] = tconst >> 8;
367 
368           /* Caller will stuff the pending registers. */
369           return 0;
370 }
371 
372 int
zs_set_modes(struct zs_chanstate * cs,int cflag)373 zs_set_modes(struct zs_chanstate *cs, int cflag)
374 {
375           int s;
376 
377           /*
378            * Output hardware flow control on the chip is horrendous:
379            * if carrier detect drops, the receiver is disabled, and if
380            * CTS drops, the transmitter is stopped IN MID CHARACTER!
381            * Therefore, NEVER set the HFC bit, and instead use the
382            * status interrupt to detect CTS changes.
383            */
384           s = splzs();
385           cs->cs_rr0_pps = 0;
386           if ((cflag & (CLOCAL | MDMBUF)) != 0) {
387                     cs->cs_rr0_dcd = 0;
388                     if ((cflag & MDMBUF) == 0)
389                               cs->cs_rr0_pps = ZSRR0_DCD;
390           } else
391                     cs->cs_rr0_dcd = ZSRR0_DCD;
392           if ((cflag & CRTSCTS) != 0) {
393                     cs->cs_wr5_dtr = ZSWR5_DTR;
394                     cs->cs_wr5_rts = ZSWR5_RTS;
395                     cs->cs_rr0_cts = ZSRR0_CTS;
396           } else if ((cflag & MDMBUF) != 0) {
397                     cs->cs_wr5_dtr = 0;
398                     cs->cs_wr5_rts = ZSWR5_DTR;
399                     cs->cs_rr0_cts = ZSRR0_DCD;
400           } else {
401                     cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
402                     cs->cs_wr5_rts = 0;
403                     cs->cs_rr0_cts = 0;
404           }
405           splx(s);
406 
407           /* Caller will stuff the pending registers. */
408           return 0;
409 }
410 
411 
412 /*
413  * Read or write the chip with suitable delays.
414  */
415 
416 uint8_t
zs_read_reg(struct zs_chanstate * cs,uint8_t reg)417 zs_read_reg(struct zs_chanstate *cs, uint8_t reg)
418 {
419           uint8_t val;
420 
421           *cs->cs_reg_csr = reg;
422           ZS_DELAY();
423           val = *cs->cs_reg_csr;
424           ZS_DELAY();
425           return val;
426 }
427 
428 void
zs_write_reg(struct zs_chanstate * cs,uint8_t reg,uint8_t val)429 zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val)
430 {
431 
432           *cs->cs_reg_csr = reg;
433           ZS_DELAY();
434           *cs->cs_reg_csr = val;
435           ZS_DELAY();
436 }
437 
438 uint8_t
zs_read_csr(struct zs_chanstate * cs)439 zs_read_csr(struct zs_chanstate *cs)
440 {
441           uint8_t val;
442 
443           val = *cs->cs_reg_csr;
444           ZS_DELAY();
445           return val;
446 }
447 
448 void
zs_write_csr(struct zs_chanstate * cs,uint8_t val)449 zs_write_csr(struct zs_chanstate *cs, uint8_t val)
450 {
451 
452           *cs->cs_reg_csr = val;
453           ZS_DELAY();
454 }
455 
456 uint8_t
zs_read_data(struct zs_chanstate * cs)457 zs_read_data(struct zs_chanstate *cs)
458 {
459           uint8_t val;
460 
461           val = *cs->cs_reg_data;
462           ZS_DELAY();
463           return val;
464 }
465 
466 void
zs_write_data(struct zs_chanstate * cs,uint8_t val)467 zs_write_data(struct zs_chanstate *cs, uint8_t val)
468 {
469 
470           *cs->cs_reg_data = val;
471           ZS_DELAY();
472 }
473 
474 void
zs_abort(struct zs_chanstate * cs)475 zs_abort(struct zs_chanstate *cs)
476 {
477 
478 #ifdef DDB
479           Debugger();
480 #endif
481 }
482 
483 /*
484  * Polled input char.
485  */
486 int
zs_getc(void * arg)487 zs_getc(void *arg)
488 {
489           struct zs_chanstate *cs = arg;
490           int s, c, rr0;
491 
492           s = splhigh();
493           /* Wait for a character to arrive. */
494           do {
495                     rr0 = *cs->cs_reg_csr;
496                     ZS_DELAY();
497           } while ((rr0 & ZSRR0_RX_READY) == 0);
498 
499           c = *cs->cs_reg_data;
500           ZS_DELAY();
501           splx(s);
502 
503           return c;
504 }
505 
506 /*
507  * Polled output char.
508  */
509 void
zs_putc(void * arg,int c)510 zs_putc(void *arg, int c)
511 {
512           struct zs_chanstate *cs = arg;
513           int s, rr0;
514 
515           s = splhigh();
516           /* Wait for transmitter to become ready. */
517           do {
518                     rr0 = *cs->cs_reg_csr;
519                     ZS_DELAY();
520           } while ((rr0 & ZSRR0_TX_READY) == 0);
521 
522           *cs->cs_reg_data = c;
523           ZS_DELAY();
524           splx(s);
525 }
526 
527 /*****************************************************************/
528 
529 static void zscnprobe(struct consdev *);
530 static void zscninit(struct consdev *);
531 static int  zscngetc(dev_t);
532 static void zscnputc(dev_t, int);
533 
534 struct consdev consdev_zs = {
535           zscnprobe,
536           zscninit,
537           zscngetc,
538           zscnputc,
539           nullcnpollc,
540           NULL,
541           NULL,
542           NULL,
543           NODEV,
544           CN_DEAD
545 };
546 
547 static void
zscnprobe(struct consdev * cn)548 zscnprobe(struct consdev *cn)
549 {
550 }
551 
552 static void
zscninit(struct consdev * cn)553 zscninit(struct consdev *cn)
554 {
555           struct zs_chanstate *cs;
556 
557           extern const struct cdevsw zstty_cdevsw;
558           extern int tty00_is_console;
559           extern uint32_t sccport0a;
560 
561           cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
562           if (tty00_is_console)
563                     cn->cn_pri = CN_REMOTE;
564           else
565                     cn->cn_pri = CN_NORMAL;
566 
567           zc_cons = (struct zschan *)sccport0a; /* XXX */
568 
569           zs_conschan = cs = &zs_conschan_store;
570 
571           /* Setup temporary chanstate. */
572           cs->cs_reg_csr  = &zc_cons->zc_csr;
573           cs->cs_reg_data = &zc_cons->zc_data;
574 
575           /* Initialize the pending registers. */
576           memcpy(cs->cs_preg, zs_init_reg, 16);
577           cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
578 
579           cs->cs_preg[12] = BPS_TO_TCONST(pclk[systype] / 16, 9600); /* XXX */
580           cs->cs_preg[13] = 0;
581           cs->cs_defspeed = 9600;
582 
583           /* Clear the master interrupt enable. */
584           zs_write_reg(cs, 9, 0);
585 
586           /* Reset the whole SCC chip. */
587           zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
588 
589           /* Copy "pending" to "current" and H/W */
590           zs_loadchannelregs(cs);
591 }
592 
593 static int
zscngetc(dev_t dev)594 zscngetc(dev_t dev)
595 {
596 
597           return zs_getc((void *)zs_conschan);
598 }
599 
600 static void
zscnputc(dev_t dev,int c)601 zscnputc(dev_t dev, int c)
602 {
603 
604           zs_putc((void *)zs_conschan, c);
605 }
606