linux/drivers/tty/serial/sh-sci.c

// SPDX-License-Identifier: GPL-2.0
/*
 * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
 *
 *  Copyright (C) 2002 - 2011  Paul Mundt
 *  Copyright (C) 2015 Glider bvba
 *  Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
 *
 * based off of the old drivers/char/sh-sci.c by:
 *
 *   Copyright (C) 1999, 2000  Niibe Yutaka
 *   Copyright (C) 2000  Sugioka Toshinobu
 *   Modified to support multiple serial ports. Stuart Menefy (May 2000).
 *   Modified to support SecureEdge. David McCullough (2002)
 *   Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003).
 *   Removed SH7300 support (Jul 2007).
 */
#undef DEBUG

#include <linux/clk.h>
#include <linux/console.h>
#include <linux/ctype.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/ktime.h>
#include <linux/major.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/scatterlist.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysrq.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>

#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
#include <asm/platform_early.h>
#endif

#include "serial_mctrl_gpio.h"
#include "sh-sci.h"

/* Offsets into the sci_port->irqs array */
enum {};

#define SCIx_IRQ_IS_MUXED(port)

enum SCI_CLKS {};

/* Bit x set means sampling rate x + 1 is supported */
#define SCI_SR(x)
#define SCI_SR_RANGE(x, y)

#define SCI_SR_SCIFAB

#define min_sr(_port)
#define max_sr(_port)

/* Iterate over all supported sampling rates, from high to low */
#define for_each_sr(_sr, _port)

struct plat_sci_reg {};

struct sci_port_params {};

struct sci_port {};

#define SCI_NPORTS

static struct sci_port sci_ports[SCI_NPORTS];
static unsigned long sci_ports_in_use;
static struct uart_driver sci_uart_driver;

static inline struct sci_port *
to_sci_port(struct uart_port *uart)
{}

static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] =;

#define sci_getreg(up, offset)

/*
 * The "offset" here is rather misleading, in that it refers to an enum
 * value relative to the port mapping rather than the fixed offset
 * itself, which needs to be manually retrieved from the platform's
 * register map for the given port.
 */
static unsigned int sci_serial_in(struct uart_port *p, int offset)
{}

static void sci_serial_out(struct uart_port *p, int offset, int value)
{}

static void sci_port_enable(struct sci_port *sci_port)
{}

static void sci_port_disable(struct sci_port *sci_port)
{}

static inline unsigned long port_rx_irq_mask(struct uart_port *port)
{}

static void sci_start_tx(struct uart_port *port)
{}

static void sci_stop_tx(struct uart_port *port)
{}

static void sci_start_rx(struct uart_port *port)
{}

static void sci_stop_rx(struct uart_port *port)
{}

static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
{}

#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \
    defined(CONFIG_SERIAL_SH_SCI_EARLYCON)

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

static void sci_poll_put_char(struct uart_port *port, unsigned char c)
{}
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE ||
	  CONFIG_SERIAL_SH_SCI_EARLYCON */

static void sci_init_pins(struct uart_port *port, unsigned int cflag)
{}

static int sci_txfill(struct uart_port *port)
{}

static int sci_txroom(struct uart_port *port)
{}

static int sci_rxfill(struct uart_port *port)
{}

/* ********************************************************************** *
 *                   the interrupt related routines                       *
 * ********************************************************************** */

static void sci_transmit_chars(struct uart_port *port)
{}

static void sci_receive_chars(struct uart_port *port)
{}

static int sci_handle_errors(struct uart_port *port)
{}

static int sci_handle_fifo_overrun(struct uart_port *port)
{}

static int sci_handle_breaks(struct uart_port *port)
{}

static int scif_set_rtrg(struct uart_port *port, int rx_trig)
{}

static int scif_rtrg_enabled(struct uart_port *port)
{}

static void rx_fifo_timer_fn(struct timer_list *t)
{}

