linux/drivers/tty/serial/sc16is7xx.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * SC16IS7xx tty serial driver - common code
 *
 * Copyright (C) 2014 GridPoint
 * Author: Jon Ringle <[email protected]>
 * Based on max310x.c, by Alexander Shiyan <[email protected]>
 */

#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE

#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/idr.h>
#include <linux/kthread.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/sched.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/uaccess.h>
#include <linux/units.h>

#include "sc16is7xx.h"

#define SC16IS7XX_MAX_DEVS

/* SC16IS7XX register definitions */
#define SC16IS7XX_RHR_REG
#define SC16IS7XX_THR_REG
#define SC16IS7XX_IER_REG
#define SC16IS7XX_IIR_REG
#define SC16IS7XX_FCR_REG
#define SC16IS7XX_LCR_REG
#define SC16IS7XX_MCR_REG
#define SC16IS7XX_LSR_REG
#define SC16IS7XX_MSR_REG
#define SC16IS7XX_SPR_REG
#define SC16IS7XX_TXLVL_REG
#define SC16IS7XX_RXLVL_REG
#define SC16IS7XX_IODIR_REG
#define SC16IS7XX_IOSTATE_REG
#define SC16IS7XX_IOINTENA_REG
#define SC16IS7XX_IOCONTROL_REG
#define SC16IS7XX_EFCR_REG

/* TCR/TLR Register set: Only if ((MCR[2] == 1) && (EFR[4] == 1)) */
#define SC16IS7XX_TCR_REG
#define SC16IS7XX_TLR_REG

/* Special Register set: Only if ((LCR[7] == 1) && (LCR != 0xBF)) */
#define SC16IS7XX_DLL_REG
#define SC16IS7XX_DLH_REG

/* Enhanced Register set: Only if (LCR == 0xBF) */
#define SC16IS7XX_EFR_REG
#define SC16IS7XX_XON1_REG
#define SC16IS7XX_XON2_REG
#define SC16IS7XX_XOFF1_REG
#define SC16IS7XX_XOFF2_REG

/* IER register bits */
#define SC16IS7XX_IER_RDI_BIT
#define SC16IS7XX_IER_THRI_BIT
#define SC16IS7XX_IER_RLSI_BIT
#define SC16IS7XX_IER_MSI_BIT

/* IER register bits - write only if (EFR[4] == 1) */
#define SC16IS7XX_IER_SLEEP_BIT
#define SC16IS7XX_IER_XOFFI_BIT
#define SC16IS7XX_IER_RTSI_BIT
#define SC16IS7XX_IER_CTSI_BIT

/* FCR register bits */
#define SC16IS7XX_FCR_FIFO_BIT
#define SC16IS7XX_FCR_RXRESET_BIT
#define SC16IS7XX_FCR_TXRESET_BIT
#define SC16IS7XX_FCR_RXLVLL_BIT
#define SC16IS7XX_FCR_RXLVLH_BIT

/* FCR register bits - write only if (EFR[4] == 1) */
#define SC16IS7XX_FCR_TXLVLL_BIT
#define SC16IS7XX_FCR_TXLVLH_BIT

/* IIR register bits */
#define SC16IS7XX_IIR_NO_INT_BIT
#define SC16IS7XX_IIR_ID_MASK
#define SC16IS7XX_IIR_THRI_SRC
#define SC16IS7XX_IIR_RDI_SRC
#define SC16IS7XX_IIR_RLSE_SRC
#define SC16IS7XX_IIR_RTOI_SRC
#define SC16IS7XX_IIR_MSI_SRC
#define SC16IS7XX_IIR_INPIN_SRC
#define SC16IS7XX_IIR_XOFFI_SRC
#define SC16IS7XX_IIR_CTSRTS_SRC
/* LCR register bits */
#define SC16IS7XX_LCR_LENGTH0_BIT
#define SC16IS7XX_LCR_LENGTH1_BIT
#define SC16IS7XX_LCR_STOPLEN_BIT
#define SC16IS7XX_LCR_PARITY_BIT
#define SC16IS7XX_LCR_EVENPARITY_BIT
#define SC16IS7XX_LCR_FORCEPARITY_BIT
#define SC16IS7XX_LCR_TXBREAK_BIT
#define SC16IS7XX_LCR_DLAB_BIT
#define SC16IS7XX_LCR_WORD_LEN_5
#define SC16IS7XX_LCR_WORD_LEN_6
#define SC16IS7XX_LCR_WORD_LEN_7
#define SC16IS7XX_LCR_WORD_LEN_8
#define SC16IS7XX_LCR_CONF_MODE_A
#define SC16IS7XX_LCR_CONF_MODE_B

