From 187094feeb77b5f49513f6a1cfe12749c080bd96 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sun, 3 Nov 2013 18:38:12 +0200 Subject: serial: pl011: remove redundant early amba_ports declaration This early amba_ports declaration was introduced by commit c16d51a32 (amba pl011: workaround for uart registers lockup) for use in the pl011_lockup_wa() routine. This routine was later removed by commit 4fd0690bb (serial: pl011: implement workaround for CTS clear event issue). Signed-off-by: Baruch Siach Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 7203864992a5..742c8bf0c2d2 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -112,8 +112,6 @@ static struct vendor_data vendor_st = { .get_fifosize = get_fifosize_st, }; -static struct uart_amba_port *amba_ports[UART_NR]; - /* Deals with DMA transactions */ struct pl011_sgbuf { -- cgit v1.2.3 From d0ce850d60166e99d5cca011d4b871a7cc1f930c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 3 Dec 2013 11:04:28 +0100 Subject: serial: pl011: Convert to modern PM ops Convert to modern PM ops and use the SIMPLE_DEV_PM_OPS macro to set up the PM callbacks. Cc: Greg Kroah-Hartman Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 742c8bf0c2d2..a183aceb6d15 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2167,10 +2167,10 @@ static int pl011_remove(struct amba_device *dev) return 0; } -#ifdef CONFIG_PM -static int pl011_suspend(struct amba_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pl011_suspend(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (!uap) return -EINVAL; @@ -2178,9 +2178,9 @@ static int pl011_suspend(struct amba_device *dev, pm_message_t state) return uart_suspend_port(&amba_reg, &uap->port); } -static int pl011_resume(struct amba_device *dev) +static int pl011_resume(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (!uap) return -EINVAL; @@ -2189,6 +2189,8 @@ static int pl011_resume(struct amba_device *dev) } #endif +static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume); + static struct amba_id pl011_ids[] = { { .id = 0x00041011, @@ -2208,14 +2210,11 @@ MODULE_DEVICE_TABLE(amba, pl011_ids); static struct amba_driver pl011_driver = { .drv = { .name = "uart-pl011", + .pm = &pl011_dev_pm_ops, }, .id_table = pl011_ids, .probe = pl011_probe, .remove = pl011_remove, -#ifdef CONFIG_PM - .suspend = pl011_suspend, - .resume = pl011_resume, -#endif }; static int __init pl011_init(void) -- cgit v1.2.3 From 17438217a6f5e33d920ed3821a4b857311cc2872 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Nov 2013 10:41:04 +0100 Subject: serial: pl011: use DMA RX polling by default Making DMA RX polling optional when DMA is on was just over-cautious: there is one single system in the kernel tree using this facility, Ux500 and after some testing I turned this on also for Ux500, which means it should simply be on by default if DMA is enabled. Cc: Jongsung Kim Cc: Chanho Min Cc: Russell King Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- include/linux/amba/serial.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index a183aceb6d15..c8cc8f02b092 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -325,7 +325,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * dmaengine_slave_config(chan, &rx_conf); uap->dmarx.chan = chan; - if (plat && plat->dma_rx_poll_enable) { + if (plat) { /* Set poll rate if specified. */ if (plat->dma_rx_poll_rate) { uap->dmarx.auto_poll_rate = false; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 0ddb5c02ad8b..0891ea0458f6 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -203,7 +203,6 @@ struct amba_pl011_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; - bool dma_rx_poll_enable; unsigned int dma_rx_poll_rate; unsigned int dma_rx_poll_timeout; void (*init) (void); -- cgit v1.2.3 From 8f898bfd048f65856d8911a89b1616ad3e677c6c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Dec 2013 09:33:18 -0800 Subject: Revert "serial: pl011: use DMA RX polling by default" This reverts commit 17438217a6f5e33d920ed3821a4b857311cc2872 on request of Linus Walleij: Greg can you please drop or revert commit 17438217a6f5e33d920ed3821a4b857311cc2872 "serial: pl011: use DMA RX polling by default" from the TTY tree until this has been sorted out? Cc: Linus Walleij Cc: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- include/linux/amba/serial.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c8cc8f02b092..a183aceb6d15 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -325,7 +325,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * dmaengine_slave_config(chan, &rx_conf); uap->dmarx.chan = chan; - if (plat) { + if (plat && plat->dma_rx_poll_enable) { /* Set poll rate if specified. */ if (plat->dma_rx_poll_rate) { uap->dmarx.auto_poll_rate = false; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 0891ea0458f6..0ddb5c02ad8b 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -203,6 +203,7 @@ struct amba_pl011_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; + bool dma_rx_poll_enable; unsigned int dma_rx_poll_rate; unsigned int dma_rx_poll_timeout; void (*init) (void); -- cgit v1.2.3 From fe43390702a1b5741fdf217063b05c7612b38303 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Tue, 10 Dec 2013 10:18:58 +0000 Subject: serial: amba-pl011: use port lock to guard control register access When the pl011 is being used for a console, pl011_console_write forces the control register (CR) to enable the UART for transmission and then restores this to the original value afterwards. It does this while holding the port lock. Unfortunately, when the uart is started or shutdown - say in response to userland using the serial device for a terminal - then this updates the control register without any locking. This means we can have pl011_console_write Save CR pl011_startup Initialise CR, e.g. enable receive pl011_console_write Restore old CR with receive not enabled this result is a serial port which doesn't respond to any input. A similar race in reverse could happen when the device is shutdown. We can fix these problems by taking the port lock when updating CR. Signed-off-by: Jon Medhurst Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index a183aceb6d15..a576a5bc2d15 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1535,6 +1535,8 @@ static int pl011_startup(struct uart_port *port) /* * Provoke TX FIFO interrupt into asserting. */ + spin_lock_irq(&uap->port.lock); + cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; writew(cr, uap->port.membase + UART011_CR); writew(0, uap->port.membase + UART011_FBRD); @@ -1559,6 +1561,8 @@ static int pl011_startup(struct uart_port *port) cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); + spin_unlock_irq(&uap->port.lock); + /* * initialise the old status of the modem signals */ @@ -1627,11 +1631,13 @@ static void pl011_shutdown(struct uart_port *port) * it during startup(). */ uap->autorts = false; + spin_lock_irq(&uap->port.lock); cr = readw(uap->port.membase + UART011_CR); uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); + spin_unlock_irq(&uap->port.lock); /* * disable break condition and fifos -- cgit v1.2.3 From b60f2f66a58c43e8c928336ec72f64e72f1237ea Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Tue, 10 Dec 2013 10:18:59 +0000 Subject: serial: amba-pl011: factor out code for writing LCR_H register The code to cope with a split tx/rx LCR_H register is non-trivial so put it into it's own function to avoid duplication. Signed-off-by: Jon Medhurst Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index a576a5bc2d15..844bfba9d0ab 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1511,6 +1511,21 @@ static int pl011_hwinit(struct uart_port *port) return retval; } +static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) +{ + writew(lcr_h, uap->port.membase + uap->lcrh_rx); + if (uap->lcrh_rx != uap->lcrh_tx) { + int i; + /* + * Wait 10 PCLKs before writing LCRH_TX register, + * to get this delay write read only register 10 times + */ + for (i = 0; i < 10; ++i) + writew(0xff, uap->port.membase + UART011_MIS); + writew(lcr_h, uap->port.membase + uap->lcrh_tx); + } +} + static int pl011_startup(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1541,17 +1556,7 @@ static int pl011_startup(struct uart_port *port) writew(cr, uap->port.membase + UART011_CR); writew(0, uap->port.membase + UART011_FBRD); writew(1, uap->port.membase + UART011_IBRD); - writew(0, uap->port.membase + uap->lcrh_rx); - if (uap->lcrh_tx != uap->lcrh_rx) { - int i; - /* - * Wait 10 PCLKs before writing LCRH_TX register, - * to get this delay write read only register 10 times - */ - for (i = 0; i < 10; ++i) - writew(0xff, uap->port.membase + UART011_MIS); - writew(0, uap->port.membase + uap->lcrh_tx); - } + pl011_write_lcr_h(uap, 0); writew(0, uap->port.membase + UART01x_DR); while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) barrier(); @@ -1801,17 +1806,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ - writew(lcr_h, port->membase + uap->lcrh_rx); - if (uap->lcrh_rx != uap->lcrh_tx) { - int i; - /* - * Wait 10 PCLKs before writing LCRH_TX register, - * to get this delay write read only register 10 times - */ - for (i = 0; i < 10; ++i) - writew(0xff, uap->port.membase + UART011_MIS); - writew(lcr_h, port->membase + uap->lcrh_tx); - } + pl011_write_lcr_h(uap, lcr_h); writew(old_cr, port->membase + UART011_CR); spin_unlock_irqrestore(&port->lock, flags); -- cgit v1.2.3 From 570d291048aecc02271884f6a5f50ad555f271a5 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Tue, 10 Dec 2013 10:19:00 +0000 Subject: serial: amba-pl011: preseserve hardware settings during initialisation During initialisation, a UART may already be in use for a console, so take care to preserve things like baud rate and data format to avoid corrupting console output. Signed-off-by: Jon Medhurst Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 844bfba9d0ab..182a922e1942 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1529,7 +1529,7 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) static int pl011_startup(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int cr; + unsigned int cr, lcr_h, fbrd, ibrd; int retval; retval = pl011_hwinit(port); @@ -1548,10 +1548,16 @@ static int pl011_startup(struct uart_port *port) writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); /* - * Provoke TX FIFO interrupt into asserting. + * Provoke TX FIFO interrupt into asserting. Taking care to preserve + * baud rate and data format specified by FBRD, IBRD and LCRH as the + * UART may already be in use as a console. */ spin_lock_irq(&uap->port.lock); + fbrd = readw(uap->port.membase + UART011_FBRD); + ibrd = readw(uap->port.membase + UART011_IBRD); + lcr_h = readw(uap->port.membase + uap->lcrh_rx); + cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; writew(cr, uap->port.membase + UART011_CR); writew(0, uap->port.membase + UART011_FBRD); @@ -1561,6 +1567,10 @@ static int pl011_startup(struct uart_port *port) while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) barrier(); + writew(fbrd, uap->port.membase + UART011_FBRD); + writew(ibrd, uap->port.membase + UART011_IBRD); + pl011_write_lcr_h(uap, lcr_h); + /* restore RTS and DTR */ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; -- cgit v1.2.3 From 30ae5859186f564d40cee04579e901e41c3826e2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 10 Dec 2013 14:54:42 +0100 Subject: serial: pl011: (cosmetic) remove superfluous register write In pl011_rx_chars() if pl011_dma_rx_trigger_dma() succeeds it will disable the receive interrupt, no need to do this again. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 182a922e1942..ea6c2a3798ff 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1214,8 +1214,8 @@ __acquires(&uap->port.lock) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; + writew(uap->im, uap->port.membase + UART011_IMSC); } else { - uap->im &= ~UART011_RXIM; #ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ if (uap->dmarx.poll_rate) { @@ -1227,8 +1227,6 @@ __acquires(&uap->port.lock) } #endif } - - writew(uap->im, uap->port.membase + UART011_IMSC); } spin_lock(&uap->port.lock); } -- cgit v1.2.3 From c25a1ad7077ab9914bad1374df8b9cdb9bf5f0ad Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 10 Dec 2013 14:54:47 +0100 Subject: serial: pl011: fix fall back from DMA to interrupt mode When falling back from DMA to interrupt mode the receive interrupt has to be re-enabled to catch new incoming data. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial/amba-pl011.c') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index ea6c2a3798ff..d58783d364e3 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -967,6 +967,8 @@ static void pl011_dma_rx_poll(unsigned long args) spin_lock_irqsave(&uap->port.lock, flags); pl011_dma_rx_stop(uap); + uap->im |= UART011_RXIM; + writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irqrestore(&uap->port.lock, flags); uap->dmarx.running = false; -- cgit v1.2.3