3309 lines · 79.4 KB · C
RawDownload
/* * 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). * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. */#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)#define SUPPORT_SYSRQ#endif #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/major.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/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>#endif #include "serial_mctrl_gpio.h"#include "sh-sci.h" /* Offsets into the sci_port->irqs array */enum {	SCIx_ERI_IRQ,	SCIx_RXI_IRQ,	SCIx_TXI_IRQ,	SCIx_BRI_IRQ,	SCIx_NR_IRQS, 	SCIx_MUX_IRQ = SCIx_NR_IRQS,	/* special case */}; #define SCIx_IRQ_IS_MUXED(port)			\	((port)->irqs[SCIx_ERI_IRQ] ==	\	 (port)->irqs[SCIx_RXI_IRQ]) ||	\	((port)->irqs[SCIx_ERI_IRQ] &&	\	 ((port)->irqs[SCIx_RXI_IRQ] < 0)) enum SCI_CLKS {	SCI_FCK,		/* Functional Clock */	SCI_SCK,		/* Optional External Clock */	SCI_BRG_INT,		/* Optional BRG Internal Clock Source */	SCI_SCIF_CLK,		/* Optional BRG External Clock Source */	SCI_NUM_CLKS}; /* Bit x set means sampling rate x + 1 is supported */#define SCI_SR(x)		BIT((x) - 1)#define SCI_SR_RANGE(x, y)	GENMASK((y) - 1, (x) - 1) #define SCI_SR_SCIFAB		SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \				SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \				SCI_SR(19) | SCI_SR(27) #define min_sr(_port)		ffs((_port)->sampling_rate_mask)#define max_sr(_port)		fls((_port)->sampling_rate_mask) /* Iterate over all supported sampling rates, from high to low */#define for_each_sr(_sr, _port)						\	for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)	\		if ((_port)->sampling_rate_mask & SCI_SR((_sr))) struct plat_sci_reg {	u8 offset, size;}; struct sci_port_params {	const struct plat_sci_reg regs[SCIx_NR_REGS];	unsigned int fifosize;	unsigned int overrun_reg;	unsigned int overrun_mask;	unsigned int sampling_rate_mask;	unsigned int error_mask;	unsigned int error_clear;}; struct sci_port {	struct uart_port	port; 	/* Platform configuration */	const struct sci_port_params *params;	const struct plat_sci_port *cfg;	unsigned int		sampling_rate_mask;	resource_size_t		reg_size;	struct mctrl_gpios	*gpios; 	/* Clocks */	struct clk		*clks[SCI_NUM_CLKS];	unsigned long		clk_rates[SCI_NUM_CLKS]; 	int			irqs[SCIx_NR_IRQS];	char			*irqstr[SCIx_NR_IRQS]; 	struct dma_chan			*chan_tx;	struct dma_chan			*chan_rx; #ifdef CONFIG_SERIAL_SH_SCI_DMA	dma_cookie_t			cookie_tx;	dma_cookie_t			cookie_rx[2];	dma_cookie_t			active_rx;	dma_addr_t			tx_dma_addr;	unsigned int			tx_dma_len;	struct scatterlist		sg_rx[2];	void				*rx_buf[2];	size_t				buf_len_rx;	struct work_struct		work_tx;	struct timer_list		rx_timer;	unsigned int			rx_timeout;#endif	unsigned int			rx_frame;	int				rx_trigger;	struct timer_list		rx_fifo_timer;	int				rx_fifo_timeout; 	bool has_rtscts;	bool autorts;}; #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS static struct sci_port sci_ports[SCI_NPORTS];static struct uart_driver sci_uart_driver; static inline struct sci_port *to_sci_port(struct uart_port *uart){	return container_of(uart, struct sci_port, port);} static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {	/*	 * Common SCI definitions, dependent on the port's regshift	 * value.	 */	[SCIx_SCI_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00,  8 },			[SCBRR]		= { 0x01,  8 },			[SCSCR]		= { 0x02,  8 },			[SCxTDR]	= { 0x03,  8 },			[SCxSR]		= { 0x04,  8 },			[SCxRDR]	= { 0x05,  8 },		},		.fifosize = 1,		.overrun_reg = SCxSR,		.overrun_mask = SCI_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,		.error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,	}, 	/*	 * Common definitions for legacy IrDA ports.	 */	[SCIx_IRDA_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00,  8 },			[SCBRR]		= { 0x02,  8 },			[SCSCR]		= { 0x04,  8 },			[SCxTDR]	= { 0x06,  8 },			[SCxSR]		= { 0x08, 16 },			[SCxRDR]	= { 0x0a,  8 },			[SCFCR]		= { 0x0c,  8 },			[SCFDR]		= { 0x0e, 16 },		},		.fifosize = 1,		.overrun_reg = SCxSR,		.overrun_mask = SCI_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,		.error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,	}, 	/*	 * Common SCIFA definitions.	 */	[SCIx_SCIFA_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x20,  8 },			[SCxSR]		= { 0x14, 16 },			[SCxRDR]	= { 0x24,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCPCR]		= { 0x30, 16 },			[SCPDR]		= { 0x34, 16 },		},		.fifosize = 64,		.overrun_reg = SCxSR,		.overrun_mask = SCIFA_ORER,		.sampling_rate_mask = SCI_SR_SCIFAB,		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,	}, 	/*	 * Common SCIFB definitions.	 */	[SCIx_SCIFB_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x40,  8 },			[SCxSR]		= { 0x14, 16 },			[SCxRDR]	= { 0x60,  8 },			[SCFCR]		= { 0x18, 16 },			[SCTFDR]	= { 0x38, 16 },			[SCRFDR]	= { 0x3c, 16 },			[SCPCR]		= { 0x30, 16 },			[SCPDR]		= { 0x34, 16 },		},		.fifosize = 256,		.overrun_reg = SCxSR,		.overrun_mask = SCIFA_ORER,		.sampling_rate_mask = SCI_SR_SCIFAB,		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,	}, 	/*	 * Common SH-2(A) SCIF definitions for ports with FIFO data	 * count registers.	 */	[SCIx_SH2_SCIF_FIFODATA_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCSPTR]	= { 0x20, 16 },			[SCLSR]		= { 0x24, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common SH-3 SCIF definitions.	 */	[SCIx_SH3_SCIF_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00,  8 },			[SCBRR]		= { 0x02,  8 },			[SCSCR]		= { 0x04,  8 },			[SCxTDR]	= { 0x06,  8 },			[SCxSR]		= { 0x08, 16 },			[SCxRDR]	= { 0x0a,  8 },			[SCFCR]		= { 0x0c,  8 },			[SCFDR]		= { 0x0e, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common SH-4(A) SCIF(B) definitions.	 */	[SCIx_SH4_SCIF_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCSPTR]	= { 0x20, 16 },			[SCLSR]		= { 0x24, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common SCIF definitions for ports with a Baud Rate Generator for	 * External Clock (BRG).	 */	[SCIx_SH4_SCIF_BRG_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCSPTR]	= { 0x20, 16 },			[SCLSR]		= { 0x24, 16 },			[SCDL]		= { 0x30, 16 },			[SCCKS]		= { 0x34, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common HSCIF definitions.	 */	[SCIx_HSCIF_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCSPTR]	= { 0x20, 16 },			[SCLSR]		= { 0x24, 16 },			[HSSRR]		= { 0x40, 16 },			[SCDL]		= { 0x30, 16 },			[SCCKS]		= { 0x34, 16 },			[HSRTRGR]	= { 0x54, 16 },			[HSTTRGR]	= { 0x58, 16 },		},		.fifosize = 128,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR_RANGE(8, 32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common SH-4(A) SCIF(B) definitions for ports without an SCSPTR	 * register.	 */	[SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCLSR]		= { 0x24, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * Common SH-4(A) SCIF(B) definitions for ports with FIFO data	 * count registers.	 */	[SCIx_SH4_SCIF_FIFODATA_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x0c,  8 },			[SCxSR]		= { 0x10, 16 },			[SCxRDR]	= { 0x14,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },			[SCTFDR]	= { 0x1c, 16 },	/* aliased to SCFDR */			[SCRFDR]	= { 0x20, 16 },			[SCSPTR]	= { 0x24, 16 },			[SCLSR]		= { 0x28, 16 },		},		.fifosize = 16,		.overrun_reg = SCLSR,		.overrun_mask = SCLSR_ORER,		.sampling_rate_mask = SCI_SR(32),		.error_mask = SCIF_DEFAULT_ERROR_MASK,		.error_clear = SCIF_ERROR_CLEAR,	}, 	/*	 * SH7705-style SCIF(B) ports, lacking both SCSPTR and SCLSR	 * registers.	 */	[SCIx_SH7705_SCIF_REGTYPE] = {		.regs = {			[SCSMR]		= { 0x00, 16 },			[SCBRR]		= { 0x04,  8 },			[SCSCR]		= { 0x08, 16 },			[SCxTDR]	= { 0x20,  8 },			[SCxSR]		= { 0x14, 16 },			[SCxRDR]	= { 0x24,  8 },			[SCFCR]		= { 0x18, 16 },			[SCFDR]		= { 0x1c, 16 },		},		.fifosize = 64,		.overrun_reg = SCxSR,		.overrun_mask = SCIFA_ORER,		.sampling_rate_mask = SCI_SR(16),		.error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,		.error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,	},}; #define sci_getreg(up, offset)		(&to_sci_port(up)->params->regs[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){	const struct plat_sci_reg *reg = sci_getreg(p, offset); 	if (reg->size == 8)		return ioread8(p->membase + (reg->offset << p->regshift));	else if (reg->size == 16)		return ioread16(p->membase + (reg->offset << p->regshift));	else		WARN(1, "Invalid register access\n"); 	return 0;} static void sci_serial_out(struct uart_port *p, int offset, int value){	const struct plat_sci_reg *reg = sci_getreg(p, offset); 	if (reg->size == 8)		iowrite8(value, p->membase + (reg->offset << p->regshift));	else if (reg->size == 16)		iowrite16(value, p->membase + (reg->offset << p->regshift));	else		WARN(1, "Invalid register access\n");} static void sci_port_enable(struct sci_port *sci_port)

Lines 1–500 of 3309.