1 /* $NetBSD: zs.c,v 1.7 2003/04/09 11:04:41 drochner 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Zilog Z8530 Dual UART driver (machine-dependent part) 41 * 42 * Runs two serial lines per chip using slave drivers. 43 * Plain tty/async lines use the zs_async slave. 44 */ 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/file.h> 53 #include <sys/ioctl.h> 54 #include <sys/kernel.h> 55 #include <sys/malloc.h> 56 #include <sys/proc.h> 57 #include <sys/tty.h> 58 #include <sys/time.h> 59 #include <sys/syslog.h> 60 61 #include <dev/cons.h> 62 #include <dev/ic/z8530reg.h> 63 64 #include <machine/cpu.h> 65 66 #include <machine/z8530var.h> 67 #include <cesfic/dev/zsvar.h> 68 69 int zs_getc __P((void*)); 70 void zs_putc __P((void*, int)); 71 72 static struct zs_chanstate zs_conschan_store; 73 static int zs_hwflags[2][2]; 74 int zssoftpending; 75 76 extern struct cfdriver zsc_cd; 77 78 u_char zs_init_reg[16] = { 79 0, /* 0: CMD (reset, etc.) */ 80 0, /* 1: No interrupts yet. */ 81 0x18 + ZSHARD_PRI, /* IVECT */ 82 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 83 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 84 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 85 0, /* 6: TXSYNC/SYNCLO */ 86 0, /* 7: RXSYNC/SYNCHI */ 87 0, /* 8: alias for data port */ 88 ZSWR9_MASTER_IE, 89 0, /*10: Misc. TX/RX control bits */ 90 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 91 11, /*12: BAUDLO (default=9600) */ 92 0, /*13: BAUDHI (default=9600) */ 93 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 94 ZSWR15_BREAK_IE | ZSWR15_DCD_IE, 95 }; 96 97 static int zsc_print __P((void *, const char *)); 98 int zscngetc __P((dev_t)); 99 void zscnputc __P((dev_t, int)); 100 101 static struct consdev zscons = { 102 NULL, NULL, 103 zscngetc, zscnputc, nullcnpollc, NULL, NULL, NULL, 104 NODEV, 1 105 }; 106 107 void 108 zs_config(zsc, base) 109 struct zsc_softc *zsc; 110 char *base; 111 { 112 struct zsc_attach_args zsc_args; 113 struct zs_chanstate *cs; 114 int zsc_unit, channel, s; 115 116 zsc_unit = zsc->zsc_dev.dv_unit; 117 printf(": Zilog 8530 SCC\n"); 118 119 /* 120 * Initialize software state for each channel. 121 */ 122 for (channel = 0; channel < 2; channel++) { 123 zsc_args.channel = channel; 124 zsc_args.hwflags = zs_hwflags[zsc_unit][channel]; 125 126 /* 127 * If we're the console, copy the channel state, and 128 * adjust the console channel pointer. 129 */ 130 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 131 cs = &zs_conschan_store; 132 } else { 133 cs = malloc(sizeof(struct zs_chanstate), 134 M_DEVBUF, M_NOWAIT | M_ZERO); 135 if(channel==0){ 136 cs->cs_reg_csr = base+7; 137 cs->cs_reg_data = base+15; 138 } else { 139 cs->cs_reg_csr = base+3; 140 cs->cs_reg_data = base+11; 141 } 142 bcopy(zs_init_reg, cs->cs_creg, 16); 143 bcopy(zs_init_reg, cs->cs_preg, 16); 144 cs->cs_defspeed = 9600; 145 } 146 zsc->zsc_cs[channel] = cs; 147 simple_lock_init(&cs->cs_lock); 148 149 cs->cs_defcflag = CREAD | CS8 | HUPCL; 150 151 /* Make these correspond to cs_defcflag (-crtscts) */ 152 cs->cs_rr0_dcd = ZSRR0_DCD; 153 cs->cs_rr0_cts = 0; 154 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 155 cs->cs_wr5_rts = 0; 156 157 cs->cs_channel = channel; 158 cs->cs_private = NULL; 159 cs->cs_ops = &zsops_null; 160 cs->cs_brg_clk = 4000000 / 16; 161 162 /* 163 * Clear the master interrupt enable. 164 * The INTENA is common to both channels, 165 * so just do it on the A channel. 166 */ 167 if (channel == 0) { 168 zs_write_reg(cs, 9, 0); 169 } 170 171 /* 172 * Look for a child driver for this channel. 173 * The child attach will setup the hardware. 174 */ 175 if (!config_found(&zsc->zsc_dev, (void *)&zsc_args, zsc_print)) { 176 /* No sub-driver. Just reset it. */ 177 u_char reset = (channel == 0) ? 178 ZSWR9_A_RESET : ZSWR9_B_RESET; 179 s = splzs(); 180 zs_write_reg(cs, 9, reset); 181 splx(s); 182 } 183 } 184 } 185 186 static int 187 zsc_print(aux, name) 188 void *aux; 189 const char *name; 190 { 191 struct zsc_attach_args *args = aux; 192 193 if (name != NULL) 194 aprint_normal("%s: ", name); 195 196 if (args->channel != -1) 197 aprint_normal(" channel %d", args->channel); 198 199 return UNCONF; 200 } 201 202 int 203 zshard(arg) 204 void *arg; 205 { 206 register struct zsc_softc *zsc; 207 register int unit, rval; 208 209 rval = 0; 210 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 211 zsc = zsc_cd.cd_devs[unit]; 212 if (zsc == NULL) 213 continue; 214 rval |= zsc_intr_hard(zsc); 215 if ((zsc->zsc_cs[0]->cs_softreq) || 216 (zsc->zsc_cs[1]->cs_softreq)) 217 { 218 /* zsc_req_softint(zsc); */ 219 /* We are at splzs here, so no need to lock. */ 220 if (zssoftpending == 0) { 221 zssoftpending = 1; 222 setsoftzs(); 223 } 224 } 225 } 226 return (rval); 227 } 228 229 void 230 softzs() 231 { 232 register struct zsc_softc *zsc; 233 register int unit; 234 235 /* This is not the only ISR on this IPL. */ 236 if (zssoftpending == 0) 237 return; 238 239 /* 240 * The soft intr. bit will be set by zshard only if 241 * the variable zssoftpending is zero. 242 */ 243 zssoftpending = 0; 244 245 for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) { 246 zsc = zsc_cd.cd_devs[unit]; 247 if (zsc == NULL) 248 continue; 249 (void) zsc_intr_soft(zsc); 250 } 251 return; 252 } 253 254 u_char 255 zs_read_reg(cs, reg) 256 struct zs_chanstate *cs; 257 u_char reg; 258 { 259 u_char val; 260 261 *cs->cs_reg_csr = reg; 262 ZS_DELAY(); 263 val = *cs->cs_reg_csr; 264 ZS_DELAY(); 265 return val; 266 } 267 268 void 269 zs_write_reg(cs, reg, val) 270 struct zs_chanstate *cs; 271 u_char reg, val; 272 { 273 *cs->cs_reg_csr = reg; 274 ZS_DELAY(); 275 *cs->cs_reg_csr = val; 276 ZS_DELAY(); 277 } 278 279 u_char zs_read_csr(cs) 280 struct zs_chanstate *cs; 281 { 282 register u_char val; 283 284 val = *cs->cs_reg_csr; 285 ZS_DELAY(); 286 return val; 287 } 288 289 void zs_write_csr(cs, val) 290 struct zs_chanstate *cs; 291 u_char val; 292 { 293 *cs->cs_reg_csr = val; 294 ZS_DELAY(); 295 } 296 297 u_char zs_read_data(cs) 298 struct zs_chanstate *cs; 299 { 300 register u_char val; 301 302 val = *cs->cs_reg_data; 303 ZS_DELAY(); 304 return val; 305 } 306 307 void zs_write_data(cs, val) 308 struct zs_chanstate *cs; 309 u_char val; 310 { 311 *cs->cs_reg_data = val; 312 ZS_DELAY(); 313 } 314 315 int 316 zs_set_speed(cs, bps) 317 struct zs_chanstate *cs; 318 int bps; /* bits per second */ 319 { 320 int tconst, real_bps; 321 322 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 323 324 if (tconst < 0) 325 return (EINVAL); 326 327 /* Convert back to make sure we can do it. */ 328 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 329 #if 0 330 /* XXX - Allow some tolerance here? */ 331 if (real_bps != bps) 332 return (EINVAL); 333 #endif 334 cs->cs_preg[12] = tconst; 335 cs->cs_preg[13] = tconst >> 8; 336 337 return (0); 338 } 339 340 int 341 zs_set_modes(cs, cflag) 342 struct zs_chanstate *cs; 343 int cflag; /* bits per second */ 344 { 345 int s; 346 347 /* 348 * Output hardware flow control on the chip is horrendous: 349 * if carrier detect drops, the receiver is disabled, and if 350 * CTS drops, the transmitter is stoped IN MID CHARACTER! 351 * Therefore, NEVER set the HFC bit, and instead use the 352 * status interrupt to detect CTS changes. 353 */ 354 s = splzs(); 355 #if 0 /* XXX - See below. */ 356 if (cflag & CLOCAL) { 357 cs->cs_rr0_dcd = 0; 358 cs->cs_preg[15] &= ~ZSWR15_DCD_IE; 359 } else { 360 /* XXX - Need to notice DCD change here... */ 361 cs->cs_rr0_dcd = ZSRR0_DCD; 362 cs->cs_preg[15] |= ZSWR15_DCD_IE; 363 } 364 #endif /* XXX */ 365 if (cflag & CRTSCTS) { 366 cs->cs_wr5_dtr = ZSWR5_DTR; 367 cs->cs_wr5_rts = ZSWR5_RTS; 368 cs->cs_rr0_cts = ZSRR0_CTS; 369 cs->cs_preg[15] |= ZSWR15_CTS_IE; 370 } else { 371 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 372 cs->cs_wr5_rts = 0; 373 cs->cs_rr0_cts = 0; 374 cs->cs_preg[15] &= ~ZSWR15_CTS_IE; 375 } 376 splx(s); 377 378 /* Caller will stuff the pending registers. */ 379 return (0); 380 } 381 382 /* 383 * Handle user request to enter kernel debugger. 384 */ 385 void 386 zs_abort(cs) 387 struct zs_chanstate *cs; 388 { 389 int rr0; 390 391 /* Wait for end of break to avoid PROM abort. */ 392 /* XXX - Limit the wait? */ 393 do { 394 rr0 = *cs->cs_reg_csr; 395 ZS_DELAY(); 396 } while (rr0 & ZSRR0_BREAK); 397 #ifdef DDB 398 console_debugger(); 399 #endif 400 } 401 402 /* 403 * Polled input char. 404 */ 405 int 406 zs_getc(arg) 407 void *arg; 408 { 409 register struct zs_chanstate *cs = arg; 410 register int s, c, rr0, stat; 411 412 s = splhigh(); 413 top: 414 /* Wait for a character to arrive. */ 415 do { 416 rr0 = *cs->cs_reg_csr; 417 ZS_DELAY(); 418 } while ((rr0 & ZSRR0_RX_READY) == 0); 419 420 /* Read error register. */ 421 stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE); 422 if (stat) { 423 zs_write_csr(cs, ZSM_RESET_ERR); 424 goto top; 425 } 426 427 /* Read character. */ 428 c = *cs->cs_reg_data; 429 ZS_DELAY(); 430 splx(s); 431 432 return (c); 433 } 434 435 /* 436 * Polled output char. 437 */ 438 void 439 zs_putc(arg, c) 440 void *arg; 441 int c; 442 { 443 register struct zs_chanstate *cs = arg; 444 register int s, rr0; 445 446 s = splhigh(); 447 /* Wait for transmitter to become ready. */ 448 do { 449 rr0 = *cs->cs_reg_csr; 450 ZS_DELAY(); 451 } while ((rr0 & ZSRR0_TX_READY) == 0); 452 453 *cs->cs_reg_data = c; 454 ZS_DELAY(); 455 splx(s); 456 } 457 458 int zscngetc(dev) 459 dev_t dev; 460 { 461 register struct zs_chanstate *cs = &zs_conschan_store; 462 register int c; 463 464 c = zs_getc(cs); 465 return (c); 466 } 467 468 void zscnputc(dev, c) 469 dev_t dev; 470 int c; 471 { 472 register struct zs_chanstate *cs = &zs_conschan_store; 473 474 zs_putc(cs, c); 475 } 476 477 /* 478 * Common parts of console init. 479 */ 480 void 481 zs_cninit(base) 482 void *base; 483 { 484 struct zs_chanstate *cs; 485 /* 486 * Pointer to channel state. Later, the console channel 487 * state is copied into the softc, and the console channel 488 * pointer adjusted to point to the new copy. 489 */ 490 cs = &zs_conschan_store; 491 zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE; 492 493 /* Setup temporary chanstate. */ 494 cs->cs_reg_csr = (char *)base + 7; 495 cs->cs_reg_data = (char *)base + 15; 496 497 /* Initialize the pending registers. */ 498 bcopy(zs_init_reg, cs->cs_preg, 16); 499 cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS); 500 501 /* XXX: Preserve BAUD rate from boot loader. */ 502 /* XXX: Also, why reset the chip here? -gwr */ 503 /* cs->cs_defspeed = zs_get_speed(cs); */ 504 cs->cs_defspeed = 9600; /* XXX */ 505 506 /* Clear the master interrupt enable. */ 507 zs_write_reg(cs, 9, 0); 508 509 /* Reset the whole SCC chip. */ 510 zs_write_reg(cs, 9, ZSWR9_HARD_RESET); 511 512 /* Copy "pending" to "current" and H/W. */ 513 zs_loadchannelregs(cs); 514 515 /* Point the console at the SCC. */ 516 cn_tab = &zscons; 517 } 518