Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: zs.c,v 1.24 2021/09/11 20:28:03 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 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.24 2021/09/11 20:28:03 andvar Exp $");
     41 
     42 #include "opt_ddb.h"
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/conf.h>
     47 #include <sys/device.h>
     48 #include <sys/file.h>
     49 #include <sys/ioctl.h>
     50 #include <sys/kernel.h>
     51 #include <sys/kmem.h>
     52 #include <sys/proc.h>
     53 #include <sys/tty.h>
     54 #include <sys/time.h>
     55 #include <sys/syslog.h>
     56 
     57 #include <dev/cons.h>
     58 #include <dev/ic/z8530reg.h>
     59 
     60 #include <machine/cpu.h>
     61 
     62 #include <machine/z8530var.h>
     63 #include <cesfic/dev/zsvar.h>
     64 
     65 #include "ioconf.h"
     66 
     67 int zs_getc(void *);
     68 void zs_putc(void*, int);
     69 
     70 static struct zs_chanstate zs_conschan_store;
     71 static int zs_hwflags[2][2];
     72 
     73 static uint8_t zs_init_reg[16] = {
     74 	0,	/* 0: CMD (reset, etc.) */
     75 	0,	/* 1: No interrupts yet. */
     76 	0x18 + ZSHARD_PRI,	/* IVECT */
     77 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
     78 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
     79 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
     80 	0,	/* 6: TXSYNC/SYNCLO */
     81 	0,	/* 7: RXSYNC/SYNCHI */
     82 	0,	/* 8: alias for data port */
     83 	ZSWR9_MASTER_IE,
     84 	0,	/*10: Misc. TX/RX control bits */
     85 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
     86 	11,	/*12: BAUDLO (default=9600) */
     87 	0,	/*13: BAUDHI (default=9600) */
     88 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
     89 	ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
     90 };
     91 
     92 static int zsc_print(void *, const char *);
     93 int zscngetc(dev_t);
     94 void zscnputc(dev_t, int);
     95 
     96 static struct consdev zscons = {
     97 	NULL, NULL,
     98 	zscngetc, zscnputc, nullcnpollc, NULL, NULL, NULL,
     99 	NODEV, 1
    100 };
    101 
    102 void
    103 zs_config(struct zsc_softc *zsc, char *base)
    104 {
    105 	struct zsc_attach_args zsc_args;
    106 	struct zs_chanstate *cs;
    107 	int zsc_unit, channel, s;
    108 
    109 	zsc_unit = device_unit(zsc->zsc_dev);
    110 	aprint_normal(": Zilog 8530 SCC\n");
    111 
    112 	/*
    113 	 * Initialize software state for each channel.
    114 	 */
    115 	for (channel = 0; channel < 2; channel++) {
    116 		zsc_args.channel = channel;
    117 		zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
    118 
    119 		/*
    120 		 * If we're the console, copy the channel state, and
    121 		 * adjust the console channel pointer.
    122 		 */
    123 		if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) {
    124 			cs = &zs_conschan_store;
    125 		} else {
    126 			cs = kmem_zalloc(sizeof(*cs), KM_SLEEP);
    127 			if(channel==0){
    128 				cs->cs_reg_csr  = base + 7;
    129 				cs->cs_reg_data = base + 15;
    130 			} else {
    131 				cs->cs_reg_csr  = base + 3;
    132 				cs->cs_reg_data = base + 11;
    133 			}
    134 			memcpy(cs->cs_creg, zs_init_reg, 16);
    135 			memcpy(cs->cs_preg, zs_init_reg, 16);
    136 			cs->cs_defspeed = 9600;
    137 		}
    138 		zsc->zsc_cs[channel] = cs;
    139 		zs_lock_init(cs);
    140 
    141 		cs->cs_defcflag = CREAD | CS8 | HUPCL;
    142 
    143 		/* Make these correspond to cs_defcflag (-crtscts) */
    144 		cs->cs_rr0_dcd = ZSRR0_DCD;
    145 		cs->cs_rr0_cts = 0;
    146 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    147 		cs->cs_wr5_rts = 0;
    148 
    149 		cs->cs_channel = channel;
    150 		cs->cs_private = NULL;
    151 		cs->cs_ops = &zsops_null;
    152 		cs->cs_brg_clk = 4000000 / 16;
    153 
    154 		/*
    155 		 * Clear the master interrupt enable.
    156 		 * The INTENA is common to both channels,
    157 		 * so just do it on the A channel.
    158 		 */
    159 		if (channel == 0) {
    160 			zs_write_reg(cs, 9, 0);
    161 		}
    162 
    163 		/*
    164 		 * Look for a child driver for this channel.
    165 		 * The child attach will setup the hardware.
    166 		 */
    167 		if (!config_found(zsc->zsc_dev, (void *)&zsc_args,
    168 		    zsc_print, CFARGS_NONE)) {
    169 			/* No sub-driver.  Just reset it. */
    170 			uint8_t reset = (channel == 0) ?
    171 				ZSWR9_A_RESET : ZSWR9_B_RESET;
    172 			s = splzs();
    173 			zs_write_reg(cs,  9, reset);
    174 			splx(s);
    175 		}
    176 	}
    177 }
    178 
    179 static int
    180 zsc_print(void *aux, const char *name)
    181 {
    182 	struct zsc_attach_args *args = aux;
    183 
    184 	if (name != NULL)
    185 		aprint_normal("%s: ", name);
    186 
    187 	if (args->channel != -1)
    188 		aprint_normal(" channel %d", args->channel);
    189 
    190 	return UNCONF;
    191 }
    192 
    193 int
    194 zshard(void *arg)
    195 {
    196 	struct zsc_softc *zsc;
    197 	int unit, rval;
    198 
    199 	rval = 0;
    200 	for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
    201 		zsc = device_lookup_private(&zsc_cd, unit);
    202 		if (zsc == NULL)
    203 			continue;
    204 		rval |= zsc_intr_hard(zsc);
    205 		if ((zsc->zsc_cs[0]->cs_softreq) ||
    206 		    (zsc->zsc_cs[1]->cs_softreq)) {
    207 			softint_schedule(zsc->zsc_softintr_cookie);
    208 		}
    209 	}
    210 	return (rval);
    211 }
    212 
    213 uint8_t
    214 zs_read_reg(struct zs_chanstate *cs, uint8_t reg)
    215 {
    216 	uint8_t val;
    217 
    218 	*cs->cs_reg_csr = reg;
    219 	ZS_DELAY();
    220 	val = *cs->cs_reg_csr;
    221 	ZS_DELAY();
    222 	return val;
    223 }
    224 
    225 void
    226 zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val)
    227 {
    228 	*cs->cs_reg_csr = reg;
    229 	ZS_DELAY();
    230 	*cs->cs_reg_csr = val;
    231 	ZS_DELAY();
    232 }
    233 
    234 uint8_t
    235 zs_read_csr(struct zs_chanstate *cs)
    236 {
    237 	uint8_t val;
    238 
    239 	val = *cs->cs_reg_csr;
    240 	ZS_DELAY();
    241 	return val;
    242 }
    243 
    244 void
    245 zs_write_csr(struct zs_chanstate *cs, uint8_t val)
    246 {
    247 
    248 	*cs->cs_reg_csr = val;
    249 	ZS_DELAY();
    250 }
    251 
    252 uint8_t
    253 zs_read_data(struct zs_chanstate *cs)
    254 {
    255 	uint8_t val;
    256 
    257 	val = *cs->cs_reg_data;
    258 	ZS_DELAY();
    259 	return val;
    260 }
    261 
    262 void
    263 zs_write_data(struct zs_chanstate *cs, uint8_t val)
    264 {
    265 
    266 	*cs->cs_reg_data = val;
    267 	ZS_DELAY();
    268 }
    269 
    270 int
    271 zs_set_speed(struct zs_chanstate *cs, int bps)
    272 {
    273 	int tconst;
    274 
    275 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
    276 
    277 	if (tconst < 0)
    278 		return (EINVAL);
    279 
    280 #if 0
    281 	/* Convert back to make sure we can do it. */
    282 	int real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
    283 	/* XXX - Allow some tolerance here? */
    284 	if (real_bps != bps)
    285 		return (EINVAL);
    286 #endif
    287 	cs->cs_preg[12] = tconst;
    288 	cs->cs_preg[13] = tconst >> 8;
    289 
    290 	return (0);
    291 }
    292 
    293 int
    294 zs_set_modes(struct zs_chanstate *cs, int cflag)
    295 {
    296 	int s;
    297 
    298 	/*
    299 	 * Output hardware flow control on the chip is horrendous:
    300 	 * if carrier detect drops, the receiver is disabled, and if
    301 	 * CTS drops, the transmitter is stopped IN MID CHARACTER!
    302 	 * Therefore, NEVER set the HFC bit, and instead use the
    303 	 * status interrupt to detect CTS changes.
    304 	 */
    305 	s = splzs();
    306 #if 0	/* XXX - See below. */
    307 	if (cflag & CLOCAL) {
    308 		cs->cs_rr0_dcd = 0;
    309 		cs->cs_preg[15] &= ~ZSWR15_DCD_IE;
    310 	} else {
    311 		/* XXX - Need to notice DCD change here... */
    312 		cs->cs_rr0_dcd = ZSRR0_DCD;
    313 		cs->cs_preg[15] |= ZSWR15_DCD_IE;
    314 	}
    315 #endif	/* XXX */
    316 	if (cflag & CRTSCTS) {
    317 		cs->cs_wr5_dtr = ZSWR5_DTR;
    318 		cs->cs_wr5_rts = ZSWR5_RTS;
    319 		cs->cs_rr0_cts = ZSRR0_CTS;
    320 		cs->cs_preg[15] |= ZSWR15_CTS_IE;
    321 	} else {
    322 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    323 		cs->cs_wr5_rts = 0;
    324 		cs->cs_rr0_cts = 0;
    325 		cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
    326 	}
    327 	splx(s);
    328 
    329 	/* Caller will stuff the pending registers. */
    330 	return (0);
    331 }
    332 
    333 /*
    334  * Handle user request to enter kernel debugger.
    335  */
    336 void
    337 zs_abort(struct zs_chanstate *cs)
    338 {
    339 	int rr0;
    340 
    341 	/* Wait for end of break to avoid PROM abort. */
    342 	/* XXX - Limit the wait? */
    343 	do {
    344 		rr0 = *cs->cs_reg_csr;
    345 		ZS_DELAY();
    346 	} while (rr0 & ZSRR0_BREAK);
    347 #ifdef DDB
    348 	console_debugger();
    349 #endif
    350 }
    351 
    352 /*
    353  * Polled input char.
    354  */
    355 int
    356 zs_getc(void *arg)
    357 {
    358 	struct zs_chanstate *cs = arg;
    359 	int s, c;
    360 	uint8_t rr0, stat;
    361 
    362 	s = splhigh();
    363 top:
    364 	/* Wait for a character to arrive. */
    365 	do {
    366 		rr0 = *cs->cs_reg_csr;
    367 		ZS_DELAY();
    368 	} while ((rr0 & ZSRR0_RX_READY) == 0);
    369 
    370 	/* Read error register. */
    371 	stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE);
    372 	if (stat) {
    373 		zs_write_csr(cs, ZSM_RESET_ERR);
    374 		goto top;
    375 	}
    376 
    377 	/* Read character. */
    378 	c = *cs->cs_reg_data;
    379 	ZS_DELAY();
    380 	splx(s);
    381 
    382 	return (c);
    383 }
    384 
    385 /*
    386  * Polled output char.
    387  */
    388 void
    389 zs_putc(void *arg, int c)
    390 {
    391 	struct zs_chanstate *cs = arg;
    392 	int s;
    393 	uint8_t rr0;
    394 
    395 	s = splhigh();
    396 	/* Wait for transmitter to become ready. */
    397 	do {
    398 		rr0 = *cs->cs_reg_csr;
    399 		ZS_DELAY();
    400 	} while ((rr0 & ZSRR0_TX_READY) == 0);
    401 
    402 	*cs->cs_reg_data = c;
    403 	ZS_DELAY();
    404 	splx(s);
    405 }
    406 
    407 int
    408 zscngetc(dev_t dev)
    409 {
    410 	struct zs_chanstate *cs = &zs_conschan_store;
    411 	int c;
    412 
    413 	c = zs_getc(cs);
    414 	return (c);
    415 }
    416 
    417 void
    418 zscnputc(dev_t dev, int c)
    419 {
    420 	struct zs_chanstate *cs = &zs_conschan_store;
    421 
    422 	zs_putc(cs, c);
    423 }
    424 
    425 /*
    426  * Common parts of console init.
    427  */
    428 void
    429 zs_cninit(void *base)
    430 {
    431 	struct zs_chanstate *cs;
    432 	/*
    433 	 * Pointer to channel state.  Later, the console channel
    434 	 * state is copied into the softc, and the console channel
    435 	 * pointer adjusted to point to the new copy.
    436 	 */
    437 	cs = &zs_conschan_store;
    438 	zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE;
    439 
    440 	/* Setup temporary chanstate. */
    441 	cs->cs_reg_csr  = (uint8_t *)base + 7;
    442 	cs->cs_reg_data = (uint8_t *)base + 15;
    443 
    444 	/* Initialize the pending registers. */
    445 	memcpy(cs->cs_preg, zs_init_reg, 16);
    446 	cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
    447 
    448 	/* XXX: Preserve BAUD rate from boot loader. */
    449 	/* XXX: Also, why reset the chip here? -gwr */
    450 	/* cs->cs_defspeed = zs_get_speed(cs); */
    451 	cs->cs_defspeed = 9600;	/* XXX */
    452 
    453 	/* Clear the master interrupt enable. */
    454 	zs_write_reg(cs, 9, 0);
    455 
    456 	/* Reset the whole SCC chip. */
    457 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    458 
    459 	/* Copy "pending" to "current" and H/W. */
    460 	zs_loadchannelregs(cs);
    461 
    462 	/* Point the console at the SCC. */
    463 	cn_tab = &zscons;
    464 }
    465