1 /* $NetBSD: zs.c,v 1.2 2008/03/29 19:15:34 tsutsui 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.2 2008/03/29 19:15:34 tsutsui 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/tty.h> 56 #include <sys/intr.h> 57 58 #include <dev/cons.h> 59 #include <dev/ic/z8530reg.h> 60 61 #include <machine/autoconf.h> 62 #include <machine/z8530var.h> 63 64 #include <cobalt/cobalt/console.h> 65 66 #include "ioconf.h" 67 68 /* 69 * Some warts needed by z8530tty.c - 70 * The default parity REALLY needs to be the same as the PROM uses, 71 * or you can not see messages done with printf during boot-up... 72 */ 73 int zs_def_cflag = (CREAD | CS8 | HUPCL); 74 75 #define ZS_DEFSPEED 115200 76 #define PCLK (115200 * 96) /* 11.0592MHz */ 77 78 #define ZS_DELAY() delay(2) 79 80 /* The layout of this is hardware-dependent (padding, order). */ 81 /* A/~B (Channel A/Channel B) pin is connected to DAdr0 */ 82 #define ZS_CHAN_A 0x01 83 #define ZS_CHAN_B 0x00 84 85 /* D/~C (Data/Control) pin is connected to DAdr1 */ 86 #define ZS_CSR 0x00 /* ctrl, status, and indirect access */ 87 #define ZS_DATA 0x02 /* data */ 88 89 90 /* Definition of the driver for autoconfig. */ 91 static int zs_match(device_t, cfdata_t, void *); 92 static void zs_attach(device_t, device_t, void *); 93 static int zs_print(void *, const char *name); 94 95 CFATTACH_DECL_NEW(zsc, sizeof(struct zsc_softc), 96 zs_match, zs_attach, NULL, NULL); 97 98 static int zshard(void *); 99 #if 0 100 static int zs_get_speed(struct zs_chanstate *); 101 #endif 102 static int zs_getc(void *); 103 static void zs_putc(void *, int); 104 105 /* console status from cninit */ 106 static struct zs_chanstate zs_conschan_store; 107 static struct zs_chanstate *zs_conschan; 108 static uint8_t *zs_cons; 109 110 /* default speed for all channels */ 111 static int zs_defspeed = ZS_DEFSPEED; 112 113 static uint8_t zs_init_reg[16] = { 114 0, /* 0: CMD (reset, etc.) */ 115 0, /* 1: No interrupts yet. */ 116 0, /* 2: no IVECT */ 117 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, /* 3: RX params and ctrl */ 118 ZSWR4_CLK_X16 | ZSWR4_ONESB, /* 4: TX/RX misc params */ 119 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, /* 5: TX params and ctrl */ 120 0, /* 6: TXSYNC/SYNCLO */ 121 0, /* 7: RXSYNC/SYNCHI */ 122 0, /* 8: alias for data port */ 123 ZSWR9_MASTER_IE, /* 9: Master interrupt ctrl */ 124 0, /*10: Misc TX/RX ctrl */ 125 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, /*11: Clock Mode ctrl */ 126 BPS_TO_TCONST((PCLK/16), ZS_DEFSPEED), /*12: BAUDLO */ 127 0, /*13: BAUDHI */ 128 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, /*14: Misc ctrl */ 129 ZSWR15_BREAK_IE, /*15: Ext/Status intr ctrl */ 130 }; 131 132 /* register address offset for each channel */ 133 static const int chanoff[] = { ZS_CHAN_A, ZS_CHAN_B }; 134 135 136 static int 137 zs_match(device_t parent, cfdata_t cf, void *aux) 138 { 139 static int matched; 140 141 /* only one zs */ 142 if (matched) 143 return 0; 144 145 /* only Qube 2700 could have Z85C30 serial */ 146 if (cobalt_id != COBALT_ID_QUBE2700) 147 return 0; 148 149 if (!console_present) 150 return 0; 151 152 matched = 1; 153 return 1; 154 } 155 156 /* 157 * Attach a found zs. 158 */ 159 static void 160 zs_attach(device_t parent, device_t self, void *aux) 161 { 162 struct zsc_softc *zsc = device_private(self); 163 struct mainbus_attach_args *maa = aux; 164 struct zsc_attach_args zsc_args; 165 uint8_t *zs_base; 166 struct zs_chanstate *cs; 167 int s, channel; 168 169 zsc->zsc_dev = self; 170 171 /* XXX: MI z8530 doesn't use bus_space(9) yet */ 172 zs_base = (void *)MIPS_PHYS_TO_KSEG1(maa->ma_addr); 173 174 aprint_normal(": optional Z85C30 serial port\n"); 175 176 /* 177 * Initialize software state for each channel. 178 */ 179 for (channel = 0; channel < 2; channel++) { 180 zsc_args.channel = channel; 181 cs = &zsc->zsc_cs_store[channel]; 182 183 zsc->zsc_cs[channel] = cs; 184 185 zs_init_reg[2] = 0; 186 187 if ((zs_base + chanoff[channel]) == zs_cons) { 188 memcpy(cs, zs_conschan, sizeof(struct zs_chanstate)); 189 zs_conschan = cs; 190 zsc_args.hwflags = ZS_HWFLAG_CONSOLE; 191 } else { 192 cs->cs_reg_csr = zs_base + chanoff[channel] + ZS_CSR; 193 cs->cs_reg_data = zs_base + chanoff[channel] + ZS_DATA; 194 memcpy(cs->cs_creg, zs_init_reg, 16); 195 memcpy(cs->cs_preg, zs_init_reg, 16); 196 cs->cs_defspeed = zs_defspeed; 197 zsc_args.hwflags = 0; 198 } 199 200 zs_lock_init(cs); 201 cs->cs_defcflag = zs_def_cflag; 202 203 cs->cs_channel = channel; 204 cs->cs_private = NULL; 205 cs->cs_ops = &zsops_null; 206 cs->cs_brg_clk = PCLK / 16; 207 208 /* Make these correspond to cs_defcflag (-crtscts) */ 209 cs->cs_rr0_dcd = ZSRR0_DCD; 210 cs->cs_rr0_cts = 0; 211 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 212 cs->cs_wr5_rts = 0; 213 214 /* 215 * Clear the master interrupt enable. 216 * The INTENA is common to both channels, 217 * so just do it on the A channel. 218 */ 219 if (channel == 0) { 220 s = splhigh(); 221 zs_write_reg(cs, 9, 0); 222 splx(s); 223 } 224 225 /* 226 * Look for a child driver for this channel. 227 * The child attach will setup the hardware. 228 */ 229 if (!config_found(self, (void *)&zsc_args, zs_print)) { 230 /* No sub-driver. Just reset it. */ 231 uint8_t reset = (channel == 0) ? 232 ZSWR9_A_RESET : ZSWR9_B_RESET; 233 s = splhigh(); 234 zs_write_reg(cs, 9, reset); 235 splx(s); 236 } 237 } 238 239 /* 240 * Now safe to install interrupt handlers. 241 */ 242 icu_intr_establish(maa->ma_irq, IST_EDGE, IPL_SERIAL, zshard, zsc); 243 zsc->zsc_softintr_cookie = softint_establish(SOFTINT_SERIAL, 244 (void (*)(void *))zsc_intr_soft, zsc); 245 246 /* 247 * Set the master interrupt enable and interrupt vector. 248 * (common to both channels, do it on A) 249 */ 250 cs = zsc->zsc_cs[0]; 251 s = splhigh(); 252 /* interrupt vector */ 253 zs_write_reg(cs, 2, 0); 254 /* master interrupt control (enable) */ 255 zs_write_reg(cs, 9, zs_init_reg[9]); 256 splx(s); 257 } 258 259 static int 260 zs_print(void *aux, const char *name) 261 { 262 struct zsc_attach_args *args = aux; 263 264 if (name != NULL) 265 aprint_normal("%s: ", name); 266 267 if (args->channel != -1) 268 aprint_normal(" channel %d", args->channel); 269 270 return UNCONF; 271 } 272 273 static int 274 zshard(void *arg) 275 { 276 struct zsc_softc *zsc = arg; 277 int rval; 278 279 rval = zsc_intr_hard(zsc); 280 281 #if 1 282 /* XXX: there is some race condition? */ 283 if (rval) 284 while (zsc_intr_hard(zsc)) 285 ; 286 #endif 287 288 /* We are at splzs here, so no need to lock. */ 289 if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) 290 softint_schedule(zsc->zsc_softintr_cookie); 291 292 return rval; 293 } 294 295 /* 296 * Compute the current baud rate given a ZS channel. 297 */ 298 #if 0 299 static int 300 zs_get_speed(struct zs_chanstate *cs) 301 { 302 int tconst; 303 304 tconst = zs_read_reg(cs, 12); 305 tconst |= zs_read_reg(cs, 13) << 8; 306 return TCONST_TO_BPS(cs->cs_brg_clk, tconst); 307 } 308 #endif 309 310 /* 311 * MD functions for setting the baud rate and control modes. 312 */ 313 int 314 zs_set_speed(struct zs_chanstate *cs, int bps) 315 { 316 int tconst, real_bps; 317 318 if (bps == 0) 319 return 0; 320 321 #ifdef DIAGNOSTIC 322 if (cs->cs_brg_clk == 0) 323 panic("zs_set_speed"); 324 #endif 325 326 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 327 if (tconst < 0) 328 return EINVAL; 329 330 /* Convert back to make sure we can do it. */ 331 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 332 333 /* Allow ~4% tolerance here */ 334 if (abs(real_bps - bps) >= bps * 4 / 100) 335 return EINVAL; 336 337 cs->cs_preg[12] = tconst; 338 cs->cs_preg[13] = tconst >> 8; 339 340 /* Caller will stuff the pending registers. */ 341 return 0; 342 } 343 344 int 345 zs_set_modes(struct zs_chanstate *cs, int cflag) 346 { 347 int s; 348 349 /* 350 * Output hardware flow control on the chip is horrendous: 351 * if carrier detect drops, the receiver is disabled, and if 352 * CTS drops, the transmitter is stoped IN MID CHARACTER! 353 * Therefore, NEVER set the HFC bit, and instead use the 354 * status interrupt to detect CTS changes. 355 */ 356 s = splzs(); 357 cs->cs_rr0_pps = 0; 358 if ((cflag & (CLOCAL | MDMBUF)) != 0) { 359 cs->cs_rr0_dcd = 0; 360 if ((cflag & MDMBUF) == 0) 361 cs->cs_rr0_pps = ZSRR0_DCD; 362 } else 363 cs->cs_rr0_dcd = ZSRR0_DCD; 364 if ((cflag & CRTSCTS) != 0) { 365 cs->cs_wr5_dtr = ZSWR5_DTR; 366 cs->cs_wr5_rts = ZSWR5_RTS; 367 cs->cs_rr0_cts = ZSRR0_CTS; 368 } else if ((cflag & MDMBUF) != 0) { 369 cs->cs_wr5_dtr = 0; 370 cs->cs_wr5_rts = ZSWR5_DTR; 371 cs->cs_rr0_cts = ZSRR0_DCD; 372 } else { 373 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 374 cs->cs_wr5_rts = 0; 375 cs->cs_rr0_cts = 0; 376 } 377 splx(s); 378 379 /* Caller will stuff the pending registers. */ 380 return 0; 381 } 382 383 384 /* 385 * Read or write the chip with suitable delays. 386 */ 387 388 uint8_t 389 zs_read_reg(struct zs_chanstate *cs, uint8_t reg) 390 { 391 uint8_t val; 392 393 *cs->cs_reg_csr = reg; 394 ZS_DELAY(); 395 val = *cs->cs_reg_csr; 396 ZS_DELAY(); 397 return val; 398 } 399 400 void 401 zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val) 402 { 403 404 *cs->cs_reg_csr = reg; 405 ZS_DELAY(); 406 *cs->cs_reg_csr = val; 407 ZS_DELAY(); 408 } 409 410 uint8_t 411 zs_read_csr(struct zs_chanstate *cs) 412 { 413 uint8_t val; 414 415 val = *cs->cs_reg_csr; 416 ZS_DELAY(); 417 return val; 418 } 419 420 void 421 zs_write_csr(struct zs_chanstate *cs, uint8_t val) 422 { 423 424 *cs->cs_reg_csr = val; 425 ZS_DELAY(); 426 } 427 428 uint8_t 429 zs_read_data(struct zs_chanstate *cs) 430 { 431 uint8_t val; 432 433 val = *cs->cs_reg_data; 434 ZS_DELAY(); 435 return val; 436 } 437 438 void 439 zs_write_data(struct zs_chanstate *cs, uint8_t val) 440 { 441 442 *cs->cs_reg_data = val; 443 ZS_DELAY(); 444 } 445 446 void 447 zs_abort(struct zs_chanstate *cs) 448 { 449 450 #ifdef DDB 451 Debugger(); 452 #endif 453 } 454 455 /* 456 * Polled input char. 457 */ 458 int 459 zs_getc(void *arg) 460 { 461 struct zs_chanstate *cs = arg; 462 int s, c; 463 uint8_t rr0; 464 465 s = splhigh(); 466 /* Wait for a character to arrive. */ 467 do { 468 rr0 = *cs->cs_reg_csr; 469 ZS_DELAY(); 470 } while ((rr0 & ZSRR0_RX_READY) == 0); 471 472 c = *cs->cs_reg_data; 473 ZS_DELAY(); 474 splx(s); 475 476 return c; 477 } 478 479 /* 480 * Polled output char. 481 */ 482 void 483 zs_putc(void *arg, int c) 484 { 485 struct zs_chanstate *cs = arg; 486 int s; 487 uint8_t rr0; 488 489 s = splhigh(); 490 /* Wait for transmitter to become ready. */ 491 do { 492 rr0 = *cs->cs_reg_csr; 493 ZS_DELAY(); 494 } while ((rr0 & ZSRR0_TX_READY) == 0); 495 496 *cs->cs_reg_data = c; 497 ZS_DELAY(); 498 splx(s); 499 } 500 501 void 502 zscnprobe(struct consdev *cn) 503 { 504 505 cn->cn_pri = (console_present != 0 && cobalt_id == COBALT_ID_QUBE2700) 506 ? CN_NORMAL : CN_DEAD; 507 } 508 509 void 510 zscninit(struct consdev *cn) 511 { 512 struct zs_chanstate *cs; 513 514 extern const struct cdevsw zstty_cdevsw; 515 516 cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0); 517 518 zs_cons = (uint8_t *)MIPS_PHYS_TO_KSEG1(ZS_BASE) + ZS_CHAN_A; /* XXX */ 519 520 zs_conschan = cs = &zs_conschan_store; 521 522 /* Setup temporary chanstate. */ 523 cs->cs_reg_csr = zs_cons + ZS_CSR; 524 cs->cs_reg_data = zs_cons + ZS_DATA; 525 526 /* Initialize the pending registers. */ 527 memcpy(cs->cs_preg, zs_init_reg, 16); 528 cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; 529 530 cs->cs_preg[12] = BPS_TO_TCONST(PCLK / 16, ZS_DEFSPEED); 531 cs->cs_preg[13] = 0; 532 cs->cs_defspeed = ZS_DEFSPEED; 533 534 /* Clear the master interrupt enable. */ 535 zs_write_reg(cs, 9, 0); 536 537 /* Reset the whole SCC chip. */ 538 zs_write_reg(cs, 9, ZSWR9_HARD_RESET); 539 540 /* Copy "pending" to "current" and H/W */ 541 zs_loadchannelregs(cs); 542 } 543 544 int 545 zscngetc(dev_t dev) 546 { 547 548 return zs_getc((void *)zs_conschan); 549 } 550 551 void 552 zscnputc(dev_t dev, int c) 553 { 554 555 zs_putc((void *)zs_conschan, c); 556 } 557