// SPDX-License-Identifier: GPL-2.0
/* sunzilog.c: Zilog serial driver for Sparc systems.
*
* Driver for Zilog serial chips found on Sun workstations and
* servers. This driver could actually be made more generic.
*
* This is based on the old drivers/sbus/char/zs.c code. A lot
* of code has been simply moved over directly from there but
* much has been rewritten. Credits therefore go out to Eddie
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
* Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/circ_buf.h>
#include <linux/serial.h>
#include <linux/sysrq.h>
#include <linux/console.h>
#include <linux/spinlock.h>
#ifdef CONFIG_SERIO
#include <linux/serio.h>
#endif
#include <linux/init.h>
#include <linux/of_device.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/setup.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <linux/sunserialcore.h>
#include "sunzilog.h"
/* On 32-bit sparcs we need to delay after register accesses
* to accommodate sun4 systems, but we do not need to flush writes.
* On 64-bit sparc we only need to flush single writes to ensure
* completion.
*/
#ifndef CONFIG_SPARC64
#define ZSDELAY() udelay(5)
#define ZSDELAY_LONG() udelay(20)
#define ZS_WSYNC(channel) do { } while (0)
#else
#define ZSDELAY()
#define ZSDELAY_LONG()
#define ZS_WSYNC(__channel) \
readb(&((__channel)->control))
#endif
#define ZS_CLOCK 4915200 /* Zilog input clock rate. */
#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
/*
* We wrap our port structure around the generic uart_port.
*/
struct uart_sunzilog_port {
struct uart_port port;
/* IRQ servicing chain. */
struct uart_sunzilog_port *next;
/* Current values of Zilog write registers. */
unsigned char curregs[NUM_ZSREGS];
unsigned int flags;
#define SUNZILOG_FLAG_CONS_KEYB 0x00000001
#define SUNZILOG_FLAG_CONS_MOUSE 0x00000002
#define SUNZILOG_FLAG_IS_CONS 0x00000004
#define SUNZILOG_FLAG_IS_KGDB 0x00000008
#define SUNZILOG_FLAG_MODEM_STATUS 0x00000010
#define SUNZILOG_FLAG_IS_CHANNEL_A 0x00000020
#define SUNZILOG_FLAG_REGS_HELD 0x00000040
#define SUNZILOG_FLAG_TX_STOPPED 0x00000080
#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
#define SUNZILOG_FLAG_ESCC 0x00000200
#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400
unsigned int cflag;
uns