linux/drivers/tty/serial/imx.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Driver for Motorola/Freescale IMX serial ports
 *
 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
 *
 * Author: Sascha Hauer <[email protected]>
 * Copyright (C) 2004 Pengutronix
 */

#include <linux/circ_buf.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/pinctrl/consumer.h>
#include <linux/rational.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/dma-mapping.h>

#include <asm/irq.h>
#include <linux/dma/imx-dma.h>

#include "serial_mctrl_gpio.h"

/* Register definitions */
#define URXD0
#define URTX0
#define UCR1
#define UCR2
#define UCR3
#define UCR4
#define UFCR
#define USR1
#define USR2
#define UESC
#define UTIM
#define UBIR
#define UBMR
#define UBRC
#define IMX21_ONEMS
#define IMX1_UTS
#define IMX21_UTS

/* UART Control Register Bit Fields.*/
#define URXD_DUMMY_READ
#define URXD_CHARRDY
#define URXD_ERR
#define URXD_OVRRUN
#define URXD_FRMERR
#define URXD_BRK
#define URXD_PRERR
#define URXD_RX_DATA
#define UCR1_ADEN
#define UCR1_ADBR
#define UCR1_TRDYEN
#define UCR1_IDEN
#define UCR1_ICD_REG(x)
#define UCR1_RRDYEN
#define UCR1_RXDMAEN
#define UCR1_IREN
#define UCR1_TXMPTYEN
#define UCR1_RTSDEN
#define UCR1_SNDBRK
#define UCR1_TXDMAEN
#define IMX1_UCR1_UARTCLKEN
#define UCR1_ATDMAEN
#define UCR1_DOZE
#define UCR1_UARTEN
#define UCR2_ESCI
#define UCR2_IRTS
#define UCR2_CTSC
#define UCR2_CTS
#define UCR2_ESCEN
#define UCR2_PREN
#define UCR2_PROE
#define UCR2_STPB
#define UCR2_WS
#define UCR2_RTSEN
#define UCR2_ATEN
#define UCR2_TXEN
#define UCR2_RXEN
#define UCR2_SRST
#define UCR3_DTREN
#define UCR3_PARERREN
#define UCR3_FRAERREN
#define UCR3_DSR
#define UCR3_DCD
#define UCR3_RI
#define UCR3_ADNIMP
#define UCR3_RXDSEN
#define UCR3_AIRINTEN
#define UCR3_AWAKEN
#define UCR3_DTRDEN
#define IMX21_UCR3_RXDMUXSEL
#define UCR3_INVT
#define UCR3_BPEN
#define UCR4_CTSTL_SHF
#define UCR4_CTSTL_MASK
#define UCR4_INVR
#define UCR4_ENIRI
#define UCR4_WKEN
#define UCR4_REF16
#define UCR4_IDDMAEN
#define UCR4_IRSC
#define UCR4_TCEN
#define UCR4_BKEN
#define UCR4_OREN
#define UCR4_DREN
#define UFCR_RXTL_SHF
#define UFCR_RXTL_MASK
#define UFCR_DCEDTE
#define UFCR_RFDIV
#define UFCR_RFDIV_REG(x)
#define UFCR_TXTL_SHF
#define USR1_PARITYERR
#define USR1_RTSS
#define USR1_TRDY
#define USR1_RTSD
#define USR1_ESCF
#define USR1_FRAMERR
#define USR1_RRDY
#define USR1_AGTIM
#define USR1_DTRD
#define USR1_RXDS
#define USR1_AIRINT
#define USR1_AWAKE
#define USR2_ADET
#define USR2_TXFE
#define USR2_DTRF
#define USR2_IDLE
#define USR2_RIDELT
#define USR2_RIIN
#define USR2_IRINT
#define USR2_WAKE
#define USR2_DCDIN
#define USR2_RTSF
#define USR2_TXDC
#define USR2_BRCD
#define USR2_ORE
#define USR2_RDR
#define UTS_FRCPERR
#define UTS_LOOP
#define UTS_TXEMPTY
#define UTS_RXEMPTY
#define UTS_TXFULL
#define UTS_RXFULL
#define UTS_SOFTRST

