linux/drivers/tty/serial/atmel_serial.c

// SPDX-License-Identifier: GPL-2.0+
/*
 *  Driver for Atmel AT91 Serial ports
 *  Copyright (C) 2003 Rick Bronson
 *
 *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
 *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
 *
 *  DMA support added by Chip Coldwell.
 */
#include <linux/circ_buf.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty_flip.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/atmel_pdc.h>
#include <linux/uaccess.h>
#include <linux/platform_data/atmel.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/suspend.h>
#include <linux/mm.h>
#include <linux/io.h>

#include <asm/div64.h>
#include <asm/ioctls.h>

#define PDC_BUFFER_SIZE
/* Revisit: We should calculate this based on the actual port settings */
#define PDC_RX_TIMEOUT

/* The minium number of data FIFOs should be able to contain */
#define ATMEL_MIN_FIFO_SIZE
/*
 * These two offsets are substracted from the RX FIFO size to define the RTS
 * high and low thresholds
 */
#define ATMEL_RTS_HIGH_OFFSET
#define ATMEL_RTS_LOW_OFFSET

#include <linux/serial_core.h>

#include "serial_mctrl_gpio.h"
#include "atmel_serial.h"

static void atmel_start_rx(struct uart_port *port);
static void atmel_stop_rx(struct uart_port *port);

#ifdef CONFIG_SERIAL_ATMEL_TTYAT

/* Use device name ttyAT, major 204 and minor 154-169.  This is necessary if we
 * should coexist with the 8250 driver, such as if we have an external 16C550
 * UART. */
#define SERIAL_ATMEL_MAJOR
#define MINOR_START
#define ATMEL_DEVICENAME

#else

/* Use device name ttyS, major 4, minor 64-68.  This is the usual serial port
 * name, but it is legally reserved for the 8250 driver. */
#define SERIAL_ATMEL_MAJOR
#define MINOR_START
#define ATMEL_DEVICENAME

#endif

#define ATMEL_ISR_PASS_LIMIT

struct atmel_dma_buffer {};

struct atmel_uart_char {};

/*
 * Be careful, the real size of the ring buffer is
 * sizeof(atmel_uart_char) * ATMEL_SERIAL_RINGSIZE. It means that ring buffer
 * can contain up to 1024 characters in PIO mode and up to 4096 characters in
 * DMA mode.
 */
#define ATMEL_SERIAL_RINGSIZE
#define ATMEL_SERIAL_RX_SIZE

/*
 * at91: 6 USARTs and one DBGU port (SAM9260)
 * samx7: 3 USARTs and 5 UARTs
 */
#define ATMEL_MAX_UART

/*
 * We wrap our port structure around the generic uart_port.
 */
struct atmel_uart_port {};

static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);

#if defined(CONFIG_OF)
static const struct of_device_id atmel_serial_dt_ids[] =;
#endif

static inline struct atmel_uart_port *
to_atmel_uart_port(struct uart_port *uart)
{}

static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
{}

static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
{}

static inline u8 atmel_uart_read_char(struct uart_port *port)
{}

static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
{}

static inline int atmel_uart_is_half_duplex(struct uart_port *port)
{}

static inline int atmel_error_rate(int desired_value, int actual_value)
{}

#ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port)
{}

static bool atmel_use_pdc_tx(struct uart_port *port)
{}
#else
static bool atmel_use_pdc_rx(struct uart_port *port)
{
	return false;
}

static bool atmel_use_pdc_tx(struct uart_port *port)
{
	return false;
}
#endif

static bool atmel_use_dma_tx(struct uart_port *port)
{}

static bool atmel_use_dma_rx(struct uart_port *port)
{}

static bool atmel_use_fifo(struct uart_port *port)
{}

static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port,
				   struct tasklet_struct *t)
{}

/* Enable or disable the rs485 support */
static int atmel_config_rs485(struct uart_port *port, struct ktermios *termios,
			      struct serial_rs485 *rs485conf)
{}

static unsigned int atmel_calc_cd(struct uart_port *port,
				  struct serial_iso7816 *iso7816conf)
{}

static unsigned int atmel_calc_fidi(struct uart_port *port,
				    struct serial_iso7816 *iso7816conf)
{}

/* Enable or disable the iso7816 support */
/* Called with interrupts disabled */
static int atmel_config_iso7816(struct uart_port *port,
				struct serial_iso7816 *iso7816conf)
{}

/*
 * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
 */
static u_int atmel_tx_empty(struct uart_port *port)
{}

/*
 * Set state of the modem control output lines
 */
static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
{}

/*
 * Get state of the modem control input lines
 */
static u_int atmel_get_mctrl(struct uart_port *port)
{}

/*
 * Stop transmitting.
 */
static void atmel_stop_tx(struct uart_port *port)
{}

/*
 * Start transmitting.
 */
static void atmel_start_tx(struct uart_port *port)
{}

/*
 * start receiving - port is in process of being opened.
 */
static void atmel_start_rx(struct uart_port *port)
{}

/*
 * Stop receiving - port is in process of being closed.
 */
static void atmel_stop_rx(struct uart_port *port)
{}

/*
 * Enable modem status interrupts
 */
static void atmel_enable_ms(struct uart_port *port)
{}

/*
 * Disable modem status interrupts
 */
static void atmel_disable_ms(struct uart_port *port)
{}

/*
 * Control the transmission of a break signal
 */
static void atmel_break_ctl(struct uart_port *port, int break_state)
{}

/*
 * Stores the incoming character in the ring buffer
 */
static void
atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
		     unsigned int ch)
{}

/*
 * Deal with parity, framing and overrun errors.
 */
static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
{}

