linux/drivers/tty/serial/8250/8250_exar.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  Probe module for 8250/16550-type Exar chips PCI serial ports.
 *
 *  Based on drivers/tty/serial/8250/8250_pci.c,
 *
 *  Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved.
 */
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/property.h>
#include <linux/string.h>
#include <linux/types.h>

#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>

#include <asm/byteorder.h>

#include "8250.h"
#include "8250_pcilib.h"

#define PCI_DEVICE_ID_ACCESSIO_COM_2S
#define PCI_DEVICE_ID_ACCESSIO_COM_4S
#define PCI_DEVICE_ID_ACCESSIO_COM_8S
#define PCI_DEVICE_ID_ACCESSIO_COM232_8
#define PCI_DEVICE_ID_ACCESSIO_COM_2SM
#define PCI_DEVICE_ID_ACCESSIO_COM_4SM
#define PCI_DEVICE_ID_ACCESSIO_COM_8SM

#define PCI_DEVICE_ID_COMMTECH_4224PCI335
#define PCI_DEVICE_ID_COMMTECH_4222PCI335
#define PCI_DEVICE_ID_COMMTECH_2324PCI335
#define PCI_DEVICE_ID_COMMTECH_2328PCI335
#define PCI_DEVICE_ID_COMMTECH_4224PCIE
#define PCI_DEVICE_ID_COMMTECH_4228PCIE
#define PCI_DEVICE_ID_COMMTECH_4222PCIE

#define PCI_VENDOR_ID_CONNECT_TECH
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_SP_OPTO
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_SP_OPTO_A
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_SP_OPTO_B
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_XPRS
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_XPRS_A
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_XPRS_B
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_XPRS
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_16_XPRS_A
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_16_XPRS_B
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_XPRS_OPTO
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_XPRS_OPTO_A
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_XPRS_OPTO_B
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_SP
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_SP_232
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_SP_485
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4_SP
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_6_2_SP
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_6_SP
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_SP_232_NS
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_XP_OPTO_LEFT
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_XP_OPTO_RIGHT
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_XP_OPTO
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4_XPRS_OPTO
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_XPRS_LP
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_XPRS_LP_232
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_XPRS_LP_485
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_XPRS_LP_232_NS
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XEG001
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_BASE
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_2
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_4
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_8
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_12
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCIE_XR35X_16
#define PCI_DEVICE_ID_CONNECT_TECH_PCI_XR79X_12_XIG00X
#define PCI_DEVICE_ID_CONNECT_TECH_PCI_XR79X_12_XIG01X
#define PCI_DEVICE_ID_CONNECT_TECH_PCI_XR79X_16

#define PCI_DEVICE_ID_EXAR_XR17V4358
#define PCI_DEVICE_ID_EXAR_XR17V8358
#define PCI_DEVICE_ID_EXAR_XR17V252
#define PCI_DEVICE_ID_EXAR_XR17V254
#define PCI_DEVICE_ID_EXAR_XR17V258

#define PCI_SUBDEVICE_ID_USR_2980
#define PCI_SUBDEVICE_ID_USR_2981

#define UART_EXAR_INT0
#define UART_EXAR_8XMODE
#define UART_EXAR_SLEEP
#define UART_EXAR_DVID

#define UART_EXAR_FCTR
#define UART_FCTR_EXAR_IRDA
#define UART_FCTR_EXAR_485
#define UART_FCTR_EXAR_TRGA
#define UART_FCTR_EXAR_TRGB
#define UART_FCTR_EXAR_TRGC
#define UART_FCTR_EXAR_TRGD

#define UART_EXAR_TXTRG
#define UART_EXAR_RXTRG

#define UART_EXAR_MPIOINT_7_0
#define UART_EXAR_MPIOLVL_7_0
#define UART_EXAR_MPIO3T_7_0
#define UART_EXAR_MPIOINV_7_0
#define UART_EXAR_MPIOSEL_7_0
#define UART_EXAR_MPIOOD_7_0
#define UART_EXAR_MPIOINT_15_8
#define UART_EXAR_MPIOLVL_15_8
#define UART_EXAR_MPIO3T_15_8
#define UART_EXAR_MPIOINV_15_8
#define UART_EXAR_MPIOSEL_15_8
#define UART_EXAR_MPIOOD_15_8

#define UART_EXAR_RS485_DLY(x)

#define UART_EXAR_DLD
#define UART_EXAR_DLD_485_POLARITY

/* EEPROM registers */
#define UART_EXAR_REGB
#define UART_EXAR_REGB_EECK
#define UART_EXAR_REGB_EECS
#define UART_EXAR_REGB_EEDI
#define UART_EXAR_REGB_EEDO
#define UART_EXAR_REGB_EE_ADDR_SIZE
#define UART_EXAR_REGB_EE_DATA_SIZE

