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