From 1cb40d08726468602389c9a7ec345af5ade99775 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 17 Sep 2013 12:53:34 -0400 Subject: n_tty: Remove superfluous reader wakeup n_tty's .set_termios method unconditionally performs reader wakeup; remove extra reader wakeup for canonical mode changes. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c9a9ddd..41c0c80 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1764,9 +1764,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ldata->lnext = 0; } - if (canon_change && !L_ICANON(tty) && read_cnt(ldata)) - wake_up_interruptible(&tty->read_wait); - ldata->icanon = (L_ICANON(tty) != 0); if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || -- cgit v0.10.2 From c786f74e0bcc457e85cc1eee551732afa60d6308 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 17 Sep 2013 12:53:35 -0400 Subject: n_tty: Remove unnecessary local variable Flatten conditional evaluation in n_tty_set_termios; remove canon_change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 41c0c80..5372bf0 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1752,11 +1752,8 @@ int is_ignored(int sig) static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) { struct n_tty_data *ldata = tty->disc_data; - int canon_change = 1; - if (old) - canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON; - if (canon_change) { + if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) { bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); ldata->line_start = 0; ldata->canon_head = ldata->read_tail; -- cgit v0.10.2 From 103fcbe2eeb56d6ee693c573eac81e398fa276bd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 17 Sep 2013 12:53:36 -0400 Subject: n_tty: Style fix in n_tty_set_termios Remove braces from single-statement conditional in n_tty_set_termios. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5372bf0..2ba7bf8 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1815,9 +1815,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. */ - if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) start_tty(tty); - } /* The termios change make the tty ready for I/O */ wake_up_interruptible(&tty->write_wait); -- cgit v0.10.2 From e3bfea23a62dccfd12875a6cc24fa5c77e8a3c07 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 18 Sep 2013 20:42:39 -0400 Subject: tty: Prevent tty_port destruction if tty not released If the tty driver mistakenly drops the last port reference before the tty has been released, issue a diagnostic and abort the port destruction. This will leak memory and may zombify the port, but might otherwise keep the machine in runnable state. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index f597e88..7efbca4 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -140,6 +140,10 @@ EXPORT_SYMBOL(tty_port_destroy); static void tty_port_destructor(struct kref *kref) { struct tty_port *port = container_of(kref, struct tty_port, kref); + + /* check if last port ref was dropped before tty release */ + if (WARN_ON(port->itty)) + return; if (port->xmit_buf) free_page((unsigned long)port->xmit_buf); tty_port_destroy(port); -- cgit v0.10.2 From 469d6d0631386e6865a30c9ded87a5cc0fdf8e2e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 18 Sep 2013 20:47:06 -0400 Subject: tty: Remove unused drop() method from tty_port interface Although originally conceived as a hook for port drivers to know when a port reference is dropped, no driver uses this method. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 7efbca4..c94d234 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -484,8 +484,6 @@ int tty_port_close_start(struct tty_port *port, if (port->count) { spin_unlock_irqrestore(&port->lock, flags); - if (port->ops->drop) - port->ops->drop(port); return 0; } set_bit(ASYNCB_CLOSING, &port->flags); @@ -504,9 +502,7 @@ int tty_port_close_start(struct tty_port *port, /* Flush the ldisc buffering */ tty_ldisc_flush(tty); - /* Don't call port->drop for the last reference. Callers will want - to drop the last active reference in ->shutdown() or the tty - shutdown path */ + /* Report to caller this is the last port reference */ return 1; } EXPORT_SYMBOL(tty_port_close_start); diff --git a/include/linux/tty.h b/include/linux/tty.h index 64f8646..2f47989 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -180,7 +180,6 @@ struct tty_port_operations { IFF the port was initialized. Do not use to free resources. Called under the port mutex to serialize against activate/shutdowns */ void (*shutdown)(struct tty_port *port); - void (*drop)(struct tty_port *port); /* Called under the port mutex from tty_port_open, serialized using the port mutex */ /* FIXME: long term getting the tty argument *out* of this would be -- cgit v0.10.2 From f377775dc083506e2fd7739d8615971c46b5246e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 24 Sep 2013 21:05:58 -0500 Subject: TTY: hvc_dcc: probe for a JTAG connection before registering Enabling the ARM DCC console and using without a JTAG connection will simply hang the system. Since distros like to turn on all options, this is a reoccurring problem to debug. We can do better by checking if anything is attached and handling characters. There is no way to probe this, so send a newline and check that it is handled. Cc: Paolo Pisati Cc: Tim Gardner Cc: Greg Kroah-Hartman Cc: Jiri Slaby Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c index 44fbeba..3502a7b 100644 --- a/drivers/tty/hvc/hvc_dcc.c +++ b/drivers/tty/hvc/hvc_dcc.c @@ -86,6 +86,21 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count) return i; } +static bool hvc_dcc_check(void) +{ + unsigned long time = jiffies + (HZ / 10); + + /* Write a test character to check if it is handled */ + __dcc_putchar('\n'); + + while (time_is_after_jiffies(time)) { + if (!(__dcc_getstatus() & DCC_STATUS_TX)) + return true; + } + + return false; +} + static const struct hv_ops hvc_dcc_get_put_ops = { .get_chars = hvc_dcc_get_chars, .put_chars = hvc_dcc_put_chars, @@ -93,6 +108,9 @@ static const struct hv_ops hvc_dcc_get_put_ops = { static int __init hvc_dcc_console_init(void) { + if (!hvc_dcc_check()) + return -ENODEV; + hvc_instantiate(0, 0, &hvc_dcc_get_put_ops); return 0; } @@ -100,6 +118,9 @@ console_initcall(hvc_dcc_console_init); static int __init hvc_dcc_init(void) { + if (!hvc_dcc_check()) + return -ENODEV; + hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128); return 0; } -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index a0ebbc9..65d9b2f 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 v0.10.2 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 diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index febd45c..701ca60 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 v0.10.2 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 diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index d3db042..a187cd4b 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 v0.10.2 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 diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 52379e5..e0fbf87 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 570df9d..e33d38c 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index daf710f..d7a405b 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d7a405b..8edf769 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 v0.10.2 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 diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 569872f..c9f5c9d 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 v0.10.2 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 diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 8d70267..e30a3ca 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 v0.10.2 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 diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 3c75e8e..74749a6 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 v0.10.2 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 diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index 87636cc..4f22970 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 v0.10.2 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 diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index af286e6..5903909 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 v0.10.2 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 diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index f3dfa19..81f3dba 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 aaa617a..8827e54 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 v0.10.2 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 diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 5be1df3..e05a3b1 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 v0.10.2 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 diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 81f3dba..c1af04d 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 v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 65d9b2f..c07d9bb 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 v0.10.2 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 diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index a187cd4b..503dcc7 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 v0.10.2 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 diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index 440a962..90a080b 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index c810da7..515fd0f 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 v0.10.2 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 diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 61c1ad0..f186a8f 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 816d1a2..7e7da40 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 7e7da40..7b005206 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 v0.10.2 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 diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 49e9bbf..a447f71 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 v0.10.2 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 diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 7e4e408..8d0b994 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 v0.10.2 From 1926d0aeecf0280c67bf7464b2d68fe4e92c566b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 1 Sep 2013 17:24:16 +0100 Subject: hvc_vio: Do not override preferred console set by kernel parameter The original version of this was done by Bastian Blank, who wrote: > The problem is the following: > - Architecture specific code sets preferred console to something bogus. > - Command line handling tries to set preferred console but is overruled > by the old setting. > > The udbg0 console is a boot console and independant. References: http://bugs.debian.org/492703 Signed-off-by: Ben Hutchings Cc: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index c791b18..b594abf 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "hvc_console.h" @@ -457,7 +458,9 @@ void __init hvc_vio_init_early(void) if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) goto out; #endif - add_preferred_console("hvc", 0, NULL); + /* Check whether the user has requested a different console. */ + if (!strstr(cmd_line, "console=")) + add_preferred_console("hvc", 0, NULL); hvc_instantiate(0, 0, ops); out: of_node_put(stdout_node); -- cgit v0.10.2 From 64545880927e15d5e82a9f33c3fd0704c775bd80 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Tue, 10 Sep 2013 22:54:35 +0200 Subject: vt: break a couple of obsolete SCOish codes. No modern terminal supports them, and SGR 38 conflicts with detecting xterm-256 colours. This also makes SGR 39 consistent with other popular terminals. Neither are used by ncurses' terminfo. Signed-off-by: Adam Borowski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 9a8e8c5..ef95c6c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1300,21 +1300,8 @@ static void csi_m(struct vc_data *vc) case 27: vc->vc_reverse = 0; break; - case 38: /* ANSI X3.64-1979 (SCO-ish?) - * Enables underscore, white foreground - * with white underscore (Linux - use - * default foreground). - */ - vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0); - vc->vc_underline = 1; - break; - case 39: /* ANSI X3.64-1979 (SCO-ish?) - * Disable underline option. - * Reset colour to default? It did this - * before... - */ + case 39: vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0); - vc->vc_underline = 0; break; case 49: vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f); -- cgit v0.10.2 From 3415097ff0529eac264b8ccfa06572871e45c090 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 12 Jul 2013 22:23:41 +0200 Subject: vt: properly ignore xterm-256 colour codes This is not a bug on our side, but a misdesign in ITU T.416, yet with all popular terminals supporting these codes, people consider this to be a bug in Linux. By breaking the design principles behind SGR codes (gracefully ignoring unsupported ones should not require knowing about them), 256 colour ones tend to turn blinking on before invoking an arbitrary unrelated command. This commit doesn't add such support, merely skips such codes without ill effects. Signed-off-by: Adam Borowski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index ef95c6c..61b1137 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1300,6 +1300,28 @@ static void csi_m(struct vc_data *vc) case 27: vc->vc_reverse = 0; break; + case 38: + case 48: /* ITU T.416 + * Higher colour modes. + * They break the usual properties of SGR codes + * and thus need to be detected and ignored by + * hand. Strictly speaking, that standard also + * wants : rather than ; as separators, contrary + * to ECMA-48, but no one produces such codes + * and almost no one accepts them. + */ + i++; + if (i > vc->vc_npar) + break; + if (vc->vc_par[i] == 5) /* 256 colours */ + i++; /* ubiquitous */ + else if (vc->vc_par[i] == 2) /* 24 bit colours */ + i += 3; /* extremely rare */ + /* Subcommands 3 (CMY) and 4 (CMYK) are so insane + * that detecting them is not worth the few extra + * bytes of kernel's size. + */ + break; case 39: vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0); break; -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 515fd0f..d917bbb 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 8edf769..d04a037 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 v0.10.2 From f829452390cf817f0321b91e3096e06b85c4a07a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 30 Sep 2013 15:19:36 +0200 Subject: TTY: bfin_jtag_comm: fix incorrect placement of __initdata tag __initdata tag should be placed between the variable name and equal sign for the variable to be placed in the intended .init.data section. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c index a93a424..8096fcb 100644 --- a/drivers/tty/bfin_jtag_comm.c +++ b/drivers/tty/bfin_jtag_comm.c @@ -349,7 +349,7 @@ bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) bfin_jc_straight_buffer_write(buf, count); } -static struct __initdata console bfin_jc_early_console = { +static struct console bfin_jc_early_console __initdata = { .name = "early_BFJC", .write = bfin_jc_early_write, .flags = CON_ANYTIME | CON_PRINTBUFFER, -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index d917bbb..0774c02 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d04a037..4658e3e 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 v0.10.2 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 diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 8b90f0b..33bd860 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 aaa2286..7203864 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 v0.10.2 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 diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 10e9d70..d8b6fee 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 v0.10.2 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 diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 0489a2b..dfe79cc 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 v0.10.2 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 diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 74749a6..8f9b349 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 v0.10.2 From e8b5cbb041130ef297c90f8af2d3d45dfb9e6d15 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 7 Oct 2013 00:48:46 +0100 Subject: sysrq: Document hexadecimal values for kernel.sysrq bitmask It makes more sense to enter a bitmask in hexadecimal rather than decimal. Sadly we can't make it read back as hexadecimal. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 8cb4d78..1c0471d 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -20,18 +20,21 @@ in /proc/sys/kernel/sysrq: 1 - enable all functions of sysrq >1 - bitmask of allowed sysrq functions (see below for detailed function description): - 2 - enable control of console logging level - 4 - enable control of keyboard (SAK, unraw) - 8 - enable debugging dumps of processes etc. - 16 - enable sync command - 32 - enable remount read-only - 64 - enable signalling of processes (term, kill, oom-kill) - 128 - allow reboot/poweroff - 256 - allow nicing of all RT tasks + 2 = 0x2 - enable control of console logging level + 4 = 0x4 - enable control of keyboard (SAK, unraw) + 8 = 0x8 - enable debugging dumps of processes etc. + 16 = 0x10 - enable sync command + 32 = 0x20 - enable remount read-only + 64 = 0x40 - enable signalling of processes (term, kill, oom-kill) + 128 = 0x80 - allow reboot/poweroff + 256 = 0x100 - allow nicing of all RT tasks You can set the value in the file by the following command: echo "number" >/proc/sys/kernel/sysrq +The number may be written either as decimal or as hexadecimal with the +0x prefix. + Note that the value of /proc/sys/kernel/sysrq influences only the invocation via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always allowed (by a user with admin privileges). -- cgit v0.10.2 From 8eaede49dfdc1ff1d727f9c913665b8009945191 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 7 Oct 2013 01:05:46 +0100 Subject: sysrq: Allow magic SysRq key functions to be disabled through Kconfig Turn the initial value of sysctl kernel.sysrq (SYSRQ_DEFAULT_ENABLE) into a Kconfig variable. Original version by Bastian Blank . Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 1c0471d..0e307c9 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -11,11 +11,9 @@ regardless of whatever else it is doing, unless it is completely locked up. You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when configuring the kernel. When running a kernel with SysRq compiled in, /proc/sys/kernel/sysrq controls the functions allowed to be invoked via -the SysRq key. By default the file contains 1 which means that every -possible SysRq request is allowed (in older versions SysRq was disabled -by default, and you were required to specifically enable it at run-time -but this is not the case any more). Here is the list of possible values -in /proc/sys/kernel/sysrq: +the SysRq key. The default value in this file is set by the +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults +to 1. Here is the list of possible values in /proc/sys/kernel/sysrq: 0 - disable sysrq completely 1 - enable all functions of sysrq >1 - bitmask of allowed sysrq functions (see below for detailed function @@ -32,8 +30,9 @@ in /proc/sys/kernel/sysrq: You can set the value in the file by the following command: echo "number" >/proc/sys/kernel/sysrq -The number may be written either as decimal or as hexadecimal with the -0x prefix. +The number may be written here either as decimal or as hexadecimal +with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be +written in hexadecimal. Note that the value of /proc/sys/kernel/sysrq influences only the invocation via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 40a9fe9..ce396ec 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -51,7 +51,7 @@ #include /* Whether we react on sysrq keys or just ignore them */ -static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE; +static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static bool __read_mostly sysrq_always_enabled; unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 7faf933..387fa7d 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -17,9 +17,6 @@ #include #include -/* Enable/disable SYSRQ support by default (0==no, 1==yes). */ -#define SYSRQ_DEFAULT_ENABLE 1 - /* Possible values of bitmask for enabling sysrq functions */ /* 0x0001 is reserved for enable everything */ #define SYSRQ_ENABLE_LOG 0x0002 diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b2f06f3..8b80f1b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -190,7 +190,7 @@ static int proc_dostring_coredump(struct ctl_table *table, int write, #ifdef CONFIG_MAGIC_SYSRQ /* Note: sysrq code uses it's own private copy */ -static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; +static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static int sysrq_sysctl_handler(ctl_table *table, int write, void __user *buffer, size_t *lenp, diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 06344d9..2932937 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -312,6 +312,15 @@ config MAGIC_SYSRQ keys are documented in . Don't say Y unless you really know what this hack does. +config MAGIC_SYSRQ_DEFAULT_ENABLE + hex "Enable magic SysRq key functions by default" + depends on MAGIC_SYSRQ + default 0x1 + help + Specifies which SysRq key functions are enabled by default. + This may be set to 1 or 0 to enable or disable them all, or + to a bitmask as described in Documentation/sysrq.txt. + config DEBUG_KERNEL bool "Kernel debugging" help -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 5f3bba1..d1a9078 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 v0.10.2 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 diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index a67e708..ee77e73 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 v0.10.2 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 diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index ee77e73..565779d 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 v0.10.2 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 diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index d6080c3..cd04293 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -959,7 +959,7 @@ static int receive_flow_control(struct nozomi *dc) dev_err(&dc->pdev->dev, "ERROR: flow control received for non-existing port\n"); return 0; - }; + } DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl), *((u16 *)&ctrl_dl)); @@ -1025,7 +1025,7 @@ static enum ctrl_port_type port2ctrl(enum port_type port, dev_err(&dc->pdev->dev, "ERROR: send flow control " \ "received for non-existing port\n"); - }; + } return CTRL_ERROR; } @@ -1805,7 +1805,7 @@ static int ntty_ioctl(struct tty_struct *tty, default: DBG1("ERR: 0x%08X, %d", cmd, cmd); break; - }; + } return rval; } diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 8f9b349..869ceba 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 cb3c81e..1d94205 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 b2e707aa..8d71e40 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 f87f1a0..95917ce 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 5d6136b2..380fb53 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 699cc1b..db79b76 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 135a152..45a8c6a 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 8831748..2fd1e17 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 v0.10.2 From c476f6584b0011741b4f0316f1ac4aa3a99403e1 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 11 Oct 2013 22:08:49 +0200 Subject: tty: incorrect test of echo_buf() result for ECHO_OP_START test echo_buf() result for ECHO_OP_START Signed-off-by: Roel Kluin Acked-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4e69f3b..7cdd1eb 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -767,7 +767,7 @@ static size_t __process_echoes(struct tty_struct *tty) * of echo overrun before the next commit), then discard enough * data at the tail to prevent a subsequent overrun */ while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { - if (echo_buf(ldata, tail == ECHO_OP_START)) { + if (echo_buf(ldata, tail) == ECHO_OP_START) { if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB) tail += 3; else -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 7b005206..c715778 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 v0.10.2 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 diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index ba25722..753d452 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 v0.10.2 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 diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index e05a3b1..ec06505 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 v0.10.2 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 diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 87f25de..0aa2b52 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 v0.10.2 From fa2b5ea09e48186041f68649ab8192447b31bffc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Oct 2013 09:20:52 +0200 Subject: serial: core: delete .set_wake() callback This deletes the .set_wake() callback in the struct uart_ops. Apparently this has been unused since pre-git times. In the old-2.6-bkcvs it is deleted as part of a changeset removing the PM_SET_WAKEUP from pm_request_t which is since also deleted from the kernel. The apropriate way to set wakeups in the kernel is to have a code snippet like this in .suspend() or .runtime_suspend() callbacks: static int foo_suspend(struct device *dev) { if (device_may_wakeup(dev)) { /* Enable wakeups, set internal states */ } } This specific callback is not coming back. Cc: Rafael J. Wysocki Cc: Len Brown Cc: Pavel Machek Cc: Kevin Hilman Cc: Dmitry Artamonow Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 067c47d..c3a7689 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -264,10 +264,6 @@ hardware. Locking: none. Interrupts: caller dependent. - set_wake(port,state) - Enable/disable power management wakeup on serial activity. Not - currently implemented. - type(port) Return a pointer to a string constant describing the specified port, or return NULL, in which case the string 'unknown' is diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index b98291a..f729be9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -66,7 +66,6 @@ struct uart_ops { void (*set_ldisc)(struct uart_port *, int new); void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate); - int (*set_wake)(struct uart_port *, unsigned int state); /* * Return a string describing the type of the port -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c07d9bb..708ba89 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 v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 708ba89..c6c3b16 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 v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c6c3b16..cadf7e5 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 v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index cadf7e5..13c2c2d 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 v0.10.2 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 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 13c2c2d..bb84f8d 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0774c02..4ea45c15 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 v0.10.2 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 diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index d067285..6b0f75e 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 v0.10.2 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 diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 6b0f75e..c7d99af 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"); + } } } diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h index be201ca..00beddf 100644 --- a/include/linux/atmel_serial.h +++ b/include/linux/atmel_serial.h @@ -125,5 +125,6 @@ #define ATMEL_US_IF 0x4c /* IrDA Filter Register */ #define ATMEL_US_NAME 0xf0 /* Ip Name */ +#define ATMEL_US_VERSION 0xfc /* Ip Version */ #endif -- cgit v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 7e4150a..103ba88 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 103ba88..8c07459 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8c07459..5d5557a 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5d5557a..62259f3 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 62259f3..6e8ec6e 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6e8ec6e..fdc739b 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index fdc739b..95e12c2 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 95e12c2..8219504 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8219504..9ecd8ea 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 9ecd8ea..c7c96c2 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 v0.10.2 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 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4ea45c15..4697a51 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, @@ -2016,6 +2039,31 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index c7c96c2..5ac6c48 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5ac6c48..ca4a2f1 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 v0.10.2 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 diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ca4a2f1..e46e9f3 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 v0.10.2 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 diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index fb8d0a0..b7d679c 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index c715778..b69393f 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 v0.10.2 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 diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 565779d..db0448a 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b69393f..e42eb1e 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index e42eb1e..97c07f6 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 v0.10.2 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 diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 503dcc7..52c930f 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 v0.10.2 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 diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 701ca60..a3817ab 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 v0.10.2 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 diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 97c07f6..fa511eb 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 v0.10.2