#define UART_EXAR_XR17C15X_PORT_OFFSET
#define UART_EXAR_XR17V25X_PORT_OFFSET
#define UART_EXAR_XR17V35X_PORT_OFFSET

/*
 * IOT2040 MPIO wiring semantics:
 *
 * MPIO		Port	Function
 * ----		----	--------
 * 0		2	Mode bit 0
 * 1		2	Mode bit 1
 * 2		2	Terminate bus
 * 3		-	<reserved>
 * 4		3	Mode bit 0
 * 5		3	Mode bit 1
 * 6		3	Terminate bus
 * 7		-	<reserved>
 * 8		2	Enable
 * 9		3	Enable
 * 10		-	Red LED
 * 11..15	-	<unused>
 */

/* IOT2040 MPIOs 0..7 */
#define IOT2040_UART_MODE_RS232
#define IOT2040_UART_MODE_RS485
#define IOT2040_UART_MODE_RS422
#define IOT2040_UART_TERMINATE_BUS

#define IOT2040_UART1_MASK
#define IOT2040_UART2_SHIFT

#define IOT2040_UARTS_DEFAULT_MODE
#define IOT2040_UARTS_GPIO_LO_MODE

/* IOT2040 MPIOs 8..15 */
#define IOT2040_UARTS_ENABLE
#define IOT2040_UARTS_GPIO_HI_MODE

/* CTI EEPROM offsets */
#define CTI_EE_OFF_XR17C15X_OSC_FREQ
#define CTI_EE_OFF_XR17V25X_OSC_FREQ
#define CTI_EE_OFF_XR17C15X_PART_NUM
#define CTI_EE_OFF_XR17V25X_PART_NUM
#define CTI_EE_OFF_XR17C15X_SERIAL_NUM
#define CTI_EE_OFF_XR17V25X_SERIAL_NUM
#define CTI_EE_OFF_XR17V35X_SERIAL_NUM
#define CTI_EE_OFF_XR17V35X_BRD_FLAGS
#define CTI_EE_OFF_XR17V35X_PORT_FLAGS

#define CTI_EE_MASK_PORT_FLAGS_TYPE
#define CTI_EE_MASK_OSC_FREQ_LOWER
#define CTI_EE_MASK_OSC_FREQ_UPPER

#define CTI_FPGA_RS485_IO_REG
#define CTI_FPGA_CFG_INT_EN_REG
#define CTI_FPGA_CFG_INT_EN_EXT_BIT

#define CTI_DEFAULT_PCI_OSC_FREQ
#define CTI_DEFAULT_PCIE_OSC_FREQ
#define CTI_DEFAULT_FPGA_OSC_FREQ

/*
 * CTI Serial port line types. These match the values stored in the first
 * nibble of the CTI EEPROM port_flags word.
 */
enum cti_port_type {};

#define CTI_PORT_TYPE_VALID(_port_type)

#define CTI_PORT_TYPE_RS485(_port_type)

struct exar8250;

struct exar8250_platform {};

/**
 * struct exar8250_board - board information
 * @num_ports: number of serial ports
 * @reg_shift: describes UART register mapping in PCI memory
 * @setup: quirk run at ->probe() stage for each port
 * @exit: quirk run at ->remove() stage
 */
struct exar8250_board {};

struct exar8250 {};

static inline void exar_write_reg(struct exar8250 *priv,
				unsigned int reg, u8 value)
{}

static inline u8 exar_read_reg(struct exar8250 *priv, unsigned int reg)
{}

static inline void exar_ee_select(struct exar8250 *priv)
{}

static inline void exar_ee_deselect(struct exar8250 *priv)
{}

static inline void exar_ee_write_bit(struct exar8250 *priv, u8 bit)
{}

static inline u8 exar_ee_read_bit(struct exar8250 *priv)
{}

/**
 * exar_ee_read() - Read a word from the EEPROM
 * @priv: Device's private structure
 * @ee_addr: Offset of EEPROM to read word from
 *
 * Read a single 16bit word from an Exar UART's EEPROM.
 * The type of the EEPROM is AT93C46D.
 *
 * Return: EEPROM word
 */
static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
{}

/**
 * exar_mpio_config_output() - Configure an Exar MPIO as an output
 * @priv: Device's private structure
 * @mpio_num: MPIO number/offset to configure
 *
 * Configure a single MPIO as an output and disable tristate. It is reccomended
 * to set the level with exar_mpio_set_high()/exar_mpio_set_low() prior to
 * calling this function to ensure default MPIO pin state.
 *
 * Return: 0 on success, negative error code on failure
 */
static int exar_mpio_config_output(struct exar8250 *priv,
				unsigned int mpio_num)
{}

