brintos

brintos / linux-shallow public Read only

0
0
Text · 22.3 KiB · eba91da Raw
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