diff options
Diffstat (limited to 'drivers/tty/serial/samsung_tty.c')
-rw-r--r-- | drivers/tty/serial/samsung_tty.c | 296 |
1 files changed, 173 insertions, 123 deletions
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index d002a4e48ed9..e1585fbae909 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -63,7 +63,7 @@ enum s3c24xx_port_type { }; struct s3c24xx_uart_info { - char *name; + const char *name; enum s3c24xx_port_type type; unsigned int port_type; unsigned int fifosize; @@ -85,9 +85,9 @@ struct s3c24xx_uart_info { }; struct s3c24xx_serial_drv_data { - struct s3c24xx_uart_info *info; - struct s3c2410_uartcfg *def_cfg; - unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; + const struct s3c24xx_uart_info info; + const struct s3c2410_uartcfg def_cfg; + const unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; }; struct s3c24xx_uart_dma { @@ -136,14 +136,14 @@ struct s3c24xx_uart_port { unsigned int tx_mode; unsigned int rx_mode; - struct s3c24xx_uart_info *info; + const struct s3c24xx_uart_info *info; struct clk *clk; struct clk *baudclk; struct uart_port port; - struct s3c24xx_serial_drv_data *drv_data; + const struct s3c24xx_serial_drv_data *drv_data; /* reference to platform data */ - struct s3c2410_uartcfg *cfg; + const struct s3c2410_uartcfg *cfg; struct s3c24xx_uart_dma *dma; @@ -164,7 +164,7 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport); #define portaddrl(port, reg) \ ((unsigned long *)(unsigned long)((port)->membase + (reg))) -static u32 rd_reg(struct uart_port *port, u32 reg) +static u32 rd_reg(const struct uart_port *port, u32 reg) { switch (port->iotype) { case UPIO_MEM: @@ -179,7 +179,7 @@ static u32 rd_reg(struct uart_port *port, u32 reg) #define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg))) -static void wr_reg(struct uart_port *port, u32 reg, u32 val) +static void wr_reg(const struct uart_port *port, u32 reg, u32 val) { switch (port->iotype) { case UPIO_MEM: @@ -195,7 +195,7 @@ static void wr_reg(struct uart_port *port, u32 reg, u32 val) /* Byte-order aware bit setting/clearing functions. */ -static inline void s3c24xx_set_bit(struct uart_port *port, int idx, +static inline void s3c24xx_set_bit(const struct uart_port *port, int idx, unsigned int reg) { unsigned long flags; @@ -208,7 +208,7 @@ static inline void s3c24xx_set_bit(struct uart_port *port, int idx, local_irq_restore(flags); } -static inline void s3c24xx_clear_bit(struct uart_port *port, int idx, +static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx, unsigned int reg) { unsigned long flags; @@ -228,12 +228,12 @@ static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) /* translate a port to the device name */ -static inline const char *s3c24xx_serial_portname(struct uart_port *port) +static inline const char *s3c24xx_serial_portname(const struct uart_port *port) { return to_platform_device(port->dev)->name; } -static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) +static int s3c24xx_serial_txempty_nofifo(const struct uart_port *port) { return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE; } @@ -358,7 +358,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args) static void enable_tx_dma(struct s3c24xx_uart_port *ourport) { - struct uart_port *port = &ourport->port; + const struct uart_port *port = &ourport->port; u32 ucon; /* Mask Tx interrupt */ @@ -387,7 +387,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport) static void enable_tx_pio(struct s3c24xx_uart_port *ourport) { - struct uart_port *port = &ourport->port; + const struct uart_port *port = &ourport->port; u32 ucon, ufcon; /* Set ufcon txtrig */ @@ -573,16 +573,16 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port) } } -static inline struct s3c24xx_uart_info +static inline const struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) { return to_ourport(port)->info; } -static inline struct s3c2410_uartcfg - *s3c24xx_port_to_cfg(struct uart_port *port) +static inline const struct s3c2410_uartcfg + *s3c24xx_port_to_cfg(const struct uart_port *port) { - struct s3c24xx_uart_port *ourport; + const struct s3c24xx_uart_port *ourport; if (port->dev == NULL) return NULL; @@ -591,10 +591,10 @@ static inline struct s3c2410_uartcfg return ourport->cfg; } -static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, +static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport, unsigned long ufstat) { - struct s3c24xx_uart_info *info = ourport->info; + const struct s3c24xx_uart_info *info = ourport->info; if (ufstat & info->rx_fifofull) return ourport->port.fifosize; @@ -921,11 +921,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport) return; } - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { - spin_unlock(&port->lock); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); - spin_lock(&port->lock); - } if (uart_circ_empty(xmit)) s3c24xx_serial_stop_tx(port); @@ -947,8 +944,8 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id) /* interrupt handler for s3c64xx and later SoC's.*/ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) { - struct s3c24xx_uart_port *ourport = id; - struct uart_port *port = &ourport->port; + const struct s3c24xx_uart_port *ourport = id; + const struct uart_port *port = &ourport->port; unsigned int pend = rd_regl(port, S3C64XX_UINTP); irqreturn_t ret = IRQ_HANDLED; @@ -966,8 +963,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) /* interrupt handler for Apple SoC's.*/ static irqreturn_t apple_serial_handle_irq(int irq, void *id) { - struct s3c24xx_uart_port *ourport = id; - struct uart_port *port = &ourport->port; + const struct s3c24xx_uart_port *ourport = id; + const struct uart_port *port = &ourport->port; unsigned int pend = rd_regl(port, S3C2410_UTRSTAT); irqreturn_t ret = IRQ_NONE; @@ -986,7 +983,7 @@ static irqreturn_t apple_serial_handle_irq(int irq, void *id) static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); unsigned long ufcon = rd_regl(port, S3C2410_UFCON); @@ -1405,7 +1402,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, static inline int s3c24xx_serial_getsource(struct uart_port *port) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned int ucon; if (info->num_clks == 1) @@ -1419,7 +1416,7 @@ static inline int s3c24xx_serial_getsource(struct uart_port *port) static void s3c24xx_serial_setsource(struct uart_port *port, unsigned int clk_sel) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned int ucon; if (info->num_clks == 1) @@ -1438,7 +1435,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, unsigned int req_baud, struct clk **best_clk, unsigned int *clk_num) { - struct s3c24xx_uart_info *info = ourport->info; + const struct s3c24xx_uart_info *info = ourport->info; struct clk *clk; unsigned long rate; unsigned int cnt, baud, quot, best_quot = 0; @@ -1499,7 +1496,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, * This table takes the fractional value of the baud divisor and gives * the recommended setting for the UDIVSLOT register. */ -static u16 udivslot_table[16] = { +static const u16 udivslot_table[16] = { [0] = 0x0000, [1] = 0x0080, [2] = 0x0808, @@ -1522,7 +1519,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); + const struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); struct clk *clk = ERR_PTR(-EINVAL); unsigned long flags; @@ -1675,7 +1672,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, static const char *s3c24xx_serial_type(struct uart_port *port) { - struct s3c24xx_uart_port *ourport = to_ourport(port); + const struct s3c24xx_uart_port *ourport = to_ourport(port); switch (ourport->info->type) { case TYPE_S3C24XX: @@ -1691,7 +1688,7 @@ static const char *s3c24xx_serial_type(struct uart_port *port) static void s3c24xx_serial_config_port(struct uart_port *port, int flags) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); if (flags & UART_CONFIG_TYPE) port->type = info->port_type; @@ -1703,7 +1700,7 @@ 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) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); if (ser->type != PORT_UNKNOWN && ser->type != info->port_type) return -EINVAL; @@ -1873,9 +1870,9 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { */ static void s3c24xx_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) + const struct s3c2410_uartcfg *cfg) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned long ucon = rd_regl(port, S3C2410_UCON); ucon &= (info->clksel_mask | info->ucon_mask); @@ -1979,7 +1976,7 @@ s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport) { struct device *dev = ourport->port.dev; - struct s3c24xx_uart_info *info = ourport->info; + const struct s3c24xx_uart_info *info = ourport->info; char clk_name[MAX_CLK_NAME_LENGTH]; unsigned int clk_sel; struct clk *clk; @@ -2021,7 +2018,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, struct platform_device *platdev) { struct uart_port *port = &ourport->port; - struct s3c2410_uartcfg *cfg = ourport->cfg; + const struct s3c2410_uartcfg *cfg = ourport->cfg; struct resource *res; int ret; @@ -2150,23 +2147,14 @@ err: /* Device driver serial port probe */ -#ifdef CONFIG_OF -static const struct of_device_id s3c24xx_uart_dt_match[]; -#endif - static int probe_index; -static inline struct s3c24xx_serial_drv_data * +static inline const struct s3c24xx_serial_drv_data * s3c24xx_get_driver_data(struct platform_device *pdev) { -#ifdef CONFIG_OF - if (pdev->dev.of_node) { - const struct of_device_id *match; + if (dev_of_node(&pdev->dev)) + return of_device_get_match_data(&pdev->dev); - match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); - return (struct s3c24xx_serial_drv_data *)match->data; - } -#endif return (struct s3c24xx_serial_drv_data *) platform_get_device_id(pdev)->driver_data; } @@ -2197,10 +2185,10 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) } ourport->baudclk = ERR_PTR(-EINVAL); - ourport->info = ourport->drv_data->info; + ourport->info = &ourport->drv_data->info; ourport->cfg = (dev_get_platdata(&pdev->dev)) ? dev_get_platdata(&pdev->dev) : - ourport->drv_data->def_cfg; + &ourport->drv_data->def_cfg; switch (ourport->info->type) { case TYPE_S3C24XX: @@ -2419,7 +2407,7 @@ static struct uart_port *cons_uart; static int s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) { - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned long ufstat, utrstat; if (ufcon & S3C2410_UFCON_FIFOMODE) { @@ -2450,7 +2438,7 @@ s3c24xx_port_configured(unsigned int ucon) static int s3c24xx_serial_get_poll_char(struct uart_port *port) { - struct s3c24xx_uart_port *ourport = to_ourport(port); + const struct s3c24xx_uart_port *ourport = to_ourport(port); unsigned int ufstat; ufstat = rd_regl(port, S3C2410_UFSTAT); @@ -2478,7 +2466,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ static void -s3c24xx_serial_console_putchar(struct uart_port *port, int ch) +s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch) { unsigned int ufcon = rd_regl(port, S3C2410_UFCON); @@ -2615,8 +2603,8 @@ static struct console s3c24xx_serial_console = { #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ #ifdef CONFIG_CPU_S3C2410 -static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { + .info = { .name = "Samsung S3C2410 UART", .type = TYPE_S3C24XX, .port_type = PORT_S3C2410, @@ -2632,19 +2620,19 @@ static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { .clksel_mask = S3C2410_UCON_CLKMASK, .clksel_shift = S3C2410_UCON_CLKSHIFT, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = S3C2410_UCON_DEFAULT, .ufcon = S3C2410_UFCON_DEFAULT, }, }; -#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data) +#define S3C2410_SERIAL_DRV_DATA (&s3c2410_serial_drv_data) #else -#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define S3C2410_SERIAL_DRV_DATA NULL #endif #ifdef CONFIG_CPU_S3C2412 -static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { + .info = { .name = "Samsung S3C2412 UART", .type = TYPE_S3C24XX, .port_type = PORT_S3C2412, @@ -2661,20 +2649,20 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { .clksel_mask = S3C2412_UCON_CLKMASK, .clksel_shift = S3C2412_UCON_CLKSHIFT, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = S3C2410_UCON_DEFAULT, .ufcon = S3C2410_UFCON_DEFAULT, }, }; -#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data) +#define S3C2412_SERIAL_DRV_DATA (&s3c2412_serial_drv_data) #else -#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define S3C2412_SERIAL_DRV_DATA NULL #endif #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442) -static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { + .info = { .name = "Samsung S3C2440 UART", .type = TYPE_S3C24XX, .port_type = PORT_S3C2440, @@ -2692,19 +2680,19 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { .clksel_shift = S3C2412_UCON_CLKSHIFT, .ucon_mask = S3C2440_UCON0_DIVMASK, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = S3C2410_UCON_DEFAULT, .ufcon = S3C2410_UFCON_DEFAULT, }, }; -#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data) +#define S3C2440_SERIAL_DRV_DATA (&s3c2440_serial_drv_data) #else -#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define S3C2440_SERIAL_DRV_DATA NULL #endif #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) -static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { + .info = { .name = "Samsung S3C6400 UART", .type = TYPE_S3C6400, .port_type = PORT_S3C6400, @@ -2721,19 +2709,19 @@ static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { .clksel_mask = S3C6400_UCON_CLKMASK, .clksel_shift = S3C6400_UCON_CLKSHIFT, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = S3C2410_UCON_DEFAULT, .ufcon = S3C2410_UFCON_DEFAULT, }, }; -#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data) +#define S3C6400_SERIAL_DRV_DATA (&s3c6400_serial_drv_data) #else -#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define S3C6400_SERIAL_DRV_DATA NULL #endif #ifdef CONFIG_CPU_S5PV210 -static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { + .info = { .name = "Samsung S5PV210 UART", .type = TYPE_S3C6400, .port_type = PORT_S3C6400, @@ -2749,20 +2737,20 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { .clksel_mask = S5PV210_UCON_CLKMASK, .clksel_shift = S5PV210_UCON_CLKSHIFT, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = S5PV210_UCON_DEFAULT, .ufcon = S5PV210_UFCON_DEFAULT, }, .fifosize = { 256, 64, 16, 16 }, }; -#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data) +#define S5PV210_SERIAL_DRV_DATA (&s5pv210_serial_drv_data) #else -#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#define S5PV210_SERIAL_DRV_DATA NULL #endif #if defined(CONFIG_ARCH_EXYNOS) #define EXYNOS_COMMON_SERIAL_DRV_DATA() \ - .info = &(struct s3c24xx_uart_info) { \ + .info = { \ .name = "Samsung Exynos UART", \ .type = TYPE_S3C6400, \ .port_type = PORT_S3C6400, \ @@ -2778,40 +2766,40 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { .clksel_mask = 0, \ .clksel_shift = 0, \ }, \ - .def_cfg = &(struct s3c2410_uartcfg) { \ + .def_cfg = { \ .ucon = S5PV210_UCON_DEFAULT, \ .ufcon = S5PV210_UFCON_DEFAULT, \ .has_fracval = 1, \ } \ -static struct s3c24xx_serial_drv_data exynos4210_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 struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { +static const struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { EXYNOS_COMMON_SERIAL_DRV_DATA(), .fifosize = { 64, 256, 16, 256 }, }; -static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { +static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { EXYNOS_COMMON_SERIAL_DRV_DATA(), .fifosize = { 256, 64, 64, 64 }, }; -#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data) -#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data) -#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data) +#define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data) +#define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data) +#define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data) #else -#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) -#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) -#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) +#define EXYNOS4210_SERIAL_DRV_DATA NULL +#define EXYNOS5433_SERIAL_DRV_DATA NULL +#define EXYNOS850_SERIAL_DRV_DATA NULL #endif #ifdef CONFIG_ARCH_APPLE -static struct s3c24xx_serial_drv_data s5l_serial_drv_data = { - .info = &(struct s3c24xx_uart_info) { +static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = { + .info = { .name = "Apple S5L UART", .type = TYPE_APPLE_S5L, .port_type = PORT_8250, @@ -2827,44 +2815,77 @@ static struct s3c24xx_serial_drv_data s5l_serial_drv_data = { .clksel_mask = 0, .clksel_shift = 0, }, - .def_cfg = &(struct s3c2410_uartcfg) { + .def_cfg = { .ucon = APPLE_S5L_UCON_DEFAULT, .ufcon = S3C2410_UFCON_DEFAULT, }, }; -#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)&s5l_serial_drv_data) +#define S5L_SERIAL_DRV_DATA (&s5l_serial_drv_data) #else -#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)NULL) +#define S5L_SERIAL_DRV_DATA NULL +#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, + .fifosize = 64, + .has_divslot = 1, + .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 (&artpec8_serial_drv_data) +#else +#define ARTPEC8_SERIAL_DRV_DATA (NULL) #endif static const struct platform_device_id s3c24xx_serial_driver_ids[] = { { .name = "s3c2410-uart", - .driver_data = S3C2410_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S3C2410_SERIAL_DRV_DATA, }, { .name = "s3c2412-uart", - .driver_data = S3C2412_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S3C2412_SERIAL_DRV_DATA, }, { .name = "s3c2440-uart", - .driver_data = S3C2440_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S3C2440_SERIAL_DRV_DATA, }, { .name = "s3c6400-uart", - .driver_data = S3C6400_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S3C6400_SERIAL_DRV_DATA, }, { .name = "s5pv210-uart", - .driver_data = S5PV210_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S5PV210_SERIAL_DRV_DATA, }, { .name = "exynos4210-uart", - .driver_data = EXYNOS4210_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)EXYNOS4210_SERIAL_DRV_DATA, }, { .name = "exynos5433-uart", - .driver_data = EXYNOS5433_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)EXYNOS5433_SERIAL_DRV_DATA, }, { .name = "s5l-uart", - .driver_data = S5L_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)S5L_SERIAL_DRV_DATA, }, { .name = "exynos850-uart", - .driver_data = EXYNOS850_SERIAL_DRV_DATA, + .driver_data = (kernel_ulong_t)EXYNOS850_SERIAL_DRV_DATA, + }, { + .name = "artpec8-uart", + .driver_data = (kernel_ulong_t)ARTPEC8_SERIAL_DRV_DATA, }, { }, }; @@ -2873,23 +2894,25 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids); #ifdef CONFIG_OF static const struct of_device_id s3c24xx_uart_dt_match[] = { { .compatible = "samsung,s3c2410-uart", - .data = (void *)S3C2410_SERIAL_DRV_DATA }, + .data = S3C2410_SERIAL_DRV_DATA }, { .compatible = "samsung,s3c2412-uart", - .data = (void *)S3C2412_SERIAL_DRV_DATA }, + .data = S3C2412_SERIAL_DRV_DATA }, { .compatible = "samsung,s3c2440-uart", - .data = (void *)S3C2440_SERIAL_DRV_DATA }, + .data = S3C2440_SERIAL_DRV_DATA }, { .compatible = "samsung,s3c6400-uart", - .data = (void *)S3C6400_SERIAL_DRV_DATA }, + .data = S3C6400_SERIAL_DRV_DATA }, { .compatible = "samsung,s5pv210-uart", - .data = (void *)S5PV210_SERIAL_DRV_DATA }, + .data = S5PV210_SERIAL_DRV_DATA }, { .compatible = "samsung,exynos4210-uart", - .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, + .data = EXYNOS4210_SERIAL_DRV_DATA }, { .compatible = "samsung,exynos5433-uart", - .data = (void *)EXYNOS5433_SERIAL_DRV_DATA }, + .data = EXYNOS5433_SERIAL_DRV_DATA }, { .compatible = "apple,s5l-uart", - .data = (void *)S5L_SERIAL_DRV_DATA }, + .data = S5L_SERIAL_DRV_DATA }, { .compatible = "samsung,exynos850-uart", - .data = (void *)EXYNOS850_SERIAL_DRV_DATA }, + .data = EXYNOS850_SERIAL_DRV_DATA }, + { .compatible = "axis,artpec8-uart", + .data = ARTPEC8_SERIAL_DRV_DATA }, {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); @@ -2935,7 +2958,7 @@ module_exit(samsung_serial_exit); * Early console. */ -static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val) +static void wr_reg_barrier(const struct uart_port *port, u32 reg, u32 val) { switch (port->iotype) { case UPIO_MEM: @@ -2949,23 +2972,24 @@ static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val) struct samsung_early_console_data { u32 txfull_mask; + u32 rxfifo_mask; }; -static void samsung_early_busyuart(struct uart_port *port) +static void samsung_early_busyuart(const struct uart_port *port) { while (!(readl(port->membase + S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE)) ; } -static void samsung_early_busyuart_fifo(struct uart_port *port) +static void samsung_early_busyuart_fifo(const struct uart_port *port) { - struct samsung_early_console_data *data = port->private_data; + const struct samsung_early_console_data *data = port->private_data; while (readl(port->membase + S3C2410_UFSTAT) & data->txfull_mask) ; } -static void samsung_early_putc(struct uart_port *port, int c) +static void samsung_early_putc(struct uart_port *port, unsigned char c) { if (readl(port->membase + S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) samsung_early_busyuart_fifo(port); @@ -2983,6 +3007,26 @@ static void samsung_early_write(struct console *con, const char *s, uart_console_write(&dev->port, s, n, samsung_early_putc); } +static int samsung_early_read(struct console *con, char *s, unsigned int n) +{ + struct earlycon_device *dev = con->data; + const struct samsung_early_console_data *data = dev->port.private_data; + int ch, ufstat, num_read = 0; + + while (num_read < n) { + ufstat = rd_regl(&dev->port, S3C2410_UFSTAT); + if (!(ufstat & data->rxfifo_mask)) + break; + ch = rd_reg(&dev->port, S3C2410_URXH); + if (ch == NO_POLL_CHAR) + break; + + s[num_read++] = ch; + } + + return num_read; +} + static int __init samsung_early_console_setup(struct earlycon_device *device, const char *opt) { @@ -2990,12 +3034,14 @@ static int __init samsung_early_console_setup(struct earlycon_device *device, return -ENODEV; device->con->write = samsung_early_write; + device->con->read = samsung_early_read; return 0; } /* S3C2410 */ static struct samsung_early_console_data s3c2410_early_console_data = { .txfull_mask = S3C2410_UFSTAT_TXFULL, + .rxfifo_mask = S3C2410_UFSTAT_RXFULL | S3C2410_UFSTAT_RXMASK, }; static int __init s3c2410_early_console_setup(struct earlycon_device *device, @@ -3011,6 +3057,7 @@ OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", /* S3C2412, S3C2440, S3C64xx */ static struct samsung_early_console_data s3c2440_early_console_data = { .txfull_mask = S3C2440_UFSTAT_TXFULL, + .rxfifo_mask = S3C2440_UFSTAT_RXFULL | S3C2440_UFSTAT_RXMASK, }; static int __init s3c2440_early_console_setup(struct earlycon_device *device, @@ -3030,6 +3077,7 @@ OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart", /* S5PV210, Exynos */ static struct samsung_early_console_data s5pv210_early_console_data = { .txfull_mask = S5PV210_UFSTAT_TXFULL, + .rxfifo_mask = S5PV210_UFSTAT_RXFULL | S5PV210_UFSTAT_RXMASK, }; static int __init s5pv210_early_console_setup(struct earlycon_device *device, @@ -3043,6 +3091,8 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", s5pv210_early_console_setup); +OF_EARLYCON_DECLARE(artpec8, "axis,artpec8-uart", + s5pv210_early_console_setup); /* Apple S5L */ static int __init apple_s5l_early_console_setup(struct earlycon_device *device, |