/*
* zs.c: Serial port driver for IOASIC DECstations.
*
* Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
* Derived from drivers/macintosh/macserial.c by Harald Koerfgen.
*
* DECstation changes
* Copyright (C) 1998-2000 Harald Koerfgen
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki
*
* For the rest of the code the original Copyright applies:
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*
*
* Note: for IOASIC systems the wiring is as follows:
*
* mouse/keyboard:
* DIN-7 MJ-4 signal SCC
* 2 1 TxD <- A.TxD
* 3 4 RxD -> A.RxD
*
* EIA-232/EIA-423:
* DB-25 MMJ-6 signal SCC
* 2 2 TxD <- B.TxD
* 3 5 RxD -> B.RxD
* 4 RTS <- ~A.RTS
* 5 CTS -> ~B.CTS
* 6 6 DSR -> ~A.SYNC
* 8 CD -> ~B.DCD
* 12 DSRS(DCE) -> ~A.CTS (*)
* 15 TxC -> B.TxC
* 17 RxC -> B.RxC
* 20 1 DTR <- ~A.DTR
* 22 RI -> ~A.DCD
* 23 DSRS(DTE) <- ~B.RTS
*
* (*) EIA-232 defines the signal at this pin to be SCD, while DSRS(DCE)
* is shared with DSRS(DTE) at pin 23.
*
* As you can immediately notice the wiring of the RTS, DTR and DSR signals
* is a bit odd. This makes the handling of port B unnecessarily
* complicated and prevents the use of some automatic modes of operation.
*/
#if defined(CONFIG_SERIAL_ZS_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/bug.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irqflags.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/spinlock.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/system.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/system.h>
#include "zs.h"
MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
MODULE_DESCRIPTION("DECstation Z85C30 serial driver");
MODULE_LICENSE("GPL");
static char zs_name[] __initdata = "DECstation Z85C30 serial driver version ";
static char zs_version[] __initdata = "0.10";
/*
* It would be nice to dynamically allocate everything that
* depends on ZS_NUM_SCCS, so we could support any number of
* Z85C30s, but for now...
*/
#define ZS_NUM_SCCS 2 /* Max # of ZS chips supported. */
#define ZS_NUM_CHAN 2 /* 2 channels per chip. */
#define ZS_CHAN_A 0 /* Index of the channel A. */
#define ZS_CHAN_B 1 /* Index of the channel B. */
#define ZS_CHAN_IO_SIZE 8 /* IOMEM space size. */
#define ZS_CHAN_IO_STRIDE 4 /* Register alignment. */
#define ZS_CHAN_IO_OFFSET 1 /* The SCC resides on the high byte
of the 16-bit IOBUS. */
#define ZS_CLOCK 7372800 /* Z85C30 PCLK input clock rate. */
#define to_zport(uport) container_of(uport, struct zs_port, port)
struct zs_parms {
resource_size_t scc[ZS_NUM_SCCS];
int irq[ZS_NUM_SCCS];
};
static struct zs_scc zs_sccs[ZS_NUM_SCCS];
static u8 zs_init_regs[ZS_NUM_REGS] __initdata = {
0, /* write 0 */
PAR_SPEC, /* write 1 */
0, /* write 2 */
0, /* write 3 */
X16CLK | SB1, /* write 4 */
0, /* write 5 */
0, 0, 0, /* write 6, 7, 8 */
MIE | DLC | NV, /* write 9 */
NRZ, /* write 10 */
TCBR | RCBR, /* write 11 */
0, 0, /* BRG time constant, write 12 + 13 */
BRSRC | BRENABL, /* write 14 */
0, /* write 15 */
};
/*
* Debugging.
*/
#undef ZS_DEBUG_REGS
/*
* Reading and writing Z85C30 registers.
*/
static void recovery_delay(void)
{
udelay(2