/**
 * _exar_mpio_set() - Set an Exar MPIO output high or low
 * @priv: Device's private structure
 * @mpio_num: MPIO number/offset to set
 * @high: Set MPIO high if true, low if false
 *
 * Set a single MPIO high or low. exar_mpio_config_output() must also be called
 * to configure the pin as an output.
 *
 * Return: 0 on success, negative error code on failure
 */
static int _exar_mpio_set(struct exar8250 *priv,
			unsigned int mpio_num, bool high)
{}

static int exar_mpio_set_low(struct exar8250 *priv, unsigned int mpio_num)
{}

static int exar_mpio_set_high(struct exar8250 *priv, unsigned int mpio_num)
{}

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

static const struct serial_rs485 generic_rs485_supported =;

static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old)
{}

/*
 * XR17V35x UARTs have an extra fractional divisor register (DLD)
 * Calculate divisor with extra 4-bit fractional portion
 */
static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud,
					 unsigned int *frac)
{}

static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
				 unsigned int quot, unsigned int quot_frac)
{}

static int xr17v35x_startup(struct uart_port *port)
{}

static void exar_shutdown(struct uart_port *port)
{}

static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
			 int idx, unsigned int offset,
			 struct uart_8250_port *port)
{}

static int
pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev,
		     struct uart_8250_port *port, int idx)
{}

/**
 * cti_tristate_disable() - Disable RS485 transciever tristate
 * @priv: Device's private structure
 * @port_num: Port number to set tristate off
 *
 * Most RS485 capable cards have a power on tristate jumper/switch that ensures
 * the RS422/RS485 transceiver does not drive a multi-drop RS485 bus when it is
 * not the master. When this jumper is installed the user must set the RS485
 * mode to Full or Half duplex to disable tristate prior to using the port.
 *
 * Some Exar UARTs have an auto-tristate feature while others require setting
 * an MPIO to disable the tristate.
 *
 * Return: 0 on success, negative error code on failure
 */
static int cti_tristate_disable(struct exar8250 *priv, unsigned int port_num)
{}

/**
 * cti_plx_int_enable() - Enable UART interrupts to PLX bridge
 * @priv: Device's private structure
 *
 * Some older CTI cards require MPIO_0 to be set low to enable the
 * interrupts from the UART to the PLX PCI->PCIe bridge.
 *
 * Return: 0 on success, negative error code on failure
 */
static int cti_plx_int_enable(struct exar8250 *priv)
{}

/**
 * cti_read_osc_freq() - Read the UART oscillator frequency from EEPROM
 * @priv: Device's private structure
 * @eeprom_offset: Offset where the oscillator frequency is stored
 *
 * CTI XR17x15X and XR17V25X cards have the serial boards oscillator frequency
 * stored in the EEPROM. FPGA and XR17V35X based cards use the PCI/PCIe clock.
 *
 * Return: frequency on success, negative error code on failure
 */
static int cti_read_osc_freq(struct exar8250 *priv, u8 eeprom_offset)
{}

/**
 * cti_get_port_type_xr17c15x_xr17v25x() - Get port type of xr17c15x/xr17v25x
 * @priv: Device's private structure
 * @pcidev: Pointer to the PCI device for this port
 * @port_num: Port to get type of
 *
 * CTI xr17c15x and xr17v25x based cards port types are based on PCI IDs.
 *
 * Return: port type on success, CTI_PORT_TYPE_NONE on failure
 */
static enum cti_port_type cti_get_port_type_xr17c15x_xr17v25x(struct exar8250 *priv,
							struct pci_dev *pcidev,
							unsigned int port_num)
{}

/**
 * cti_get_port_type_fpga() - Get the port type of a CTI FPGA card
 * @priv: Device's private structure
 * @pcidev: Pointer to the PCI device for this port
 * @port_num: Port to get type of
 *
 * FPGA based cards port types are based on PCI IDs.
 *
 * Return: port type on success, CTI_PORT_TYPE_NONE on failure
 */
static enum cti_port_type cti_get_port_type_fpga(struct exar8250 *priv,
						struct pci_dev *pcidev,
						unsigned int port_num)
{}

/**
 * cti_get_port_type_xr17v35x() - Read port type from the EEPROM
 * @priv: Device's private structure
 * @pcidev: Pointer to the PCI device for this port
 * @port_num: port offset
 *
 * CTI XR17V35X based cards have the port types stored in the EEPROM.
 * This function reads the port type for a single port.
 *
 * Return: port type on success, CTI_PORT_TYPE_NONE on failure
 */
static enum cti_port_type cti_get_port_type_xr17v35x(struct exar8250 *priv,
						struct pci_dev *pcidev,
						unsigned int port_num)
{}

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

static void cti_board_init_osc_freq(struct exar8250 *priv, struct pci_dev *pcidev, u8 eeprom_offset)
{}

static int cti_port_setup_common(struct exar8250 *priv,
				struct pci_dev *pcidev,
				int idx, unsigned int offset,
				struct uart_8250_port *port)
{}

