// SPDX-License-Identifier: GPL-2.0
/* sunsab.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*
* Rewrote buffer handling to use CIRC(Circular Buffer) macros.
* Maxim Krasnyanskiy <maxk@qualcomm.com>
*
* Fixed to use tty_get_baud_rate, and to allow for arbitrary baud
* rates to be programmed into the UART. Also eliminated a lot of
* duplicated code in the console setup.
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Ported to new 2.5.x UART layer.
* David S. Miller <davem@davemloft.net>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.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/circ_buf.h>
#include <linux/serial.h>
#include <linux/sysrq.h>
#include <linux/console.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/delay.h>
#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_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <linux/sunserialcore.h>
#include "sunsab.h"
struct uart_sunsab_port {
struct uart_port port; /* Generic UART port */
union sab82532_async_regs __iomem *regs; /* Chip registers */
unsigned long irqflags; /* IRQ state flags */
int dsr; /* Current DSR state */
unsigned int cec_timeout; /* Chip poll timeout... */
unsigned int tec_timeout; /* likewise */
unsigned char interrupt_mask0;/* ISR0 masking */
unsigned char interrupt_mask1;/* ISR1 masking */
unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
unsigned int gis_shift;
int type; /* SAB82532 version */
/* Setting configuration bits while the transmitter is active
* can cause garbage characters to get emitted by the chip.
* Therefore, we cache such writes here and do the real register
* write the next time the transmitter becomes idle.
*/
unsigned int cached_ebrg;
unsigned char cached_mode;
unsigned char cached_pvr;
unsigned char cached_dafo;
};
/*
* This assumes you have a 29.4912 MHz clock for your UART.
*/
#define SAB_BASE_BAUD ( 29491200 / 16 )
static char *sab82532_version[16] = {
"V1.0", "V2.0", "V3.2", "V(0x03)",
"V(0x04)", "V(0x05)", "V(0x06)", "V(0x07)",
"V(0x08)", "V(0x09)", "V(0x0a)", "V(0x0b)",
"V(0x0c)", "V(0x0d)", "V(0x0e)", "V(0x0f)"
};
#define SAB82532_MAX_TEC_TIMEOUT 200000 /* 1 character time (at 50 baud) */
#define SAB82532_MAX_CEC_TIMEOUT 50000 /* 2.5 TX CLKs (at 50 baud) */
#define SAB82532_RECV_FIFO_SIZE 32 /* Standard async fifo sizes */
#define SAB82532_XMIT_FIFO_SIZE 32
static __inline__ void sunsab_tec_wait(struct uart_sunsab_port *up)
{
int timeout = up->tec_timeout;
while ((readb(&up->regs->r.star) & SAB82532_STAR_TEC) && --timeout)
udelay(1);
}
static __inline__ void sunsab_cec_wait(struct uart_sunsab_port *up)
{
int timeout = up->cec_timeout;
while ((readb(&up->regs->r.star) & SAB82532_STAR_CEC) && --timeout)
udelay(1);
}
static struct tty_port *
receive_chars(struct uart_sunsab_port *up,
union sab82532_irq_status *stat)
{
struct tty_port *port = NULL;
unsigned char buf[32];
int saw_console_brk = 0;
int free_fifo = 0;
int count = 0;
int i;
if (up->port.state != NULL) /* Unopened serial console */
port = &up->port.state->port;
/* Read number of BYTES (Character + Status) available. */
if (stat->sreg.isr0