#include <linux/console.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/slab.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/types.h>
#include <asm/irq.h>
#define S3C24XX_SERIAL_NAME …
#define S3C24XX_SERIAL_MAJOR …
#define S3C24XX_SERIAL_MINOR …
#ifdef CONFIG_ARM64
#define UART_NR …
#else
#define UART_NR …
#endif
#define S3C24XX_TX_PIO …
#define S3C24XX_TX_DMA …
#define S3C24XX_RX_PIO …
#define S3C24XX_RX_DMA …
#define RXSTAT_DUMMY_READ …
enum s3c24xx_port_type { … };
struct s3c24xx_uart_info { … };
struct s3c24xx_serial_drv_data { … };
struct s3c24xx_uart_dma { … };
struct s3c24xx_uart_port { … };
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport);
#define s3c24xx_dev_to_port(__dev) …
#define portaddr(port, reg) …
#define portaddrl(port, reg) …
static u32 rd_reg(const struct uart_port *port, u32 reg)
{ … }
#define rd_regl(port, reg) …
static void wr_reg(const struct uart_port *port, u32 reg, u32 val)
{ … }
#define wr_regl(port, reg, val) …
static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
u32 reg)
{ … }
static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
u32 reg)
{ … }
static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
{ … }
static inline const char *s3c24xx_serial_portname(const struct uart_port *port)
{ … }
static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
{ … }
static void s3c24xx_serial_rx_enable(struct uart_port *port)
{ … }
static void s3c24xx_serial_rx_disable(struct uart_port *port)
{ … }
static void s3c24xx_serial_stop_tx(struct uart_port *port)
{ … }
static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport);
static void s3c24xx_serial_tx_dma_complete(void *args)
{ … }
static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
{ … }
static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
{ … }
static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport)
{ … }
static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
unsigned int count, unsigned int tail)
{ … }
static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
{ … }
static void s3c24xx_serial_start_tx(struct uart_port *port)
{ … }
static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
struct tty_port *tty, int count)
{ … }
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{ … }
static inline const struct s3c24xx_uart_info
*s3c24xx_port_to_info(struct uart_port *port)
{ … }
static inline const struct s3c2410_uartcfg
*s3c24xx_port_to_cfg(const struct uart_port *port)
{ … }
static unsigned int
s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, u32 ufstat)
{ … }
static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport);
static void s3c24xx_serial_rx_dma_complete(void *args)
{ … }
static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
{ … }
#define S3C2410_UERSTAT_PARITY …
static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
{ … }
static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
{ … }
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
static irqreturn_t s3c24xx_serial_rx_chars_dma(struct s3c24xx_uart_port *ourport)
{ … }
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
{ … }
static irqreturn_t s3c24xx_serial_rx_chars_pio(struct s3c24xx_uart_port *ourport)
{ … }
static irqreturn_t s3c24xx_serial_rx_irq(struct s3c24xx_uart_port *ourport)
{ … }
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
{ … }
static irqreturn_t s3c24xx_serial_tx_irq(struct s3c24xx_uart_port *ourport)
{ … }
static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
{ … }
static irqreturn_t apple_serial_handle_irq(int irq, void *id)
{ … }
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
{ … }
static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
{ … }
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{ … }
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
{ … }
static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
{ … }
static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
{ … }
static void s3c64xx_serial_shutdown(struct uart_port *port)
{ … }
static void apple_s5l_serial_shutdown(struct uart_port *port)
{ … }
static int s3c64xx_serial_startup(struct uart_port *port)
{ … }
static int apple_s5l_serial_startup(struct uart_port *port)
{ … }
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
unsigned int old)
{ … }
#define MAX_CLK_NAME_LENGTH …
static inline u8 s3c24xx_serial_getsource(struct uart_port *port)
{ … }
static void s3c24xx_serial_setsource(struct uart_port *port, u8 clk_sel)
{ … }
static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
unsigned int req_baud, struct clk **best_clk,
u8 *clk_num)
{ … }
static const u16 udivslot_table[16] = …;
static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
const struct ktermios *old)
{ … }
static const char *s3c24xx_serial_type(struct uart_port *port)
{ … }
static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
{ … }
static int
s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
{ … }
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
static struct console s3c24xx_serial_console;
static void __init s3c24xx_serial_register_console(void)
{ … }
static void s3c24xx_serial_unregister_console(void)
{ … }
#define S3C24XX_SERIAL_CONSOLE …
#else
static inline void s3c24xx_serial_register_console(void) { }
static inline void s3c24xx_serial_unregister_console(void) { }
#define S3C24XX_SERIAL_CONSOLE …
#endif
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
static int s3c24xx_serial_get_poll_char(struct uart_port *port);
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c);
#endif
static const struct uart_ops s3c64xx_serial_ops = …;
static const struct uart_ops apple_s5l_serial_ops = …;
static struct uart_driver s3c24xx_uart_drv = …;
static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR];
static void s3c24xx_serial_init_port_default(int index)
{ … }
static void s3c24xx_serial_resetport(struct uart_port *port,
const struct s3c2410_uartcfg *cfg)
{ … }
static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
{ … }
static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
struct platform_device *platdev)
{ … }
static int probe_index;
static inline const struct s3c24xx_serial_drv_data *
s3c24xx_get_driver_data(struct platform_device *pdev)
{ … }
static int s3c24xx_serial_probe(struct platform_device *pdev)
{ … }
static void s3c24xx_serial_remove(struct platform_device *dev)
{ … }
#ifdef CONFIG_PM_SLEEP
static int s3c24xx_serial_suspend(struct device *dev)
{ … }
static int s3c24xx_serial_resume(struct device *dev)
{ … }
static int s3c24xx_serial_resume_noirq(struct device *dev)
{ … }
static const struct dev_pm_ops s3c24xx_serial_pm_ops = …;
#define SERIAL_SAMSUNG_PM_OPS …
#else
#define SERIAL_SAMSUNG_PM_OPS …
#endif
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
static struct uart_port *cons_uart;
static bool
s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon)
{ … }
static bool
s3c24xx_port_configured(u32 ucon)
{ … }
#ifdef CONFIG_CONSOLE_POLL
static int s3c24xx_serial_get_poll_char(struct uart_port *port)
{ … }
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c)
{ … }
#endif
static void
s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
{ … }
static void
s3c24xx_serial_console_write(struct console *co, const char *s,
unsigned int count)
{ … }
static void
s3c24xx_serial_get_options(struct uart_port *port, int *baud,
int *parity, int *bits)
{ … }
static int
s3c24xx_serial_console_setup(struct console *co, char *options)
{ … }
static struct console s3c24xx_serial_console = …;
#endif
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = {
.name = "Samsung S3C6400 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.iotype = UPIO_MEM,
.fifosize = 64,
.has_divslot = true,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL2,
.num_clks = 4,
.clksel_mask = S3C6400_UCON_CLKMASK,
.clksel_shift = S3C6400_UCON_CLKSHIFT,
},
.def_cfg = {
.ucon = S3C2410_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S3C6400_SERIAL_DRV_DATA …
#else
#define S3C6400_SERIAL_DRV_DATA …
#endif
#ifdef CONFIG_CPU_S5PV210
static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.info = {
.name = "Samsung S5PV210 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.iotype = UPIO_MEM,
.has_divslot = true,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
.tx_fifofull = S5PV210_UFSTAT_TXFULL,
.tx_fifomask = S5PV210_UFSTAT_TXMASK,
.tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 2,
.clksel_mask = S5PV210_UCON_CLKMASK,
.clksel_shift = S5PV210_UCON_CLKSHIFT,
},
.def_cfg = {
.ucon = S5PV210_UCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
},
.fifosize = { 256, 64, 16, 16 },
};
#define S5PV210_SERIAL_DRV_DATA …
#else
#define S5PV210_SERIAL_DRV_DATA …
#endif
#if defined(CONFIG_ARCH_EXYNOS)
#define EXYNOS_COMMON_SERIAL_DRV_DATA … \
static const struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
.fifosize = { 256, 64, 16, 16 },
};
static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
.fifosize = { 64, 256, 16, 256 },
};
static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
.fifosize = { 256, 64, 64, 64 },
};
static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
.info = {
.name = "Google GS101 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.iotype = UPIO_MEM32,
.has_divslot = true,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
.tx_fifofull = S5PV210_UFSTAT_TXFULL,
.tx_fifomask = S5PV210_UFSTAT_TXMASK,
.tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
},
.def_cfg = {
.ucon = S5PV210_UCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
.has_fracval = 1,
},
.fifosize = { 0 },
};
#define EXYNOS4210_SERIAL_DRV_DATA …
#define EXYNOS5433_SERIAL_DRV_DATA …
#define EXYNOS850_SERIAL_DRV_DATA …
#define GS101_SERIAL_DRV_DATA …
#else
#define EXYNOS4210_SERIAL_DRV_DATA …
#define EXYNOS5433_SERIAL_DRV_DATA …
#define EXYNOS850_SERIAL_DRV_DATA …
#define GS101_SERIAL_DRV_DATA …
#endif
#ifdef CONFIG_ARCH_APPLE
static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.info = {
.name = "Apple S5L UART",
.type = TYPE_APPLE_S5L,
.port_type = PORT_8250,
.iotype = UPIO_MEM32,
.fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2410_UFSTAT_RXFULL,
.tx_fifofull = S3C2410_UFSTAT_TXFULL,
.tx_fifomask = S3C2410_UFSTAT_TXMASK,
.tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
.ucon_mask = APPLE_S5L_UCON_MASK,
},
.def_cfg = {
.ucon = APPLE_S5L_UCON_DEFAULT,
.ufcon = S3C2410_UFCON_DEFAULT,
},
};
#define S5L_SERIAL_DRV_DATA …
#else
#define S5L_SERIAL_DRV_DATA …
#endif
#if defined(CONFIG_ARCH_ARTPEC)
static const struct s3c24xx_serial_drv_data artpec8_serial_drv_data = {
.info = {
.name = "Axis ARTPEC-8 UART",
.type = TYPE_S3C6400,
.port_type = PORT_S3C6400,
.iotype = UPIO_MEM,
.fifosize = 64,
.has_divslot = true,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
.rx_fifofull = S5PV210_UFSTAT_RXFULL,
.tx_fifofull = S5PV210_UFSTAT_TXFULL,
.tx_fifomask = S5PV210_UFSTAT_TXMASK,
.tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
.def_clk_sel = S3C2410_UCON_CLKSEL0,
.num_clks = 1,
.clksel_mask = 0,
.clksel_shift = 0,
},
.def_cfg = {
.ucon = S5PV210_UCON_DEFAULT,
.ufcon = S5PV210_UFCON_DEFAULT,
.has_fracval = 1,
}
};
#define ARTPEC8_SERIAL_DRV_DATA …
#else
#define ARTPEC8_SERIAL_DRV_DATA …
#endif
static const struct platform_device_id s3c24xx_serial_driver_ids[] = …;
MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_uart_dt_match[] = …;
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
#endif
static struct platform_driver samsung_serial_driver = …;
static int __init samsung_serial_init(void)
{ … }
static void __exit samsung_serial_exit(void)
{ … }
module_init(…) …;
module_exit(samsung_serial_exit);
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
static void wr_reg_barrier(const struct uart_port *port, u32 reg, u32 val)
{ … }
struct samsung_early_console_data { … };
static void samsung_early_busyuart(const struct uart_port *port)
{ … }
static void samsung_early_busyuart_fifo(const struct uart_port *port)
{ … }
static void samsung_early_putc(struct uart_port *port, unsigned char c)
{ … }
static void samsung_early_write(struct console *con, const char *s,
unsigned int n)
{ … }
static int samsung_early_read(struct console *con, char *s, unsigned int n)
{ … }
static int __init samsung_early_console_setup(struct earlycon_device *device,
const char *opt)
{ … }
static struct samsung_early_console_data s3c2410_early_console_data = …;
static struct samsung_early_console_data s3c2440_early_console_data = …;
static int __init s3c2440_early_console_setup(struct earlycon_device *device,
const char *opt)
{ … }
OF_EARLYCON_DECLARE(…);
static struct samsung_early_console_data s5pv210_early_console_data = …;
static int __init s5pv210_early_console_setup(struct earlycon_device *device,
const char *opt)
{ … }
OF_EARLYCON_DECLARE(…);
OF_EARLYCON_DECLARE(…);
OF_EARLYCON_DECLARE(…);
static int __init gs101_early_console_setup(struct earlycon_device *device,
const char *opt)
{ … }
OF_EARLYCON_DECLARE(…);
static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
const char *opt)
{ … }
OF_EARLYCON_DECLARE(…);
#endif
MODULE_ALIAS(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;