static int cti_board_init_fpga(struct exar8250 *priv, struct pci_dev *pcidev)
{}

static int cti_port_setup_fpga(struct exar8250 *priv,
				struct pci_dev *pcidev,
				struct uart_8250_port *port,
				int idx)
{}

static void cti_board_init_xr17v35x(struct exar8250 *priv, struct pci_dev *pcidev)
{}

static int cti_port_setup_xr17v35x(struct exar8250 *priv,
				struct pci_dev *pcidev,
				struct uart_8250_port *port,
				int idx)
{}

static void cti_board_init_xr17v25x(struct exar8250 *priv, struct pci_dev *pcidev)
{}

static int cti_port_setup_xr17v25x(struct exar8250 *priv,
				struct pci_dev *pcidev,
				struct uart_8250_port *port,
				int idx)
{}

static void cti_board_init_xr17c15x(struct exar8250 *priv, struct pci_dev *pcidev)
{}

static int cti_port_setup_xr17c15x(struct exar8250 *priv,
				struct pci_dev *pcidev,
				struct uart_8250_port *port,
				int idx)
{}

static int
pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev,
		   struct uart_8250_port *port, int idx)
{}

static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
{}

static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
							const struct software_node *node)
{}

static void __xr17v35x_unregister_gpio(struct platform_device *pdev)
{}

static const struct property_entry exar_gpio_properties[] =;

static const struct software_node exar_gpio_node =;

static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port)
{}

static void xr17v35x_unregister_gpio(struct uart_8250_port *port)
{}

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

static const struct exar8250_platform exar8250_default_platform =;

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

static const struct serial_rs485 iot2040_rs485_supported =;

static const struct property_entry iot2040_gpio_properties[] =;

static const struct software_node iot2040_gpio_node =;

static int iot2040_register_gpio(struct pci_dev *pcidev,
			      struct uart_8250_port *port)
{}

static const struct exar8250_platform iot2040_platform =;

/*
 * For SIMATIC IOT2000, only IOT2040 and its variants have the Exar device,
 * IOT2020 doesn't have. Therefore it is sufficient to match on the common
 * board name after the device was found.
 */
static const struct dmi_system_id exar_platforms[] =;

static const struct exar8250_platform *exar_get_platform(void)
{}

static int
pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
		   struct uart_8250_port *port, int idx)
{}

static void pci_xr17v35x_exit(struct pci_dev *pcidev)
{}

static inline void exar_misc_clear(struct exar8250 *priv)
{}

/*
 * These Exar UARTs have an extra interrupt indicator that could fire for a
 * few interrupts that are not presented/cleared through IIR.  One of which is
 * a wakeup interrupt when coming out of sleep.  These interrupts are only
 * cleared by reading global INT0 or INT1 registers as interrupts are
 * associated with channel 0. The INT[3:0] registers _are_ accessible from each
 * channel's address space, but for the sake of bus efficiency we register a
 * dedicated handler at the PCI device level to handle them.
 */
static irqreturn_t exar_misc_handler(int irq, void *data)
{}

static unsigned int exar_get_nr_ports(struct exar8250_board *board, struct pci_dev *pcidev)
{}

static int
exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
{}

static void exar_pci_remove(struct pci_dev *pcidev)
{}

static int exar_suspend(struct device *dev)
{}

static int exar_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);

static const struct exar8250_board pbn_fastcom335_2 =;

static const struct exar8250_board pbn_fastcom335_4 =;

static const struct exar8250_board pbn_fastcom335_8 =;

static const struct exar8250_board pbn_cti_xr17c15x =;

static const struct exar8250_board pbn_cti_xr17v25x =;

static const struct exar8250_board pbn_cti_xr17v35x =;

static const struct exar8250_board pbn_cti_fpga =;

static const struct exar8250_board pbn_exar_ibm_saturn =;

static const struct exar8250_board pbn_exar_XR17C15x =;

static const struct exar8250_board pbn_exar_XR17V35x =;

static const struct exar8250_board pbn_fastcom35x_2 =;

static const struct exar8250_board pbn_fastcom35x_4 =;

static const struct exar8250_board pbn_fastcom35x_8 =;

static const struct exar8250_board pbn_exar_XR17V4358 =;

static const struct exar8250_board pbn_exar_XR17V8358 =;

#define CTI_EXAR_DEVICE(devid, bd)

#define EXAR_DEVICE(vend, devid, bd)

#define IBM_DEVICE(devid, sdevid, bd)

#define USR_DEVICE(devid, sdevid, bd)

static const struct pci_device_id exar_pci_tbl[] =;
MODULE_DEVICE_TABLE(pci, exar_pci_tbl);

static struct pci_driver exar_pci_driver =;
module_pci_driver();

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