1/* $NetBSD: zs.c,v 1.41 2008/06/13 12:26:02 cegger 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 * Modified for NetBSD/mvme68k by Jason R. Thorpe <thorpej@NetBSD.org> 39 */ 40 41#include <sys/cdefs.h> 42__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.41 2008/06/13 12:26:02 cegger Exp $"); 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/proc.h> 52#include <sys/tty.h> 53#include <sys/time.h> 54#include <sys/syslog.h> 55#include <sys/cpu.h> 56#include <sys/bus.h> 57#include <sys/intr.h> 58 59#include <dev/cons.h> 60#include <dev/ic/z8530reg.h> 61#include <machine/z8530var.h> 62 63#include <mvme68k/dev/zsvar.h> 64 65#include "ioconf.h" 66 67/* 68 * Some warts needed by z8530tty.c - 69 * The default parity REALLY needs to be the same as the PROM uses, 70 * or you can not see messages done with printf during boot-up... 71 */ 72int zs_def_cflag = (CREAD | CS8 | HUPCL); 73 74/* Flags from zscnprobe() */ 75static int zs_hwflags[NZSC][2]; 76 77/* Default speed for each channel */ 78static int zs_defspeed[NZSC][2] = { 79 { 9600, /* port 1 */ 80 9600 }, /* port 2 */ 81 { 9600, /* port 3 */ 82 9600 }, /* port 4 */ 83}; 84 85static struct zs_chanstate zs_conschan_store; 86static struct zs_chanstate *zs_conschan; 87 88uint8_t zs_init_reg[16] = { 89 0, /* 0: CMD (reset, etc.) */ 90 0, /* 1: No interrupts yet. */ 91 0x18 + ZSHARD_PRI, /* IVECT */ 92 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 93 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 94 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 95 0, /* 6: TXSYNC/SYNCLO */ 96 0, /* 7: RXSYNC/SYNCHI */ 97 0, /* 8: alias for data port */ 98 ZSWR9_MASTER_IE, 99 0, /*10: Misc. TX/RX control bits */ 100 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 101 0, /*12: BAUDLO (default=9600) */ 102 0, /*13: BAUDHI (default=9600) */ 103 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 104 ZSWR15_BREAK_IE, 105}; 106 107 108/**************************************************************** 109 * Autoconfig 110 ****************************************************************/ 111 112/* Definition of the driver for autoconfig. */ 113static int zsc_print(void *, const char *name); 114int zs_getc(void *); 115void zs_putc(void *, int); 116 117#if 0 118static int zs_get_speed(struct zs_chanstate *); 119#endif 120 121cons_decl(zsc_pcc); 122 123 124/* 125 * Configure children of an SCC. 126 */ 127void 128zs_config(struct zsc_softc *zsc, struct zsdevice *zs, int vector, int pclk) 129{ 130 struct zsc_attach_args zsc_args; 131 volatile struct zschan *zc; 132 struct zs_chanstate *cs; 133 int zsc_unit, channel, s; 134 135 zsc_unit = device_unit(zsc->zsc_dev); 136 printf(": Zilog 8530 SCC at vector 0x%x\n", vector); 137 138 /* 139 * Initialize software state for each channel. 140 */ 141 for (channel = 0; channel < 2; channel++) { 142 zsc_args.channel = channel; 143 zsc_args.hwflags = zs_hwflags[zsc_unit][channel]; 144 cs = &zsc->zsc_cs_store[channel]; 145 zsc->zsc_cs[channel] = cs; 146 147 /* 148 * If we're the console, copy the channel state, and 149 * adjust the console channel pointer. 150 */ 151 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 152 memcpy(cs, zs_conschan, sizeof(struct zs_chanstate)); 153 zs_conschan = cs; 154 } else { 155 zc = (channel == 0) ? &zs->zs_chan_a : &zs->zs_chan_b; 156 cs->cs_reg_csr = zc->zc_csr; 157 cs->cs_reg_data = zc->zc_data; 158 memcpy(cs->cs_creg, zs_init_reg, 16); 159 memcpy(cs->cs_preg, zs_init_reg, 16); 160 cs->cs_defspeed = zs_defspeed[zsc_unit][channel]; 161 } 162 163 zs_lock_init(cs); 164 cs->cs_brg_clk = pclk / 16; 165 cs->cs_creg[2] = cs->cs_preg[2] = vector; 166 zs_set_speed(cs, cs->cs_defspeed); 167 cs->cs_creg[12] = cs->cs_preg[12]; 168 cs->cs_creg[13] = cs->cs_preg[13]; 169 cs->cs_defcflag = zs_def_cflag; 170 171 /* Make these correspond to cs_defcflag (-crtscts) */ 172 cs->cs_rr0_dcd = ZSRR0_DCD; 173 cs->cs_rr0_cts = 0; 174 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 175 cs->cs_wr5_rts = 0; 176 177 cs->cs_channel = channel; 178 cs->cs_private = NULL; 179 cs->cs_ops = &zsops_null; 180 181 /* 182 * Clear the master interrupt enable. 183 * The INTENA is common to both channels, 184 * so just do it on the A channel. 185 * Write the interrupt vector while we're at it. 186 */ 187 if (channel == 0) { 188 zs_write_reg(cs, 9, 0); 189 zs_write_reg(cs, 2, vector); 190 } 191 192 /* 193 * Look for a child driver for this channel. 194 * The child attach will setup the hardware. 195 */ 196 if (!config_found(zsc->zsc_dev, (void *)&zsc_args, 197 zsc_print)) { 198 /* No sub-driver. Just reset it. */ 199 uint8_t reset = (channel == 0) ? 200 ZSWR9_A_RESET : ZSWR9_B_RESET; 201 s = splzs(); 202 zs_write_reg(cs, 9, reset); 203 splx(s); 204 } 205 } 206 207 /* 208 * Allocate a software interrupt cookie. 209 */ 210 zsc->zsc_softintr_cookie = softint_establish(SOFTINT_SERIAL, 211 (void (*)(void *)) zsc_intr_soft, zsc); 212#ifdef DEBUG 213 assert(zsc->zsc_softintr_cookie); 214#endif 215} 216 217static int 218zsc_print(void *aux, const char *name) 219{ 220 struct zsc_attach_args *args = aux; 221 222 if (name != NULL) 223 aprint_normal("%s: ", name); 224 225 if (args->channel != -1) 226 aprint_normal(" channel %d", args->channel); 227 228 return UNCONF; 229} 230 231#if defined(MVME162) || defined(MVME172) 232/* 233 * Our ZS chips each have their own interrupt vector. 234 */ 235int 236zshard_unshared(void *arg) 237{ 238 struct zsc_softc *zsc = arg; 239 int rval; 240 241 rval = zsc_intr_hard(zsc); 242 243 if (rval) { 244 if ((zsc->zsc_cs[0]->cs_softreq) || 245 (zsc->zsc_cs[1]->cs_softreq)) 246 softint_schedule(zsc->zsc_softintr_cookie); 247 zsc->zsc_evcnt.ev_count++; 248 } 249 250 return rval; 251} 252#endif 253 254#ifdef MVME147 255/* 256 * Our ZS chips all share a common, PCC-vectored interrupt, 257 * so we have to look at all of them on each interrupt. 258 */ 259int 260zshard_shared(void *arg) 261{ 262 struct zsc_softc *zsc; 263 int unit, rval; 264 265 rval = 0; 266 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 267 zsc = device_lookup_private(&zsc_cd, unit); 268 if (zsc != NULL && zsc_intr_hard(zsc)) { 269 if ((zsc->zsc_cs[0]->cs_softreq) || 270 (zsc->zsc_cs[1]->cs_softreq)) 271 softint_schedule(zsc->zsc_softintr_cookie); 272 zsc->zsc_evcnt.ev_count++; 273 rval++; 274 } 275 } 276 return rval; 277} 278#endif 279 280 281#if 0 282/* 283 * Compute the current baud rate given a ZSCC channel. 284 */ 285static int 286zs_get_speed(struct zs_chanstate *cs) 287{ 288 int tconst; 289 290 tconst = zs_read_reg(cs, 12); 291 tconst |= zs_read_reg(cs, 13) << 8; 292 return TCONST_TO_BPS(cs->cs_brg_clk, tconst); 293} 294#endif 295 296/* 297 * MD functions for setting the baud rate and control modes. 298 */ 299int 300zs_set_speed(struct zs_chanstate *cs, int bps) 301{ 302 int tconst, real_bps; 303 304 if (bps == 0) 305 return 0; 306 307#ifdef DIAGNOSTIC 308 if (cs->cs_brg_clk == 0) 309 panic("zs_set_speed"); 310#endif 311 312 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 313 if (tconst < 0) 314 return EINVAL; 315 316 /* Convert back to make sure we can do it. */ 317 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 318 319 /* Allow 2% tolerance WRT the required bps */ 320 if (((abs(real_bps - bps) * 1000) / bps) > 20) 321 return EINVAL; 322 323 cs->cs_preg[12] = tconst; 324 cs->cs_preg[13] = tconst >> 8; 325 326 /* Caller will stuff the pending registers. */ 327 return 0; 328} 329 330int 331zs_set_modes(struct zs_chanstate *cs, int cflag) 332{ 333 int s; 334 335 /* 336 * Output hardware flow control on the chip is horrendous: 337 * if carrier detect drops, the receiver is disabled, and if 338 * CTS drops, the transmitter is stoped IN MID CHARACTER! 339 * Therefore, NEVER set the HFC bit, and instead use the 340 * status interrupt to detect CTS changes. 341 */ 342 s = splzs(); 343 cs->cs_rr0_pps = 0; 344 if ((cflag & (CLOCAL | MDMBUF)) != 0) { 345 cs->cs_rr0_dcd = 0; 346 if ((cflag & MDMBUF) == 0) 347 cs->cs_rr0_pps = ZSRR0_DCD; 348 } else 349 cs->cs_rr0_dcd = ZSRR0_DCD; 350 if ((cflag & CRTSCTS) != 0) { 351 cs->cs_wr5_dtr = ZSWR5_DTR; 352 cs->cs_wr5_rts = ZSWR5_RTS; 353 cs->cs_rr0_cts = ZSRR0_CTS; 354 } else if ((cflag & MDMBUF) != 0) { 355 cs->cs_wr5_dtr = 0; 356 cs->cs_wr5_rts = ZSWR5_DTR; 357 cs->cs_rr0_cts = ZSRR0_DCD; 358 } else { 359 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 360 cs->cs_wr5_rts = 0; 361 cs->cs_rr0_cts = 0; 362 } 363 splx(s); 364 365 /* Caller will stuff the pending registers. */ 366 return 0; 367} 368 369 370/* 371 * Read or write the chip with suitable delays. 372 */ 373 374uint8_t 375zs_read_reg(struct zs_chanstate *cs, uint8_t reg) 376{ 377 uint8_t val; 378 379 *cs->cs_reg_csr = reg; 380 ZS_DELAY(); 381 val = *cs->cs_reg_csr; 382 ZS_DELAY(); 383 return val; 384} 385 386void 387zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val) 388{ 389 390 *cs->cs_reg_csr = reg; 391 ZS_DELAY(); 392 *cs->cs_reg_csr = val; 393 ZS_DELAY(); 394} 395 396uint8_t 397zs_read_csr(struct zs_chanstate *cs) 398{ 399 uint8_t val; 400 401 val = *cs->cs_reg_csr; 402 ZS_DELAY(); 403 return val; 404} 405 406void 407zs_write_csr(struct zs_chanstate *cs, uint8_t val) 408{ 409 410 *cs->cs_reg_csr = val; 411 ZS_DELAY(); 412} 413 414uint8_t 415zs_read_data(struct zs_chanstate *cs) 416{ 417 uint8_t val; 418 419 val = *cs->cs_reg_data; 420 ZS_DELAY(); 421 return val; 422} 423 424void 425zs_write_data(struct zs_chanstate *cs, uint8_t val) 426{ 427 428 *cs->cs_reg_data = val; 429 ZS_DELAY(); 430} 431 432/**************************************************************** 433 * Console support functions (MVME specific!) 434 ****************************************************************/ 435 436/* 437 * Polled input char. 438 */ 439int 440zs_getc(void *arg) 441{ 442 struct zs_chanstate *cs = arg; 443 int s, c, rr0, stat; 444 445 s = splhigh(); 446 top: 447 /* Wait for a character to arrive. */ 448 do { 449 rr0 = *cs->cs_reg_csr; 450 ZS_DELAY(); 451 } while ((rr0 & ZSRR0_RX_READY) == 0); 452 453 /* Read error register. */ 454 stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE); 455 if (stat) { 456 zs_write_csr(cs, ZSM_RESET_ERR); 457 goto top; 458 } 459 460 /* Read character. */ 461 c = *cs->cs_reg_data; 462 ZS_DELAY(); 463 splx(s); 464 465 return c; 466} 467 468/* 469 * Polled output char. 470 */ 471void 472zs_putc(void *arg, int c) 473{ 474 struct zs_chanstate *cs = arg; 475 int s, rr0; 476 477 s = splhigh(); 478 /* Wait for transmitter to become ready. */ 479 do { 480 rr0 = *cs->cs_reg_csr; 481 ZS_DELAY(); 482 } while ((rr0 & ZSRR0_TX_READY) == 0); 483 484 *cs->cs_reg_data = c; 485 ZS_DELAY(); 486 splx(s); 487} 488 489/* 490 * Common parts of console init. 491 */ 492void 493zs_cnconfig(int zsc_unit, int channel, struct zsdevice *zs, int pclk) 494{ 495 struct zs_chanstate *cs; 496 struct zschan *zc; 497 498 zc = (channel == 0) ? &zs->zs_chan_a : &zs->zs_chan_b; 499 500 /* 501 * Pointer to channel state. Later, the console channel 502 * state is copied into the softc, and the console channel 503 * pointer adjusted to point to the new copy. 504 */ 505 zs_conschan = cs = &zs_conschan_store; 506 zs_hwflags[zsc_unit][channel] = ZS_HWFLAG_CONSOLE; 507 508 /* Setup temporary chanstate. */ 509 cs->cs_brg_clk = pclk / 16; 510 cs->cs_reg_csr = zc->zc_csr; 511 cs->cs_reg_data = zc->zc_data; 512 513 /* Initialize the pending registers. */ 514 memcpy(cs->cs_preg, zs_init_reg, 16); 515 cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS); 516 517#if 0 518 /* XXX: Preserve BAUD rate from boot loader. */ 519 /* XXX: Also, why reset the chip here? -gwr */ 520 cs->cs_defspeed = zs_get_speed(cs); 521#else 522 cs->cs_defspeed = 9600; /* XXX */ 523#endif 524 zs_set_speed(cs, cs->cs_defspeed); 525 cs->cs_creg[12] = cs->cs_preg[12]; 526 cs->cs_creg[13] = cs->cs_preg[13]; 527 528 /* Clear the master interrupt enable. */ 529 zs_write_reg(cs, 9, 0); 530 531 /* Reset the whole SCC chip. */ 532 zs_write_reg(cs, 9, ZSWR9_HARD_RESET); 533 534 /* Copy "pending" to "current" and H/W. */ 535 zs_loadchannelregs(cs); 536} 537 538/* 539 * Polled console input putchar. 540 */ 541int 542zsc_pcccngetc(dev_t dev) 543{ 544 struct zs_chanstate *cs = zs_conschan; 545 int c; 546 547 c = zs_getc(cs); 548 return c; 549} 550 551/* 552 * Polled console output putchar. 553 */ 554void 555zsc_pcccnputc(dev_t dev, int c) 556{ 557 struct zs_chanstate *cs = zs_conschan; 558 559 zs_putc(cs, c); 560} 561 562/* 563 * Handle user request to enter kernel debugger. 564 */ 565void 566zs_abort(struct zs_chanstate *cs) 567{ 568 int rr0; 569 570 /* Wait for end of break to avoid PROM abort. */ 571 /* XXX - Limit the wait? */ 572 do { 573 rr0 = *cs->cs_reg_csr; 574 ZS_DELAY(); 575 } while (rr0 & ZSRR0_BREAK); 576 577 mvme68k_abort("SERIAL LINE ABORT"); 578} 579