/* MCR register bits */
#define SC16IS7XX_MCR_DTR_BIT
#define SC16IS7XX_MCR_RTS_BIT
#define SC16IS7XX_MCR_TCRTLR_BIT
#define SC16IS7XX_MCR_LOOP_BIT
#define SC16IS7XX_MCR_XONANY_BIT
#define SC16IS7XX_MCR_IRDA_BIT
#define SC16IS7XX_MCR_CLKSEL_BIT

/* LSR register bits */
#define SC16IS7XX_LSR_DR_BIT
#define SC16IS7XX_LSR_OE_BIT
#define SC16IS7XX_LSR_PE_BIT
#define SC16IS7XX_LSR_FE_BIT
#define SC16IS7XX_LSR_BI_BIT
#define SC16IS7XX_LSR_BRK_ERROR_MASK

#define SC16IS7XX_LSR_THRE_BIT
#define SC16IS7XX_LSR_TEMT_BIT
#define SC16IS7XX_LSR_FIFOE_BIT

/* MSR register bits */
#define SC16IS7XX_MSR_DCTS_BIT
#define SC16IS7XX_MSR_DDSR_BIT
#define SC16IS7XX_MSR_DRI_BIT
#define SC16IS7XX_MSR_DCD_BIT
#define SC16IS7XX_MSR_CTS_BIT
#define SC16IS7XX_MSR_DSR_BIT
#define SC16IS7XX_MSR_RI_BIT
#define SC16IS7XX_MSR_CD_BIT

/*
 * TCR register bits
 * TCR trigger levels are available from 0 to 60 characters with a granularity
 * of four.
 * The programmer must program the TCR such that TCR[3:0] > TCR[7:4]. There is
 * no built-in hardware check to make sure this condition is met. Also, the TCR
 * must be programmed with this condition before auto RTS or software flow
 * control is enabled to avoid spurious operation of the device.
 */
#define SC16IS7XX_TCR_RX_HALT(words)
#define SC16IS7XX_TCR_RX_RESUME(words)

/*
 * TLR register bits
 * If TLR[3:0] or TLR[7:4] are logical 0, the selectable trigger levels via the
 * FIFO Control Register (FCR) are used for the transmit and receive FIFO
 * trigger levels. Trigger levels from 4 characters to 60 characters are
 * available with a granularity of four.
 *
 * When the trigger level setting in TLR is zero, the SC16IS74x/75x/76x uses the
 * trigger level setting defined in FCR. If TLR has non-zero trigger level value
 * the trigger level defined in FCR is discarded. This applies to both transmit
 * FIFO and receive FIFO trigger level setting.
 *
 * When TLR is used for RX trigger level control, FCR[7:6] should be left at the
 * default state, that is, '00'.
 */
#define SC16IS7XX_TLR_TX_TRIGGER(words)
#define SC16IS7XX_TLR_RX_TRIGGER(words)

/* IOControl register bits (Only 75x/76x) */
#define SC16IS7XX_IOCONTROL_LATCH_BIT
#define SC16IS7XX_IOCONTROL_MODEM_A_BIT
#define SC16IS7XX_IOCONTROL_MODEM_B_BIT
#define SC16IS7XX_IOCONTROL_SRESET_BIT

/* EFCR register bits */
#define SC16IS7XX_EFCR_9BIT_MODE_BIT
#define SC16IS7XX_EFCR_RXDISABLE_BIT
#define SC16IS7XX_EFCR_TXDISABLE_BIT
#define SC16IS7XX_EFCR_AUTO_RS485_BIT
#define SC16IS7XX_EFCR_RTS_INVERT_BIT
#define SC16IS7XX_EFCR_IRDA_MODE_BIT

