1 /* $NetBSD: zs.c,v 1.22 2021/04/24 23:36:30 thorpej 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.22 2021/04/24 23:36:30 thorpej 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, CFARG_EOL)) { 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 stoped 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