/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_IMX_MAJOR
#define MINOR_START
#define DEV_NAME

/*
 * This determines how often we check the modem status signals
 * for any change.  They generally aren't connected to an IRQ
 * so we have to poll them.  We also check immediately before
 * filling the TX fifo incase CTS has been dropped.
 */
#define MCTRL_TIMEOUT

#define DRIVER_NAME

#define UART_NR

/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
enum imx_uart_type {};

/* device type dependent stuff */
struct imx_uart_data {};

enum imx_tx_state {};

struct imx_port {};

struct imx_port_ucrs {};

static const struct imx_uart_data imx_uart_imx1_devdata =;

static const struct imx_uart_data imx_uart_imx21_devdata =;

static const struct of_device_id imx_uart_dt_ids[] =;
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);

static inline struct imx_port *to_imx_port(struct uart_port *port)
{}

static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
{}

static inline u32 imx_uart_readl(struct imx_port *sport, u32 offset)
{}

static inline unsigned imx_uart_uts_reg(struct imx_port *sport)
{}

static inline int imx_uart_is_imx1(struct imx_port *sport)
{}

/*
 * Save and restore functions for UCR1, UCR2 and UCR3 registers
 */
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_ucrs_save(struct imx_port *sport,
			       struct imx_port_ucrs *ucr)
{}

static void imx_uart_ucrs_restore(struct imx_port *sport,
				  struct imx_port_ucrs *ucr)
{}
#endif

/* called with port.lock taken and irqs caller dependent */
static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2)
{}

/* called with port.lock taken and irqs caller dependent */
static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
{}

static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_soft_reset(struct imx_port *sport)
{}

static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_stop_tx(struct uart_port *port)
{}

static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx(struct uart_port *port)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_enable_ms(struct uart_port *port)
{}

static void imx_uart_dma_tx(struct imx_port *sport);

/* called with port.lock taken and irqs off */
static inline void imx_uart_transmit_buffer(struct imx_port *sport)
{}

static void imx_uart_dma_tx_callback(void *data)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_dma_tx(struct imx_port *sport)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_start_tx(struct uart_port *port)
{}

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

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

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

/* Check if hardware Rx flood is in progress, and issue soft reset to stop it.
 * This is to be called from Rx ISRs only when some bytes were actually
 * received.
 *
 * A way to reproduce the flood (checked on iMX6SX) is: open iMX UART at 9600
 * 8N1, and from external source send 0xf0 char at 115200 8N1. In about 90% of
 * cases this starts a flood of "receiving" of 0xff characters by the iMX6 UART
 * that is terminated by any activity on RxD line, or could be stopped by
 * issuing soft reset to the UART (just stop/start of RX does not help). Note
 * that what we do here is sending isolated start bit about 2.4 times shorter
 * than it is to be on UART configured baud rate.
 */
static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
{}

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

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

static void imx_uart_clear_rx_errors(struct imx_port *sport);

/*
 * We have a modem side uart, so the meanings of RTS and CTS are inverted.
 */
static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
{}

/*
 * Handle any change of modem status signal since we were last called.
 */
static void imx_uart_mctrl_check(struct imx_port *sport)
{}

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

/*
 * Return TIOCSER_TEMT when transmitter is not busy.
 */
static unsigned int imx_uart_tx_empty(struct uart_port *port)
{}

/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_mctrl(struct uart_port *port)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{}

/*
 * Interrupts always disabled.
 */
static void imx_uart_break_ctl(struct uart_port *port, int break_state)
{}

/*
 * This is our per-port timeout handler, for checking the
 * modem status signals.
 */
static void imx_uart_timeout(struct timer_list *t)
{}

