947 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * dz.c: Serial port driver for DECstations equipped4 * with the DZ chipset.5 *6 * Copyright (C) 1998 Olivier A. D. Lebaillif7 *8 * Email: olivier.lebaillif@ifrsys.com9 *10 * Copyright (C) 2004, 2006, 2007 Maciej W. Rozycki11 *12 * [31-AUG-98] triemer13 * Changed IRQ to use Harald's dec internals interrupts.h14 * removed base_addr code - moving address assignment to setup.c15 * Changed name of dz_init to rs_init to be consistent with tc code16 * [13-NOV-98] triemer fixed code to receive characters17 * after patches by harald to irq code.18 * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout19 * field from "current" - somewhere between 2.1.121 and 2.1.13120 Qua Jun 27 15:02:26 BRT 200121 * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups22 *23 * Parts (C) 1999 David Airlie, airlied@linux.ie24 * [07-SEP-99] Bugfixes25 *26 * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>27 * Converted to new serial core28 */29 30#undef DEBUG_DZ31 32#include <linux/bitops.h>33#include <linux/compiler.h>34#include <linux/console.h>35#include <linux/delay.h>36#include <linux/errno.h>37#include <linux/init.h>38#include <linux/interrupt.h>39#include <linux/ioport.h>40#include <linux/kernel.h>41#include <linux/major.h>42#include <linux/module.h>43#include <linux/serial.h>44#include <linux/serial_core.h>45#include <linux/sysrq.h>46#include <linux/tty.h>47#include <linux/tty_flip.h>48 49#include <linux/atomic.h>50#include <linux/io.h>51#include <asm/bootinfo.h>52 53#include <asm/dec/interrupts.h>54#include <asm/dec/kn01.h>55#include <asm/dec/kn02.h>56#include <asm/dec/machtype.h>57#include <asm/dec/prom.h>58#include <asm/dec/system.h>59 60#include "dz.h"61 62 63MODULE_DESCRIPTION("DECstation DZ serial driver");64MODULE_LICENSE("GPL");65 66 67static char dz_name[] __initdata = "DECstation DZ serial driver version ";68static char dz_version[] __initdata = "1.04";69 70struct dz_port {71 struct dz_mux *mux;72 struct uart_port port;73 unsigned int cflag;74};75 76struct dz_mux {77 struct dz_port dport[DZ_NB_PORT];78 atomic_t map_guard;79 atomic_t irq_guard;80 int initialised;81};82 83static struct dz_mux dz_mux;84 85static inline struct dz_port *to_dport(struct uart_port *uport)86{87 return container_of(uport, struct dz_port, port);88}89 90/*91 * ------------------------------------------------------------92 * dz_in () and dz_out ()93 *94 * These routines are used to access the registers of the DZ95 * chip, hiding relocation differences between implementation.96 * ------------------------------------------------------------97 */98 99static u16 dz_in(struct dz_port *dport, unsigned offset)100{101 void __iomem *addr = dport->port.membase + offset;102 103 return readw(addr);104}105 106static void dz_out(struct dz_port *dport, unsigned offset, u16 value)107{108 void __iomem *addr = dport->port.membase + offset;109 110 writew(value, addr);111}112 113/*114 * ------------------------------------------------------------115 * rs_stop () and rs_start ()116 *117 * These routines are called before setting or resetting118 * tty->flow.stopped. They enable or disable transmitter interrupts,119 * as necessary.120 * ------------------------------------------------------------121 */122 123static void dz_stop_tx(struct uart_port *uport)124{125 struct dz_port *dport = to_dport(uport);126 u16 tmp, mask = 1 << dport->port.line;127 128 tmp = dz_in(dport, DZ_TCR); /* read the TX flag */129 tmp &= ~mask; /* clear the TX flag */130 dz_out(dport, DZ_TCR, tmp);131}132 133static void dz_start_tx(struct uart_port *uport)134{135 struct dz_port *dport = to_dport(uport);136 u16 tmp, mask = 1 << dport->port.line;137 138 tmp = dz_in(dport, DZ_TCR); /* read the TX flag */139 tmp |= mask; /* set the TX flag */140 dz_out(dport, DZ_TCR, tmp);141}142 143static void dz_stop_rx(struct uart_port *uport)144{145 struct dz_port *dport = to_dport(uport);146 147 dport->cflag &= ~DZ_RXENAB;148 dz_out(dport, DZ_LPR, dport->cflag);149}150 151/*152 * ------------------------------------------------------------153 *154 * Here start the interrupt handling routines. All of the following155 * subroutines are declared as inline and are folded into156 * dz_interrupt. They were separated out for readability's sake.157 *158 * Note: dz_interrupt() is a "fast" interrupt, which means that it159 * runs with interrupts turned off. People who may want to modify160 * dz_interrupt() should try to keep the interrupt handler as fast as161 * possible. After you are done making modifications, it is not a bad162 * idea to do:163 *164 * make drivers/serial/dz.s165 *166 * and look at the resulting assemble code in dz.s.167 *168 * ------------------------------------------------------------169 */170 171/*172 * ------------------------------------------------------------173 * receive_char ()174 *175 * This routine deals with inputs from any lines.176 * ------------------------------------------------------------177 */178static inline void dz_receive_chars(struct dz_mux *mux)179{180 struct uart_port *uport;181 struct dz_port *dport = &mux->dport[0];182 struct uart_icount *icount;183 int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };184 u16 status;185 u8 ch, flag;186 int i;187 188 while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) {189 dport = &mux->dport[LINE(status)];190 uport = &dport->port;191 192 ch = UCHAR(status); /* grab the char */193 flag = TTY_NORMAL;194 195 icount = &uport->icount;196 icount->rx++;197 198 if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) {199 200 /*201 * There is no separate BREAK status bit, so treat202 * null characters with framing errors as BREAKs;203 * normally, otherwise. For this move the Framing204 * Error bit to a simulated BREAK bit.205 */206 if (!ch) {207 status |= (status & DZ_FERR) >>208 (ffs(DZ_FERR) - ffs(DZ_BREAK));209 status &= ~DZ_FERR;210 }211 212 /* Handle SysRq/SAK & keep track of the statistics. */213 if (status & DZ_BREAK) {214 icount->brk++;215 if (uart_handle_break(uport))216 continue;217 } else if (status & DZ_FERR)218 icount->frame++;219 else if (status & DZ_PERR)220 icount->parity++;221 if (status & DZ_OERR)222 icount->overrun++;223 224 status &= uport->read_status_mask;225 if (status & DZ_BREAK)226 flag = TTY_BREAK;227 else if (status & DZ_FERR)228 flag = TTY_FRAME;229 else if (status & DZ_PERR)230 flag = TTY_PARITY;231 232 }233 234 if (uart_handle_sysrq_char(uport, ch))235 continue;236 237 uart_insert_char(uport, status, DZ_OERR, ch, flag);238 lines_rx[LINE(status)] = 1;239 }240 for (i = 0; i < DZ_NB_PORT; i++)241 if (lines_rx[i])242 tty_flip_buffer_push(&mux->dport[i].port.state->port);243}244 245/*246 * ------------------------------------------------------------247 * transmit_char ()248 *249 * This routine deals with outputs to any lines.250 * ------------------------------------------------------------251 */252static inline void dz_transmit_chars(struct dz_mux *mux)253{254 struct dz_port *dport = &mux->dport[0];255 struct tty_port *tport;256 unsigned char tmp;257 u16 status;258 259 status = dz_in(dport, DZ_CSR);260 dport = &mux->dport[LINE(status)];261 tport = &dport->port.state->port;262 263 if (dport->port.x_char) { /* XON/XOFF chars */264 dz_out(dport, DZ_TDR, dport->port.x_char);265 dport->port.icount.tx++;266 dport->port.x_char = 0;267 return;268 }269 /* If nothing to do or stopped or hardware stopped. */270 if (uart_tx_stopped(&dport->port) ||271 !uart_fifo_get(&dport->port, &tmp)) {272 uart_port_lock(&dport->port);273 dz_stop_tx(&dport->port);274 uart_port_unlock(&dport->port);275 return;276 }277 278 /*279 * If something to do... (remember the dz has no output fifo,280 * so we go one char at a time) :-<281 */282 dz_out(dport, DZ_TDR, tmp);283 284 if (kfifo_len(&tport->xmit_fifo) < DZ_WAKEUP_CHARS)285 uart_write_wakeup(&dport->port);286 287 /* Are we are done. */288 if (kfifo_is_empty(&tport->xmit_fifo)) {289 uart_port_lock(&dport->port);290 dz_stop_tx(&dport->port);291 uart_port_unlock(&dport->port);292 }293}294 295/*296 * ------------------------------------------------------------297 * check_modem_status()298 *299 * DS 3100 & 5100: Only valid for the MODEM line, duh!300 * DS 5000/200: Valid for the MODEM and PRINTER line.301 * ------------------------------------------------------------302 */303static inline void check_modem_status(struct dz_port *dport)304{305 /*306 * FIXME:307 * 1. No status change interrupt; use a timer.308 * 2. Handle the 3100/5000 as appropriate. --macro309 */310 u16 status;311 312 /* If not the modem line just return. */313 if (dport->port.line != DZ_MODEM)314 return;315 316 status = dz_in(dport, DZ_MSR);317 318 /* it's easy, since DSR2 is the only bit in the register */319 if (status)320 dport->port.icount.dsr++;321}322 323/*324 * ------------------------------------------------------------325 * dz_interrupt ()326 *327 * this is the main interrupt routine for the DZ chip.328 * It deals with the multiple ports.329 * ------------------------------------------------------------330 */331static irqreturn_t dz_interrupt(int irq, void *dev_id)332{333 struct dz_mux *mux = dev_id;334 struct dz_port *dport = &mux->dport[0];335 u16 status;336 337 /* get the reason why we just got an irq */338 status = dz_in(dport, DZ_CSR);339 340 if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))341 dz_receive_chars(mux);342 343 if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))344 dz_transmit_chars(mux);345 346 return IRQ_HANDLED;347}348 349/*350 * -------------------------------------------------------------------351 * Here ends the DZ interrupt routines.352 * -------------------------------------------------------------------353 */354 355static unsigned int dz_get_mctrl(struct uart_port *uport)356{357 /*358 * FIXME: Handle the 3100/5000 as appropriate. --macro359 */360 struct dz_port *dport = to_dport(uport);361 unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;362 363 if (dport->port.line == DZ_MODEM) {364 if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)365 mctrl &= ~TIOCM_DSR;366 }367 368 return mctrl;369}370 371static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)372{373 /*374 * FIXME: Handle the 3100/5000 as appropriate. --macro375 */376 struct dz_port *dport = to_dport(uport);377 u16 tmp;378 379 if (dport->port.line == DZ_MODEM) {380 tmp = dz_in(dport, DZ_TCR);381 if (mctrl & TIOCM_DTR)382 tmp &= ~DZ_MODEM_DTR;383 else384 tmp |= DZ_MODEM_DTR;385 dz_out(dport, DZ_TCR, tmp);386 }387}388 389/*390 * -------------------------------------------------------------------391 * startup ()392 *393 * various initialization tasks394 * -------------------------------------------------------------------395 */396static int dz_startup(struct uart_port *uport)397{398 struct dz_port *dport = to_dport(uport);399 struct dz_mux *mux = dport->mux;400 unsigned long flags;401 int irq_guard;402 int ret;403 u16 tmp;404 405 irq_guard = atomic_add_return(1, &mux->irq_guard);406 if (irq_guard != 1)407 return 0;408 409 ret = request_irq(dport->port.irq, dz_interrupt,410 IRQF_SHARED, "dz", mux);411 if (ret) {412 atomic_add(-1, &mux->irq_guard);413 printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq);414 return ret;415 }416 417 uart_port_lock_irqsave(&dport->port, &flags);418 419 /* Enable interrupts. */420 tmp = dz_in(dport, DZ_CSR);421 tmp |= DZ_RIE | DZ_TIE;422 dz_out(dport, DZ_CSR, tmp);423 424 uart_port_unlock_irqrestore(&dport->port, flags);425 426 return 0;427}428 429/*430 * -------------------------------------------------------------------431 * shutdown ()432 *433 * This routine will shutdown a serial port; interrupts are disabled, and434 * DTR is dropped if the hangup on close termio flag is on.435 * -------------------------------------------------------------------436 */437static void dz_shutdown(struct uart_port *uport)438{439 struct dz_port *dport = to_dport(uport);440 struct dz_mux *mux = dport->mux;441 unsigned long flags;442 int irq_guard;443 u16 tmp;444 445 uart_port_lock_irqsave(&dport->port, &flags);446 dz_stop_tx(&dport->port);447 uart_port_unlock_irqrestore(&dport->port, flags);448 449 irq_guard = atomic_add_return(-1, &mux->irq_guard);450 if (!irq_guard) {451 /* Disable interrupts. */452 tmp = dz_in(dport, DZ_CSR);453 tmp &= ~(DZ_RIE | DZ_TIE);454 dz_out(dport, DZ_CSR, tmp);455 456 free_irq(dport->port.irq, mux);457 }458}459 460/*461 * -------------------------------------------------------------------462 * dz_tx_empty() -- get the transmitter empty status463 *464 * Purpose: Let user call ioctl() to get info when the UART physically465 * is emptied. On bus types like RS485, the transmitter must466 * release the bus after transmitting. This must be done when467 * the transmit shift register is empty, not be done when the468 * transmit holding register is empty. This functionality469 * allows an RS485 driver to be written in user space.470 * -------------------------------------------------------------------471 */472static unsigned int dz_tx_empty(struct uart_port *uport)473{474 struct dz_port *dport = to_dport(uport);475 unsigned short tmp, mask = 1 << dport->port.line;476 477 tmp = dz_in(dport, DZ_TCR);478 tmp &= mask;479 480 return tmp ? 0 : TIOCSER_TEMT;481}482 483static void dz_break_ctl(struct uart_port *uport, int break_state)484{485 /*486 * FIXME: Can't access BREAK bits in TDR easily;487 * reuse the code for polled TX. --macro488 */489 struct dz_port *dport = to_dport(uport);490 unsigned long flags;491 unsigned short tmp, mask = 1 << dport->port.line;492 493 uart_port_lock_irqsave(uport, &flags);494 tmp = dz_in(dport, DZ_TCR);495 if (break_state)496 tmp |= mask;497 else498 tmp &= ~mask;499 dz_out(dport, DZ_TCR, tmp);500 uart_port_unlock_irqrestore(uport, flags);501}502 503static int dz_encode_baud_rate(unsigned int baud)504{505 switch (baud) {506 case 50:507 return DZ_B50;508 case 75:509 return DZ_B75;510 case 110:511 return DZ_B110;512 case 134:513 return DZ_B134;514 case 150:515 return DZ_B150;516 case 300:517 return DZ_B300;518 case 600:519 return DZ_B600;520 case 1200:521 return DZ_B1200;522 case 1800:523 return DZ_B1800;524 case 2000:525 return DZ_B2000;526 case 2400:527 return DZ_B2400;528 case 3600:529 return DZ_B3600;530 case 4800:531 return DZ_B4800;532 case 7200:533 return DZ_B7200;534 case 9600:535 return DZ_B9600;536 default:537 return -1;538 }539}540 541 542static void dz_reset(struct dz_port *dport)543{544 struct dz_mux *mux = dport->mux;545 546 if (mux->initialised)547 return;548 549 dz_out(dport, DZ_CSR, DZ_CLR);550 while (dz_in(dport, DZ_CSR) & DZ_CLR);551 iob();552 553 /* Enable scanning. */554 dz_out(dport, DZ_CSR, DZ_MSE);555 556 mux->initialised = 1;557}558 559static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,560 const struct ktermios *old_termios)561{562 struct dz_port *dport = to_dport(uport);563 unsigned long flags;564 unsigned int cflag, baud;565 int bflag;566 567 cflag = dport->port.line;568 569 switch (termios->c_cflag & CSIZE) {570 case CS5:571 cflag |= DZ_CS5;572 break;573 case CS6:574 cflag |= DZ_CS6;575 break;576 case CS7:577 cflag |= DZ_CS7;578 break;579 case CS8:580 default:581 cflag |= DZ_CS8;582 }583 584 if (termios->c_cflag & CSTOPB)585 cflag |= DZ_CSTOPB;586 if (termios->c_cflag & PARENB)587 cflag |= DZ_PARENB;588 if (termios->c_cflag & PARODD)589 cflag |= DZ_PARODD;590 591 baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);592 bflag = dz_encode_baud_rate(baud);593 if (bflag < 0) {594 if (old_termios) {595 /* Keep unchanged. */596 baud = tty_termios_baud_rate(old_termios);597 bflag = dz_encode_baud_rate(baud);598 }599 if (bflag < 0) { /* Resort to 9600. */600 baud = 9600;601 bflag = DZ_B9600;602 }603 tty_termios_encode_baud_rate(termios, baud, baud);604 }605 cflag |= bflag;606 607 if (termios->c_cflag & CREAD)608 cflag |= DZ_RXENAB;609 610 uart_port_lock_irqsave(&dport->port, &flags);611 612 uart_update_timeout(uport, termios->c_cflag, baud);613 614 dz_out(dport, DZ_LPR, cflag);615 dport->cflag = cflag;616 617 /* setup accept flag */618 dport->port.read_status_mask = DZ_OERR;619 if (termios->c_iflag & INPCK)620 dport->port.read_status_mask |= DZ_FERR | DZ_PERR;621 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))622 dport->port.read_status_mask |= DZ_BREAK;623 624 /* characters to ignore */625 uport->ignore_status_mask = 0;626 if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))627 dport->port.ignore_status_mask |= DZ_OERR;628 if (termios->c_iflag & IGNPAR)629 dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;630 if (termios->c_iflag & IGNBRK)631 dport->port.ignore_status_mask |= DZ_BREAK;632 633 uart_port_unlock_irqrestore(&dport->port, flags);634}635 636/*637 * Hack alert!638 * Required solely so that the initial PROM-based console639 * works undisturbed in parallel with this one.640 */641static void dz_pm(struct uart_port *uport, unsigned int state,642 unsigned int oldstate)643{644 struct dz_port *dport = to_dport(uport);645 unsigned long flags;646 647 uart_port_lock_irqsave(&dport->port, &flags);648 if (state < 3)649 dz_start_tx(&dport->port);650 else651 dz_stop_tx(&dport->port);652 uart_port_unlock_irqrestore(&dport->port, flags);653}654 655 656static const char *dz_type(struct uart_port *uport)657{658 return "DZ";659}660 661static void dz_release_port(struct uart_port *uport)662{663 struct dz_mux *mux = to_dport(uport)->mux;664 int map_guard;665 666 iounmap(uport->membase);667 uport->membase = NULL;668 669 map_guard = atomic_add_return(-1, &mux->map_guard);670 if (!map_guard)671 release_mem_region(uport->mapbase, dec_kn_slot_size);672}673 674static int dz_map_port(struct uart_port *uport)675{676 if (!uport->membase)677 uport->membase = ioremap(uport->mapbase,678 dec_kn_slot_size);679 if (!uport->membase) {680 printk(KERN_ERR "dz: Cannot map MMIO\n");681 return -ENOMEM;682 }683 return 0;684}685 686static int dz_request_port(struct uart_port *uport)687{688 struct dz_mux *mux = to_dport(uport)->mux;689 int map_guard;690 int ret;691 692 map_guard = atomic_add_return(1, &mux->map_guard);693 if (map_guard == 1) {694 if (!request_mem_region(uport->mapbase, dec_kn_slot_size,695 "dz")) {696 atomic_add(-1, &mux->map_guard);697 printk(KERN_ERR698 "dz: Unable to reserve MMIO resource\n");699 return -EBUSY;700 }701 }702 ret = dz_map_port(uport);703 if (ret) {704 map_guard = atomic_add_return(-1, &mux->map_guard);705 if (!map_guard)706 release_mem_region(uport->mapbase, dec_kn_slot_size);707 return ret;708 }709 return 0;710}711 712static void dz_config_port(struct uart_port *uport, int flags)713{714 struct dz_port *dport = to_dport(uport);715 716 if (flags & UART_CONFIG_TYPE) {717 if (dz_request_port(uport))718 return;719 720 uport->type = PORT_DZ;721 722 dz_reset(dport);723 }724}725 726/*727 * Verify the new serial_struct (for TIOCSSERIAL).728 */729static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser)730{731 int ret = 0;732 733 if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)734 ret = -EINVAL;735 if (ser->irq != uport->irq)736 ret = -EINVAL;737 return ret;738}739 740static const struct uart_ops dz_ops = {741 .tx_empty = dz_tx_empty,742 .get_mctrl = dz_get_mctrl,743 .set_mctrl = dz_set_mctrl,744 .stop_tx = dz_stop_tx,745 .start_tx = dz_start_tx,746 .stop_rx = dz_stop_rx,747 .break_ctl = dz_break_ctl,748 .startup = dz_startup,749 .shutdown = dz_shutdown,750 .set_termios = dz_set_termios,751 .pm = dz_pm,752 .type = dz_type,753 .release_port = dz_release_port,754 .request_port = dz_request_port,755 .config_port = dz_config_port,756 .verify_port = dz_verify_port,757};758 759static void __init dz_init_ports(void)760{761 static int first = 1;762 unsigned long base;763 int line;764 765 if (!first)766 return;767 first = 0;768 769 if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100)770 base = dec_kn_slot_base + KN01_DZ11;771 else772 base = dec_kn_slot_base + KN02_DZ11;773 774 for (line = 0; line < DZ_NB_PORT; line++) {775 struct dz_port *dport = &dz_mux.dport[line];776 struct uart_port *uport = &dport->port;777 778 dport->mux = &dz_mux;779 780 uport->irq = dec_interrupt[DEC_IRQ_DZ11];781 uport->fifosize = 1;782 uport->iotype = UPIO_MEM;783 uport->flags = UPF_BOOT_AUTOCONF;784 uport->ops = &dz_ops;785 uport->line = line;786 uport->mapbase = base;787 uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_DZ_CONSOLE);788 }789}790 791#ifdef CONFIG_SERIAL_DZ_CONSOLE792/*793 * -------------------------------------------------------------------794 * dz_console_putchar() -- transmit a character795 *796 * Polled transmission. This is tricky. We need to mask transmit797 * interrupts so that they do not interfere, enable the transmitter798 * for the line requested and then wait till the transmit scanner799 * requests data for this line. But it may request data for another800 * line first, in which case we have to disable its transmitter and801 * repeat waiting till our line pops up. Only then the character may802 * be transmitted. Finally, the state of the transmitter mask is803 * restored. Welcome to the world of PDP-11!804 * -------------------------------------------------------------------805 */806static void dz_console_putchar(struct uart_port *uport, unsigned char ch)807{808 struct dz_port *dport = to_dport(uport);809 unsigned long flags;810 unsigned short csr, tcr, trdy, mask;811 int loops = 10000;812 813 uart_port_lock_irqsave(&dport->port, &flags);814 csr = dz_in(dport, DZ_CSR);815 dz_out(dport, DZ_CSR, csr & ~DZ_TIE);816 tcr = dz_in(dport, DZ_TCR);817 tcr |= 1 << dport->port.line;818 mask = tcr;819 dz_out(dport, DZ_TCR, mask);820 iob();821 uart_port_unlock_irqrestore(&dport->port, flags);822 823 do {824 trdy = dz_in(dport, DZ_CSR);825 if (!(trdy & DZ_TRDY))826 continue;827 trdy = (trdy & DZ_TLINE) >> 8;828 if (trdy == dport->port.line)829 break;830 mask &= ~(1 << trdy);831 dz_out(dport, DZ_TCR, mask);832 iob();833 udelay(2);834 } while (--loops);835 836 if (loops) /* Cannot send otherwise. */837 dz_out(dport, DZ_TDR, ch);838 839 dz_out(dport, DZ_TCR, tcr);840 dz_out(dport, DZ_CSR, csr);841}842 843/*844 * -------------------------------------------------------------------845 * dz_console_print ()846 *847 * dz_console_print is registered for printk.848 * The console must be locked when we get here.849 * -------------------------------------------------------------------850 */851static void dz_console_print(struct console *co,852 const char *str,853 unsigned int count)854{855 struct dz_port *dport = &dz_mux.dport[co->index];856#ifdef DEBUG_DZ857 prom_printf((char *) str);858#endif859 uart_console_write(&dport->port, str, count, dz_console_putchar);860}861 862static int __init dz_console_setup(struct console *co, char *options)863{864 struct dz_port *dport = &dz_mux.dport[co->index];865 struct uart_port *uport = &dport->port;866 int baud = 9600;867 int bits = 8;868 int parity = 'n';869 int flow = 'n';870 int ret;871 872 ret = dz_map_port(uport);873 if (ret)874 return ret;875 876 spin_lock_init(&dport->port.lock); /* For dz_pm(). */877 878 dz_reset(dport);879 dz_pm(uport, 0, -1);880 881 if (options)882 uart_parse_options(options, &baud, &parity, &bits, &flow);883 884 return uart_set_options(&dport->port, co, baud, parity, bits, flow);885}886 887static struct uart_driver dz_reg;888static struct console dz_console = {889 .name = "ttyS",890 .write = dz_console_print,891 .device = uart_console_device,892 .setup = dz_console_setup,893 .flags = CON_PRINTBUFFER,894 .index = -1,895 .data = &dz_reg,896};897 898static int __init dz_serial_console_init(void)899{900 if (!IOASIC) {901 dz_init_ports();902 register_console(&dz_console);903 return 0;904 } else905 return -ENXIO;906}907 908console_initcall(dz_serial_console_init);909 910#define SERIAL_DZ_CONSOLE &dz_console911#else912#define SERIAL_DZ_CONSOLE NULL913#endif /* CONFIG_SERIAL_DZ_CONSOLE */914 915static struct uart_driver dz_reg = {916 .owner = THIS_MODULE,917 .driver_name = "serial",918 .dev_name = "ttyS",919 .major = TTY_MAJOR,920 .minor = 64,921 .nr = DZ_NB_PORT,922 .cons = SERIAL_DZ_CONSOLE,923};924 925static int __init dz_init(void)926{927 int ret, i;928 929 if (IOASIC)930 return -ENXIO;931 932 printk("%s%s\n", dz_name, dz_version);933 934 dz_init_ports();935 936 ret = uart_register_driver(&dz_reg);937 if (ret)938 return ret;939 940 for (i = 0; i < DZ_NB_PORT; i++)941 uart_add_one_port(&dz_reg, &dz_mux.dport[i].port);942 943 return 0;944}945 946module_init(dz_init);947