// SPDX-License-Identifier: GPL-2.0
/*
* su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1998-1999 Pete Zaitcev (zaitcev@yahoo.com)
*
* This is mainly a variation of 8250.c, credits go to authors mentioned
* therein. In fact this driver should be merged into the generic 8250.c
* infrastructure perhaps using a 8250_sparc.c module.
*
* Fixed to use tty_get_baud_rate().
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Converted to new 2.5.x UART layer.
* David S. Miller (davem@davemloft.net), 2002-Jul-29
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spinlock.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/slab.h>
#ifdef CONFIG_SERIO
#include <linux/serio.h>
#endif
#include <linux/serial_reg.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <linux/serial_core.h>
#include <linux/sunserialcore.h>
/* We are on a NS PC87303 clocked with 24.0 MHz, which results
* in a UART clock of 1.8462 MHz.
*/
#define SU_BASE_BAUD (1846200 / 16)
enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" };
struct serial_uart_config {
char *name;
int dfl_xmit_fifo_size;
int flags;
};
/*
* Here we define the default xmit fifo size used for each type of UART.
*/
static const struct serial_uart_config uart_config[] = {
{ "unknown", 1, 0 },
{ "8250", 1, 0 },
{ "16450", 1, 0 },
{ "16550", 1, 0 },
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "Cirrus", 1, 0 },
{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "Startech", 1, 0 },
{ "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
};
struct uart_sunsu_port {
struct uart_port port;
unsigned char acr;
unsigned char ier;
unsigned short rev;
unsigned char lcr;
unsigned int lsr_break_flag;
unsigned int cflag;
/* Probing information. */
enum su_type su_type;
unsigned int type_probed; /* XXX Stupid */
unsigned long reg_size;
#ifdef CONFIG_SERIO
struct serio serio;
int serio_open;
#endif
};
static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
{
offset <<= up->port.regshift;
switch (up->port.iotype) {
case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
return inb(up->port.iobase + 1);
case UPIO_MEM:
return readb(up->port.membase + offset);
default:
return inb(up->port.iobase + offset);
}
}
static void serial_out(struct uart_sunsu_port *up, int offset, int value)
{
#ifndef CONFIG_SPARC64
/*
* MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are
* connected with a gate then go to SlavIO. When IRQ4 goes tristated
* gate outputs a logical one. Since we use level triggered interrupts
* we have lockup and watchdog reset. We cannot mask IRQ because
* keyboard shares IRQ with us (Word has it as Bob Smelik's design).
* This problem is similar to what Alpha people suffer, see
* 8250_alpha.c.
*/
if (offset == UART_MCR)
value |= UART_MCR_OUT2;
#endif
offset <<= up->port.regshift;
switch (up->port.iotype) {
case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
outb(value, up->port.iobase + 1);
break;
case UPIO_MEM:
writeb(value, up->port.membase + offset);
break;
default:
outb(value, up->port.iobase + offset);
}
}
/*
* For the 16C950
*/
static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value)
{
serial_out(up, UART_SCR, offset);
serial_out(up, UART_ICR, value);
}
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Attempts to turn on the RSA FIFO. Returns zero on failure.
* We set the port uart clock rate if we succeed.
*/
static int __enable_rsa(struct uart_sunsu_port *up)
{
unsigned char mode;
int result;
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
if (!result) {
serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
mode = serial_in(up, UART_RSA_MSR);
result = mode & UART_RSA_MSR_FIFO;
}
if (result)
up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
return result;
}
static void enable_rsa(struct uart_sunsu_port *up)
{
if (up->port.type == PORT_RSA) {
if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
uart_port_lock_irq(&up->port);
__enable_rsa(up);
uart_port_unlock_irq(&up->port);
}
if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
serial_out(up, UART_RSA_FRR, 0);
}
}
/*
* Attempts to turn off the RSA FIFO. Returns zero on failure.
* It is unknown why interrupts were disabled in here. However,
* the caller is expected to preserve this behaviour by grabbing
* the spinlock before calling this function.
*/
static void disable_rsa(struct uart_sunsu_port *up)
{
unsigned char mode;
int result;
if (up->port.type == PORT_RSA &&
up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
uart_port_lock_irq(&up->port);
mode = serial_in(up, UART_RSA_MSR);
result = !(mode & UART_RSA_MSR_FIFO);
i
|