/* EFR register bits */
#define SC16IS7XX_EFR_AUTORTS_BIT
#define SC16IS7XX_EFR_AUTOCTS_BIT
#define SC16IS7XX_EFR_XOFF2_DETECT_BIT
#define SC16IS7XX_EFR_ENABLE_BIT
#define SC16IS7XX_EFR_SWFLOW3_BIT
#define SC16IS7XX_EFR_SWFLOW2_BIT
						 /*
						  * SWFLOW bits 3 & 2 table:
						  * 00 -> no transmitter flow
						  *       control
						  * 01 -> transmitter generates
						  *       XON2 and XOFF2
						  * 10 -> transmitter generates
						  *       XON1 and XOFF1
						  * 11 -> transmitter generates
						  *       XON1, XON2, XOFF1 and
						  *       XOFF2
						  */
#define SC16IS7XX_EFR_SWFLOW1_BIT
#define SC16IS7XX_EFR_SWFLOW0_BIT
						 /*
						  * SWFLOW bits 1 & 0 table:
						  * 00 -> no received flow
						  *       control
						  * 01 -> receiver compares
						  *       XON2 and XOFF2
						  * 10 -> receiver compares
						  *       XON1 and XOFF1
						  * 11 -> receiver compares
						  *       XON1, XON2, XOFF1 and
						  *       XOFF2
						  */
#define SC16IS7XX_EFR_FLOWCTRL_BITS


/* Misc definitions */
#define SC16IS7XX_FIFO_SIZE
#define SC16IS7XX_GPIOS_PER_BANK

#define SC16IS7XX_RECONF_MD
#define SC16IS7XX_RECONF_IER
#define SC16IS7XX_RECONF_RS485

struct sc16is7xx_one_config {};

struct sc16is7xx_one {};

struct sc16is7xx_port {};

static DEFINE_IDA(sc16is7xx_lines);

static struct uart_driver sc16is7xx_uart =;

#define to_sc16is7xx_one(p,e)

static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
{}

static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
{}

static void sc16is7xx_fifo_read(struct uart_port *port, u8 *rxbuf, unsigned int rxlen)
{}

static void sc16is7xx_fifo_write(struct uart_port *port, u8 *txbuf, u8 to_send)
{}

static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
				  u8 mask, u8 val)
{}

static void sc16is7xx_power(struct uart_port *port, int on)
{}

/*
 * In an amazing feat of design, the Enhanced Features Register (EFR)
 * shares the address of the Interrupt Identification Register (IIR).
 * Access to EFR is switched on by writing a magic value (0xbf) to the
 * Line Control Register (LCR). Any interrupt firing during this time will
 * see the EFR where it expects the IIR to be, leading to
 * "Unexpected interrupt" messages.
 *
 * Prevent this possibility by claiming a mutex while accessing the EFR,
 * and claiming the same mutex from within the interrupt handler. This is
 * similar to disabling the interrupt, but that doesn't work because the
 * bulk of the interrupt processing is run as a workqueue job in thread
 * context.
 */
static void sc16is7xx_efr_lock(struct uart_port *port)
{}

static void sc16is7xx_efr_unlock(struct uart_port *port)
{}

static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit)
{}

static void sc16is7xx_ier_set(struct uart_port *port, u8 bit)
{}

static void sc16is7xx_stop_tx(struct uart_port *port)
{}

static void sc16is7xx_stop_rx(struct uart_port *port)
{}

const struct sc16is7xx_devtype sc16is74x_devtype =;
EXPORT_SYMBOL_GPL();

const struct sc16is7xx_devtype sc16is750_devtype =;
EXPORT_SYMBOL_GPL();

const struct sc16is7xx_devtype sc16is752_devtype =;
EXPORT_SYMBOL_GPL();

const struct sc16is7xx_devtype sc16is760_devtype =;
EXPORT_SYMBOL_GPL();

const struct sc16is7xx_devtype sc16is762_devtype =;
EXPORT_SYMBOL_GPL();

static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
{}

static bool sc16is7xx_regmap_precious(struct device *dev, unsigned int reg)
{}

static bool sc16is7xx_regmap_noinc(struct device *dev, unsigned int reg)
{}

