// SPDX-License-Identifier: GPL-2.0
/*
* Derived from many drivers using generic_serial interface,
* especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
* (was in Linux/VR tree) by Jim Pick.
*
* Copyright (C) 1999 Harald Koerfgen
* Copyright (C) 2000 Jim Pick <jim@jimpick.com>
* Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
* Copyright (C) 2000-2002 Toshiba Corporation
*
* Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/io.h>
#define PASS_LIMIT 256
#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
/* "ttyS" is used for standard serial driver */
#define TXX9_TTY_NAME "ttyTX"
#define TXX9_TTY_MINOR_START 196
#define TXX9_TTY_MAJOR 204
#else
/* acts like standard serial driver */
#define TXX9_TTY_NAME "ttyS"
#define TXX9_TTY_MINOR_START 64
#define TXX9_TTY_MAJOR TTY_MAJOR
#endif
/* flag aliases */
#define UPF_TXX9_HAVE_CTS_LINE UPF_BUGGY_UART
#define UPF_TXX9_USE_SCLK UPF_MAGIC_MULTIPLIER
#ifdef CONFIG_PCI
/* support for Toshiba TC86C001 SIO */
#define ENABLE_SERIAL_TXX9_PCI
#endif
/*
* Number of serial ports
*/
#define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS
#define TXX9_REGION_SIZE 0x24
/* TXX9 Serial Registers */
#define TXX9_SILCR 0x00
#define TXX9_SIDICR 0x04
#define TXX9_SIDISR 0x08
#define TXX9_SICISR 0x0c
#define TXX9_SIFCR 0x10
#define TXX9_SIFLCR 0x14
#define TXX9_SIBGR 0x18
#define TXX9_SITFIFO 0x1c
#define TXX9_SIRFIFO 0x20
/* SILCR : Line Control */
#define TXX9_SILCR_SCS_MASK 0x00000060
#define TXX9_SILCR_SCS_IMCLK 0x00000000
#define TXX9_SILCR_SCS_IMCLK_BG 0x00000020
#define TXX9_SILCR_SCS_SCLK 0x00000040
#define TXX9_SILCR_SCS_SCLK_BG 0x00000060
#define TXX9_SILCR_UEPS 0x00000010
#define TXX9_SILCR_UPEN 0x00000008
#define TXX9_SILCR_USBL_MASK 0x00000004
#define TXX9_SILCR_USBL_1BIT 0x00000000
#define TXX9_SILCR_USBL_2BIT 0x00000004
#define TXX9_SILCR_UMODE_MASK 0x00000003
#define TXX9_SILCR_UMODE_8BIT 0x00000000
#define TXX9_SILCR_UMODE_7BIT 0x00000001
/* SIDICR : DMA/Int. Control */
#define TXX9_SIDICR_TDE 0x00008000
#define TXX9_SIDICR_RDE 0x00004000
#define TXX9_SIDICR_TIE 0x00002000
#define TXX9_SIDICR_RIE 0x00001000
#define TXX9_SIDICR_SPIE 0x00000800
#define TXX9_SIDICR_CTSAC 0x00000600
#define TXX9_SIDICR_STIE_MASK 0x0000003f
#define TXX9_SIDICR_STIE_OERS 0x00000020
#define TXX9_SIDICR_STIE_CTSS 0x00000010
#define TXX9_SIDICR_STIE_RBRKD 0x00000008
#define TXX9_SIDICR_STIE_TRDY 0x00000004
#define TXX9_SIDICR_STIE_TXALS 0x00000002
#define TXX9_SIDICR_STIE_UBRKD 0x00000001
/* SIDISR : DMA/Int. Status */
#define TXX9_SIDISR_UBRK 0x00008000
#define TXX9_SIDISR_UVALID 0x00004000
#define TXX9_SIDISR_UFER 0x00002000
#define TXX9_SIDISR_UPER 0x00001000
#define TXX9_SIDISR_UOER 0x00000800
#define TXX9_SIDISR_ERI 0x00000400
#define TXX9_SIDISR_TOUT 0x00000200
#define TXX9_SIDISR_TDIS 0x00000100
#define TXX9_SIDISR_RDIS 0x00000080
#define TXX9_SIDISR_STIS 0x00000040
#define TXX9_SIDISR_RFDN_MASK 0x0000001f
/* SICISR : Change Int. Status */
#define TXX9_SICISR_OERS 0x00000020
#define TXX9_SICISR_CTSS 0x00000010
#define TXX9_SICISR_RBRKD 0x00000008
#define TXX9_SICISR_TRDY 0x00000004
#define TXX9_SICISR_TXALS 0x00000002
#define TXX9_SICISR_UBRKD 0x00000001
/* SIFCR : FIFO Control */
#define TXX9_SIFCR_SWRST 0x00008000
#define TXX9_SIFCR_RDIL_MASK 0x00000180
#define TXX9_SIFCR_RDIL_1 0x00000000
#define TXX9_SIFCR_RDIL_4 0x00000080
#define TXX9_SIFCR_RDIL_8 0x00000100
#define TXX9_SIFCR_RDIL_12 0x00000180
#define TXX9_SIFCR_RDIL_MAX 0x00000180
#define TXX9_SIFCR_TDIL_MASK 0x00000018
#define TXX9_SIFCR_TDIL_1 0x00000000
#define TXX9_SIFCR_TDIL_4 0x00000001
#define TXX9_SIFCR_TDIL_8 0x00000010
#define TXX9_SIFCR_TDIL_MAX 0x00000010
#define TXX9_SIFCR_TFRST 0x00000004
#define TXX9_SIFCR_RFRST 0x00000002
#define TXX9_SIFCR_FRSTE 0x00000001
#define TXX9_SIO_TX_FIFO 8
#define TXX9_SIO_RX_FIFO 16
/* SIFLCR : Flow Control */
#define TXX9_SIFLCR_RCS 0x00001000
#define TXX9_SIFLCR_TES 0x00000800
#define TXX9_SIFLCR_RTSSC 0x00000200
#define TXX9_SIFLCR_RSDE 0x00000100
#define TXX9_SIFLCR_TSDE 0x00000080
#define TXX9_SIFLCR_RTSTL_MASK 0x0000001e
#define TXX9_SIFLCR_RTSTL_MAX 0x0000001e
#define TXX9_SIFLCR_TBRK 0x00000001
/* SIBGR : Baudrate Control */
#define TXX9_SIBGR_BCLK_MASK 0x00000300
#define TXX9_SIBGR_BCLK_T0 0x00000000
#define TXX9_SIBGR_BCLK_T2 0x00000100
#define TXX9_SIBGR_BCLK_T4 0x00000200
#define TXX9_SIBGR_BCLK_T6 0x00000300
#define TXX9_SIBGR_BRD_MASK 0x000000ff
static inline unsigned int sio_in(struct uart_port *up, int offset)
{
switch (up->iotype) {
default:
return __raw_readl(up->membase + offset);
case UPIO_PORT:
return inl(up->iobase + offset);
}
}
static inline void
sio_out(struct uart_port *up, int offset, int value)
{
switch (up->iotype) {
default:
__raw_writel(value, up->membase + offset);
break;
case UPIO_PORT:
outl(value, up->iobase + offset);
break;
}
}
static inline void
sio_mask(struct uart_port *up, int offset, unsigned int value)
{
sio_out(up, offset, sio_in(up, offset) & ~value);
}
static inline