/*
 * Characters received (called from interrupt handler)
 */
static void atmel_rx_chars(struct uart_port *port)
{}

/*
 * Transmit characters (called from tasklet with TXRDY interrupt
 * disabled)
 */
static void atmel_tx_chars(struct uart_port *port)
{}

static void atmel_complete_tx_dma(void *arg)
{}

static void atmel_release_tx_dma(struct uart_port *port)
{}

/*
 * Called from tasklet with TXRDY interrupt is disabled.
 */
static void atmel_tx_dma(struct uart_port *port)
{}

static int atmel_prepare_tx_dma(struct uart_port *port)
{}

static void atmel_complete_rx_dma(void *arg)
{}

static void atmel_release_rx_dma(struct uart_port *port)
{}

static void atmel_rx_from_dma(struct uart_port *port)
{}

static int atmel_prepare_rx_dma(struct uart_port *port)
{}

static void atmel_uart_timer_callback(struct timer_list *t)
{}

/*
 * receive interrupt handler.
 */
static void
atmel_handle_receive(struct uart_port *port, unsigned int pending)
{}

/*
 * transmit interrupt handler. (Transmit is IRQF_NODELAY safe)
 */
static void
atmel_handle_transmit(struct uart_port *port, unsigned int pending)
{}

/*
 * status flags interrupt handler.
 */
static void
atmel_handle_status(struct uart_port *port, unsigned int pending,
		    unsigned int status)
{}

/*
 * Interrupt handler
 */
static irqreturn_t atmel_interrupt(int irq, void *dev_id)
{}

static void atmel_release_tx_pdc(struct uart_port *port)
{}

/*
 * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
 */
static void atmel_tx_pdc(struct uart_port *port)
{}

static int atmel_prepare_tx_pdc(struct uart_port *port)
{}

static void atmel_rx_from_ring(struct uart_port *port)
{}

static void atmel_release_rx_pdc(struct uart_port *port)
{}

static void atmel_rx_from_pdc(struct uart_port *port)
{}

static int atmel_prepare_rx_pdc(struct uart_port *port)
{}

/*
 * tasklet handling tty stuff outside the interrupt handler.
 */
static void atmel_tasklet_rx_func(struct tasklet_struct *t)
{}

static void atmel_tasklet_tx_func(struct tasklet_struct *t)
{}

static void atmel_init_property(struct atmel_uart_port *atmel_port,
				struct platform_device *pdev)
{}

static void atmel_set_ops(struct uart_port *port)
{}

/*
 * Get ip name usart or uart
 */
static void atmel_get_ip_name(struct uart_port *port)
{}

/*
 * Perform initialization and enable port for reception
 */
static int atmel_startup(struct uart_port *port)
{}

/*
 * Flush any TX data submitted for DMA. Called when the TX circular
 * buffer is reset.
 */
static void atmel_flush_buffer(struct uart_port *port)
{}

/*
 * Disable the port
 */
static void atmel_shutdown(struct uart_port *port)
{}

/*
 * Power / Clock management.
 */
static void atmel_serial_pm(struct uart_port *port, unsigned int state,
			    unsigned int oldstate)
{}

/*
 * Change the port parameters
 */
static void atmel_set_termios(struct uart_port *port,
			      struct ktermios *termios,
			      const struct ktermios *old)
{}

static void atmel_set_ldisc(struct uart_port *port, struct ktermios *termios)
{}

/*
 * Return string describing the specified port
 */
static const char *atmel_type(struct uart_port *port)
{}

/*
 * Release the memory region(s) being used by 'port'.
 */
static void atmel_release_port(struct uart_port *port)
{}

/*
 * Request the memory region(s) being used by 'port'.
 */
static int atmel_request_port(struct uart_port *port)
{}

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

/*
 * Verify the new serial_struct (for TIOCSSERIAL).
 */
static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
{}

#ifdef CONFIG_CONSOLE_POLL
static int atmel_poll_get_char(struct uart_port *port)
{}

static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
{}
#endif

static const struct uart_ops atmel_pops =;

static const struct serial_rs485 atmel_rs485_supported =;

/*
 * Configure the port from the platform device resource info.
 */
static int atmel_init_port(struct atmel_uart_port *atmel_port,
				      struct platform_device *pdev)
{}

#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
static void atmel_console_putchar(struct uart_port *port, unsigned char ch)
{}

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

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

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

static struct uart_driver atmel_uart;

static struct console atmel_console =;

static void atmel_serial_early_write(struct console *con, const char *s,
				     unsigned int n)
{}

static int __init atmel_early_console_setup(struct earlycon_device *device,
					    const char *options)
{}

OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();

#define ATMEL_CONSOLE_DEVICE

#else
#define ATMEL_CONSOLE_DEVICE
#endif

static struct uart_driver atmel_uart =;

static bool atmel_serial_clk_will_stop(void)
{}

static int __maybe_unused atmel_serial_suspend(struct device *dev)
{}

static int __maybe_unused atmel_serial_resume(struct device *dev)
{}

static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port,
				     struct platform_device *pdev)
{}

static int atmel_serial_probe(struct platform_device *pdev)
{}

/*
 * Even if the driver is not modular, it makes sense to be able to
 * unbind a device: there can be many bound devices, and there are
 * situations where dynamic binding and unbinding can be useful.
 *
 * For example, a connected device can require a specific firmware update
 * protocol that needs bitbanging on IO lines, but use the regular serial
 * port in the normal case.
 */
static void atmel_serial_remove(struct platform_device *pdev)
{}

static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
			 atmel_serial_resume);

static struct platform_driver atmel_serial_driver =;

static int __init atmel_serial_init(void)
{}
device_initcall(atmel_serial_init);