/*
 * Configure programmable baud rate generator (divisor) according to the
 * desired baud rate.
 *
 * From the datasheet, the divisor is computed according to:
 *
 *              XTAL1 input frequency
 *             -----------------------
 *                    prescaler
 * divisor = ---------------------------
 *            baud-rate x sampling-rate
 */
static int sc16is7xx_set_baud(struct uart_port *port, int baud)
{}

static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
				unsigned int iir)
{}

static void sc16is7xx_handle_tx(struct uart_port *port)
{}

static unsigned int sc16is7xx_get_hwmctrl(struct uart_port *port)
{}

static void sc16is7xx_update_mlines(struct sc16is7xx_one *one)
{}

static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
{}

static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
{}

static void sc16is7xx_tx_proc(struct kthread_work *ws)
{}

static void sc16is7xx_reconf_rs485(struct uart_port *port)
{}

static void sc16is7xx_reg_proc(struct kthread_work *ws)
{}

static void sc16is7xx_ms_proc(struct kthread_work *ws)
{}

static void sc16is7xx_enable_ms(struct uart_port *port)
{}

static void sc16is7xx_start_tx(struct uart_port *port)
{}

static void sc16is7xx_throttle(struct uart_port *port)
{}

static void sc16is7xx_unthrottle(struct uart_port *port)
{}

static unsigned int sc16is7xx_tx_empty(struct uart_port *port)
{}

static unsigned int sc16is7xx_get_mctrl(struct uart_port *port)
{}

static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
{}

static void sc16is7xx_break_ctl(struct uart_port *port, int break_state)
{}

static void sc16is7xx_set_termios(struct uart_port *port,
				  struct ktermios *termios,
				  const struct ktermios *old)
{}

static int sc16is7xx_config_rs485(struct uart_port *port, struct ktermios *termios,
				  struct serial_rs485 *rs485)
{}

static int sc16is7xx_startup(struct uart_port *port)
{}

static void sc16is7xx_shutdown(struct uart_port *port)
{}

static const char *sc16is7xx_type(struct uart_port *port)
{}

static int sc16is7xx_request_port(struct uart_port *port)
{}

static void sc16is7xx_config_port(struct uart_port *port, int flags)
{}

static int sc16is7xx_verify_port(struct uart_port *port,
				 struct serial_struct *s)
{}

static void sc16is7xx_pm(struct uart_port *port, unsigned int state,
			 unsigned int oldstate)
{}

static void sc16is7xx_null_void(struct uart_port *port)
{}

static const struct uart_ops sc16is7xx_ops =;

#ifdef CONFIG_GPIOLIB
static int sc16is7xx_gpio_get(struct gpio_chip *chip, unsigned offset)
{}

static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
{}

static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip,
					  unsigned offset)
{}

static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
					   unsigned offset, int val)
{}

static int sc16is7xx_gpio_init_valid_mask(struct gpio_chip *chip,
					  unsigned long *valid_mask,
					  unsigned int ngpios)
{}

static int sc16is7xx_setup_gpio_chip(struct sc16is7xx_port *s)
{}
#endif

static void sc16is7xx_setup_irda_ports(struct sc16is7xx_port *s)
{}

/*
 * Configure ports designated to operate as modem control lines.
 */
static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s,
				       struct regmap *regmap)
{}

static const struct serial_rs485 sc16is7xx_rs485_supported =;

/* Reset device, purging any pending irq / data */
static int sc16is7xx_reset(struct device *dev, struct regmap *regmap)
{}

int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
		    struct regmap *regmaps[], int irq)
{}
EXPORT_SYMBOL_GPL();

void sc16is7xx_remove(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

const struct of_device_id __maybe_unused sc16is7xx_dt_ids[] =;
EXPORT_SYMBOL_GPL();
MODULE_DEVICE_TABLE(of, sc16is7xx_dt_ids);

const struct regmap_config sc16is7xx_regcfg =;
EXPORT_SYMBOL_GPL();

const char *sc16is7xx_regmap_name(u8 port_id)
{}
EXPORT_SYMBOL_GPL();

unsigned int sc16is7xx_regmap_port_mask(unsigned int port_id)
{}
EXPORT_SYMBOL_GPL();

static int __init sc16is7xx_init(void)
{}
module_init();

static void __exit sc16is7xx_exit(void)
{}
module_exit(sc16is7xx_exit);

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();