From e2c2725338cb5c51e8f1eada2b3dfb938bdb03ae Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 1 Sep 2013 22:24:35 -0300 Subject: serial: imx: Use NULL as the last argument of add_preferred_console() Commit f7d2c0bbd (serial: i.MX: evaluate linux,stdout-path property) introduced the following sparse warning: drivers/tty/serial/imx.c:1916:77: warning: Using plain integer as NULL pointer Pass NULL as the last argument of add_preferred_console() instead of zero. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index a0ebbc9ce5cd..65d9b2f4882b 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1913,7 +1913,8 @@ static int serial_imx_probe_dt(struct imx_port *sport, sport->devdata = of_id->data; if (of_device_is_stdout_path(np)) - add_preferred_console(imx_reg.cons->name, sport->port.line, 0); + add_preferred_console(imx_reg.cons->name, sport->port.line, + NULL); return 0; } -- cgit v1.2.3 From 965e260a064a35359bc6281aa76c39e3f43ed9ba Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Sep 2013 17:13:23 -0400 Subject: tty: serial: Restrict ST ASC driver to only build on !ARM when COMPILE_TEST is set. The Kconfig for this option suggests it's only relevant on STi SoCs, so add depends to have it not show up on archs that won't ever run it. Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index febd45cd5027..701ca60076ed 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1512,6 +1512,7 @@ config SERIAL_FSL_LPUART_CONSOLE config SERIAL_ST_ASC tristate "ST ASC serial port support" select SERIAL_CORE + depends on ARM || COMPILE_TEST help This driver is for the on-chip Asychronous Serial Controller on STMicroelectronics STi SoCs. -- cgit v1.2.3 From 12d493c791876519393a483fa46bc4893379d523 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 1 Sep 2013 19:34:06 +0100 Subject: serial: mfd: Replace MODULE_ALIAS with MODULE_DEVICE_TABLE This is a PCI driver and should be auto-loaded based on PCI ID. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index d3db042f649e..a187cd4b1e53 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -1504,4 +1504,4 @@ module_init(hsu_pci_init); module_exit(hsu_pci_exit); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:medfield-hsu"); +MODULE_DEVICE_TABLE(pci, pci_ids); -- cgit v1.2.3 From 52592da32b85e8be7e6ab534059b9457b3dea4e5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 1 Sep 2013 19:26:37 +0100 Subject: serial: pch_uart: Add MODULE_DEVICE_TABLE pch_uart currently isn't auto-loaded if built as a module. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 52379e56a31e..e0fbf87478b9 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -2003,6 +2003,8 @@ module_exit(pch_uart_module_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver"); +MODULE_DEVICE_TABLE(pci, pch_uart_pci_id); + module_param(default_baud, uint, S_IRUGO); MODULE_PARM_DESC(default_baud, "Default BAUD for initial driver state and console (default 9600)"); -- cgit v1.2.3 From 2797f6fb6727d8ac5127f88aee1fd059db0be24b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 5 Sep 2013 17:34:52 +0300 Subject: serial: 8250: don't change the fifo trigger level when using dma DMA engines usually expect the fifo trigger level to be aligned with the burst size. It should not be changed even with small baud rates. This will fix an issue with Designware DMA engine where the data can not be transferred over UART with lower baud rates then 2400. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 570df9d2a5d2..e33d38cb170f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -2322,7 +2322,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { fcr = uart_config[port->type].fcr; - if (baud < 2400 || fifo_bug) { + if ((baud < 2400 && !up->dma) || fifo_bug) { fcr &= ~UART_FCR_TRIGGER_MASK; fcr |= UART_FCR_TRIGGER_1; } -- cgit v1.2.3 From fe95855539fd0a0e54412efc596adfe802a5c605 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 5 Sep 2013 17:34:53 +0300 Subject: serial: 8250_dw: don't limit DMA support to ACPI It should be available for DT users as well. This does not enable DMA by default except with ACPI. DT users can enable DMA based on a property. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index daf710f5c3fc..d7a405b12600 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -56,11 +56,12 @@ struct dw8250_data { - int last_lcr; - int last_mcr; - int line; - struct clk *clk; - u8 usr_reg; + u8 usr_reg; + int last_lcr; + int last_mcr; + int line; + struct clk *clk; + struct uart_8250_dma dma; }; static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) @@ -241,7 +242,8 @@ static int dw8250_probe_of(struct uart_port *p, } #ifdef CONFIG_ACPI -static int dw8250_probe_acpi(struct uart_8250_port *up) +static int dw8250_probe_acpi(struct uart_8250_port *up, + struct dw8250_data *data) { const struct acpi_device_id *id; struct uart_port *p = &up->port; @@ -260,9 +262,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up) if (!p->uartclk) p->uartclk = (unsigned int)id->driver_data; - up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL); - if (!up->dma) - return -ENOMEM; + up->dma = &data->dma; up->dma->rxconf.src_maxburst = p->fifosize / 4; up->dma->txconf.dst_maxburst = p->fifosize / 4; @@ -324,7 +324,7 @@ static int dw8250_probe(struct platform_device *pdev) if (err) return err; } else if (ACPI_HANDLE(&pdev->dev)) { - err = dw8250_probe_acpi(&uart); + err = dw8250_probe_acpi(&uart, data); if (err) return err; } else { -- cgit v1.2.3 From 7fb8c56c7fa0fa11168d3788d4591951bec27f4b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 5 Sep 2013 17:34:54 +0300 Subject: serial: 8250_dw: provide a filter for DMA channel detection The channel IDs are set to -1 by default. It will prevent dmaengine from trying to provide the first free channel if it fails to allocate exclusive channel. This will fix an issue with ACPI enumerated UARTs that do not support DMA but still end up getting a DMA channel incorrectly. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d7a405b12600..8edf7697fdb2 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -154,6 +154,14 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) pm_runtime_put_sync_suspend(port->dev); } +static bool dw8250_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw8250_data *data = param; + + return chan->chan_id == data->dma.tx_chan_id || + chan->chan_id == data->dma.rx_chan_id; +} + static void dw8250_setup_port(struct uart_8250_port *up) { struct uart_port *p = &up->port; @@ -314,6 +322,12 @@ static int dw8250_probe(struct platform_device *pdev) uart.port.uartclk = clk_get_rate(data->clk); } + data->dma.rx_chan_id = -1; + data->dma.tx_chan_id = -1; + data->dma.rx_param = data; + data->dma.tx_param = data; + data->dma.fn = dw8250_dma_filter; + uart.port.iotype = UPIO_MEM; uart.port.serial_in = dw8250_serial_in; uart.port.serial_out = dw8250_serial_out; -- cgit v1.2.3 From 0d8570ad7ec99f4c89135657ea2821bdae78423f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:06:45 +0900 Subject: serial: arc_uart: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/arc_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 569872f4c9b8..c9f5c9dcc15c 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -533,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id) unsigned long *plat_data; struct arc_uart_port *uart = &arc_uart_ports[dev_id]; - plat_data = (unsigned long *)dev_get_platdata(&pdev->dev); + plat_data = dev_get_platdata(&pdev->dev); if (!plat_data) return -ENODEV; -- cgit v1.2.3 From 5c02fab62e953a5281d7daa7bdd18892c4b43741 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:07:54 +0900 Subject: serial: mpsc: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 8d702677acc5..e30a3ca3cea3 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -2030,7 +2030,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, { struct mpsc_pdata *pdata; - pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev); + pdata = dev_get_platdata(&pd->dev); pi->port.uartclk = pdata->brg_clk_freq; pi->port.iotype = UPIO_MEM; -- cgit v1.2.3 From 0e03e3f8ea2c8c1f1fe099932c1c4f34d44d5231 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:08:43 +0900 Subject: serial: bfin_uart: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Sonic Zhang Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 3c75e8e04028..74749a6d3565 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -1240,7 +1240,7 @@ static int bfin_serial_probe(struct platform_device *pdev) */ #endif ret = peripheral_request_list( - (unsigned short *)dev_get_platdata(&pdev->dev), + dev_get_platdata(&pdev->dev), DRIVER_NAME); if (ret) { dev_err(&pdev->dev, @@ -1358,8 +1358,7 @@ static int bfin_serial_probe(struct platform_device *pdev) out_error_unmap: iounmap(uart->port.membase); out_error_free_peripherals: - peripheral_free_list( - (unsigned short *)dev_get_platdata(&pdev->dev)); + peripheral_free_list(dev_get_platdata(&pdev->dev)); out_error_free_mem: kfree(uart); bfin_serial_ports[pdev->id] = NULL; @@ -1377,8 +1376,7 @@ static int bfin_serial_remove(struct platform_device *pdev) if (uart) { uart_remove_one_port(&bfin_serial_reg, &uart->port); iounmap(uart->port.membase); - peripheral_free_list( - (unsigned short *)dev_get_platdata(&pdev->dev)); + peripheral_free_list(dev_get_platdata(&pdev->dev)); kfree(uart); bfin_serial_ports[pdev->id] = NULL; } @@ -1432,8 +1430,8 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev) return -ENOENT; } - ret = peripheral_request_list( - (unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME); + ret = peripheral_request_list(dev_get_platdata(&pdev->dev), + DRIVER_NAME); if (ret) { dev_err(&pdev->dev, "fail to request bfin serial peripherals\n"); @@ -1463,8 +1461,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev) return 0; out_error_free_peripherals: - peripheral_free_list( - (unsigned short *)dev_get_platdata(&pdev->dev)); + peripheral_free_list(dev_get_platdata(&pdev->dev)); return ret; } -- cgit v1.2.3 From aaba105e66e98bb11e017eece341346bd3e91871 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:09:20 +0900 Subject: serial: bfin_sport_uart: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_sport_uart.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index 87636cc61a21..4f229703328b 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c @@ -766,9 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev) return -ENOMEM; } - ret = peripheral_request_list( - (unsigned short *)dev_get_platdata(&pdev->dev), - DRV_NAME); + ret = peripheral_request_list(dev_get_platdata(&pdev->dev), + DRV_NAME); if (ret) { dev_err(&pdev->dev, "Fail to request SPORT peripherals\n"); @@ -844,8 +843,7 @@ static int sport_uart_probe(struct platform_device *pdev) out_error_unmap: iounmap(sport->port.membase); out_error_free_peripherals: - peripheral_free_list( - (unsigned short *)dev_get_platdata(&pdev->dev)); + peripheral_free_list(dev_get_platdata(&pdev->dev)); out_error_free_mem: kfree(sport); bfin_sport_uart_ports[pdev->id] = NULL; @@ -864,8 +862,7 @@ static int sport_uart_remove(struct platform_device *pdev) if (sport) { uart_remove_one_port(&sport_uart_reg, &sport->port); iounmap(sport->port.membase); - peripheral_free_list( - (unsigned short *)dev_get_platdata(&pdev->dev)); + peripheral_free_list(dev_get_platdata(&pdev->dev)); kfree(sport); bfin_sport_uart_ports[pdev->id] = NULL; } -- cgit v1.2.3 From 7a89c79a946d72597fb96a06a9a9e95ff6b832b4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:09:55 +0900 Subject: serial: ifx6x60: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index af286e6713eb..590390970996 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) return -ENODEV; } - pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev); + pl_data = dev_get_platdata(&spi->dev); if (!pl_data) { dev_err(&spi->dev, "missing platform data!"); return -ENODEV; -- cgit v1.2.3 From d4aab2064adbd0660ab9cbfc3e93eae8216b41aa Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:10:30 +0900 Subject: serial: samsung: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 2 +- drivers/tty/serial/samsung.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index f3dfa19a1cb8..81f3dbabaaed 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1254,7 +1254,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ourport->baudclk = ERR_PTR(-EINVAL); ourport->info = ourport->drv_data->info; ourport->cfg = (dev_get_platdata(&pdev->dev)) ? - (struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) : + dev_get_platdata(&pdev->dev) : ourport->drv_data->def_cfg; ourport->port.fifosize = (ourport->info->fifosize) ? diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index aaa617a6c499..8827e5424cef 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h @@ -63,7 +63,7 @@ struct s3c24xx_uart_port { /* conversion functions */ -#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) +#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev) /* register access controls */ -- cgit v1.2.3 From 4190390ad282e5f69bdb02af094c09787f34ca38 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Sep 2013 14:11:17 +0900 Subject: serial: mpc512x: Remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Acked-by: Vineet Gupta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpc52xx_uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 5be1df39f9f5..e05a3b1a87c7 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -1766,7 +1766,7 @@ mpc52xx_uart_of_remove(struct platform_device *op) static int mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) { - struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); + struct uart_port *port = platform_get_drvdata(op); if (port) uart_suspend_port(&mpc52xx_uart_driver, port); @@ -1777,7 +1777,7 @@ mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) static int mpc52xx_uart_of_resume(struct platform_device *op) { - struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); + struct uart_port *port = platform_get_drvdata(op); if (port) uart_resume_port(&mpc52xx_uart_driver, port); -- cgit v1.2.3 From 2d1e5a48965be57eefce033894d9795672f6ab63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20Gon=C3=A7alves?= Date: Wed, 18 Sep 2013 16:52:49 +0100 Subject: serial: samsung: add support for manual RTS setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Samsung serial driver currently does not support setting the RTS pin with an ioctl(TIOCMSET) call. This patch adds this support. Changes in v2: - Preserve the RTS pin's manual setting in set_termios() also when enabling CRTSCTS. Signed-off-by: José Miguel Gonçalves Reviewed-by: Tomasz Figa Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 81f3dbabaaed..c1af04d46682 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -407,7 +407,14 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* todo - possibly remove AFC and do manual CTS */ + unsigned int umcon = rd_regl(port, S3C2410_UMCON); + + if (mctrl & TIOCM_RTS) + umcon |= S3C2410_UMCOM_RTS_LOW; + else + umcon &= ~S3C2410_UMCOM_RTS_LOW; + + wr_regl(port, S3C2410_UMCON, umcon); } static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) @@ -774,8 +781,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (termios->c_cflag & CSTOPB) ulcon |= S3C2410_LCON_STOPB; - umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0; - if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) ulcon |= S3C2410_LCON_PODD; @@ -792,6 +797,15 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, wr_regl(port, S3C2410_ULCON, ulcon); wr_regl(port, S3C2410_UBRDIV, quot); + + umcon = rd_regl(port, S3C2410_UMCON); + if (termios->c_cflag & CRTSCTS) { + umcon |= S3C2410_UMCOM_AFC; + /* Disable RTS when RX FIFO contains 63 bytes */ + umcon &= ~S3C2412_UMCON_AFC_8; + } else { + umcon &= ~S3C2410_UMCOM_AFC; + } wr_regl(port, S3C2410_UMCON, umcon); if (ourport->info->has_divslot) -- cgit v1.2.3 From a50c44ce2463c427552bd0dab635d4980ed84131 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 11 Sep 2013 21:27:53 -0700 Subject: serial: imx: Change cast to handle 64-bit resource_size_t This resolves a warning where resource_size_t is larger than void *: drivers/tty/serial/imx.c:1542:6: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] Since iomem_base is a void *, casting to unsigned long is safe. It's unclear to me that this comparison is truly needed, but it's there on several other drivers as well. Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 65d9b2f4882b..c07d9bb39695 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1539,7 +1539,7 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser) ret = -EINVAL; if (sport->port.uartclk / 16 != ser->baud_base) ret = -EINVAL; - if ((void *)sport->port.mapbase != ser->iomem_base) + if (sport->port.mapbase != (unsigned long)ser->iomem_base) ret = -EINVAL; if (sport->port.iobase != ser->port) ret = -EINVAL; -- cgit v1.2.3 From f8bf876209a9828a456a9ac09ef6369a007dda2d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 12 Sep 2013 15:31:06 +0900 Subject: serial: mfd: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mfd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index a187cd4b1e53..503dcc77b2bd 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -1451,7 +1451,6 @@ static void serial_hsu_remove(struct pci_dev *pdev) uart_remove_one_port(&serial_hsu_reg, &up->port); } - pci_set_drvdata(pdev, NULL); free_irq(pdev->irq, priv); pci_disable_device(pdev); } -- cgit v1.2.3 From b9465f4dcf0c261cdd68263ccade8dfc75ed51f9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 12 Sep 2013 15:35:01 +0900 Subject: serial: txx9: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_txx9.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index 440a962412da..90a080b1f9ee 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -1220,8 +1220,6 @@ static void pciserial_txx9_remove_one(struct pci_dev *dev) { struct uart_txx9_port *up = pci_get_drvdata(dev); - pci_set_drvdata(dev, NULL); - if (up) { serial_txx9_unregister_port(up->port.line); pci_disable_device(dev); -- cgit v1.2.3 From 66be084885979bf8718383846a156c9da56c5a5c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 12 Sep 2013 15:33:48 +0900 Subject: serial: 8250_pci: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index c810da7c7a88..515fd0ff4e4e 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -3520,8 +3520,6 @@ static void pciserial_remove_one(struct pci_dev *dev) { struct serial_private *priv = pci_get_drvdata(dev); - pci_set_drvdata(dev, NULL); - pciserial_remove_ports(priv); pci_disable_device(dev); -- cgit v1.2.3 From 59f8a62c25b9c2a53e7c359ba9ca611639a4c0b0 Mon Sep 17 00:00:00 2001 From: Qipan Li Date: Sat, 21 Sep 2013 09:02:10 +0800 Subject: serial: sirf: don't submit dma desc after timeout irqs occur In rx timeout ISR and tasklet, we don't issue new dma desc as rx_done ISR will do that. Signed-off-by: Qipan Li Signed-off-by: Barry Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sirfsoc_uart.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 61c1ad03db5b..f186a8fb8887 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -529,7 +529,7 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) while (sirfport->rx_completed != sirfport->rx_issued) { sirfsoc_uart_insert_rx_buf_to_tty(sirfport, SIRFSOC_RX_DMA_BUF_SIZE); - sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); + sirfport->rx_completed++; sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; } count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head, @@ -706,12 +706,19 @@ static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param) { struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; struct uart_port *port = &sirfport->port; + struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; + struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; unsigned long flags; spin_lock_irqsave(&sirfport->rx_lock, flags); while (sirfport->rx_completed != sirfport->rx_issued) { sirfsoc_uart_insert_rx_buf_to_tty(sirfport, SIRFSOC_RX_DMA_BUF_SIZE); - sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); + if (rd_regl(port, ureg->sirfsoc_int_en_reg) & + uint_en->sirfsoc_rx_timeout_en) + sirfsoc_rx_submit_one_dma_desc(port, + sirfport->rx_completed++); + else + sirfport->rx_completed++; sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; } spin_unlock_irqrestore(&sirfport->rx_lock, flags); -- cgit v1.2.3 From 4250b5d9a47e8281b964935d5fee6a32d4ccdedb Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 21 Sep 2013 04:04:35 -0400 Subject: OMAP/serial: Fix misnamed variable Fix misnamed variable to eliminate confusion. Signed-off-by: Alexey Pelykh Cc: Tony Lindgren Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 816d1a23f9d0..7e7da4066856 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -258,13 +258,13 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) static unsigned int serial_omap_get_divisor(struct uart_port *port, unsigned int baud) { - unsigned int divisor; + unsigned int mode; if (!serial_omap_baud_is_mode16(port, baud)) - divisor = 13; + mode = 13; else - divisor = 16; - return port->uartclk/(baud * divisor); + mode = 16; + return port->uartclk/(mode * baud); } static void serial_omap_enable_ms(struct uart_port *port) -- cgit v1.2.3 From 18d8519d35cb0b794d9b9c6f4ff7b97940a95bda Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 21 Sep 2013 04:10:54 -0400 Subject: OMAP/serial: Fix Mode13 vs Mode16 priority Make Mode16 more preferred than Mode13, to match TRM baudrates table. Signed-off-by: Alexey Pelykh Cc: Tony Lindgren Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 7e7da4066856..7b00520624f9 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -247,7 +247,7 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) if(baudAbsDiff16 < 0) baudAbsDiff16 = -baudAbsDiff16; - return (baudAbsDiff13 > baudAbsDiff16); + return (baudAbsDiff13 >= baudAbsDiff16); } /* -- cgit v1.2.3 From 7a95b815da307d66430f30d7b18dcddce62507bd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 23 Sep 2013 21:54:20 +0800 Subject: serial: sccnxp: missing uart_unregister_driver() on error in sccnxp_probe() Add the missing uart_unregister_driver() before return from sccnxp_probe() in the error handling case. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 49e9bbfe6cab..a447f71538ef 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -986,6 +986,7 @@ static int sccnxp_probe(struct platform_device *pdev) return 0; } + uart_unregister_driver(&s->uart); err_out: if (!IS_ERR(s->regulator)) return regulator_disable(s->regulator); -- cgit v1.2.3 From 216fce2e78acd6558b6c16b28295ed7a639dd2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 23 Sep 2013 17:53:32 +0200 Subject: serial: clps711x: drop needless devm_clk_put MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nice thing about devm_* is that the driver doesn't need to free the resources but the driver core takes care about that. These calls were introduced in commit c08f015 (serial: clps711x: Using CPU clock subsystem for getting base UART speed). Signed-off-by: Uwe Kleine-König Cc: Alexander Shiyan Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/clps711x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 7e4e4088471c..8d0b994357c8 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -459,7 +459,6 @@ static int uart_clps711x_probe(struct platform_device *pdev) ret = uart_register_driver(&s->uart); if (ret) { dev_err(&pdev->dev, "Registering UART driver failed\n"); - devm_clk_put(&pdev->dev, s->uart_clk); return ret; } @@ -487,7 +486,6 @@ static int uart_clps711x_remove(struct platform_device *pdev) for (i = 0; i < UART_CLPS711X_NR; i++) uart_remove_one_port(&s->uart, &s->port[i]); - devm_clk_put(&pdev->dev, s->uart_clk); uart_unregister_driver(&s->uart); return 0; -- cgit v1.2.3 From b15e5691cc98b5e17db8ba8a433a4ac78efbf590 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 27 Sep 2013 10:52:59 +0300 Subject: serial: 8250_pci: add support for Intel BayTrail Intel BayTrail has two HS-UARTs with 64 byte fifo, support for DMA and support for 16750 compatible Auto Flow Control. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 515fd0ff4e4e..d917bbb30484 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1324,6 +1324,120 @@ ce4100_serial_setup(struct serial_private *priv, return ret; } +#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a +#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c + +#define BYT_PRV_CLK 0x800 +#define BYT_PRV_CLK_EN (1 << 0) +#define BYT_PRV_CLK_M_VAL_SHIFT 1 +#define BYT_PRV_CLK_N_VAL_SHIFT 16 +#define BYT_PRV_CLK_UPDATE (1 << 31) + +#define BYT_GENERAL_REG 0x808 +#define BYT_GENERAL_DIS_RTS_N_OVERRIDE (1 << 3) + +#define BYT_TX_OVF_INT 0x820 +#define BYT_TX_OVF_INT_MASK (1 << 1) + +static void +byt_set_termios(struct uart_port *p, struct ktermios *termios, + struct ktermios *old) +{ + unsigned int baud = tty_termios_baud_rate(termios); + unsigned int m = 6912; + unsigned int n = 15625; + u32 reg; + + /* For baud rates 1M, 2M, 3M and 4M the dividers must be adjusted. */ + if (baud == 1000000 || baud == 2000000 || baud == 4000000) { + m = 64; + n = 100; + + p->uartclk = 64000000; + } else if (baud == 3000000) { + m = 48; + n = 100; + + p->uartclk = 48000000; + } else { + p->uartclk = 44236800; + } + + /* Reset the clock */ + reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT); + writel(reg, p->membase + BYT_PRV_CLK); + reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE; + writel(reg, p->membase + BYT_PRV_CLK); + + /* + * If auto-handshake mechanism is not enabled, + * disable rts_n override + */ + reg = readl(p->membase + BYT_GENERAL_REG); + reg &= ~BYT_GENERAL_DIS_RTS_N_OVERRIDE; + if (termios->c_cflag & CRTSCTS) + reg |= BYT_GENERAL_DIS_RTS_N_OVERRIDE; + writel(reg, p->membase + BYT_GENERAL_REG); + + serial8250_do_set_termios(p, termios, old); +} + +static bool byt_dma_filter(struct dma_chan *chan, void *param) +{ + return chan->chan_id == *(int *)param; +} + +static int +byt_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct uart_8250_dma *dma; + int ret; + + dma = devm_kzalloc(port->port.dev, sizeof(*dma), GFP_KERNEL); + if (!dma) + return -ENOMEM; + + switch (priv->dev->device) { + case PCI_DEVICE_ID_INTEL_BYT_UART1: + dma->rx_chan_id = 3; + dma->tx_chan_id = 2; + break; + case PCI_DEVICE_ID_INTEL_BYT_UART2: + dma->rx_chan_id = 5; + dma->tx_chan_id = 4; + break; + default: + return -EINVAL; + } + + dma->rxconf.slave_id = dma->rx_chan_id; + dma->rxconf.src_maxburst = 16; + + dma->txconf.slave_id = dma->tx_chan_id; + dma->txconf.dst_maxburst = 16; + + dma->fn = byt_dma_filter; + dma->rx_param = &dma->rx_chan_id; + dma->tx_param = &dma->tx_chan_id; + + ret = pci_default_setup(priv, board, port, idx); + port->port.iotype = UPIO_MEM; + port->port.type = PORT_16550A; + port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + port->port.set_termios = byt_set_termios; + port->port.fifosize = 64; + port->tx_loadsz = 64; + port->dma = dma; + port->capabilities = UART_CAP_FIFO | UART_CAP_AFE; + + /* Disable Tx counter interrupts */ + writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT); + + return ret; +} + static int pci_omegapci_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1662,6 +1776,20 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = kt_serial_setup, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_BYT_UART1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_BYT_UART2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, /* * ITE */ @@ -2449,6 +2577,7 @@ enum pci_board_num_t { pbn_ADDIDATA_PCIe_4_3906250, pbn_ADDIDATA_PCIe_8_3906250, pbn_ce4100_1_115200, + pbn_byt, pbn_omegapci, pbn_NETMOS9900_2s_115200, pbn_brcm_trumanage, @@ -3185,6 +3314,13 @@ static struct pciserial_board pci_boards[] = { .base_baud = 921600, .reg_shift = 2, }, + [pbn_byt] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 2764800, + .uart_offset = 0x80, + .reg_shift = 2, + }, [pbn_omegapci] = { .flags = FL_BASE0, .num_ports = 8, @@ -4846,6 +4982,15 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_ce4100_1_115200 }, + /* Intel BayTrail */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, /* * Cronyx Omega PCI -- cgit v1.2.3 From 058555739166561b97313123521574f0a9b2c9d7 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 27 Sep 2013 10:21:07 +0300 Subject: serial: 8250_dw: fix broken function call The stub for dw8250_probe_acpi() is missing an argument. Reported-by: kbuild test robot Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 8edf7697fdb2..d04a037d6b6f 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -278,7 +278,8 @@ static int dw8250_probe_acpi(struct uart_8250_port *up, return 0; } #else -static inline int dw8250_probe_acpi(struct uart_8250_port *up) +static inline int dw8250_probe_acpi(struct uart_8250_port *up, + struct dw8250_data *data) { return -ENODEV; } -- cgit v1.2.3 From af8c5b8debb04633170ab4c95143dbcdd941cfa8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 28 Sep 2013 13:01:59 -0700 Subject: serial: 8250_pci: clean up printk() calls Move the printk() calls to to dev_*() instead, to tie into the dynamic debugging infrastructure. Also change some "raw" printk() calls to dev_err() to provide a better error message to userspace so it can properly identify the device and not just have to guess. Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 40 ++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index d917bbb30484..0774c02d6c49 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -9,6 +9,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. */ +#undef DEBUG #include #include #include @@ -27,8 +28,6 @@ #include "8250.h" -#undef SERIAL_DEBUG_PCI - /* * init function returns: * > 0 - number of ports @@ -63,7 +62,7 @@ static int pci_default_setup(struct serial_private*, static void moan_device(const char *str, struct pci_dev *dev) { - printk(KERN_WARNING + dev_err(&dev->dev, "%s: %s\n" "Please send the output of lspci -vv, this\n" "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" @@ -233,7 +232,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev) /* is firmware started? */ pci_read_config_dword(dev, 0x44, (void *)&oldval); if (oldval == 0x00001000L) { /* RESET value */ - printk(KERN_DEBUG "Local i960 firmware missing"); + dev_dbg(&dev->dev, "Local i960 firmware missing\n"); return -ENODEV; } return 0; @@ -827,7 +826,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) if (sub_serports > 0) { return sub_serports; } else { - printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); return 0; } } @@ -931,7 +930,7 @@ static int pci_ite887x_init(struct pci_dev *dev) } if (!inta_addr[i]) { - printk(KERN_ERR "ite887x: could not find iobase\n"); + dev_err(&dev->dev, "ite887x: could not find iobase\n"); return -ENODEV; } @@ -1024,9 +1023,9 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) /* Tornado device */ if (deviceID == 0x07000200) { number_uarts = ioread8(p + 4); - printk(KERN_DEBUG + dev_dbg(&dev->dev, "%d ports detected on Oxford PCI Express device\n", - number_uarts); + number_uarts); } pci_iounmap(dev, p); return number_uarts; @@ -1463,12 +1462,10 @@ static int skip_tx_en_setup(struct serial_private *priv, struct uart_8250_port *port, int idx) { port->port.flags |= UPF_NO_TXEN_TEST; - printk(KERN_DEBUG "serial8250: skipping TxEn test for device " - "[%04x:%04x] subsystem [%04x:%04x]\n", - priv->dev->vendor, - priv->dev->device, - priv->dev->subsystem_vendor, - priv->dev->subsystem_device); + dev_dbg(&priv->dev->dev, + "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n", + priv->dev->vendor, priv->dev->device, + priv->dev->subsystem_vendor, priv->dev->subsystem_device); return pci_default_setup(priv, board, port, idx); } @@ -3498,14 +3495,15 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) if (quirk->setup(priv, board, &uart, i)) break; -#ifdef SERIAL_DEBUG_PCI - printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n", - uart.port.iobase, uart.port.irq, uart.port.iotype); -#endif + dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n", + uart.port.iobase, uart.port.irq, uart.port.iotype); priv->line[i] = serial8250_register_8250_port(&uart); if (priv->line[i] < 0) { - printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); + dev_err(&dev->dev, + "Couldn't register serial port %lx, irq %d, type %d, error %d\n", + uart.port.iobase, uart.port.irq, + uart.port.iotype, priv->line[i]); break; } } @@ -3598,7 +3596,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) } if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { - printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", + dev_err(&dev->dev, "invalid driver_data: %ld\n", ent->driver_data); return -EINVAL; } @@ -3689,7 +3687,7 @@ static int pciserial_resume_one(struct pci_dev *dev) err = pci_enable_device(dev); /* FIXME: We cannot simply error out here */ if (err) - printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n"); + dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n"); pciserial_resume_ports(priv); } return 0; -- cgit v1.2.3 From c49436b657d0a56a6ad90d14a7c3041add7cf64d Mon Sep 17 00:00:00 2001 From: Tim Kryger Date: Tue, 1 Oct 2013 10:18:08 -0700 Subject: serial: 8250_dw: Improve unwritable LCR workaround When configured with UART_16550_COMPATIBLE=NO or in versions prior to the introduction of this option, the Designware UART will ignore writes to the LCR if the UART is busy. The current workaround saves a copy of the last written LCR and re-writes it in the ISR for a special interrupt that is raised when a write was ignored. Unfortunately, interrupts are typically disabled prior to performing a sequence of register writes that include the LCR so the point at which the retry occurs is too late. An example is serial8250_do_set_termios() where an ignored LCR write results in the baud divisor not being set and instead a garbage character is sent out the transmitter. Furthermore, since serial_port_out() offers no way to indicate failure, a serious effort must be made to ensure that the LCR is actually updated before returning back to the caller. This is difficult, however, as a UART that was busy during the first attempt is likely to still be busy when a subsequent attempt is made unless some extra action is taken. This updated workaround reads back the LCR after each write to confirm that the new value was accepted by the hardware. Should the hardware ignore a write, the TX/RX FIFOs are cleared and the receive buffer read before attempting to rewrite the LCR out of the hope that doing so will force the UART into an idle state. While this may seem unnecessarily aggressive, writes to the LCR are used to change the baud rate, parity, stop bit, or data length so the data that may be lost is likely not important. Admittedly, this is far from ideal but it seems to be the best that can be done given the hardware limitations. Lastly, the revised workaround doesn't touch the LCR in the ISR, so it avoids the possibility of a "serial8250: too much work for irq" lock up. This problem is rare in real situations but can be reproduced easily by wiring up two UARTs and running the following commands. # stty -F /dev/ttyS1 echo # stty -F /dev/ttyS2 echo # cat /dev/ttyS1 & [1] 375 # echo asdf > /dev/ttyS1 asdf [ 27.700000] serial8250: too much work for irq96 [ 27.700000] serial8250: too much work for irq96 [ 27.710000] serial8250: too much work for irq96 [ 27.710000] serial8250: too much work for irq96 [ 27.720000] serial8250: too much work for irq96 [ 27.720000] serial8250: too much work for irq96 [ 27.730000] serial8250: too much work for irq96 [ 27.730000] serial8250: too much work for irq96 [ 27.740000] serial8250: too much work for irq96 Signed-off-by: Tim Kryger Reviewed-by: Matt Porter Reviewed-by: Markus Mayer Reviewed-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 41 ++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d04a037d6b6f..4658e3e0ec42 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -57,7 +57,6 @@ struct dw8250_data { u8 usr_reg; - int last_lcr; int last_mcr; int line; struct clk *clk; @@ -77,17 +76,33 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) return value; } +static void dw8250_force_idle(struct uart_port *p) +{ + serial8250_clear_and_reinit_fifos(container_of + (p, struct uart_8250_port, port)); + (void)p->serial_in(p, UART_RX); +} + static void dw8250_serial_out(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - if (offset == UART_LCR) - d->last_lcr = value; - if (offset == UART_MCR) d->last_mcr = value; writeb(value, p->membase + (offset << p->regshift)); + + /* Make sure LCR write wasn't ignored */ + if (offset == UART_LCR) { + int tries = 1000; + while (tries--) { + if (value == p->serial_in(p, UART_LCR)) + return; + dw8250_force_idle(p); + writeb(value, p->membase + (UART_LCR << p->regshift)); + } + dev_err(p->dev, "Couldn't set LCR to %d\n", value); + } } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) @@ -108,13 +123,22 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - if (offset == UART_LCR) - d->last_lcr = value; - if (offset == UART_MCR) d->last_mcr = value; writel(value, p->membase + (offset << p->regshift)); + + /* Make sure LCR write wasn't ignored */ + if (offset == UART_LCR) { + int tries = 1000; + while (tries--) { + if (value == p->serial_in(p, UART_LCR)) + return; + dw8250_force_idle(p); + writel(value, p->membase + (UART_LCR << p->regshift)); + } + dev_err(p->dev, "Couldn't set LCR to %d\n", value); + } } static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) @@ -132,9 +156,8 @@ static int dw8250_handle_irq(struct uart_port *p) if (serial8250_handle_irq(p, iir)) { return 1; } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { - /* Clear the USR and write the LCR again. */ + /* Clear the USR */ (void)p->serial_in(p, d->usr_reg); - p->serial_out(p, UART_LCR, d->last_lcr); return 1; } -- cgit v1.2.3 From 7ea816a0c353b668688ee6c79f5bbc5223d73f41 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 3 Oct 2013 11:46:28 +0200 Subject: serial: Remove unnecessary amba_set_drvdata() Driver core clears the driver data to NULL after device_release or on probe failure, so just remove it from here. Driver core change: "device-core: Ensure drvdata = NULL when no driver is bound" (sha1: 0998d0631001288a5974afc0b2a5f568bcdecb4d) Signed-off-by: Michal Simek Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl010.c | 3 --- drivers/tty/serial/amba-pl011.c | 3 --- 2 files changed, 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 8b90f0b6dfdf..33bd8606be62 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -728,7 +728,6 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) amba_set_drvdata(dev, uap); ret = uart_add_one_port(&amba_reg, &uap->port); if (ret) { - amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; clk_put(uap->clk); unmap: @@ -745,8 +744,6 @@ static int pl010_remove(struct amba_device *dev) struct uart_amba_port *uap = amba_get_drvdata(dev); int i; - amba_set_drvdata(dev, NULL); - uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index aaa22867e656..7203864992a5 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2147,7 +2147,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) amba_set_drvdata(dev, uap); ret = uart_add_one_port(&amba_reg, &uap->port); if (ret) { - amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; pl011_dma_remove(uap); } @@ -2160,8 +2159,6 @@ static int pl011_remove(struct amba_device *dev) struct uart_amba_port *uap = amba_get_drvdata(dev); int i; - amba_set_drvdata(dev, NULL); - uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) -- cgit v1.2.3 From 9987f76ad286887978803ece6cdcf34582279a29 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Thu, 3 Oct 2013 09:32:03 +0200 Subject: serial: mxs-auart: set the FIFO size to DMA buffer size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When DMA is enabled (with hardware flow control enabled) the FIFO size must be set to the size of the DMA buffer, as this is the size the tty subsystem can use. Signed-off-by: Hector Palacios Reviewed-by: Marek Vasut Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 10e9d70b5c40..d8b6fee77a03 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -39,6 +39,7 @@ #include #define MXS_AUART_PORTS 5 +#define MXS_AUART_FIFO_SIZE 16 #define AUART_CTRL0 0x00000000 #define AUART_CTRL0_SET 0x00000004 @@ -548,6 +549,9 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s) s->flags |= MXS_AUART_DMA_ENABLED; dev_dbg(s->dev, "enabled the DMA support."); + /* The DMA buffer is now the FIFO the TTY subsystem can use */ + s->port.fifosize = UART_XMIT_SIZE; + return 0; err_out: @@ -741,6 +745,9 @@ static int mxs_auart_startup(struct uart_port *u) writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, u->membase + AUART_INTR); + /* Reset FIFO size (it could have changed if DMA was enabled) */ + u->fifosize = MXS_AUART_FIFO_SIZE; + /* * Enable fifo so all four bytes of a DMA word are written to * output (otherwise, only the LSB is written, ie. 1 in 4 bytes) @@ -1056,7 +1063,7 @@ static int mxs_auart_probe(struct platform_device *pdev) s->port.membase = ioremap(r->start, resource_size(r)); s->port.ops = &mxs_auart_ops; s->port.iotype = UPIO_MEM; - s->port.fifosize = 16; + s->port.fifosize = MXS_AUART_FIFO_SIZE; s->port.uartclk = clk_get_rate(s->clk); s->port.type = PORT_IMX; s->port.dev = s->dev = &pdev->dev; -- cgit v1.2.3 From cf81e054d63bca1da899057802e561abc2acecce Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Sun, 6 Oct 2013 08:30:17 +0200 Subject: serial: tegra: remove deprecated IRQF_DISABLED This patch proposes to remove the use of the IRQF_DISABLED flag It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 0489a2bdcdf9..dfe79ccc4fb3 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -1018,7 +1018,7 @@ static int tegra_uart_startup(struct uart_port *u) goto fail_hw_init; } - ret = request_irq(u->irq, tegra_uart_isr, IRQF_DISABLED, + ret = request_irq(u->irq, tegra_uart_isr, 0, dev_name(u->dev), tup); if (ret < 0) { dev_err(u->dev, "Failed to register ISR for IRQ %d\n", u->irq); -- cgit v1.2.3 From 190c6cc32843844722a9897fac1929d57517db14 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Sun, 6 Oct 2013 08:27:18 +0200 Subject: serial: bfin_uart: remove deprecated IRQF_DISABLED This patch proposes to remove the use of the IRQF_DISABLED flag It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 74749a6d3565..8f9b3495ef5d 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -726,7 +726,7 @@ static int bfin_serial_startup(struct uart_port *port) #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS if (uart->cts_pin >= 0) { if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int, - IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { + 0, "BFIN_UART_MODEM_STATUS", uart)) { uart->cts_pin = -1; dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n"); } -- cgit v1.2.3 From 12082ba2cb053e547dd3faef7af4842f2abe7c19 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Tue, 8 Oct 2013 13:24:28 +0900 Subject: serial8250-em: convert to clk_prepare/unprepare Add calls to clk_prepare and unprepare so that EMMA Mobile EV2 can migrate to the common clock framework. Signed-off-by: Shinya Kuribayashi [takashi.yoshii.ze@renesas.com: edited for conflicts] Signed-off-by: Takashi Yoshii Acked-by: Greg Kroah-Hartman Acked-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Simon Horman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_em.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 5f3bba12c159..d1a9078003bd 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -122,7 +122,7 @@ static int serial8250_em_probe(struct platform_device *pdev) up.port.dev = &pdev->dev; up.port.private_data = priv; - clk_enable(priv->sclk); + clk_prepare_enable(priv->sclk); up.port.uartclk = clk_get_rate(priv->sclk); up.port.iotype = UPIO_MEM32; @@ -134,7 +134,7 @@ static int serial8250_em_probe(struct platform_device *pdev) ret = serial8250_register_8250_port(&up); if (ret < 0) { dev_err(&pdev->dev, "unable to register 8250 port\n"); - clk_disable(priv->sclk); + clk_disable_unprepare(priv->sclk); return ret; } @@ -148,7 +148,7 @@ static int serial8250_em_remove(struct platform_device *pdev) struct serial8250_em_priv *priv = platform_get_drvdata(pdev); serial8250_unregister_port(priv->line); - clk_disable(priv->sclk); + clk_disable_unprepare(priv->sclk); return 0; } -- cgit v1.2.3 From 09238443c61e58f7fac8a3892b14b1bee40b4316 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 9 Oct 2013 10:39:16 +0800 Subject: serial: mrst_max3110: Check the irq number before enable/disabe irq in PM hooks We should check the validity of the irq number before calling disable_irq() and enable_irq() in the suspend/resume function, as "max->irq == 0" means the irq is not enabled for max3110 device, otherwise it will hurt device whose irq number is really 0. Signed-off-by: Feng Tang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mrst_max3110.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index a67e7081f001..ee77e7366ed6 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -749,7 +749,8 @@ static int serial_m3110_suspend(struct device *dev) struct spi_device *spi = to_spi_device(dev); struct uart_max3110 *max = spi_get_drvdata(spi); - disable_irq(max->irq); + if (max->irq > 0) + disable_irq(max->irq); uart_suspend_port(&serial_m3110_reg, &max->port); max3110_out(max, max->cur_conf | WC_SW_SHDI); return 0; @@ -762,7 +763,8 @@ static int serial_m3110_resume(struct device *dev) max3110_out(max, max->cur_conf); uart_resume_port(&serial_m3110_reg, &max->port); - enable_irq(max->irq); + if (max->irq > 0) + enable_irq(max->irq); return 0; } -- cgit v1.2.3 From b6951b8a63e8764558c066369a6317bfe15dca55 Mon Sep 17 00:00:00 2001 From: Bin Gao Date: Wed, 9 Oct 2013 10:39:17 +0800 Subject: serial: mrst_max3110: Fix race condition between spi transfers There is a race between termios configuration and xmit that can cause the intel_mid_ssp_spi driver to stall. Serializing spi transactions fixes the problem. Signed-off-by: Bin Gao Signed-off-by: Feng Tang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mrst_max3110.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index ee77e7366ed6..565779dc7aac 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -61,6 +61,7 @@ struct uart_max3110 { struct task_struct *main_thread; struct task_struct *read_thread; struct mutex thread_mutex; + struct mutex io_mutex; u32 baud; u16 cur_conf; @@ -90,6 +91,7 @@ static int max3110_write_then_read(struct uart_max3110 *max, struct spi_transfer x; int ret; + mutex_lock(&max->io_mutex); spi_message_init(&message); memset(&x, 0, sizeof x); x.len = len; @@ -104,6 +106,7 @@ static int max3110_write_then_read(struct uart_max3110 *max, /* Do the i/o */ ret = spi_sync(spi, &message); + mutex_unlock(&max->io_mutex); return ret; } @@ -805,6 +808,7 @@ static int serial_m3110_probe(struct spi_device *spi) max->irq = (u16)spi->irq; mutex_init(&max->thread_mutex); + mutex_init(&max->io_mutex); max->word_7bits = 0; max->parity = 0; -- cgit v1.2.3 From fc811472c2167cc885b7af422b074cc9224f3a93 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 8 Oct 2013 16:14:21 -0700 Subject: tty: Remove unnecessary semicolons These aren't necessary after switch and while blocks. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 4 ++-- drivers/tty/serial/ip22zilog.c | 2 +- drivers/tty/serial/max310x.c | 2 +- drivers/tty/serial/pmac_zilog.c | 2 +- drivers/tty/serial/sunsab.c | 2 +- drivers/tty/serial/sunsu.c | 2 +- drivers/tty/serial/sunzilog.c | 6 +++--- drivers/tty/serial/ucc_uart.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 8f9b3495ef5d..869ceba2ec57 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -680,7 +680,7 @@ static int bfin_serial_startup(struct uart_port *port) default: uart_dma_ch_rx = uart_dma_ch_tx = 0; break; - }; + } if (uart_dma_ch_rx && request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { @@ -765,7 +765,7 @@ static void bfin_serial_shutdown(struct uart_port *port) break; default: break; - }; + } #endif free_irq(uart->rx_irq, uart); free_irq(uart->tx_irq, uart); diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index cb3c81eb0996..1d9420548e16 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -832,7 +832,7 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, up->curregs[5] |= Tx8; up->parity_mask = 0xff; break; - }; + } up->curregs[4] &= ~0x0c; if (cflag & CSTOPB) up->curregs[4] |= SB2; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index b2e707aa603a..8d71e4047bb3 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -690,7 +690,7 @@ static void max310x_handle_tx(struct uart_port *port) max310x_port_write(port, MAX310X_THR_REG, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - }; + } } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index f87f1a0c8c6e..95917cefe14f 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1072,7 +1072,7 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag, uap->curregs[5] |= Tx8; uap->parity_mask = 0xff; break; - }; + } uap->curregs[4] &= ~(SB_MASK); if (cflag & CSTOPB) uap->curregs[4] |= SB2; diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 5d6136b2a04a..380fb5355cb2 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -894,7 +894,7 @@ static int sunsab_console_setup(struct console *con, char *options) case B115200: baud = 115200; break; case B230400: baud = 230400; break; case B460800: baud = 460800; break; - }; + } /* * Temporary fix. diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 699cc1b5f6aa..db79b76f5c8e 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -522,7 +522,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) serio_interrupt(&up->serio, ch, 0); #endif break; - }; + } } } while (serial_in(up, UART_LSR) & UART_LSR_DR); } diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 135a15203532..45a8c6aa5837 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -319,7 +319,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, serio_interrupt(&up->serio, ch, 0); #endif break; - }; + } } } @@ -897,7 +897,7 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, up->curregs[R5] |= Tx8; up->parity_mask = 0xff; break; - }; + } up->curregs[R4] &= ~0x0c; if (cflag & CSTOPB) up->curregs[R4] |= SB2; @@ -1239,7 +1239,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) default: case B9600: baud = 9600; break; case B19200: baud = 19200; break; case B38400: baud = 38400; break; - }; + } brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 88317482b81f..2fd1e1789811 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -269,7 +269,7 @@ static unsigned int qe_uart_tx_empty(struct uart_port *port) return 1; bdp++; - }; + } } /* -- cgit v1.2.3 From e701bcadb254caf555d64af9662d5d5fbccade9d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Oct 2013 09:20:08 +0200 Subject: serial: omap: delete .set_wake callback This callback is unused by the serial core since pre-git days and is not coming back. Delete it. Enabling wakeup on the OMAP serial driver is done through other runpaths these days. Cc: Tony Lindgren Cc: Kevin Hilman Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 7b00520624f9..c715778a745c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1060,15 +1060,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); } -static int serial_omap_set_wake(struct uart_port *port, unsigned int state) -{ - struct uart_omap_port *up = to_uart_omap_port(port); - - serial_omap_enable_wakeup(up, state); - - return 0; -} - static void serial_omap_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) @@ -1401,7 +1392,6 @@ static struct uart_ops serial_omap_pops = { .shutdown = serial_omap_shutdown, .set_termios = serial_omap_set_termios, .pm = serial_omap_pm, - .set_wake = serial_omap_set_wake, .type = serial_omap_type, .release_port = serial_omap_release_port, .request_port = serial_omap_request_port, -- cgit v1.2.3 From adedb750727cdc33aa5074a7a3e68d47f1debc83 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Oct 2013 09:20:26 +0200 Subject: serial: sa1100: delete .set_wake callback This callback is unused by the serial core since pre-git days and is not coming back. Delete it. Enabling wakeup on the SA1100 platforms should be done in the suspend() callback so the platform hook is left in the serial port struct for later enablement. Cc: Russell King Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sa1100.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index ba25722a7131..753d4525b367 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -647,7 +647,10 @@ void sa1100_register_uart_fns(struct sa1100_port_fns *fns) sa1100_pops.set_mctrl = fns->set_mctrl; sa1100_pops.pm = fns->pm; - sa1100_pops.set_wake = fns->set_wake; + /* + * FIXME: fns->set_wake is unused - this should be called from + * the suspend() callback if device_may_wakeup(dev)) is set. + */ } void __init sa1100_register_uart(int idx, int port) -- cgit v1.2.3 From c38c4454d8b880f095faeb279dc7121f5789a06f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Oct 2013 09:20:35 +0200 Subject: serial: mpc52xx: remove reference to .set_wake() This callback is gone and not coming back, so will not be supported later. Cc: Gerhard Sittig Cc: Anatolij Gustschin Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpc52xx_uart.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index e05a3b1a87c7..ec06505e3ae6 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -1301,7 +1301,6 @@ static struct uart_ops mpc52xx_uart_ops = { .shutdown = mpc52xx_uart_shutdown, .set_termios = mpc52xx_uart_set_termios, /* .pm = mpc52xx_uart_pm, Not supported yet */ -/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */ .type = mpc52xx_uart_type, .release_port = mpc52xx_uart_release_port, .request_port = mpc52xx_uart_request_port, -- cgit v1.2.3 From 359250105407bca72c0402ecb1bbb1d7636e0e82 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Oct 2013 09:20:43 +0200 Subject: serial: pch_uart: remove reference to .set_wake() This callback is gone and not coming back, so will not be supported later. Cc: Johan Hovold Acked-by: Darren Hart Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 87f25def0b41..0aa2b528ef3d 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1614,7 +1614,6 @@ static struct uart_ops pch_uart_ops = { .shutdown = pch_uart_shutdown, .set_termios = pch_uart_set_termios, /* .pm = pch_uart_pm, Not supported yet */ -/* .set_wake = pch_uart_set_wake, Not supported yet */ .type = pch_uart_type, .release_port = pch_uart_release_port, .request_port = pch_uart_request_port, -- cgit v1.2.3 From eb56b7edae6ba2bfd3a07e59ea82195e2c1c28ec Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 11 Oct 2013 18:30:58 +0800 Subject: serial: imx: implement the flush_buffer hook The current driver does not implement the flush_buffer hook for uart_ops. When we enable the DMA for the driver, and test it with Bluetooth, we may meet the following bug for TX: [1] User application may call the flush operation at any time. The uart_flush_buffer() calls the uart_circ_clear() to set the xmit->head and xmit->tail with 0. [2] The TX DMA callback can be called at any time too. The dma_tx_call() will update the xmit->tail. If [2] occurs just after the [1], we will get the wrong xmit->tail. This patch implements the flush_buffer hook to fix this issue. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c07d9bb39695..708ba899258d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1303,6 +1303,16 @@ static void imx_shutdown(struct uart_port *port) clk_disable_unprepare(sport->clk_ipg); } +static void imx_flush_buffer(struct uart_port *port) +{ + struct imx_port *sport = (struct imx_port *)port; + + if (sport->dma_is_enabled) { + sport->tx_bytes = 0; + dmaengine_terminate_all(sport->dma_chan_tx); + } +} + static void imx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) @@ -1623,6 +1633,7 @@ static struct uart_ops imx_pops = { .break_ctl = imx_break_ctl, .startup = imx_startup, .shutdown = imx_shutdown, + .flush_buffer = imx_flush_buffer, .set_termios = imx_set_termios, .type = imx_type, .release_port = imx_release_port, -- cgit v1.2.3 From 1ce43e58d4d57acc9782d97270ec70a91a177abc Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 11 Oct 2013 18:30:59 +0800 Subject: serial: imx: check the DMA for imx_tx_empty Assume the following situation: If the DMA is enabled, and the a TX DMA operation is working, But we have not issued the TX DMA operation (or we have issued the TX DMA operation with dma_async_issue_pending(), but the DMA has not started to move the data from the memory to the TXFIFO). At this time, we may get the wrong status of the transmitter when we call the imx_tx_empty. In such situation, only check the USR2_TXDC does not enough for us. This patch checks the DMA's situation, and return 0 when the TX DMA is working. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 708ba899258d..c6c3b160dac7 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -795,8 +795,15 @@ static irqreturn_t imx_int(int irq, void *dev_id) static unsigned int imx_tx_empty(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; + unsigned int ret; - return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; + ret = (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; + + /* If the TX DMA is working, return 0. */ + if (sport->dma_is_enabled && sport->dma_is_txing) + ret = 0; + + return ret; } /* -- cgit v1.2.3 From 947c74eba85bff743bc15adbdd9193ffff60c29f Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 11 Oct 2013 18:31:00 +0800 Subject: serial: imx: fix the wrong number of scatterlist entries when xmit->head is 0 When the (xmit->tail > xmit->head) is true and the xmit->head is 0, we only need one DMA scatterlist in actually. Current code uses two DMA scatterlists in this case, this is obviously wrong. This patch fixes it. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c6c3b160dac7..cadf7e5848b2 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -532,7 +532,7 @@ static void dma_tx_work(struct work_struct *w) return; } - if (xmit->tail > xmit->head) { + if (xmit->tail > xmit->head && xmit->head > 0) { sport->dma_tx_nents = 2; sg_init_table(sgl, 2); sg_set_buf(sgl, xmit->buf + xmit->tail, -- cgit v1.2.3 From f0ef8834b280ebb6c271f155ea040bf4af6c1881 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 11 Oct 2013 18:31:01 +0800 Subject: serial: imx: use the dmaengine_tx_status Use the dmaengine_tx_status to simplify the code, do not change any logic. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index cadf7e5848b2..13c2c2d09cac 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -521,7 +521,7 @@ static void dma_tx_work(struct work_struct *w) unsigned long flags; int ret; - status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL); + status = dmaengine_tx_status(chan, (dma_cookie_t)0, NULL); if (DMA_IN_PROGRESS == status) return; @@ -926,7 +926,7 @@ static void dma_rx_callback(void *data) /* unmap it first */ dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE); - status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state); + status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); count = RX_BUF_SIZE - state.residue; dev_dbg(sport->port.dev, "We get %d bytes.\n", count); -- cgit v1.2.3 From 7cb92fd2a0515ea2ae905bf6c90a84aed2b78ffb Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Tue, 15 Oct 2013 15:23:40 +0800 Subject: serial: imx: optimization: remove the workqueues for DMA I worried that the delay of the sdma_run_channel0() maybe too long for interrupt context, so I added the workqueues for RX/TX DMA. But tested with bluetooth device, I find that the delay of sdma_run_channel0() is about 8us (tested in imx6dl sabreauto board). I think the delay is acceptable. This patch removes the RX/TX workqueues for DMA, it makes the code more clear. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 54 +++++++++--------------------------------------- 1 file changed, 10 insertions(+), 44 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 13c2c2d09cac..bb84f8d4c54e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -223,8 +223,7 @@ struct imx_port { struct dma_chan *dma_chan_rx, *dma_chan_tx; struct scatterlist rx_sgl, tx_sgl[2]; void *rx_buf; - unsigned int rx_bytes, tx_bytes; - struct work_struct tsk_dma_rx, tsk_dma_tx; + unsigned int tx_bytes; unsigned int dma_tx_nents; wait_queue_head_t dma_wait; }; @@ -505,32 +504,23 @@ static void dma_tx_callback(void *data) dev_dbg(sport->port.dev, "exit in %s.\n", __func__); return; } - - schedule_work(&sport->tsk_dma_tx); } -static void dma_tx_work(struct work_struct *w) +static void imx_dma_tx(struct imx_port *sport) { - struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx); struct circ_buf *xmit = &sport->port.state->xmit; struct scatterlist *sgl = sport->tx_sgl; struct dma_async_tx_descriptor *desc; struct dma_chan *chan = sport->dma_chan_tx; struct device *dev = sport->port.dev; enum dma_status status; - unsigned long flags; int ret; status = dmaengine_tx_status(chan, (dma_cookie_t)0, NULL); if (DMA_IN_PROGRESS == status) return; - spin_lock_irqsave(&sport->port.lock, flags); sport->tx_bytes = uart_circ_chars_pending(xmit); - if (sport->tx_bytes == 0) { - spin_unlock_irqrestore(&sport->port.lock, flags); - return; - } if (xmit->tail > xmit->head && xmit->head > 0) { sport->dma_tx_nents = 2; @@ -542,7 +532,6 @@ static void dma_tx_work(struct work_struct *w) sport->dma_tx_nents = 1; sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); } - spin_unlock_irqrestore(&sport->port.lock, flags); ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); if (ret == 0) { @@ -609,11 +598,7 @@ static void imx_start_tx(struct uart_port *port) } if (sport->dma_is_enabled) { - /* - * We may in the interrupt context, so arise a work_struct to - * do the real job. - */ - schedule_work(&sport->tsk_dma_tx); + imx_dma_tx(sport); return; } @@ -732,6 +717,7 @@ out: return IRQ_HANDLED; } +static int start_rx_dma(struct imx_port *sport); /* * If the RXFIFO is filled with some data, and then we * arise a DMA operation to receive them. @@ -750,7 +736,7 @@ static void imx_dma_rxint(struct imx_port *sport) writel(temp, sport->port.membase + UCR1); /* tell the DMA to receive the data. */ - schedule_work(&sport->tsk_dma_rx); + start_rx_dma(sport); } } @@ -872,22 +858,6 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) } #define RX_BUF_SIZE (PAGE_SIZE) -static int start_rx_dma(struct imx_port *sport); -static void dma_rx_work(struct work_struct *w) -{ - struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx); - struct tty_port *port = &sport->port.state->port; - - if (sport->rx_bytes) { - tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes); - tty_flip_buffer_push(port); - sport->rx_bytes = 0; - } - - if (sport->dma_is_rxing) - start_rx_dma(sport); -} - static void imx_rx_dma_done(struct imx_port *sport) { unsigned long temp; @@ -919,6 +889,7 @@ static void dma_rx_callback(void *data) struct imx_port *sport = data; struct dma_chan *chan = sport->dma_chan_rx; struct scatterlist *sgl = &sport->rx_sgl; + struct tty_port *port = &sport->port.state->port; struct dma_tx_state state; enum dma_status status; unsigned int count; @@ -931,8 +902,10 @@ static void dma_rx_callback(void *data) dev_dbg(sport->port.dev, "We get %d bytes.\n", count); if (count) { - sport->rx_bytes = count; - schedule_work(&sport->tsk_dma_rx); + tty_insert_flip_string(port, sport->rx_buf, count); + tty_flip_buffer_push(port); + + start_rx_dma(sport); } else imx_rx_dma_done(sport); } @@ -1014,7 +987,6 @@ static int imx_uart_dma_init(struct imx_port *sport) ret = -ENOMEM; goto err; } - sport->rx_bytes = 0; /* Prepare for TX : */ sport->dma_chan_tx = dma_request_slave_channel(dev, "tx"); @@ -1045,11 +1017,7 @@ err: static void imx_enable_dma(struct imx_port *sport) { unsigned long temp; - struct tty_port *port = &sport->port.state->port; - port->low_latency = 1; - INIT_WORK(&sport->tsk_dma_tx, dma_tx_work); - INIT_WORK(&sport->tsk_dma_rx, dma_rx_work); init_waitqueue_head(&sport->dma_wait); /* set UCR1 */ @@ -1070,7 +1038,6 @@ static void imx_enable_dma(struct imx_port *sport) static void imx_disable_dma(struct imx_port *sport) { unsigned long temp; - struct tty_port *port = &sport->port.state->port; /* clear UCR1 */ temp = readl(sport->port.membase + UCR1); @@ -1088,7 +1055,6 @@ static void imx_disable_dma(struct imx_port *sport) writel(temp, sport->port.membase + UCR4); sport->dma_is_enabled = 0; - port->low_latency = 0; } /* half the RX buffer size */ -- cgit v1.2.3 From 2c62a3c899805be7f054847d80210183e4a982d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Oct 2013 10:44:26 -0700 Subject: serial: 8250_pci: add support for Fintek 4, 8, and 12 port cards This adds support for Fintek's 4, 8, and 12 port PCIE serial cards. Thanks to Fintek for the sample devices, and the spec needed in order to implement this. Cc: Amanda Ying Cc: Felix Shih Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0774c02d6c49..4ea45c15388c 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1457,6 +1457,71 @@ pci_brcm_trumanage_setup(struct serial_private *priv, return ret; } +static int pci_fintek_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct pci_dev *pdev = priv->dev; + unsigned long base; + unsigned long iobase; + unsigned long ciobase = 0; + u8 config_base; + + /* + * We are supposed to be able to read these from the PCI config space, + * but the values there don't seem to match what we need to use, so + * just use these hard-coded values for now, as they are correct. + */ + switch (idx) { + case 0: iobase = 0xe000; config_base = 0x40; break; + case 1: iobase = 0xe008; config_base = 0x48; break; + case 2: iobase = 0xe010; config_base = 0x50; break; + case 3: iobase = 0xe018; config_base = 0x58; break; + case 4: iobase = 0xe020; config_base = 0x60; break; + case 5: iobase = 0xe028; config_base = 0x68; break; + case 6: iobase = 0xe030; config_base = 0x70; break; + case 7: iobase = 0xe038; config_base = 0x78; break; + case 8: iobase = 0xe040; config_base = 0x80; break; + case 9: iobase = 0xe048; config_base = 0x88; break; + case 10: iobase = 0xe050; config_base = 0x90; break; + case 11: iobase = 0xe058; config_base = 0x98; break; + default: + /* Unknown number of ports, get out of here */ + return -EINVAL; + } + + if (idx < 4) { + base = pci_resource_start(priv->dev, 3); + ciobase = (int)(base + (0x8 * idx)); + } + + dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n", + __func__, idx, iobase, ciobase, config_base); + + /* Enable UART I/O port */ + pci_write_config_byte(pdev, config_base + 0x00, 0x01); + + /* Select 128-byte FIFO and 8x FIFO threshold */ + pci_write_config_byte(pdev, config_base + 0x01, 0x33); + + /* LSB UART */ + pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff)); + + /* MSB UART */ + pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8)); + + /* irq number, this usually fails, but the spec says to do it anyway. */ + pci_write_config_byte(pdev, config_base + 0x06, pdev->irq); + + port->port.iotype = UPIO_PORT; + port->port.iobase = iobase; + port->port.mapbase = 0; + port->port.membase = NULL; + port->port.regshift = 0; + + return 0; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -2380,6 +2445,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_brcm_trumanage_setup, }, + { + .vendor = 0x1c29, + .device = 0x1104, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + }, + { + .vendor = 0x1c29, + .device = 0x1108, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + }, + { + .vendor = 0x1c29, + .device = 0x1112, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + }, /* * Default "match everything" terminator entry @@ -2578,6 +2664,9 @@ enum pci_board_num_t { pbn_omegapci, pbn_NETMOS9900_2s_115200, pbn_brcm_trumanage, + pbn_fintek_4, + pbn_fintek_8, + pbn_fintek_12, }; /* @@ -3335,6 +3424,24 @@ static struct pciserial_board pci_boards[] = { .reg_shift = 2, .base_baud = 115200, }, + [pbn_fintek_4] = { + .num_ports = 4, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, + [pbn_fintek_8] = { + .num_ports = 8, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, + [pbn_fintek_12] = { + .num_ports = 12, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, }; static const struct pci_device_id blacklist[] = { @@ -5059,6 +5166,11 @@ static struct pci_device_id serial_pci_tbl[] = { 0, 0, pbn_exar_XR17V358 }, + /* Fintek PCI serial cards */ + { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 }, + { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, + { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL -- cgit v1.2.3 From 892db58bd1285d44e6e1a1e36157161990ec5ae4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 17 Oct 2013 17:37:11 +0200 Subject: tty/serial: at91: fix uart/usart selection for older products Since commit 055560b04a8cd063aea916fd083b7aec02c2adb8 (serial: at91: distinguish usart and uart) the older products which do not have a name field in their register map are unable to use their serial output. As the main console output is usually the serial interface (aka DBGU) it is pretty unfortunate. So, instead of failing during probe() we just silently configure the serial peripheral as an uart. It allows us to use these serial outputs. The proper solution is proposed in another patch. Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index d067285a2d20..6b0f75eac8a2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1499,7 +1499,7 @@ static void atmel_set_ops(struct uart_port *port) /* * Get ip name usart or uart */ -static int atmel_get_ip_name(struct uart_port *port) +static void atmel_get_ip_name(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = UART_GET_IP_NAME(port); @@ -1518,10 +1518,7 @@ static int atmel_get_ip_name(struct uart_port *port) atmel_port->is_usart = false; } else { dev_err(port->dev, "Not supported ip name, set to uart\n"); - return -EINVAL; } - - return 0; } /* @@ -2405,9 +2402,7 @@ static int atmel_serial_probe(struct platform_device *pdev) /* * Get port name of usart or uart */ - ret = atmel_get_ip_name(&port->uart); - if (ret < 0) - goto err_add_port; + atmel_get_ip_name(&port->uart); return 0; -- cgit v1.2.3 From 731d9cae0204a8948c7db2f551edcd5d5822ed95 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 17 Oct 2013 17:37:12 +0200 Subject: tty/serial: at91: add a fallback option to determine uart/usart property On older SoC, the "name" field is not filled in the register map. Fix the way to figure out if the serial port is an uart or an usart for these older products (with corresponding properties). Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 6b0f75eac8a2..c7d99af46a96 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -99,6 +99,7 @@ static void atmel_stop_rx(struct uart_port *port); #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) #define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) #define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME) +#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION) /* PDC registers */ #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) @@ -1503,6 +1504,7 @@ static void atmel_get_ip_name(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = UART_GET_IP_NAME(port); + u32 version; int usart, uart; /* usart and uart ascii */ usart = 0x55534152; @@ -1517,7 +1519,22 @@ static void atmel_get_ip_name(struct uart_port *port) dev_dbg(port->dev, "This is uart\n"); atmel_port->is_usart = false; } else { - dev_err(port->dev, "Not supported ip name, set to uart\n"); + /* fallback for older SoCs: use version field */ + version = UART_GET_IP_VERSION(port); + switch (version) { + case 0x302: + case 0x10213: + dev_dbg(port->dev, "This version is usart\n"); + atmel_port->is_usart = true; + break; + case 0x203: + case 0x10202: + dev_dbg(port->dev, "This version is uart\n"); + atmel_port->is_usart = false; + break; + default: + dev_err(port->dev, "Not supported ip name nor version, set to uart\n"); + } } } -- cgit v1.2.3 From 991fc259361eb812ebf6c4527343d60ab4b2e1a6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:04 -0700 Subject: tty: xuartps: Use devm_clk_get() Use the device managed interface for clocks, simplifying error paths. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 7e4150aa69c6..103ba8826d06 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -953,23 +953,23 @@ static int xuartps_probe(struct platform_device *pdev) if (!xuartps_data) return -ENOMEM; - xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); + xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk"); if (IS_ERR(xuartps_data->aperclk)) { dev_err(&pdev->dev, "aper_clk clock not found.\n"); rc = PTR_ERR(xuartps_data->aperclk); goto err_out_free; } - xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); + xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk"); if (IS_ERR(xuartps_data->refclk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); rc = PTR_ERR(xuartps_data->refclk); - goto err_out_clk_put_aper; + goto err_out_free; } rc = clk_prepare_enable(xuartps_data->aperclk); if (rc) { dev_err(&pdev->dev, "Unable to enable APER clock.\n"); - goto err_out_clk_put; + goto err_out_free; } rc = clk_prepare_enable(xuartps_data->refclk); if (rc) { @@ -1020,10 +1020,6 @@ err_out_clk_disable: clk_disable_unprepare(xuartps_data->refclk); err_out_clk_dis_aper: clk_disable_unprepare(xuartps_data->aperclk); -err_out_clk_put: - clk_put(xuartps_data->refclk); -err_out_clk_put_aper: - clk_put(xuartps_data->aperclk); err_out_free: kfree(xuartps_data); @@ -1047,8 +1043,6 @@ static int xuartps_remove(struct platform_device *pdev) port->mapbase = 0; clk_disable_unprepare(xuartps_data->refclk); clk_disable_unprepare(xuartps_data->aperclk); - clk_put(xuartps_data->refclk); - clk_put(xuartps_data->aperclk); kfree(xuartps_data); return rc; } -- cgit v1.2.3 From c03cae1791407f4f4f9bc6b0354ecaeb50df787f Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:05 -0700 Subject: tty: xuartps: Use devm_kzalloc Use the device managed interface for memory allocation, simplifying error paths. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 103ba8826d06..8c0745951605 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -949,27 +949,26 @@ static int xuartps_probe(struct platform_device *pdev) struct resource *res, *res2; struct xuartps *xuartps_data; - xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); + xuartps_data = devm_kzalloc(&pdev->dev, sizeof(*xuartps_data), + GFP_KERNEL); if (!xuartps_data) return -ENOMEM; xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk"); if (IS_ERR(xuartps_data->aperclk)) { dev_err(&pdev->dev, "aper_clk clock not found.\n"); - rc = PTR_ERR(xuartps_data->aperclk); - goto err_out_free; + return PTR_ERR(xuartps_data->aperclk); } xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk"); if (IS_ERR(xuartps_data->refclk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); - rc = PTR_ERR(xuartps_data->refclk); - goto err_out_free; + return PTR_ERR(xuartps_data->refclk); } rc = clk_prepare_enable(xuartps_data->aperclk); if (rc) { dev_err(&pdev->dev, "Unable to enable APER clock.\n"); - goto err_out_free; + return rc; } rc = clk_prepare_enable(xuartps_data->refclk); if (rc) { @@ -1020,8 +1019,6 @@ err_out_clk_disable: clk_disable_unprepare(xuartps_data->refclk); err_out_clk_dis_aper: clk_disable_unprepare(xuartps_data->aperclk); -err_out_free: - kfree(xuartps_data); return rc; } @@ -1043,7 +1040,6 @@ static int xuartps_remove(struct platform_device *pdev) port->mapbase = 0; clk_disable_unprepare(xuartps_data->refclk); clk_disable_unprepare(xuartps_data->aperclk); - kfree(xuartps_data); return rc; } -- cgit v1.2.3 From 0c0c47bc40a2e358d593b2d7fb93b50027fbfc0c Mon Sep 17 00:00:00 2001 From: Vlad Lungu Date: Thu, 17 Oct 2013 14:08:06 -0700 Subject: tty: xuartps: Implement BREAK detection, add SYSRQ support The Cadence UART does not do break detection, even if the datasheet says it does. This patch adds break detection in software (tested in 8N1 mode only) and enables SYSRQ, allowing for Break-g to enter KDB and all the other goodies. Signed-off-by: Vlad Lungu Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 50 +++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8c0745951605..5d5557af4d22 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -11,13 +11,17 @@ * */ +#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include +#include #include #include #include #include -#include #include #include #include @@ -128,6 +132,9 @@ #define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ #define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */ +/* Goes in read_status_mask for break detection as the HW doesn't do it*/ +#define XUARTPS_IXR_BRK 0x80000000 + /** Channel Status Register * * The channel status register (CSR) is provided to enable the control logic @@ -171,6 +178,23 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) */ isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); + /* + * There is no hardware break detection, so we interpret framing + * error with all-zeros data as a break sequence. Most of the time, + * there's another non-zero byte at the end of the sequence. + */ + + if (isrstatus & XUARTPS_IXR_FRAMING) { + while (!(xuartps_readl(XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY)) { + if (!xuartps_readl(XUARTPS_FIFO_OFFSET)) { + port->read_status_mask |= XUARTPS_IXR_BRK; + isrstatus &= ~XUARTPS_IXR_FRAMING; + } + } + xuartps_writel(XUARTPS_IXR_FRAMING, XUARTPS_ISR_OFFSET); + } + /* drop byte with parity error if IGNPAR specified */ if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); @@ -184,6 +208,30 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { data = xuartps_readl(XUARTPS_FIFO_OFFSET); + + /* Non-NULL byte after BREAK is garbage (99%) */ + if (data && (port->read_status_mask & + XUARTPS_IXR_BRK)) { + port->read_status_mask &= ~XUARTPS_IXR_BRK; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } + + /* + * uart_handle_sysrq_char() doesn't work if + * spinlocked, for some reason + */ + if (port->sysrq) { + spin_unlock(&port->lock); + if (uart_handle_sysrq_char(port, + (unsigned char)data)) { + spin_lock(&port->lock); + continue; + } + spin_lock(&port->lock); + } + port->icount.rx++; if (isrstatus & XUARTPS_IXR_PARITY) { -- cgit v1.2.3 From 6ee04c6c5488b2b7fdfa22c771c127411f86e610 Mon Sep 17 00:00:00 2001 From: Vlad Lungu Date: Thu, 17 Oct 2013 14:08:07 -0700 Subject: tty: xuartps: Add polled mode support for xuartps This allows KDB/KGDB to run. Signed-off-by: Vlad Lungu Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5d5557af4d22..62259f37ddda 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -775,6 +775,54 @@ static void xuartps_enable_ms(struct uart_port *port) /* N/A */ } +#ifdef CONFIG_CONSOLE_POLL +static int xuartps_poll_get_char(struct uart_port *port) +{ + u32 imr; + int c; + + /* Disable all interrupts */ + imr = xuartps_readl(XUARTPS_IMR_OFFSET); + xuartps_writel(imr, XUARTPS_IDR_OFFSET); + + /* Check if FIFO is empty */ + if (xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) + c = NO_POLL_CHAR; + else /* Read a character */ + c = (unsigned char) xuartps_readl(XUARTPS_FIFO_OFFSET); + + /* Enable interrupts */ + xuartps_writel(imr, XUARTPS_IER_OFFSET); + + return c; +} + +static void xuartps_poll_put_char(struct uart_port *port, unsigned char c) +{ + u32 imr; + + /* Disable all interrupts */ + imr = xuartps_readl(XUARTPS_IMR_OFFSET); + xuartps_writel(imr, XUARTPS_IDR_OFFSET); + + /* Wait until FIFO is empty */ + while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)) + cpu_relax(); + + /* Write a character */ + xuartps_writel(c, XUARTPS_FIFO_OFFSET); + + /* Wait until FIFO is empty */ + while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)) + cpu_relax(); + + /* Enable interrupts */ + xuartps_writel(imr, XUARTPS_IER_OFFSET); + + return; +} +#endif + /** The UART operations structure */ static struct uart_ops xuartps_ops = { @@ -807,6 +855,10 @@ static struct uart_ops xuartps_ops = { .config_port = xuartps_config_port, /* Configure when driver * adds a xuartps port */ +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = xuartps_poll_get_char, + .poll_put_char = xuartps_poll_put_char, +#endif }; static struct uart_port xuartps_port[2]; -- cgit v1.2.3 From 85baf542d54ec321642194b0ebfa7316e3190dc2 Mon Sep 17 00:00:00 2001 From: Suneel Date: Thu, 17 Oct 2013 14:08:08 -0700 Subject: tty: xuartps: support 64 byte FIFO size Changes to use the 64 byte FIFO depth and fix the issue by clearing the txempty interrupt in isr status for tx after filling in data in start_tx function Signed-off-by: Suneel Garapati Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 62259f37ddda..6e8ec6e9d5a2 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -33,12 +33,22 @@ #define XUARTPS_MAJOR 0 /* use dynamic node allocation */ #define XUARTPS_MINOR 0 /* works best with devtmpfs */ #define XUARTPS_NR_PORTS 2 -#define XUARTPS_FIFO_SIZE 16 /* FIFO size */ +#define XUARTPS_FIFO_SIZE 64 /* FIFO size */ #define XUARTPS_REGISTER_SPACE 0xFFF #define xuartps_readl(offset) ioread32(port->membase + offset) #define xuartps_writel(val, offset) iowrite32(val, port->membase + offset) +/* Rx Trigger level */ +static int rx_trigger_level = 56; +module_param(rx_trigger_level, uint, S_IRUGO); +MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes"); + +/* Rx Timeout */ +static int rx_timeout = 10; +module_param(rx_timeout, uint, S_IRUGO); +MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); + /********************************Register Map********************************/ /** UART * @@ -394,7 +404,7 @@ static void xuartps_start_tx(struct uart_port *port) port->state->xmit.tail = (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); } - + xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_ISR_OFFSET); /* Enable the TX Empty interrupt */ xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET); @@ -528,7 +538,7 @@ static void xuartps_set_termios(struct uart_port *port, | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), XUARTPS_CR_OFFSET); - xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); + xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; @@ -631,11 +641,17 @@ static int xuartps_startup(struct uart_port *port) | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT, XUARTPS_MR_OFFSET); - /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */ - xuartps_writel(14, XUARTPS_RXWM_OFFSET); + /* + * Set the RX FIFO Trigger level to use most of the FIFO, but it + * can be tuned with a module parameter + */ + xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET); - /* Receive Timeout register is enabled with value of 10 */ - xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); + /* + * Receive Timeout register is enabled but it + * can be tuned with a module parameter + */ + xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); /* Clear out any pending interrupts before enabling them */ xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET); -- cgit v1.2.3 From d3755f5e6cd222cd5aff949228d32aa8446023a5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 17 Oct 2013 14:08:09 -0700 Subject: tty: xuartps: Force enable the UART in xuartps_console_write It is possible that under certain circumstances xuartps_console_write is entered while the UART disabled. When this happens the code will busy loop in xuartps_console_putchar, since the character is never written and the TXEMPTY flag is never set. The result is a system lockup. This patch force enables the UART for the duration of xuartps_console_write to avoid this. Signed-off-by: Lars-Peter Clausen Signed-off-by: John Linn Signed-off-by: Michal Simek Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6e8ec6e9d5a2..fdc739b55eb3 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -953,7 +953,7 @@ static void xuartps_console_write(struct console *co, const char *s, { struct uart_port *port = &xuartps_port[co->index]; unsigned long flags; - unsigned int imr; + unsigned int imr, ctrl; int locked = 1; if (oops_in_progress) @@ -965,9 +965,19 @@ static void xuartps_console_write(struct console *co, const char *s, imr = xuartps_readl(XUARTPS_IMR_OFFSET); xuartps_writel(imr, XUARTPS_IDR_OFFSET); + /* + * Make sure that the tx part is enabled. Set the TX enable bit and + * clear the TX disable bit to enable the transmitter. + */ + ctrl = xuartps_readl(XUARTPS_CR_OFFSET); + xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, + XUARTPS_CR_OFFSET); + uart_console_write(port, s, count, xuartps_console_putchar); xuartps_console_wait_tx(port); + xuartps_writel(ctrl, XUARTPS_CR_OFFSET); + /* restore interrupt state, it seems like there may be a h/w bug * in that the interrupt enable register should not need to be * written based on the data sheet -- cgit v1.2.3 From e6b39bfd0db207d2e9f3f78468d18f529f3b7901 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:10 -0700 Subject: tty: xuartps: Updating set_baud_rate() The original algorithm to find the best baud rate dividers does not necessarily find the best set of dividers. And in the worst case may even write illegal values to the hardware. The new function should make better use of the hardware capabilities and be able to provide valid settings for a wider range of baud rates and also input clocks. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 136 +++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 43 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index fdc739b55eb3..95e12c216984 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -156,6 +156,11 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ +/* baud dividers min/max values */ +#define XUARTPS_BDIV_MIN 4 +#define XUARTPS_BDIV_MAX 255 +#define XUARTPS_CD_MAX 65535 + /** * struct xuartps - device data * @refclk Reference clock @@ -305,59 +310,94 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) } /** - * xuartps_set_baud_rate - Calculate and set the baud rate - * @port: Handle to the uart port structure - * @baud: Baud rate to set - * + * xuartps_calc_baud_divs - Calculate baud rate divisors + * @clk: UART module input clock + * @baud: Desired baud rate + * @rbdiv: BDIV value (return value) + * @rcd: CD value (return value) + * @div8: Value for clk_sel bit in mod (return value) * Returns baud rate, requested baud when possible, or actual baud when there - * was too much error - **/ -static unsigned int xuartps_set_baud_rate(struct uart_port *port, - unsigned int baud) + * was too much error, zero if no valid divisors are found. + * + * Formula to obtain baud rate is + * baud_tx/rx rate = clk/CD * (BDIV + 1) + * input_clk = (Uart User Defined Clock or Apb Clock) + * depends on UCLKEN in MR Reg + * clk = input_clk or input_clk/8; + * depends on CLKS in MR reg + * CD and BDIV depends on values in + * baud rate generate register + * baud rate clock divisor register + */ +static unsigned int xuartps_calc_baud_divs(unsigned int clk, unsigned int baud, + u32 *rbdiv, u32 *rcd, int *div8) { - unsigned int sel_clk; - unsigned int calc_baud = 0; - unsigned int brgr_val, brdiv_val; + u32 cd, bdiv; + unsigned int calc_baud; + unsigned int bestbaud = 0; unsigned int bauderror; + unsigned int besterror = ~0; - /* Formula to obtain baud rate is - * baud_tx/rx rate = sel_clk/CD * (BDIV + 1) - * input_clk = (Uart User Defined Clock or Apb Clock) - * depends on UCLKEN in MR Reg - * sel_clk = input_clk or input_clk/8; - * depends on CLKS in MR reg - * CD and BDIV depends on values in - * baud rate generate register - * baud rate clock divisor register - */ - sel_clk = port->uartclk; - if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL) - sel_clk = sel_clk / 8; - - /* Find the best values for baud generation */ - for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) { + if (baud < clk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX)) { + *div8 = 1; + clk /= 8; + } else { + *div8 = 0; + } - brgr_val = sel_clk / (baud * (brdiv_val + 1)); - if (brgr_val < 2 || brgr_val > 65535) + for (bdiv = XUARTPS_BDIV_MIN; bdiv <= XUARTPS_BDIV_MAX; bdiv++) { + cd = DIV_ROUND_CLOSEST(clk, baud * (bdiv + 1)); + if (cd < 1 || cd > XUARTPS_CD_MAX) continue; - calc_baud = sel_clk / (brgr_val * (brdiv_val + 1)); + calc_baud = clk / (cd * (bdiv + 1)); if (baud > calc_baud) bauderror = baud - calc_baud; else bauderror = calc_baud - baud; - /* use the values when percent error is acceptable */ - if (((bauderror * 100) / baud) < 3) { - calc_baud = baud; - break; + if (besterror > bauderror) { + *rbdiv = bdiv; + *rcd = cd; + bestbaud = calc_baud; + besterror = bauderror; } } + /* use the values when percent error is acceptable */ + if (((besterror * 100) / baud) < 3) + bestbaud = baud; + + return bestbaud; +} - /* Set the values for the new baud rate */ - xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET); - xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET); +/** + * xuartps_set_baud_rate - Calculate and set the baud rate + * @port: Handle to the uart port structure + * @baud: Baud rate to set + * Returns baud rate, requested baud when possible, or actual baud when there + * was too much error, zero if no valid divisors are found. + */ +static unsigned int xuartps_set_baud_rate(struct uart_port *port, + unsigned int baud) +{ + unsigned int calc_baud; + u32 cd, bdiv; + u32 mreg; + int div8; + + calc_baud = xuartps_calc_baud_divs(port->uartclk, baud, &bdiv, &cd, + &div8); + + /* Write new divisors to hardware */ + mreg = xuartps_readl(XUARTPS_MR_OFFSET); + if (div8) + mreg |= XUARTPS_MR_CLKSEL; + else + mreg &= ~XUARTPS_MR_CLKSEL; + xuartps_writel(mreg, XUARTPS_MR_OFFSET); + xuartps_writel(cd, XUARTPS_BAUDGEN_OFFSET); + xuartps_writel(bdiv, XUARTPS_BAUDDIV_OFFSET); return calc_baud; } @@ -495,7 +535,7 @@ static void xuartps_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; - unsigned int baud; + unsigned int baud, minbaud, maxbaud; unsigned long flags; unsigned int ctrl_reg, mode_reg; @@ -512,8 +552,14 @@ static void xuartps_set_termios(struct uart_port *port, (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), XUARTPS_CR_OFFSET); - /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ - baud = uart_get_baud_rate(port, termios, old, 0, 10000000); + /* + * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk + * min and max baud should be calculated here based on port->uartclk. + * this way we get a valid baud and can safely call set_baud() + */ + minbaud = port->uartclk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX * 8); + maxbaud = port->uartclk / (XUARTPS_BDIV_MIN + 1); + baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud); baud = xuartps_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); @@ -589,13 +635,17 @@ static void xuartps_set_termios(struct uart_port *port, cval |= XUARTPS_MR_PARITY_MARK; else cval |= XUARTPS_MR_PARITY_SPACE; - } else if (termios->c_cflag & PARODD) + } else { + if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_ODD; else cval |= XUARTPS_MR_PARITY_EVEN; - } else + } + } else { cval |= XUARTPS_MR_PARITY_NONE; - xuartps_writel(cval , XUARTPS_MR_OFFSET); + } + cval |= mode_reg & 1; + xuartps_writel(cval, XUARTPS_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); } -- cgit v1.2.3 From c4b0510cc1571ff44e1d6024d92683d49a8bcfde Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:11 -0700 Subject: tty: xuartps: Dynamically adjust to input frequency changes Add a clock notifier to dynamically handle frequency changes of the input clock by reprogramming the UART in order to keep the baud rate constant. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 123 +++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 95e12c216984..82195040e906 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -163,13 +163,20 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); /** * struct xuartps - device data - * @refclk Reference clock - * @aperclk APB clock + * @port Pointer to the UART port + * @refclk Reference clock + * @aperclk APB clock + * @baud Current baud rate + * @clk_rate_change_nb Notifier block for clock changes */ struct xuartps { + struct uart_port *port; struct clk *refclk; struct clk *aperclk; + unsigned int baud; + struct notifier_block clk_rate_change_nb; }; +#define to_xuartps(_nb) container_of(_nb, struct xuartps, clk_rate_change_nb); /** * xuartps_isr - Interrupt handler @@ -385,6 +392,7 @@ static unsigned int xuartps_set_baud_rate(struct uart_port *port, u32 cd, bdiv; u32 mreg; int div8; + struct xuartps *xuartps = port->private_data; calc_baud = xuartps_calc_baud_divs(port->uartclk, baud, &bdiv, &cd, &div8); @@ -398,10 +406,105 @@ static unsigned int xuartps_set_baud_rate(struct uart_port *port, xuartps_writel(mreg, XUARTPS_MR_OFFSET); xuartps_writel(cd, XUARTPS_BAUDGEN_OFFSET); xuartps_writel(bdiv, XUARTPS_BAUDDIV_OFFSET); + xuartps->baud = baud; return calc_baud; } +/** + * xuartps_clk_notitifer_cb - Clock notifier callback + * @nb: Notifier block + * @event: Notify event + * @data: Notifier data + * Returns NOTIFY_OK on success, NOTIFY_BAD on error. + */ +static int xuartps_clk_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + u32 ctrl_reg; + struct uart_port *port; + int locked = 0; + struct clk_notifier_data *ndata = data; + unsigned long flags = 0; + struct xuartps *xuartps = to_xuartps(nb); + + port = xuartps->port; + if (port->suspended) + return NOTIFY_OK; + + switch (event) { + case PRE_RATE_CHANGE: + { + u32 bdiv; + u32 cd; + int div8; + + /* + * Find out if current baud-rate can be achieved with new clock + * frequency. + */ + if (!xuartps_calc_baud_divs(ndata->new_rate, xuartps->baud, + &bdiv, &cd, &div8)) + return NOTIFY_BAD; + + spin_lock_irqsave(&xuartps->port->lock, flags); + + /* Disable the TX and RX to set baud rate */ + xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | + (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), + XUARTPS_CR_OFFSET); + + spin_unlock_irqrestore(&xuartps->port->lock, flags); + + return NOTIFY_OK; + } + case POST_RATE_CHANGE: + /* + * Set clk dividers to generate correct baud with new clock + * frequency. + */ + + spin_lock_irqsave(&xuartps->port->lock, flags); + + locked = 1; + port->uartclk = ndata->new_rate; + + xuartps->baud = xuartps_set_baud_rate(xuartps->port, + xuartps->baud); + /* fall through */ + case ABORT_RATE_CHANGE: + if (!locked) + spin_lock_irqsave(&xuartps->port->lock, flags); + + /* Set TX/RX Reset */ + xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | + (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), + XUARTPS_CR_OFFSET); + + while (xuartps_readl(XUARTPS_CR_OFFSET) & + (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST)) + cpu_relax(); + + /* + * Clear the RX disable and TX disable bits and then set the TX + * enable bit and RX enable bit to enable the transmitter and + * receiver. + */ + xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); + ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); + xuartps_writel( + (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | + (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), + XUARTPS_CR_OFFSET); + + spin_unlock_irqrestore(&xuartps->port->lock, flags); + + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } +} + /*----------------------Uart Operations---------------------------*/ /** @@ -1164,13 +1267,19 @@ static int xuartps_probe(struct platform_device *pdev) goto err_out_clk_disable; } + xuartps_data->clk_rate_change_nb.notifier_call = + xuartps_clk_notifier_cb; + if (clk_notifier_register(xuartps_data->refclk, + &xuartps_data->clk_rate_change_nb)) + dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); + /* Initialize the port structure */ port = xuartps_get_port(); if (!port) { dev_err(&pdev->dev, "Cannot get uart_port structure\n"); rc = -ENODEV; - goto err_out_clk_disable; + goto err_out_notif_unreg; } else { /* Register the port. * This function also registers this device with the tty layer @@ -1181,16 +1290,20 @@ static int xuartps_probe(struct platform_device *pdev) port->dev = &pdev->dev; port->uartclk = clk_get_rate(xuartps_data->refclk); port->private_data = xuartps_data; + xuartps_data->port = port; platform_set_drvdata(pdev, port); rc = uart_add_one_port(&xuartps_uart_driver, port); if (rc) { dev_err(&pdev->dev, "uart_add_one_port() failed; err=%i\n", rc); - goto err_out_clk_disable; + goto err_out_notif_unreg; } return 0; } +err_out_notif_unreg: + clk_notifier_unregister(xuartps_data->refclk, + &xuartps_data->clk_rate_change_nb); err_out_clk_disable: clk_disable_unprepare(xuartps_data->refclk); err_out_clk_dis_aper: @@ -1212,6 +1325,8 @@ static int xuartps_remove(struct platform_device *pdev) int rc; /* Remove the xuartps port from the serial core */ + clk_notifier_unregister(xuartps_data->refclk, + &xuartps_data->clk_rate_change_nb); rc = uart_remove_one_port(&xuartps_uart_driver, port); port->mapbase = 0; clk_disable_unprepare(xuartps_data->refclk); -- cgit v1.2.3 From 4b47d9aa1e3b54b73f9399f3d64b47495cc67a1e Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:12 -0700 Subject: tty: xuartps: Implement suspend/resume callbacks Implement suspend and resume callbacks in order to support system suspend/hibernation. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 114 +++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 82195040e906..9ecd8ea4f3ae 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1198,6 +1198,119 @@ console_initcall(xuartps_console_init); #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ +#ifdef CONFIG_PM_SLEEP +/** + * xuartps_suspend - suspend event + * @device: Pointer to the device structure + * + * Returns 0 + */ +static int xuartps_suspend(struct device *device) +{ + struct uart_port *port = dev_get_drvdata(device); + struct tty_struct *tty; + struct device *tty_dev; + int may_wake = 0; + + /* Get the tty which could be NULL so don't assume it's valid */ + tty = tty_port_tty_get(&port->state->port); + if (tty) { + tty_dev = tty->dev; + may_wake = device_may_wakeup(tty_dev); + tty_kref_put(tty); + } + + /* + * Call the API provided in serial_core.c file which handles + * the suspend. + */ + uart_suspend_port(&xuartps_uart_driver, port); + if (console_suspend_enabled && !may_wake) { + struct xuartps *xuartps = port->private_data; + + clk_disable(xuartps->refclk); + clk_disable(xuartps->aperclk); + } else { + unsigned long flags = 0; + + spin_lock_irqsave(&port->lock, flags); + /* Empty the receive FIFO 1st before making changes */ + while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY)) + xuartps_readl(XUARTPS_FIFO_OFFSET); + /* set RX trigger level to 1 */ + xuartps_writel(1, XUARTPS_RXWM_OFFSET); + /* disable RX timeout interrups */ + xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + } + + return 0; +} + +/** + * xuartps_resume - Resume after a previous suspend + * @device: Pointer to the device structure + * + * Returns 0 + */ +static int xuartps_resume(struct device *device) +{ + struct uart_port *port = dev_get_drvdata(device); + unsigned long flags = 0; + u32 ctrl_reg; + struct tty_struct *tty; + struct device *tty_dev; + int may_wake = 0; + + /* Get the tty which could be NULL so don't assume it's valid */ + tty = tty_port_tty_get(&port->state->port); + if (tty) { + tty_dev = tty->dev; + may_wake = device_may_wakeup(tty_dev); + tty_kref_put(tty); + } + + if (console_suspend_enabled && !may_wake) { + struct xuartps *xuartps = port->private_data; + + clk_enable(xuartps->aperclk); + clk_enable(xuartps->refclk); + + spin_lock_irqsave(&port->lock, flags); + + /* Set TX/RX Reset */ + xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | + (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), + XUARTPS_CR_OFFSET); + while (xuartps_readl(XUARTPS_CR_OFFSET) & + (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST)) + cpu_relax(); + + /* restore rx timeout value */ + xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); + /* Enable Tx/Rx */ + ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); + xuartps_writel( + (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | + (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), + XUARTPS_CR_OFFSET); + + spin_unlock_irqrestore(&port->lock, flags); + } else { + spin_lock_irqsave(&port->lock, flags); + /* restore original rx trigger level */ + xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET); + /* enable RX timeout interrupt */ + xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + } + + return uart_resume_port(&xuartps_uart_driver, port); +} +#endif /* ! CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume); + /** Structure Definitions */ static struct uart_driver xuartps_uart_driver = { @@ -1348,6 +1461,7 @@ static struct platform_driver xuartps_platform_driver = { .owner = THIS_MODULE, .name = XUARTPS_NAME, /* Driver name */ .of_match_table = xuartps_of_match, + .pm = &xuartps_dev_pm_ops, }, }; -- cgit v1.2.3 From 37cd940b2044ca0c481e70742da37278a2d736ae Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 17 Oct 2013 14:08:13 -0700 Subject: tty: xuartps: Update copyright information Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 9ecd8ea4f3ae..c7c96c2f149c 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1,7 +1,7 @@ /* * Xilinx PS UART driver * - * 2011 (c) Xilinx Inc. + * 2011 - 2013 (C) Xilinx Inc. * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public -- cgit v1.2.3 From 943414752045defdd7e476a830e2d8c0ec37cca2 Mon Sep 17 00:00:00 2001 From: Angelo Butti Date: Tue, 15 Oct 2013 22:41:10 +0300 Subject: serial: 8250_pci: add Pericom PCIe Serial board Support (12d8:7952/4/8) - Chip PI7C9X7952/4/8 Signed-off-by: Angelo Butti Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4ea45c15388c..4697a514b80a 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1307,6 +1307,29 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } +static int pci_pericom_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar, offset = board->first_offset, maxnr; + + bar = FL_GET_BASE(board->flags); + if (board->flags & FL_BASE_BARS) + bar += idx; + else + offset += idx * board->uart_offset; + + maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> + (board->reg_shift + 3); + + if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) + return 1; + + port->port.uartclk = 14745600; + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + static int ce4100_serial_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -2015,6 +2038,31 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_default_setup, .exit = pci_plx9050_exit, }, + /* + * Pericom + */ + { + .vendor = 0x12d8, + .device = 0x7952, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup, + }, + { + .vendor = 0x12d8, + .device = 0x7954, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup, + }, + { + .vendor = 0x12d8, + .device = 0x7958, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup, + }, + /* * PLX */ -- cgit v1.2.3 From d54b181ea65682914cae0430f2a1efcbb6517dba Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 21 Oct 2013 16:40:59 -0700 Subject: tty: xuartps: Fix "may be used uninitialized" build warning Initialize varibles for which a 'may be used uninitalized' warning is issued. Signed-off-by: Soren Brinkmann Reported-by: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index c7c96c2f149c..5ac6c480df43 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -389,7 +389,7 @@ static unsigned int xuartps_set_baud_rate(struct uart_port *port, unsigned int baud) { unsigned int calc_baud; - u32 cd, bdiv; + u32 cd = 0, bdiv = 0; u32 mreg; int div8; struct xuartps *xuartps = port->private_data; -- cgit v1.2.3 From d3641f64bc71765682754722fd42fae24366bb3a Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 21 Oct 2013 16:41:00 -0700 Subject: tty: xuartps: Fix build error due to missing forward declaration If CONFIG_PM_SLEEP is enabled and CONFIG_SERIAL_XILINX_PS_UART_CONSOLE is not, a forward declaration of the uart_driver struct is not included, leading to a build error due to an undeclared variable. Fixing this by moving the definition of the struct uart_driver before the definition of the suspend/resume callbacks. Signed-off-by: Soren Brinkmann Reported-by: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5ac6c480df43..ca4a2f1fbca9 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1198,6 +1198,20 @@ console_initcall(xuartps_console_init); #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ +/** Structure Definitions + */ +static struct uart_driver xuartps_uart_driver = { + .owner = THIS_MODULE, /* Owner */ + .driver_name = XUARTPS_NAME, /* Driver name */ + .dev_name = XUARTPS_TTY_NAME, /* Node name */ + .major = XUARTPS_MAJOR, /* Major number */ + .minor = XUARTPS_MINOR, /* Minor number */ + .nr = XUARTPS_NR_PORTS, /* Number of UART ports */ +#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE + .cons = &xuartps_console, /* Console */ +#endif +}; + #ifdef CONFIG_PM_SLEEP /** * xuartps_suspend - suspend event @@ -1311,20 +1325,6 @@ static int xuartps_resume(struct device *device) static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume); -/** Structure Definitions - */ -static struct uart_driver xuartps_uart_driver = { - .owner = THIS_MODULE, /* Owner */ - .driver_name = XUARTPS_NAME, /* Driver name */ - .dev_name = XUARTPS_TTY_NAME, /* Node name */ - .major = XUARTPS_MAJOR, /* Major number */ - .minor = XUARTPS_MINOR, /* Minor number */ - .nr = XUARTPS_NR_PORTS, /* Number of UART ports */ -#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE - .cons = &xuartps_console, /* Console */ -#endif -}; - /* --------------------------------------------------------------------- * Platform bus binding */ -- cgit v1.2.3 From 7ac57347c23de6b6fcaf8f0a1f91067cedea57bc Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 21 Oct 2013 16:41:01 -0700 Subject: tty: xuartps: Fix build error when COMMON_CLK is not set Clock notifiers are only available when CONFIG_COMMON_CLK is enabled. Hence all notifier related code has to be protected by corresponsing ifdefs. Signed-off-by: Soren Brinkmann Reported-by: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ca4a2f1fbca9..e46e9f3f19b9 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -411,6 +411,7 @@ static unsigned int xuartps_set_baud_rate(struct uart_port *port, return calc_baud; } +#ifdef CONFIG_COMMON_CLK /** * xuartps_clk_notitifer_cb - Clock notifier callback * @nb: Notifier block @@ -504,6 +505,7 @@ static int xuartps_clk_notifier_cb(struct notifier_block *nb, return NOTIFY_DONE; } } +#endif /*----------------------Uart Operations---------------------------*/ @@ -1380,11 +1382,13 @@ static int xuartps_probe(struct platform_device *pdev) goto err_out_clk_disable; } +#ifdef CONFIG_COMMON_CLK xuartps_data->clk_rate_change_nb.notifier_call = xuartps_clk_notifier_cb; if (clk_notifier_register(xuartps_data->refclk, &xuartps_data->clk_rate_change_nb)) dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); +#endif /* Initialize the port structure */ port = xuartps_get_port(); @@ -1415,8 +1419,10 @@ static int xuartps_probe(struct platform_device *pdev) } err_out_notif_unreg: +#ifdef CONFIG_COMMON_CLK clk_notifier_unregister(xuartps_data->refclk, &xuartps_data->clk_rate_change_nb); +#endif err_out_clk_disable: clk_disable_unprepare(xuartps_data->refclk); err_out_clk_dis_aper: @@ -1438,8 +1444,10 @@ static int xuartps_remove(struct platform_device *pdev) int rc; /* Remove the xuartps port from the serial core */ +#ifdef CONFIG_COMMON_CLK clk_notifier_unregister(xuartps_data->refclk, &xuartps_data->clk_rate_change_nb); +#endif rc = uart_remove_one_port(&xuartps_uart_driver, port); port->mapbase = 0; clk_disable_unprepare(xuartps_data->refclk); -- cgit v1.2.3 From 24b6bb0714508e3a4f51dec9f4333c988f8afb76 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Mon, 21 Oct 2013 10:19:14 +0200 Subject: serial: sirf: remove duplicate defines This patch removes duplicate defines in drivers/tty/serial/sirfsoc_uart.h Signed-off-by: Michael Opdenacker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sirfsoc_uart.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index fb8d0a002607..b7d679c0881b 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -368,15 +368,6 @@ struct sirfsoc_uart_register sirfsoc_uart = { #define SIRFSOC_UART_NR 6 #define SIRFSOC_PORT_TYPE 0xa5 -/* Baud Rate Calculation */ -#define SIRF_MIN_SAMPLE_DIV 0xf -#define SIRF_MAX_SAMPLE_DIV 0x3f -#define SIRF_IOCLK_DIV_MAX 0xffff -#define SIRF_SAMPLE_DIV_SHIFT 16 -#define SIRF_IOCLK_DIV_MASK 0xffff -#define SIRF_SAMPLE_DIV_MASK 0x3f0000 -#define SIRF_BAUD_RATE_SUPPORT_NR 18 - /* Uart Common Use Macro*/ #define SIRFSOC_RX_DMA_BUF_SIZE 256 #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) @@ -453,9 +444,6 @@ struct sirfsoc_uart_port { int rx_issued; }; -/* Hardware Flow Control */ -#define SIRFUART_AFC_CTRL_RX_THD 0x70 - /* Register Access Control */ #define portaddr(port, reg) ((port)->membase + (reg)) #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) -- cgit v1.2.3 From 2a0b965cfb6efc667228831fc3a30308b4f94a87 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 22 Oct 2013 06:49:48 -0700 Subject: serial: omap: Add support for optional wake-up With the recent pinctrl-single changes, omaps can treat wake-up events from deeper idle states as interrupts. There's a separate "io chain" controller on most omaps that stays enabled when the device hits off-idle and the regular interrupt controller is powered off. Let's add support for the optional second interrupt for wake-up events. And then serial-omap can manage the wake-up interrupt from it's runtime PM calls to avoid spurious interrupts during runtime. Note that the wake interrupt is board specific as it uses the UART RX pin, and for omap3, there are six pin options for UART3 RX pin. Also Note that the legacy platform based booting handles the wake-ups in the legacy mux driver and does not need to pass the wake-up interrupt to the driver. And finally, to pass the wake-up interrupt in the dts file, either interrupt-map or the pending interrupts-extended property needs to be passed. It's probably best to use interrupts-extended when it's available. Cc: Felipe Balbi Cc: Kevin Hilman Cc: Linus Walleij Reviewed-by: Felipe Balbi Reviewed-by: Roger Quadros Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index c715778a745c..b69393f2817d 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,7 @@ struct uart_omap_port { struct uart_port port; struct uart_omap_dma uart_dma; struct device *dev; + int wakeirq; unsigned char ier; unsigned char lcr; @@ -214,10 +216,23 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up) return pdata->get_context_loss_count(up->dev); } +static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up, + bool enable) +{ + if (!up->wakeirq) + return; + + if (enable) + enable_irq(up->wakeirq); + else + disable_irq(up->wakeirq); +} + static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) { struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); + serial_omap_enable_wakeirq(up, enable); if (!pdata || !pdata->enable_wakeup) return; @@ -699,6 +714,20 @@ static int serial_omap_startup(struct uart_port *port) if (retval) return retval; + /* Optional wake-up IRQ */ + if (up->wakeirq) { + retval = request_irq(up->wakeirq, serial_omap_irq, + up->port.irqflags, up->name, up); + if (retval) { + free_irq(up->port.irq, up); + return retval; + } + disable_irq(up->wakeirq); + } else { + dev_info(up->port.dev, "no wakeirq for uart%d\n", + up->port.line); + } + dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line); pm_runtime_get_sync(up->dev); @@ -787,6 +816,8 @@ static void serial_omap_shutdown(struct uart_port *port) pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); free_irq(up->port.irq, up); + if (up->wakeirq) + free_irq(up->wakeirq, up); } static void serial_omap_uart_qos_work(struct work_struct *work) @@ -1572,11 +1603,23 @@ static int serial_omap_probe(struct platform_device *pdev) struct uart_omap_port *up; struct resource *mem, *irq; struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev); - int ret; + int ret, uartirq = 0, wakeirq = 0; + /* The optional wakeirq may be specified in the board dts file */ if (pdev->dev.of_node) { + uartirq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!uartirq) + return -EPROBE_DEFER; + wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); omap_up_info = of_get_uart_port_info(&pdev->dev); pdev->dev.platform_data = omap_up_info; + } else { + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + dev_err(&pdev->dev, "no irq resource?\n"); + return -ENODEV; + } + uartirq = irq->start; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1585,12 +1628,6 @@ static int serial_omap_probe(struct platform_device *pdev) return -ENODEV; } - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - dev_err(&pdev->dev, "no irq resource?\n"); - return -ENODEV; - } - if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), pdev->dev.driver->name)) { dev_err(&pdev->dev, "memory region already claimed\n"); @@ -1624,7 +1661,8 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.dev = &pdev->dev; up->port.type = PORT_OMAP; up->port.iotype = UPIO_MEM; - up->port.irq = irq->start; + up->port.irq = uartirq; + up->wakeirq = wakeirq; up->port.regshift = 2; up->port.fifosize = 64; -- cgit v1.2.3 From 68357c7d3f0a5930b48dcbe6d10e5324fdbd8c7a Mon Sep 17 00:00:00 2001 From: "Chen, Jie" Date: Tue, 22 Oct 2013 12:42:09 -0700 Subject: mrst_max3110: fix unbalanced IRQ issue during resume During resume, a startup will request_irq again, meantime resume function's enable_irq will cause unbalanced IRQ issue. Fix this issue by moving request_irq to probe function. Signed-off-by: David Cohen Signed-off-by: Chen, Jie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mrst_max3110.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 565779dc7aac..db0448ae59dc 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -43,6 +43,7 @@ #include #include +#include #include "mrst_max3110.h" @@ -494,19 +495,9 @@ static int serial_m3110_startup(struct uart_port *port) port->state->port.low_latency = 1; if (max->irq) { - max->read_thread = NULL; - ret = request_irq(max->irq, serial_m3110_irq, - IRQ_TYPE_EDGE_FALLING, "max3110", max); - if (ret) { - max->irq = 0; - pr_err(PR_FMT "unable to allocate IRQ, polling\n"); - } else { - /* Enable RX IRQ only */ - config |= WC_RXA_IRQ_ENABLE; - } - } - - if (max->irq == 0) { + /* Enable RX IRQ only */ + config |= WC_RXA_IRQ_ENABLE; + } else { /* If IRQ is disabled, start a read thread for input data */ max->read_thread = kthread_run(max3110_read_thread, max, "max3110_read"); @@ -520,8 +511,6 @@ static int serial_m3110_startup(struct uart_port *port) ret = max3110_out(max, config); if (ret) { - if (max->irq) - free_irq(max->irq, max); if (max->read_thread) kthread_stop(max->read_thread); max->read_thread = NULL; @@ -543,9 +532,6 @@ static void serial_m3110_shutdown(struct uart_port *port) max->read_thread = NULL; } - if (max->irq) - free_irq(max->irq, max); - /* Disable interrupts from this port */ config = WC_TAG | WC_SW_SHDI; max3110_out(max, config); @@ -846,6 +832,16 @@ static int serial_m3110_probe(struct spi_device *spi) goto err_kthread; } + if (max->irq) { + ret = request_irq(max->irq, serial_m3110_irq, + IRQ_TYPE_EDGE_FALLING, "max3110", max); + if (ret) { + max->irq = 0; + dev_warn(&spi->dev, + "unable to allocate IRQ, will use polling method\n"); + } + } + spi_set_drvdata(spi, max); pmax = max; @@ -873,6 +869,9 @@ static int serial_m3110_remove(struct spi_device *dev) free_page((unsigned long)max->con_xmit.buf); + if (max->irq) + free_irq(max->irq, max); + if (max->main_thread) kthread_stop(max->main_thread); -- cgit v1.2.3 From 018e7448f2b2beba4a58f4c7fe99a5b32542be4c Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 23 Oct 2013 18:49:58 -0400 Subject: serial: omap: improve RS-485 performance If RS-485 is enabled, make the OMAP UART fire THR interrupts when both TX FIFO and TX shift register are empty instead of polling the equivalent status bit. This removes the burst of interrupt requests seen at every end of transmission. Also: the comment said that the TX FIFO trigger level was set at 16 characters when it's 32 in reality. Signed-off-by: Philippe Proulx Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 50 ++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b69393f2817d..e42eb1e5a21a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -298,21 +298,22 @@ static void serial_omap_enable_ms(struct uart_port *port) static void serial_omap_stop_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - struct circ_buf *xmit = &up->port.state->xmit; int res; pm_runtime_get_sync(up->dev); - /* handle rs485 */ + /* Handle RS-485 */ if (up->rs485.flags & SER_RS485_ENABLED) { - /* do nothing if current tx not yet completed */ - res = serial_in(up, UART_LSR) & UART_LSR_TEMT; - if (!res) - return; - - /* if there's no more data to send, turn off rts */ - if (uart_circ_empty(xmit)) { - /* if rts not already disabled */ + if (up->scr & OMAP_UART_SCR_TX_EMPTY) { + /* THR interrupt is fired when both TX FIFO and TX + * shift register are empty. This means there's nothing + * left to transmit now, so make sure the THR interrupt + * is fired when TX FIFO is below the trigger level, + * disable THR interrupts and toggle the RS-485 GPIO + * data direction pin if needed. + */ + up->scr &= ~OMAP_UART_SCR_TX_EMPTY; + serial_out(up, UART_OMAP_SCR, up->scr); res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; if (gpio_get_value(up->rts_gpio) != res) { if (up->rs485.delay_rts_after_send > 0) { @@ -320,6 +321,18 @@ static void serial_omap_stop_tx(struct uart_port *port) } gpio_set_value(up->rts_gpio, res); } + } else { + /* We're asked to stop, but there's still stuff in the + * UART FIFO, so make sure the THR interrupt is fired + * when both TX FIFO and TX shift register are empty. + * The next THR interrupt (if no transmission is started + * in the meantime) will indicate the end of a + * transmission. Therefore we _don't_ disable THR + * interrupts in this situation. + */ + up->scr |= OMAP_UART_SCR_TX_EMPTY; + serial_out(up, UART_OMAP_SCR, up->scr); + return; } } @@ -399,8 +412,12 @@ static void serial_omap_start_tx(struct uart_port *port) pm_runtime_get_sync(up->dev); - /* handle rs485 */ + /* Handle RS-485 */ if (up->rs485.flags & SER_RS485_ENABLED) { + /* Fire THR interrupts when FIFO is below trigger level */ + up->scr &= ~OMAP_UART_SCR_TX_EMPTY; + serial_out(up, UART_OMAP_SCR, up->scr); + /* if rts not already enabled */ res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; if (gpio_get_value(up->rts_gpio) != res) { @@ -969,7 +986,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, */ /* Set receive FIFO threshold to 16 characters and - * transmit FIFO threshold to 16 spaces + * transmit FIFO threshold to 32 spaces */ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; @@ -1375,6 +1392,15 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) up->ier = mode; serial_out(up, UART_IER, up->ier); + /* If RS-485 is disabled, make sure the THR interrupt is fired when + * TX FIFO is below the trigger level. + */ + if (!(up->rs485.flags & SER_RS485_ENABLED) && + (up->scr & OMAP_UART_SCR_TX_EMPTY)) { + up->scr &= ~OMAP_UART_SCR_TX_EMPTY; + serial_out(up, UART_OMAP_SCR, up->scr); + } + spin_unlock_irqrestore(&up->port.lock, flags); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); -- cgit v1.2.3 From e5f9bf72efbcaaf7e909cd6b948e43878a27c4e5 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 23 Oct 2013 18:49:59 -0400 Subject: serial: omap: fix a few checkpatch warnings Signed-off-by: Philippe Proulx Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index e42eb1e5a21a..97c07f68cca0 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -177,7 +177,7 @@ struct uart_omap_port { bool is_suspending; }; -#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) +#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; @@ -257,9 +257,9 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) unsigned int n16 = port->uartclk / (16 * baud); int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); - if(baudAbsDiff13 < 0) + if (baudAbsDiff13 < 0) baudAbsDiff13 = -baudAbsDiff13; - if(baudAbsDiff16 < 0) + if (baudAbsDiff16 < 0) baudAbsDiff16 = -baudAbsDiff16; return (baudAbsDiff13 >= baudAbsDiff16); @@ -316,9 +316,8 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_OMAP_SCR, up->scr); res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; if (gpio_get_value(up->rts_gpio) != res) { - if (up->rs485.delay_rts_after_send > 0) { + if (up->rs485.delay_rts_after_send > 0) mdelay(up->rs485.delay_rts_after_send); - } gpio_set_value(up->rts_gpio, res); } } else { @@ -422,9 +421,8 @@ static void serial_omap_start_tx(struct uart_port *port) res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; if (gpio_get_value(up->rts_gpio) != res) { gpio_set_value(up->rts_gpio, res); - if (up->rs485.delay_rts_before_send > 0) { + if (up->rs485.delay_rts_before_send > 0) mdelay(up->rs485.delay_rts_before_send); - } } } @@ -1724,8 +1722,9 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.uartclk = omap_up_info->uartclk; if (!up->port.uartclk) { up->port.uartclk = DEFAULT_CLK_SPEED; - dev_warn(&pdev->dev, "No clock speed specified: using default:" - "%d\n", DEFAULT_CLK_SPEED); + dev_warn(&pdev->dev, + "No clock speed specified: using default: %d\n" + DEFAULT_CLK_SPEED); } up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; -- cgit v1.2.3 From 9baaa6747e84b078e42b1a6d17088049b5320167 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 28 Oct 2013 09:48:52 +0900 Subject: serial: mfd: Staticize local symbols These local symbols are used only in this file. Fix the following sparse warnings: drivers/tty/serial/mfd.c:296:6: warning: symbol 'hsu_dma_tx' was not declared. Should it be static? drivers/tty/serial/mfd.c:343:6: warning: symbol 'hsu_dma_start_rx_chan' was not declared. Should it be static? drivers/tty/serial/mfd.c:389:6: warning: symbol 'hsu_dma_rx' was not declared. Should it be static? drivers/tty/serial/mfd.c:1186:17: warning: symbol 'serial_hsu_pops' was not declared. Should it be static? Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mfd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 503dcc77b2bd..52c930fac210 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -293,7 +293,7 @@ static void serial_hsu_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -void hsu_dma_tx(struct uart_hsu_port *up) +static void hsu_dma_tx(struct uart_hsu_port *up) { struct circ_buf *xmit = &up->port.state->xmit; struct hsu_dma_buffer *dbuf = &up->txbuf; @@ -340,7 +340,8 @@ void hsu_dma_tx(struct uart_hsu_port *up) } /* The buffer is already cache coherent */ -void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) +static void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, + struct hsu_dma_buffer *dbuf) { dbuf->ofs = 0; @@ -386,7 +387,8 @@ static void serial_hsu_stop_tx(struct uart_port *port) /* This is always called in spinlock protected mode, so * modify timeout timer is safe here */ -void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts, unsigned long *flags) +static void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts, + unsigned long *flags) { struct hsu_dma_buffer *dbuf = &up->rxbuf; struct hsu_dma_chan *chan = up->rxc; @@ -1183,7 +1185,7 @@ static struct console serial_hsu_console = { #define SERIAL_HSU_CONSOLE NULL #endif -struct uart_ops serial_hsu_pops = { +static struct uart_ops serial_hsu_pops = { .tx_empty = serial_hsu_tx_empty, .set_mctrl = serial_hsu_set_mctrl, .get_mctrl = serial_hsu_get_mctrl, -- cgit v1.2.3 From d4f9e7b3d12e92ede642f6f4fc7d959f06da8ccc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Oct 2013 23:37:36 +0100 Subject: serial: sh-sci: Enable the driver on all ARM platforms Renesas ARM platforms are transitioning from single-platform to multi-platform kernels using the new ARCH_SHMOBILE_MULTI. Make the driver available on all ARM platforms to enable it on both ARCH_SHMOBILE and ARCH_SHMOBILE_MULTI, and increase build testing coverage with COMPILE_TEST. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 701ca60076ed..a3817ab8602f 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -709,7 +709,7 @@ config SERIAL_IP22_ZILOG_CONSOLE config SERIAL_SH_SCI tristate "SuperH SCI(F) serial port support" - depends on HAVE_CLK && (SUPERH || ARCH_SHMOBILE) + depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST) select SERIAL_CORE config SERIAL_SH_SCI_NR_UARTS -- cgit v1.2.3 From 80d8611dd07603736d14e4a942546bdc84dd5477 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Thu, 31 Oct 2013 09:39:58 -0400 Subject: serial: omap: fix missing comma Reported-by: Stephen Rothwell , Signed-off-by: Philippe Proulx Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 97c07f68cca0..fa511ebab67c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1723,7 +1723,7 @@ static int serial_omap_probe(struct platform_device *pdev) if (!up->port.uartclk) { up->port.uartclk = DEFAULT_CLK_SPEED; dev_warn(&pdev->dev, - "No clock speed specified: using default: %d\n" + "No clock speed specified: using default: %d\n", DEFAULT_CLK_SPEED); } -- cgit v1.2.3