static ssize_t rx_fifo_trigger_show(struct device *dev,
				    struct device_attribute *attr, char *buf)
{}

static ssize_t rx_fifo_trigger_store(struct device *dev,
				     struct device_attribute *attr,
				     const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(rx_fifo_trigger);

static ssize_t rx_fifo_timeout_show(struct device *dev,
			       struct device_attribute *attr,
			       char *buf)
{}

static ssize_t rx_fifo_timeout_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf,
				size_t count)
{}

static DEVICE_ATTR_RW(rx_fifo_timeout);


#ifdef CONFIG_SERIAL_SH_SCI_DMA
static void sci_dma_tx_complete(void *arg)
{}

/* Locking: called with port lock held */
static int sci_dma_rx_push(struct sci_port *s, void *buf, size_t count)
{}

static int sci_dma_rx_find_active(struct sci_port *s)
{}

/* Must only be called with uart_port_lock taken */
static void sci_dma_rx_chan_invalidate(struct sci_port *s)
{}

static void sci_dma_rx_release(struct sci_port *s)
{}

static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
{}

static void sci_dma_rx_reenable_irq(struct sci_port *s)
{}

static void sci_dma_rx_complete(void *arg)
{}

static void sci_dma_tx_release(struct sci_port *s)
{}

static int sci_dma_rx_submit(struct sci_port *s, bool port_lock_held)
{}

static void sci_dma_tx_work_fn(struct work_struct *work)
{}

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

static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
					     enum dma_transfer_direction dir)
{}

static void sci_request_dma(struct uart_port *port)
{}

static void sci_free_dma(struct uart_port *port)
{}

static void sci_flush_buffer(struct uart_port *port)
{}
#else /* !CONFIG_SERIAL_SH_SCI_DMA */
static inline void sci_request_dma(struct uart_port *port)
{
}

static inline void sci_free_dma(struct uart_port *port)
{
}

#define sci_flush_buffer
#endif /* !CONFIG_SERIAL_SH_SCI_DMA */

static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
{}

static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
{}

static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
{}

static irqreturn_t sci_br_interrupt(int irq, void *ptr)
{}

static irqreturn_t sci_er_interrupt(int irq, void *ptr)
{}

static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
{}

static const struct sci_irq_desc {} sci_irq_desc[] =;

static int sci_request_irq(struct sci_port *port)
{}

static void sci_free_irq(struct sci_port *port)
{}

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

static void sci_set_rts(struct uart_port *port, bool state)
{}

static bool sci_get_cts(struct uart_port *port)
{}

/*
 * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
 * CTS/RTS is supported in hardware by at least one port and controlled
 * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
 * handled via the ->init_pins() op, which is a bit of a one-way street,
 * lacking any ability to defer pin control -- this will later be
 * converted over to the GPIO framework).
 *
 * Other modes (such as loopback) are supported generically on certain
 * port types, but not others. For these it's sufficient to test for the
 * existence of the support register and simply ignore the port type.
 */
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{}

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

static void sci_enable_ms(struct uart_port *port)
{}

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

static int sci_startup(struct uart_port *port)
{}

static void sci_shutdown(struct uart_port *port)
{}

static int sci_sck_calc(struct sci_port *s, unsigned int bps,
			unsigned int *srr)
{}

static int sci_brg_calc(struct sci_port *s, unsigned int bps,
			unsigned long freq, unsigned int *dlr,
			unsigned int *srr)
{}

/* calculate sample rate, BRR, and clock select */
static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
			  unsigned int *brr, unsigned int *srr,
			  unsigned int *cks)
{}

static void sci_reset(struct uart_port *port)
{}

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

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

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

static int sci_remap_port(struct uart_port *port)
{}

static void sci_release_port(struct uart_port *port)
{}

static int sci_request_port(struct uart_port *port)
{}

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

static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{}

static const struct uart_ops sci_uart_ops =;

static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
{}