/*
 * There are two kinds of RX DMA interrupts(such as in the MX6Q):
 *   [1] the RX DMA buffer is full.
 *   [2] the aging timer expires
 *
 * Condition [2] is triggered when a character has been sitting in the FIFO
 * for at least 8 byte durations.
 */
static void imx_uart_dma_rx_callback(void *data)
{}

static int imx_uart_start_rx_dma(struct imx_port *sport)
{}

static void imx_uart_clear_rx_errors(struct imx_port *sport)
{}

#define TXTL_DEFAULT
#define RXTL_DEFAULT
#define TXTL_DMA
#define RXTL_DMA

static void imx_uart_setup_ufcr(struct imx_port *sport,
				unsigned char txwl, unsigned char rxwl)
{}

static void imx_uart_dma_exit(struct imx_port *sport)
{}

static int imx_uart_dma_init(struct imx_port *sport)
{}

static void imx_uart_enable_dma(struct imx_port *sport)
{}

static void imx_uart_disable_dma(struct imx_port *sport)
{}

/* half the RX buffer size */
#define CTSTL

static int imx_uart_startup(struct uart_port *port)
{}

static void imx_uart_shutdown(struct uart_port *port)
{}

/* called with port.lock taken and irqs off */
static void imx_uart_flush_buffer(struct uart_port *port)
{}

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

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

/*
 * Configure/autoconfigure the port.
 */
static void imx_uart_config_port(struct uart_port *port, int flags)
{}

/*
 * Verify the new serial_struct (for TIOCSSERIAL).
 * The only change we allow are to the flags and type, and
 * even then only between PORT_IMX and PORT_UNKNOWN
 */
static int
imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
{}

#if defined(CONFIG_CONSOLE_POLL)

static int imx_uart_poll_init(struct uart_port *port)
{}

static int imx_uart_poll_get_char(struct uart_port *port)
{}

static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
{}
#endif

/* called with port.lock taken and irqs off or from .probe without locking */
static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios,
				 struct serial_rs485 *rs485conf)
{}

static const struct uart_ops imx_uart_pops =;

static struct imx_port *imx_uart_ports[UART_NR];

#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
{}

/*
 * Interrupts are disabled on entering
 */
static void
imx_uart_console_write(struct console *co, const char *s, unsigned int count)
{}

/*
 * If the port was already initialised (eg, by a boot loader),
 * try to determine the current setup.
 */
static void
imx_uart_console_get_options(struct imx_port *sport, int *baud,
			     int *parity, int *bits)
{}

static int
imx_uart_console_setup(struct console *co, char *options)
{}

static int
imx_uart_console_exit(struct console *co)
{}

static struct uart_driver imx_uart_uart_driver;
static struct console imx_uart_console =;

#define IMX_CONSOLE

#else
#define IMX_CONSOLE
#endif

static struct uart_driver imx_uart_uart_driver =;

static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t)
{}

static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
{}

static const struct serial_rs485 imx_rs485_supported =;

/* Default RX DMA buffer configuration */
#define RX_DMA_PERIODS
#define RX_DMA_PERIOD_LEN

static int imx_uart_probe(struct platform_device *pdev)
{}

static void imx_uart_remove(struct platform_device *pdev)
{}

static void imx_uart_restore_context(struct imx_port *sport)
{}

static void imx_uart_save_context(struct imx_port *sport)
{}

static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
{}

static int imx_uart_suspend_noirq(struct device *dev)
{}

static int imx_uart_resume_noirq(struct device *dev)
{}

static int imx_uart_suspend(struct device *dev)
{}

static int imx_uart_resume(struct device *dev)
{}

static int imx_uart_freeze(struct device *dev)
{}

static int imx_uart_thaw(struct device *dev)
{}

static const struct dev_pm_ops imx_uart_pm_ops =;

static struct platform_driver imx_uart_platform_driver =;

static int __init imx_uart_init(void)
{}

static void __exit imx_uart_exit(void)
{}

module_init();
module_exit(imx_uart_exit);

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