static const struct sci_port_params *
sci_probe_regmap(const struct plat_sci_port *cfg)
{}

static int sci_init_single(struct platform_device *dev,
			   struct sci_port *sci_port, unsigned int index,
			   const struct plat_sci_port *p, bool early)
{}

static void sci_cleanup_single(struct sci_port *port)
{}

#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \
    defined(CONFIG_SERIAL_SH_SCI_EARLYCON)
static void serial_console_putchar(struct uart_port *port, unsigned char ch)
{}

/*
 *	Print a string to the serial port trying not to disturb
 *	any possible real use of the port...
 */
static void serial_console_write(struct console *co, const char *s,
				 unsigned count)
{}

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

static struct console serial_console =;

#ifdef CONFIG_SUPERH
static char early_serial_buf[32];

static int early_serial_console_setup(struct console *co, char *options)
{
	/*
	 * This early console is always registered using the earlyprintk=
	 * parameter, which does not call add_preferred_console(). Thus
	 * @options is always NULL and the options for this early console
	 * are passed using a custom buffer.
	 */
	WARN_ON(options);

	return serial_console_setup(co, early_serial_buf);
}

static struct console early_serial_console = {
	.name           = "early_ttySC",
	.write          = serial_console_write,
	.setup		= early_serial_console_setup,
	.flags          = CON_PRINTBUFFER,
	.index		= -1,
};

static int sci_probe_earlyprintk(struct platform_device *pdev)
{
	const struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev);

	if (early_serial_console.data)
		return -EEXIST;

	early_serial_console.index = pdev->id;

	sci_init_single(pdev, &sci_ports[pdev->id], pdev->id, cfg, true);

	if (!strstr(early_serial_buf, "keep"))
		early_serial_console.flags |= CON_BOOT;

	register_console(&early_serial_console);
	return 0;
}
#endif

#define SCI_CONSOLE

#else
static inline int sci_probe_earlyprintk(struct platform_device *pdev)
{
	return -EINVAL;
}

#define SCI_CONSOLE

#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE || CONFIG_SERIAL_SH_SCI_EARLYCON */

static const char banner[] __initconst =;

static DEFINE_MUTEX(sci_uart_registration_lock);
static struct uart_driver sci_uart_driver =;

static void sci_remove(struct platform_device *dev)
{}


#define SCI_OF_DATA(type, regtype)
#define SCI_OF_TYPE(data)
#define SCI_OF_REGTYPE(data)

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

static void sci_reset_control_assert(void *data)
{}

static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
					  unsigned int *dev_id)
{}

static int sci_probe_single(struct platform_device *dev,
				      unsigned int index,
				      struct plat_sci_port *p,
				      struct sci_port *sciport)
{}

static int sci_probe(struct platform_device *dev)
{}

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

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

static SIMPLE_DEV_PM_OPS(sci_dev_pm_ops, sci_suspend, sci_resume);

static struct platform_driver sci_driver =;

static int __init sci_init(void)
{}

static void __exit sci_exit(void)
{}

#if defined(CONFIG_SUPERH) && defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
sh_early_platform_init_buffer("earlyprintk", &sci_driver,
			   early_serial_buf, ARRAY_SIZE(early_serial_buf));
#endif
#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON
static struct plat_sci_port port_cfg __initdata;

static int __init early_console_setup(struct earlycon_device *device,
				      int type)
{}
static int __init sci_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}
static int __init scif_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}
static int __init rzscifa_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}

static int __init rzv2hscif_early_console_setup(struct earlycon_device *device,
						const char *opt)
{}

static int __init scifa_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}
static int __init scifb_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}
static int __init hscif_early_console_setup(struct earlycon_device *device,
					  const char *opt)
{}

OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
OF_EARLYCON_DECLARE();
#endif /* CONFIG_SERIAL_SH_SCI_EARLYCON */

module_init();
module_exit(sci_exit);

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