summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 16:36:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 16:36:24 -0700
commit6181073dd6a7e5deafc60e7981bd765b6c93da8c (patch)
tree15781e235b3d3f11635ed27ec77d4cf0fef09e25 /drivers/tty/serial
parent881eccbef52563feb4fde0d19d375884798783f7 (diff)
parent30963b2f75bfdbbcf1cc5d80bf88fec7aaba808d (diff)
downloadlinux-stable-6181073dd6a7e5deafc60e7981bd765b6c93da8c.tar.gz
linux-stable-6181073dd6a7e5deafc60e7981bd765b6c93da8c.tar.bz2
linux-stable-6181073dd6a7e5deafc60e7981bd765b6c93da8c.zip
Merge tag 'tty-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big set of TTY and Serial driver updates for 6.1-rc1. Lots of cleanups in here, no real new functionality this time around, with the diffstat being that we removed more lines than we added! Included in here are: - termios unification cleanups from Al Viro, it's nice to finally get this work done - tty serial transmit cleanups in various drivers in preparation for more cleanup and unification in future releases (that work was not ready for this release) - n_gsm fixes and updates - ktermios cleanups and code reductions - dt bindings json conversions and updates for new devices - some serial driver updates for new devices - lots of other tiny cleanups and janitorial stuff. Full details in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'tty-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (102 commits) serial: cpm_uart: Don't request IRQ too early for console port tty: serial: do unlock on a common path in altera_jtaguart_console_putc() tty: serial: unify TX space reads under altera_jtaguart_tx_space() tty: serial: use FIELD_GET() in lqasc_tx_ready() tty: serial: extend lqasc_tx_ready() to lqasc_console_putchar() tty: serial: allow pxa.c to be COMPILE_TESTed serial: stm32: Fix unused-variable warning tty: serial: atmel: Add COMMON_CLK dependency to SERIAL_ATMEL serial: 8250: Fix restoring termios speed after suspend serial: Deassert Transmit Enable on probe in driver-specific way serial: 8250_dma: Convert to use uart_xmit_advance() serial: 8250_omap: Convert to use uart_xmit_advance() MAINTAINERS: Solve warning regarding inexistent atmel-usart binding serial: stm32: Deassert Transmit Enable on ->rs485_config() serial: ar933x: Deassert Transmit Enable on ->rs485_config() tty: serial: atmel: Use FIELD_PREP/FIELD_GET tty: serial: atmel: Make the driver aware of the existence of GCLK tty: serial: atmel: Only divide Clock Divisor if the IP is USART tty: serial: atmel: Separate mode clearing between UART and USART dt-bindings: serial: atmel,at91-usart: Add gclk as a possible USART clock ...
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/21285.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c2
-rw-r--r--drivers/tty/serial/8250/8250_core.c16
-rw-r--r--drivers/tty/serial/8250/8250_dma.c7
-rw-r--r--drivers/tty/serial/8250/8250_dw.c2
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.c3
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.h2
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c2
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c2
-rw-r--r--drivers/tty/serial/8250/8250_men_mcb.c1
-rw-r--r--drivers/tty/serial/8250/8250_mid.c5
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c2
-rw-r--r--drivers/tty/serial/8250/8250_omap.c9
-rw-r--r--drivers/tty/serial/8250/8250_pci.c14
-rw-r--r--drivers/tty/serial/8250/8250_port.c62
-rw-r--r--drivers/tty/serial/Kconfig5
-rw-r--r--drivers/tty/serial/altera_jtaguart.c36
-rw-r--r--drivers/tty/serial/altera_uart.c18
-rw-r--r--drivers/tty/serial/amba-pl010.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c20
-rw-r--r--drivers/tty/serial/apbuart.c2
-rw-r--r--drivers/tty/serial/ar933x_uart.c9
-rw-r--r--drivers/tty/serial/arc_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c87
-rw-r--r--drivers/tty/serial/atmel_serial.h75
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c5
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart.h1
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c55
-rw-r--r--drivers/tty/serial/digicolor-usart.c2
-rw-r--r--drivers/tty/serial/dz.c11
-rw-r--r--drivers/tty/serial/earlycon.c6
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c27
-rw-r--r--drivers/tty/serial/icom.c5
-rw-r--r--drivers/tty/serial/imx.c10
-rw-r--r--drivers/tty/serial/ip22zilog.c2
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c3
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c4
-rw-r--r--drivers/tty/serial/lantiq.c25
-rw-r--r--drivers/tty/serial/liteuart.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c12
-rw-r--r--drivers/tty/serial/max3100.c2
-rw-r--r--drivers/tty/serial/max310x.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/men_z135_uart.c4
-rw-r--r--drivers/tty/serial/meson_uart.c31
-rw-r--r--drivers/tty/serial/milbeaut_usio.c3
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c30
-rw-r--r--drivers/tty/serial/mps2-uart.c2
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/mux.c2
-rw-r--r--drivers/tty/serial/mvebu-uart.c2
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/omap-serial.c49
-rw-r--r--drivers/tty/serial/owl-uart.c2
-rw-r--r--drivers/tty/serial/pch_uart.c7
-rw-r--r--drivers/tty/serial/pic32_uart.c52
-rw-r--r--drivers/tty/serial/pmac_zilog.c4
-rw-r--r--drivers/tty/serial/pxa.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c8
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/rp2.c5
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung_tty.c2
-rw-r--r--drivers/tty/serial/sb1250-duart.c2
-rw-r--r--drivers/tty/serial/sc16is7xx.c2
-rw-r--r--drivers/tty/serial/sccnxp.c3
-rw-r--r--drivers/tty/serial/serial-tegra.c15
-rw-r--r--drivers/tty/serial/serial_core.c46
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c8
-rw-r--r--drivers/tty/serial/sifive.c2
-rw-r--r--drivers/tty/serial/sprd_serial.c5
-rw-r--r--drivers/tty/serial/st-asc.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c108
-rw-r--r--drivers/tty/serial/sunhv.c2
-rw-r--r--drivers/tty/serial/sunplus-uart.c2
-rw-r--r--drivers/tty/serial/sunsab.c22
-rw-r--r--drivers/tty/serial/sunsu.c8
-rw-r--r--drivers/tty/serial/sunzilog.c8
-rw-r--r--drivers/tty/serial/tegra-tcu.c2
-rw-r--r--drivers/tty/serial/timbuart.c4
-rw-r--r--drivers/tty/serial/uartlite.c5
-rw-r--r--drivers/tty/serial/ucc_uart.c18
-rw-r--r--drivers/tty/serial/vt8500_serial.c17
-rw-r--r--drivers/tty/serial/xilinx_uartps.c62
-rw-r--r--drivers/tty/serial/zs.c2
88 files changed, 611 insertions, 516 deletions
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c
index 65d6af755567..c7d34823f715 100644
--- a/drivers/tty/serial/21285.c
+++ b/drivers/tty/serial/21285.c
@@ -243,7 +243,7 @@ static void serial21285_shutdown(struct uart_port *port)
static void
serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, quot, h_lcr, b;
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 8efdc271eb75..fa8ccf204d86 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -755,7 +755,7 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
static void brcmstb_set_termios(struct uart_port *up,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_8250_port *p8250 = up_to_u8250p(up);
struct brcmuart_priv *priv = up->private_data;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 2e83e7367441..94fbf0add2ce 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -298,10 +298,9 @@ static void serial8250_backup_timeout(struct timer_list *t)
jiffies + uart_poll_timeout(&up->port) + HZ / 5);
}
-static int univ8250_setup_irq(struct uart_8250_port *up)
+static void univ8250_setup_timer(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
- int retval = 0;
/*
* The above check will only give an accurate result the first time
@@ -322,10 +321,16 @@ static int univ8250_setup_irq(struct uart_8250_port *up)
*/
if (!port->irq)
mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
- else
- retval = serial_link_irq_chain(up);
+}
- return retval;
+static int univ8250_setup_irq(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+
+ if (port->irq)
+ return serial_link_irq_chain(up);
+
+ return 0;
}
static void univ8250_release_irq(struct uart_8250_port *up)
@@ -381,6 +386,7 @@ static struct uart_ops univ8250_port_ops;
static const struct uart_8250_ops univ8250_driver_ops = {
.setup_irq = univ8250_setup_irq,
.release_irq = univ8250_release_irq,
+ .setup_timer = univ8250_setup_timer,
};
static struct uart_8250_port serial8250_ports[UART_NR];
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index a8dba4a0a8fb..b85c82616e8c 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -26,9 +26,7 @@ static void __dma_tx_complete(void *param)
dma->tx_running = 0;
- xmit->tail += dma->tx_size;
- xmit->tail &= UART_XMIT_SIZE - 1;
- p->port.icount.tx += dma->tx_size;
+ uart_xmit_advance(&p->port, dma->tx_size);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&p->port);
@@ -107,8 +105,7 @@ int serial8250_tx_dma(struct uart_8250_port *p)
dma_async_issue_pending(dma->txchan);
serial8250_clear_THRI(p);
- if (dma->tx_err)
- dma->tx_err = 0;
+ dma->tx_err = 0;
return 0;
err:
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a604b42e4458..7db51781289e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -350,7 +350,7 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
}
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long newrate = tty_termios_baud_rate(termios) * 16;
struct dw8250_data *d = to_dw8250_data(p->private_data);
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index dbe4d44f60d4..75f32f054ebb 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -92,7 +92,8 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
serial8250_do_set_divisor(p, baud, quot, quot_frac);
}
-void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old)
+void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios,
+ const struct ktermios *old)
{
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 055bfdc87985..f13e91f2cace 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -47,7 +47,7 @@ struct dw8250_data {
unsigned int uart_16550_compatible:1;
};
-void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
+void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, const struct ktermios *old);
void dw8250_setup_port(struct uart_port *p);
static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index 65b6b3cbaff6..e2aa2a1a02dd 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -278,7 +278,7 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
static void fintek_8250_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct fintek_8250 *pdata = port->private_data;
unsigned int baud = tty_termios_baud_rate(termios);
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 4ba43bef9933..44cc755b1a29 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -70,7 +70,7 @@ static inline struct lpss8250 *to_lpss8250(struct dw8250_port_data *data)
}
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct lpss8250 *lpss = to_lpss8250(p->private_data);
diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c
index 737c4c31e8a0..f46ca13ff4aa 100644
--- a/drivers/tty/serial/8250/8250_men_mcb.c
+++ b/drivers/tty/serial/8250/8250_men_mcb.c
@@ -7,7 +7,6 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
-#include <uapi/linux/serial_core.h>
#define MEN_UART_ID_Z025 0x19
#define MEN_UART_ID_Z057 0x39
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index a2a03acb04ad..2cc78a4bf7a1 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -206,9 +206,8 @@ static void dnv_exit(struct mid8250 *mid)
/*****************************************************************************/
-static void mid8250_set_termios(struct uart_port *p,
- struct ktermios *termios,
- struct ktermios *old)
+static void mid8250_set_termios(struct uart_port *p, struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct mid8250 *mid = p->private_data;
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 54051ec7b499..fb1d5ec0940e 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -291,7 +291,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
static void
mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
static const unsigned short fraction_L_mapping[] = {
0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index f7fbef83583c..41b8c6b27136 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -342,6 +342,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
omap8250_update_mdr1(up, priv);
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
+
+ if (up->port.rs485.flags & SER_RS485_ENABLED)
+ serial8250_em485_stop_tx(up);
}
/*
@@ -350,7 +353,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
*/
static void omap_8250_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = up->port.private_data;
@@ -984,9 +987,7 @@ static void omap_8250_dma_tx_complete(void *param)
dma->tx_running = 0;
- xmit->tail += dma->tx_size;
- xmit->tail &= UART_XMIT_SIZE - 1;
- p->port.icount.tx += dma->tx_size;
+ uart_xmit_advance(&p->port, dma->tx_size);
if (priv->delayed_restore) {
priv->delayed_restore = 0;
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 6f66dc2ebacc..8e9f247590bd 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1232,6 +1232,10 @@ static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port,
serial8250_do_set_mctrl(port, mctrl);
}
+/*
+ * We require EFR features for clock programming, so set UPF_FULL_PROBE
+ * for full probing regardless of CONFIG_SERIAL_8250_16550A_VARIANTS setting.
+ */
static int pci_oxsemi_tornado_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *up, int idx)
@@ -1239,6 +1243,7 @@ static int pci_oxsemi_tornado_setup(struct serial_private *priv,
struct pci_dev *dev = priv->dev;
if (pci_oxsemi_tornado_p(dev)) {
+ up->port.flags |= UPF_FULL_PROBE;
up->port.get_divisor = pci_oxsemi_tornado_get_divisor;
up->port.set_divisor = pci_oxsemi_tornado_set_divisor;
up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl;
@@ -1627,7 +1632,6 @@ static int pci_fintek_init(struct pci_dev *dev)
resource_size_t bar_data[3];
u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev);
- struct uart_8250_port *port;
if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 4) & IORESOURCE_IO) ||
@@ -1674,13 +1678,7 @@ static int pci_fintek_init(struct pci_dev *dev)
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
- if (priv) {
- /* re-apply RS232/485 mode when
- * pciserial_resume_ports()
- */
- port = serial8250_get_port(priv->line[i]);
- uart_rs485_config(&port->port);
- } else {
+ if (!priv) {
/* First init without port data
* force init to RS232 Mode
*/
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 39b35a61958c..fe8662cd9402 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -600,7 +600,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put);
static int serial8250_em485_init(struct uart_8250_port *p)
{
if (p->em485)
- return 0;
+ goto deassert_rts;
p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC);
if (!p->em485)
@@ -616,7 +616,9 @@ static int serial8250_em485_init(struct uart_8250_port *p)
p->em485->active_timer = NULL;
p->em485->tx_stopped = true;
- p->rs485_stop_tx(p);
+deassert_rts:
+ if (p->em485->tx_stopped)
+ p->rs485_stop_tx(p);
return 0;
}
@@ -752,6 +754,14 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial8250_rpm_put(p);
}
+static void serial8250_clear_IER(struct uart_8250_port *up)
+{
+ if (up->capabilities & UART_CAP_UUE)
+ serial_out(up, UART_IER, UART_IER_UUE);
+ else
+ serial_out(up, UART_IER, 0);
+}
+
#ifdef CONFIG_SERIAL_8250_RSA
/*
* Attempts to turn on the RSA FIFO. Returns zero on failure.
@@ -1021,7 +1031,8 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
- if (!IS_ENABLED(CONFIG_SERIAL_8250_16550A_VARIANTS))
+ if (!IS_ENABLED(CONFIG_SERIAL_8250_16550A_VARIANTS) &&
+ !(up->port.flags & UPF_FULL_PROBE))
return;
/*
@@ -1133,7 +1144,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* internal UARTs.
* We're going to explicitly set the UUE bit to 0 before
* trying to write and read a 1 just to make sure it's not
- * already a 1 and maybe locked there before we even start start.
+ * already a 1 and maybe locked there before we even start.
*/
iersave = serial_in(up, UART_IER);
serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
@@ -1329,10 +1340,7 @@ static void autoconfig(struct uart_8250_port *up)
serial8250_out_MCR(up, save_mcr);
serial8250_clear_fifos(up);
serial_in(up, UART_RX);
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
+ serial8250_clear_IER(up);
out_unlock:
spin_unlock_irqrestore(&port->lock, flags);
@@ -2042,6 +2050,9 @@ EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ if (port->rs485.flags & SER_RS485_ENABLED)
+ return;
+
if (port->set_mctrl)
port->set_mctrl(port, mctrl);
else
@@ -2142,10 +2153,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
+ serial8250_clear_IER(up);
wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
/*
@@ -2294,6 +2302,10 @@ int serial8250_do_startup(struct uart_port *port)
if (port->irq && (up->port.flags & UPF_SHARE_IRQ))
up->port.irqflags |= IRQF_SHARED;
+ retval = up->ops->setup_irq(up);
+ if (retval)
+ goto out;
+
if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
unsigned char iir1;
@@ -2336,9 +2348,7 @@ int serial8250_do_startup(struct uart_port *port)
}
}
- retval = up->ops->setup_irq(up);
- if (retval)
- goto out;
+ up->ops->setup_timer(up);
/*
* Now, initialize the UART
@@ -2651,7 +2661,7 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
static unsigned int serial8250_get_baud_rate(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int tolerance = port->uartclk / 100;
unsigned int min;
@@ -2737,7 +2747,7 @@ EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char cval;
@@ -2875,7 +2885,7 @@ EXPORT_SYMBOL(serial8250_do_set_termios);
static void
serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
if (port->set_termios)
port->set_termios(port, termios, old);
@@ -3187,9 +3197,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if (flags & UART_CONFIG_TYPE)
autoconfig(up);
- if (port->rs485.flags & SER_RS485_ENABLED)
- uart_rs485_config(port);
-
/* if access method is AU, it is a 16550 with a quirk */
if (port->type == PORT_16550A && port->iotype == UPIO_AU)
up->bugs |= UART_BUG_NOMSR;
@@ -3314,8 +3321,13 @@ static void serial8250_console_restore(struct uart_8250_port *up)
unsigned int baud, quot, frac = 0;
termios.c_cflag = port->cons->cflag;
- if (port->state->port.tty && termios.c_cflag == 0)
+ termios.c_ispeed = port->cons->ispeed;
+ termios.c_ospeed = port->cons->ospeed;
+ if (port->state->port.tty && termios.c_cflag == 0) {
termios.c_cflag = port->state->port.tty->termios.c_cflag;
+ termios.c_ispeed = port->state->port.tty->termios.c_ispeed;
+ termios.c_ospeed = port->state->port.tty->termios.c_ospeed;
+ }
baud = serial8250_get_baud_rate(port, &termios, NULL);
quot = serial8250_get_divisor(port, baud, &frac);
@@ -3383,11 +3395,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
* First save the IER then disable the interrupts
*/
ier = serial_port_in(port, UART_IER);
-
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
+ serial8250_clear_IER(up);
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index ba4b63fd511e..13cdd9def087 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -127,6 +127,7 @@ config SERIAL_SB1250_DUART_CONSOLE
config SERIAL_ATMEL
bool "AT91 on-chip serial port support"
+ depends on COMMON_CLK
depends on ARCH_AT91 || COMPILE_TEST
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
@@ -427,7 +428,7 @@ config SERIAL_PXA
config SERIAL_PXA_NON8250
bool
- depends on !SERIAL_8250
+ depends on !SERIAL_8250 || COMPILE_TEST
config SERIAL_PXA_CONSOLE
bool "Console on PXA serial port (DEPRECATED)"
@@ -1325,7 +1326,7 @@ config SERIAL_FSL_LPUART
config SERIAL_FSL_LPUART_CONSOLE
bool "Console on Freescale lpuart serial port"
- depends on SERIAL_FSL_LPUART=y
+ depends on SERIAL_FSL_LPUART
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index cb791c5149a3..c2d154d78e54 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -9,6 +9,7 @@
* (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
*/
+#include <linux/bitfield.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -48,7 +49,6 @@
#define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
-#define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
/*
* Local per-uart structure.
@@ -59,10 +59,19 @@ struct altera_jtaguart {
unsigned long imr; /* Local IMR mirror */
};
+static unsigned int altera_jtaguart_tx_space(struct uart_port *port, u32 *ctlp)
+{
+ u32 ctl = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG);
+
+ if (ctlp)
+ *ctlp = ctl;
+
+ return FIELD_GET(ALTERA_JTAGUART_CONTROL_WSPACE_MSK, ctl);
+}
+
static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
{
- return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0;
+ return altera_jtaguart_tx_space(port, NULL) ? TIOCSER_TEMT : 0;
}
static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
@@ -106,8 +115,8 @@ static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
}
static void altera_jtaguart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
/* Just copy the old termios settings back */
if (old)
@@ -150,9 +159,7 @@ static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
pending = uart_circ_chars_pending(xmit);
if (pending > 0) {
- count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >>
- ALTERA_JTAGUART_CONTROL_WSPACE_OFF;
+ count = altera_jtaguart_tx_space(port, NULL);
if (count > pending)
count = pending;
if (count > 0) {
@@ -298,17 +305,17 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
{
- unsigned long status;
unsigned long flags;
+ u32 status;
spin_lock_irqsave(&port->lock, flags);
- while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
+ while (!altera_jtaguart_tx_space(port, &status)) {
+ spin_unlock_irqrestore(&port->lock, flags);
+
if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
- spin_unlock_irqrestore(&port->lock, flags);
return; /* no connection activity */
}
- spin_unlock_irqrestore(&port->lock, flags);
+
cpu_relax();
spin_lock_irqsave(&port->lock, flags);
}
@@ -321,8 +328,7 @@ static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
- ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
+ while (!altera_jtaguart_tx_space(port, NULL)) {
spin_unlock_irqrestore(&port->lock, flags);
cpu_relax();
spin_lock_irqsave(&port->lock, flags);
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 8b749ed557c6..82f2790de28d 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -175,7 +175,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
static void altera_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, baudclk;
@@ -199,9 +199,8 @@ static void altera_uart_set_termios(struct uart_port *port,
*/
}
-static void altera_uart_rx_chars(struct altera_uart *pp)
+static void altera_uart_rx_chars(struct uart_port *port)
{
- struct uart_port *port = &pp->port;
unsigned char ch, flag;
unsigned short status;
@@ -246,9 +245,8 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
tty_flip_buffer_push(&port->state->port);
}
-static void altera_uart_tx_chars(struct altera_uart *pp)
+static void altera_uart_tx_chars(struct uart_port *port)
{
- struct uart_port *port = &pp->port;
struct circ_buf *xmit = &port->state->xmit;
if (port->x_char) {
@@ -272,10 +270,8 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (xmit->head == xmit->tail) {
- pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
- altera_uart_update_ctrl_reg(pp);
- }
+ if (uart_circ_empty(xmit))
+ altera_uart_stop_tx(port);
}
static irqreturn_t altera_uart_interrupt(int irq, void *data)
@@ -288,9 +284,9 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
spin_lock(&port->lock);
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
- altera_uart_rx_chars(pp);
+ altera_uart_rx_chars(port);
if (isr & ALTERA_UART_STATUS_TRDY_MSK)
- altera_uart_tx_chars(pp);
+ altera_uart_tx_chars(port);
spin_unlock(&port->lock);
return IRQ_RETVAL(isr);
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index fae0b581ff42..af27fb8ec145 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -370,7 +370,7 @@ static void pl010_shutdown(struct uart_port *port)
static void
pl010_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int lcr_h, old_cr;
unsigned long flags;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 15f0e4d88c5a..5cdced39eafd 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2030,7 +2030,7 @@ pl011_setup_status_masks(struct uart_port *port, struct ktermios *termios)
static void
pl011_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
@@ -2162,7 +2162,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
static void
sbsa_uart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
@@ -2777,6 +2777,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
struct uart_amba_port *uap;
struct vendor_data *vendor = id->data;
int portnr, ret;
+ u32 val;
portnr = pl011_find_free_port();
if (portnr < 0)
@@ -2801,6 +2802,21 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.rs485_supported = pl011_rs485_supported;
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
+ if (device_property_read_u32(&dev->dev, "reg-io-width", &val) == 0) {
+ switch (val) {
+ case 1:
+ uap->port.iotype = UPIO_MEM;
+ break;
+ case 4:
+ uap->port.iotype = UPIO_MEM32;
+ break;
+ default:
+ dev_warn(&dev->dev, "unsupported reg-io-width (%d)\n",
+ val);
+ return -EINVAL;
+ }
+ }
+
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
if (ret)
return ret;
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index 9ef82d870ff2..450f4edfda0f 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -228,7 +228,7 @@ static void apbuart_shutdown(struct uart_port *port)
}
static void apbuart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios, const struct ktermios *old)
{
unsigned int cr;
unsigned long flags;
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 32caeac12985..925484a42c82 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -283,7 +283,7 @@ static void ar933x_uart_get_scale_step(unsigned int clk,
static void ar933x_uart_set_termios(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
@@ -583,6 +583,13 @@ static const struct uart_ops ar933x_uart_ops = {
static int ar933x_config_rs485(struct uart_port *port, struct ktermios *termios,
struct serial_rs485 *rs485conf)
{
+ struct ar933x_uart_port *up =
+ container_of(port, struct ar933x_uart_port, port);
+
+ if (port->rs485.flags & SER_RS485_ENABLED)
+ gpiod_set_value(up->rts_gpiod,
+ !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND));
+
return 0;
}
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 2a09e92ef9ed..2a65ea2660e1 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -351,7 +351,7 @@ static void arc_serial_shutdown(struct uart_port *port)
static void
arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned int baud, uartl, uarth, hw_val;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 7450d3853031..bd07f79a2df9 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty_flip.h>
@@ -110,6 +111,7 @@ struct atmel_uart_char {
struct atmel_uart_port {
struct uart_port uart; /* uart */
struct clk *clk; /* uart clock */
+ struct clk *gclk; /* uart generic clock */
int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */
u32 backup_imr; /* IMR saved during suspend */
int break_active; /* break being received */
@@ -150,6 +152,7 @@ struct atmel_uart_port {
u32 rts_low;
bool ms_irq_enabled;
u32 rtor; /* address of receiver timeout register if it exists */
+ bool is_usart;
bool has_frac_baudrate;
bool has_hw_timer;
struct timer_list uart_timer;
@@ -228,6 +231,11 @@ static inline int atmel_uart_is_half_duplex(struct uart_port *port)
(port->iso7816.flags & SER_ISO7816_ENABLED);
}
+static inline int atmel_error_rate(int desired_value, int actual_value)
+{
+ return 100 - (desired_value * 100) / actual_value;
+}
+
#ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port)
{
@@ -1825,6 +1833,7 @@ static void atmel_get_ip_name(struct uart_port *port)
*/
atmel_port->has_frac_baudrate = false;
atmel_port->has_hw_timer = false;
+ atmel_port->is_usart = false;
if (name == new_uart) {
dev_dbg(port->dev, "Uart with hw timer");
@@ -1834,6 +1843,7 @@ static void atmel_get_ip_name(struct uart_port *port)
dev_dbg(port->dev, "Usart\n");
atmel_port->has_frac_baudrate = true;
atmel_port->has_hw_timer = true;
+ atmel_port->is_usart = true;
atmel_port->rtor = ATMEL_US_RTOR;
version = atmel_uart_readl(port, ATMEL_US_VERSION);
switch (version) {
@@ -1863,6 +1873,7 @@ static void atmel_get_ip_name(struct uart_port *port)
dev_dbg(port->dev, "This version is usart\n");
atmel_port->has_frac_baudrate = true;
atmel_port->has_hw_timer = true;
+ atmel_port->is_usart = true;
atmel_port->rtor = ATMEL_US_RTOR;
break;
case 0x203:
@@ -2113,6 +2124,8 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
* This is called on uart_close() or a suspend event.
*/
clk_disable_unprepare(atmel_port->clk);
+ if (__clk_is_enabled(atmel_port->gclk))
+ clk_disable_unprepare(atmel_port->gclk);
break;
default:
dev_err(port->dev, "atmel_serial: unknown pm %d\n", state);
@@ -2122,19 +2135,25 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
/*
* Change the port parameters
*/
-static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+static void atmel_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ const struct ktermios *old)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned long flags;
- unsigned int old_mode, mode, imr, quot, baud, div, cd, fp = 0;
+ unsigned int old_mode, mode, imr, quot, div, cd, fp = 0;
+ unsigned int baud, actual_baud, gclk_rate;
+ int ret;
/* save the current mode register */
mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
/* reset the mode, clock divisor, parity, stop bits and data size */
- mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
- ATMEL_US_PAR | ATMEL_US_USMODE);
+ if (atmel_port->is_usart)
+ mode &= ~(ATMEL_US_NBSTOP | ATMEL_US_PAR | ATMEL_US_CHRL |
+ ATMEL_US_USCLKS | ATMEL_US_USMODE);
+ else
+ mode &= ~(ATMEL_UA_BRSRCCK | ATMEL_US_PAR | ATMEL_UA_FILTER);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
@@ -2282,10 +2301,60 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
cd = uart_get_divisor(port, baud);
}
- if (cd > 65535) { /* BRGR is 16-bit, so switch to slower clock */
+ /*
+ * If the current value of the Clock Divisor surpasses the 16 bit
+ * ATMEL_US_CD mask and the IP is USART, switch to the Peripheral
+ * Clock implicitly divided by 8.
+ * If the IP is UART however, keep the highest possible value for
+ * the CD and avoid needless division of CD, since UART IP's do not
+ * support implicit division of the Peripheral Clock.
+ */
+ if (atmel_port->is_usart && cd > ATMEL_US_CD) {
cd /= 8;
mode |= ATMEL_US_USCLKS_MCK_DIV8;
+ } else {
+ cd = min_t(unsigned int, cd, ATMEL_US_CD);
+ }
+
+ /*
+ * If there is no Fractional Part, there is a high chance that
+ * we may be able to generate a baudrate closer to the desired one
+ * if we use the GCLK as the clock source driving the baudrate
+ * generator.
+ */
+ if (!atmel_port->has_frac_baudrate) {
+ if (__clk_is_enabled(atmel_port->gclk))
+ clk_disable_unprepare(atmel_port->gclk);
+ gclk_rate = clk_round_rate(atmel_port->gclk, 16 * baud);
+ actual_baud = clk_get_rate(atmel_port->clk) / (16 * cd);
+ if (gclk_rate && abs(atmel_error_rate(baud, actual_baud)) >
+ abs(atmel_error_rate(baud, gclk_rate / 16))) {
+ clk_set_rate(atmel_port->gclk, 16 * baud);
+ ret = clk_prepare_enable(atmel_port->gclk);
+ if (ret)
+ goto gclk_fail;
+
+ if (atmel_port->is_usart) {
+ mode &= ~ATMEL_US_USCLKS;
+ mode |= ATMEL_US_USCLKS_GCLK;
+ } else {
+ mode |= ATMEL_UA_BRSRCCK;
+ }
+
+ /*
+ * Set the Clock Divisor for GCLK to 1.
+ * Since we were able to generate the smallest
+ * multiple of the desired baudrate times 16,
+ * then we surely can generate a bigger multiple
+ * with the exact error rate for an equally increased
+ * CD. Thus no need to take into account
+ * a higher value for CD.
+ */
+ cd = 1;
+ }
}
+
+gclk_fail:
quot = cd | fp << ATMEL_US_FP_OFFSET;
if (!(port->iso7816.flags & SER_ISO7816_ENABLED))
@@ -2881,6 +2950,12 @@ static int atmel_serial_probe(struct platform_device *pdev)
if (ret)
goto err;
+ atmel_port->gclk = devm_clk_get_optional(&pdev->dev, "gclk");
+ if (IS_ERR(atmel_port->gclk)) {
+ ret = PTR_ERR(atmel_port->gclk);
+ goto err_clk_disable_unprepare;
+ }
+
ret = atmel_init_port(atmel_port, pdev);
if (ret)
goto err_clk_disable_unprepare;
diff --git a/drivers/tty/serial/atmel_serial.h b/drivers/tty/serial/atmel_serial.h
index 0d8a0f9cc5c3..87f8f7996307 100644
--- a/drivers/tty/serial/atmel_serial.h
+++ b/drivers/tty/serial/atmel_serial.h
@@ -9,6 +9,8 @@
* Based on AT91RM9200 datasheet revision E.
*/
+#include <linux/bitfield.h>
+
#ifndef ATMEL_SERIAL_H
#define ATMEL_SERIAL_H
@@ -39,39 +41,42 @@
#define ATMEL_US_MR 0x04 /* Mode Register */
#define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
-#define ATMEL_US_USMODE_NORMAL 0
-#define ATMEL_US_USMODE_RS485 1
-#define ATMEL_US_USMODE_HWHS 2
-#define ATMEL_US_USMODE_MODEM 3
-#define ATMEL_US_USMODE_ISO7816_T0 4
-#define ATMEL_US_USMODE_ISO7816_T1 6
-#define ATMEL_US_USMODE_IRDA 8
+#define ATMEL_US_USMODE_NORMAL FIELD_PREP(ATMEL_US_USMODE, 0)
+#define ATMEL_US_USMODE_RS485 FIELD_PREP(ATMEL_US_USMODE, 1)
+#define ATMEL_US_USMODE_HWHS FIELD_PREP(ATMEL_US_USMODE, 2)
+#define ATMEL_US_USMODE_MODEM FIELD_PREP(ATMEL_US_USMODE, 3)
+#define ATMEL_US_USMODE_ISO7816_T0 FIELD_PREP(ATMEL_US_USMODE, 4)
+#define ATMEL_US_USMODE_ISO7816_T1 FIELD_PREP(ATMEL_US_USMODE, 6)
+#define ATMEL_US_USMODE_IRDA FIELD_PREP(ATMEL_US_USMODE, 8)
#define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
-#define ATMEL_US_USCLKS_MCK (0 << 4)
-#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
-#define ATMEL_US_USCLKS_SCK (3 << 4)
+#define ATMEL_US_USCLKS_MCK FIELD_PREP(ATMEL_US_USCLKS, 0)
+#define ATMEL_US_USCLKS_MCK_DIV8 FIELD_PREP(ATMEL_US_USCLKS, 1)
+#define ATMEL_US_USCLKS_GCLK FIELD_PREP(ATMEL_US_USCLKS, 2)
+#define ATMEL_US_USCLKS_SCK FIELD_PREP(ATMEL_US_USCLKS, 3)
+#define ATMEL_UA_FILTER BIT(4)
#define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
-#define ATMEL_US_CHRL_5 (0 << 6)
-#define ATMEL_US_CHRL_6 (1 << 6)
-#define ATMEL_US_CHRL_7 (2 << 6)
-#define ATMEL_US_CHRL_8 (3 << 6)
+#define ATMEL_US_CHRL_5 FIELD_PREP(ATMEL_US_CHRL, 0)
+#define ATMEL_US_CHRL_6 FIELD_PREP(ATMEL_US_CHRL, 1)
+#define ATMEL_US_CHRL_7 FIELD_PREP(ATMEL_US_CHRL, 2)
+#define ATMEL_US_CHRL_8 FIELD_PREP(ATMEL_US_CHRL, 3)
#define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
#define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
-#define ATMEL_US_PAR_EVEN (0 << 9)
-#define ATMEL_US_PAR_ODD (1 << 9)
-#define ATMEL_US_PAR_SPACE (2 << 9)
-#define ATMEL_US_PAR_MARK (3 << 9)
-#define ATMEL_US_PAR_NONE (4 << 9)
-#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
+#define ATMEL_US_PAR_EVEN FIELD_PREP(ATMEL_US_PAR, 0)
+#define ATMEL_US_PAR_ODD FIELD_PREP(ATMEL_US_PAR, 1)
+#define ATMEL_US_PAR_SPACE FIELD_PREP(ATMEL_US_PAR, 2)
+#define ATMEL_US_PAR_MARK FIELD_PREP(ATMEL_US_PAR, 3)
+#define ATMEL_US_PAR_NONE FIELD_PREP(ATMEL_US_PAR, 4)
+#define ATMEL_US_PAR_MULTI_DROP FIELD_PREP(ATMEL_US_PAR, 6)
#define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
-#define ATMEL_US_NBSTOP_1 (0 << 12)
-#define ATMEL_US_NBSTOP_1_5 (1 << 12)
-#define ATMEL_US_NBSTOP_2 (2 << 12)
+#define ATMEL_US_NBSTOP_1 FIELD_PREP(ATMEL_US_NBSTOP, 0)
+#define ATMEL_US_NBSTOP_1_5 FIELD_PREP(ATMEL_US_NBSTOP, 1)
+#define ATMEL_US_NBSTOP_2 FIELD_PREP(ATMEL_US_NBSTOP, 2)
+#define ATMEL_UA_BRSRCCK BIT(12) /* Clock Selection for UART */
#define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
-#define ATMEL_US_CHMODE_NORMAL (0 << 14)
-#define ATMEL_US_CHMODE_ECHO (1 << 14)
-#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
-#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
+#define ATMEL_US_CHMODE_NORMAL FIELD_PREP(ATMEL_US_CHMODE, 0)
+#define ATMEL_US_CHMODE_ECHO FIELD_PREP(ATMEL_US_CHMODE, 1)
+#define ATMEL_US_CHMODE_LOC_LOOP FIELD_PREP(ATMEL_US_CHMODE, 2)
+#define ATMEL_US_CHMODE_REM_LOOP FIELD_PREP(ATMEL_US_CHMODE, 3)
#define ATMEL_US_MSBF BIT(16) /* Bit Order */
#define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
#define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
@@ -79,7 +84,7 @@
#define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
#define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
#define ATMEL_US_MAX_ITER_MASK GENMASK(26, 24) /* Max Iterations */
-#define ATMEL_US_MAX_ITER(n) (((n) << 24) & ATMEL_US_MAX_ITER_MASK)
+#define ATMEL_US_MAX_ITER(n) FIELD_PREP(ATMEL_US_MAX_ITER_MASK, (n))
#define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
@@ -131,19 +136,19 @@
#define ATMEL_US_CMPR 0x90 /* Comparaison Register */
#define ATMEL_US_FMR 0xa0 /* FIFO Mode Register */
-#define ATMEL_US_TXRDYM(data) (((data) & 0x3) << 0) /* TX Ready Mode */
-#define ATMEL_US_RXRDYM(data) (((data) & 0x3) << 4) /* RX Ready Mode */
+#define ATMEL_US_TXRDYM(data) FIELD_PREP(GENMASK(1, 0), (data)) /* TX Ready Mode */
+#define ATMEL_US_RXRDYM(data) FIELD_PREP(GENMASK(5, 4), (data)) /* RX Ready Mode */
#define ATMEL_US_ONE_DATA 0x0
#define ATMEL_US_TWO_DATA 0x1
#define ATMEL_US_FOUR_DATA 0x2
#define ATMEL_US_FRTSC BIT(7) /* FIFO RTS pin Control */
-#define ATMEL_US_TXFTHRES(thr) (((thr) & 0x3f) << 8) /* TX FIFO Threshold */
-#define ATMEL_US_RXFTHRES(thr) (((thr) & 0x3f) << 16) /* RX FIFO Threshold */
-#define ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24) /* RX FIFO Threshold2 */
+#define ATMEL_US_TXFTHRES(thr) FIELD_PREP(GENMASK(13, 8), (thr)) /* TX FIFO Threshold */
+#define ATMEL_US_RXFTHRES(thr) FIELD_PREP(GENMASK(21, 16), (thr)) /* RX FIFO Threshold */
+#define ATMEL_US_RXFTHRES2(thr) FIELD_PREP(GENMASK(29, 24), (thr)) /* RX FIFO Threshold2 */
#define ATMEL_US_FLR 0xa4 /* FIFO Level Register */
-#define ATMEL_US_TXFL(reg) (((reg) >> 0) & 0x3f) /* TX FIFO Level */
-#define ATMEL_US_RXFL(reg) (((reg) >> 16) & 0x3f) /* RX FIFO Level */
+#define ATMEL_US_TXFL(reg) FIELD_GET(GENMASK(5, 0), (reg)) /* TX FIFO Level */
+#define ATMEL_US_RXFL(reg) FIELD_GET(GENMASK(21, 16), (reg)) /* RX FIFO Level */
#define ATMEL_US_FIER 0xa8 /* FIFO Interrupt Enable Register */
#define ATMEL_US_FIDR 0xac /* FIFO Interrupt Disable Register */
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 53b43174aa40..5d9737c2d1f2 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -492,9 +492,8 @@ static void bcm_uart_shutdown(struct uart_port *port)
/*
* serial core request to change current uart setting
*/
-static void bcm_uart_set_termios(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
+static void bcm_uart_set_termios(struct uart_port *port, struct ktermios *new,
+ const struct ktermios *old)
{
unsigned int ctl, baud, quot, ier;
unsigned long flags;
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index b9b66ad31a08..404b43a5ae33 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -251,7 +251,7 @@ static void uart_clps711x_shutdown(struct uart_port *port)
static void uart_clps711x_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
u32 ubrlcr;
unsigned int baud, quot;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h
index 8c582779cf22..0577618e78c0 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart.h
+++ b/drivers/tty/serial/cpm_uart/cpm_uart.h
@@ -87,7 +87,6 @@ struct uart_cpm_port {
struct gpio_desc *gpios[NUM_GPIOS];
};
-extern int cpm_uart_nr;
extern struct uart_cpm_port cpm_uart_ports[UART_NR];
/* these are located in their respective files */
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index db07d6a5d764..b4369ed45ae2 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -484,12 +484,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
static void cpm_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
int baud;
unsigned long flags;
u16 cval, scval, prev_mode;
- int bits, sbits;
struct uart_cpm_port *pinfo =
container_of(port, struct uart_cpm_port, port);
smc_t __iomem *smcp = pinfo->smcp;
@@ -515,28 +514,17 @@ static void cpm_uart_set_termios(struct uart_port *port,
if (maxidl > 0x10)
maxidl = 0x10;
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
cval = 0;
scval = 0;
- /* byte size */
- bits = tty_get_char_size(termios->c_cflag);
- sbits = bits - 5;
-
if (termios->c_cflag & CSTOPB) {
cval |= SMCMR_SL; /* Two stops */
scval |= SCU_PSMR_SL;
- bits++;
}
if (termios->c_cflag & PARENB) {
cval |= SMCMR_PEN;
scval |= SCU_PSMR_PEN;
- bits++;
if (!(termios->c_cflag & PARODD)) {
cval |= SMCMR_PM_EVEN;
scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
@@ -580,12 +568,9 @@ static void cpm_uart_set_termios(struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
- /* Start bit has not been added (so don't, because we would just
- * subtract it later), and we need to add one for the number of
- * stops bits (there is always at least one).
- */
- bits++;
if (IS_SMC(pinfo)) {
+ unsigned int bits = tty_get_frame_size(termios->c_cflag);
+
/*
* MRBLR can be changed while an SMC/SCC is operating only
* if it is done in a single bus cycle with one 16-bit move
@@ -604,13 +589,17 @@ static void cpm_uart_set_termios(struct uart_port *port,
*/
prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
/* Output in *one* operation, so we don't interrupt RX/TX if they
- * were already enabled. */
- out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
- SMCMR_SM_UART | prev_mode);
+ * were already enabled.
+ * Character length programmed into the register is frame bits minus 1.
+ */
+ out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits - 1) | cval |
+ SMCMR_SM_UART | prev_mode);
} else {
+ unsigned int bits = tty_get_char_size(termios->c_cflag);
+
out_be16(&pinfo->sccup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
out_be16(&pinfo->sccup->scc_maxidl, maxidl);
- out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
+ out_be16(&sccp->scc_psmr, (UART_LCR_WLEN(bits) << 12) | scval);
}
if (pinfo->clk)
@@ -1214,12 +1203,6 @@ static int cpm_uart_init_port(struct device_node *np,
pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
spin_lock_init(&pinfo->port.lock);
- pinfo->port.irq = irq_of_parse_and_map(np, 0);
- if (pinfo->port.irq == NO_IRQ) {
- ret = -EINVAL;
- goto out_pram;
- }
-
for (i = 0; i < NUM_GPIOS; i++) {
struct gpio_desc *gpiod;
@@ -1229,7 +1212,7 @@ static int cpm_uart_init_port(struct device_node *np,
if (IS_ERR(gpiod)) {
ret = PTR_ERR(gpiod);
- goto out_irq;
+ goto out_pram;
}
if (gpiod) {
@@ -1255,8 +1238,6 @@ static int cpm_uart_init_port(struct device_node *np,
return cpm_uart_request_port(&pinfo->port);
-out_irq:
- irq_dispose_mapping(pinfo->port.irq);
out_pram:
cpm_uart_unmap_pram(pinfo, pram);
out_mem:
@@ -1436,11 +1417,17 @@ static int cpm_uart_probe(struct platform_device *ofdev)
/* initialize the device pointer for the port */
pinfo->port.dev = &ofdev->dev;
+ pinfo->port.irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+ if (!pinfo->port.irq)
+ return -EINVAL;
+
ret = cpm_uart_init_port(ofdev->dev.of_node, pinfo);
- if (ret)
- return ret;
+ if (!ret)
+ return uart_add_one_port(&cpm_reg, &pinfo->port);
+
+ irq_dispose_mapping(pinfo->port.irq);
- return uart_add_one_port(&cpm_reg, &pinfo->port);
+ return ret;
}
static int cpm_uart_remove(struct platform_device *ofdev)
diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
index af951e6a2ef4..0c0a62346f23 100644
--- a/drivers/tty/serial/digicolor-usart.c
+++ b/drivers/tty/serial/digicolor-usart.c
@@ -287,7 +287,7 @@ static void digicolor_uart_shutdown(struct uart_port *port)
static void digicolor_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud, divisor;
u8 config = 0;
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c
index 2e21acf39720..829b452daee9 100644
--- a/drivers/tty/serial/dz.c
+++ b/drivers/tty/serial/dz.c
@@ -559,7 +559,7 @@ static void dz_reset(struct dz_port *dport)
}
static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
+ const struct ktermios *old_termios)
{
struct dz_port *dport = to_dport(uport);
unsigned long flags;
@@ -592,9 +592,12 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
bflag = dz_encode_baud_rate(baud);
- if (bflag < 0) { /* Try to keep unchanged. */
- baud = uart_get_baud_rate(uport, old_termios, NULL, 50, 9600);
- bflag = dz_encode_baud_rate(baud);
+ if (bflag < 0) {
+ if (old_termios) {
+ /* Keep unchanged. */
+ baud = tty_termios_baud_rate(old_termios);
+ bflag = dz_encode_baud_rate(baud);
+ }
if (bflag < 0) { /* Resort to 9600. */
baud = 9600;
bflag = DZ_B9600;
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 88d08ba1ca83..a5f380584cda 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -67,7 +67,7 @@ static void __init earlycon_init(struct earlycon_device *device,
if (*s)
earlycon->index = simple_strtoul(s, NULL, 10);
len = s - name;
- strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name)));
+ strscpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name)));
earlycon->data = &early_console_dev;
}
@@ -123,7 +123,7 @@ static int __init parse_options(struct earlycon_device *device, char *options)
device->baud = simple_strtoul(options, NULL, 0);
length = min(strcspn(options, " ") + 1,
(size_t)(sizeof(device->options)));
- strlcpy(device->options, options, length);
+ strscpy(device->options, options, length);
}
return 0;
@@ -304,7 +304,7 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
if (options) {
early_console_dev.baud = simple_strtoul(options, NULL, 0);
- strlcpy(early_console_dev.options, options,
+ strscpy(early_console_dev.options, options,
sizeof(early_console_dev.options));
}
earlycon_init(&early_console_dev, match->name);
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index 98bb0c315e13..84e8153e5420 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -401,7 +401,7 @@ static void linflex_shutdown(struct uart_port *port)
static void
linflex_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned long cr, old_cr, cr1;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index fbc4b071b330..67fa113f77d4 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1284,17 +1284,12 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
struct dma_slave_config dma_rx_sconfig = {};
struct circ_buf *ring = &sport->rx_ring;
int ret, nent;
- int bits, baud;
struct tty_port *port = &sport->port.state->port;
struct tty_struct *tty = port->tty;
struct ktermios *termios = &tty->termios;
struct dma_chan *chan = sport->dma_rx_chan;
-
- baud = tty_get_baud_rate(tty);
-
- bits = (termios->c_cflag & CSIZE) == CS7 ? 9 : 10;
- if (termios->c_cflag & PARENB)
- bits++;
+ unsigned int bits = tty_get_frame_size(termios->c_cflag);
+ unsigned int baud = tty_get_baud_rate(tty);
/*
* Calculate length of one DMA buffer size to keep latency below
@@ -1776,6 +1771,7 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport)
if (sport->lpuart_dma_rx_use) {
del_timer_sync(&sport->lpuart_timer);
lpuart_dma_rx_free(&sport->port);
+ sport->lpuart_dma_rx_use = false;
}
if (sport->lpuart_dma_tx_use) {
@@ -1784,6 +1780,7 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport)
sport->dma_tx_in_progress = false;
dmaengine_terminate_all(sport->dma_tx_chan);
}
+ sport->lpuart_dma_tx_use = false;
}
if (sport->dma_tx_chan)
@@ -1833,7 +1830,7 @@ static void lpuart32_shutdown(struct uart_port *port)
static void
lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long flags;
@@ -2073,7 +2070,7 @@ static void lpuart32_serial_setbrg(struct lpuart_port *sport,
static void
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long flags;
@@ -2729,15 +2726,13 @@ static int lpuart_probe(struct platform_device *pdev)
if (ret)
goto failed_reset;
- ret = uart_add_one_port(&lpuart_reg, &sport->port);
- if (ret)
- goto failed_attach_port;
-
ret = uart_get_rs485_mode(&sport->port);
if (ret)
goto failed_get_rs485;
- uart_rs485_config(&sport->port);
+ ret = uart_add_one_port(&lpuart_reg, &sport->port);
+ if (ret)
+ goto failed_attach_port;
ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0,
DRIVER_NAME, sport);
@@ -2747,9 +2742,9 @@ static int lpuart_probe(struct platform_device *pdev)
return 0;
failed_irq_request:
-failed_get_rs485:
uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
+failed_get_rs485:
failed_reset:
lpuart_disable_clks(sport);
return ret;
@@ -2800,7 +2795,7 @@ static int __maybe_unused lpuart_suspend(struct device *dev)
* EDMA driver during suspend will forcefully release any
* non-idle DMA channels. If port wakeup is enabled or if port
* is console port or 'no_console_suspend' is set the Rx DMA
- * cannot resume as as expected, hence gracefully release the
+ * cannot resume as expected, hence gracefully release the
* Rx DMA path before suspend and start Rx DMA path on resume.
*/
if (irq_wake) {
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 45df29947fe8..819f957b6b84 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -1351,9 +1351,8 @@ static void icom_close(struct uart_port *port)
kref_put(&icom_port->adapter->kref, icom_kref_release);
}
-static void icom_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old_termios)
+static void icom_set_termios(struct uart_port *port, struct ktermios *termios,
+ const struct ktermios *old_termios)
{
struct icom_port *icom_port = to_icom_port(port);
int baud;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 522445a8f666..05b432dc7a85 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -380,8 +380,7 @@ static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2)
{
*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
- sport->port.mctrl |= TIOCM_RTS;
- mctrl_gpio_set(sport->gpios, sport->port.mctrl);
+ mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
}
/* called with port.lock taken and irqs caller dependent */
@@ -390,8 +389,7 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
*ucr2 &= ~UCR2_CTSC;
*ucr2 |= UCR2_CTS;
- sport->port.mctrl &= ~TIOCM_RTS;
- mctrl_gpio_set(sport->gpios, sport->port.mctrl);
+ mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
}
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
@@ -1620,7 +1618,7 @@ static void imx_uart_flush_buffer(struct uart_port *port)
static void
imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
@@ -2347,8 +2345,6 @@ static int imx_uart_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"low-active RTS not possible when receiver is off, enabling receiver\n");
- uart_rs485_config(&sport->port);
-
/* Disable interrupts before requesting them */
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | UCR1_RTSDEN);
diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c
index 655e64b26852..dd0a8915ce4f 100644
--- a/drivers/tty/serial/ip22zilog.c
+++ b/drivers/tty/serial/ip22zilog.c
@@ -873,7 +873,7 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
/* The port lock is not held. */
static void
ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_ip22zilog_port *up =
container_of(port, struct uart_ip22zilog_port, port);
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 0ea799bf8dbb..417a5b6bffc3 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -211,7 +211,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
default:
- return -ENXIO;
+ rc = -ENXIO;
+ goto out_kfree_brd;
}
rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "JSM", brd);
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index cb58bdec2f43..222afc270c88 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -300,8 +300,8 @@ static void jsm_tty_close(struct uart_port *port)
}
static void jsm_tty_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old_termios)
+ struct ktermios *termios,
+ const struct ktermios *old_termios)
{
unsigned long lock_flags;
struct jsm_channel *channel =
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index a3120c3347dd..c892f3c7d1ab 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -8,6 +8,7 @@
* Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/device.h>
@@ -93,7 +94,6 @@
#define ASCFSTAT_RXFFLMASK 0x003F
#define ASCFSTAT_TXFFLMASK 0x3F00
#define ASCFSTAT_TXFREEMASK 0x3F000000
-#define ASCFSTAT_TXFREEOFF 24
static void lqasc_tx_chars(struct uart_port *port);
static struct ltq_uart_port *lqasc_port[MAXPORTS];
@@ -139,6 +139,13 @@ lqasc_stop_tx(struct uart_port *port)
return;
}
+static bool lqasc_tx_ready(struct uart_port *port)
+{
+ u32 fstat = __raw_readl(port->membase + LTQ_ASC_FSTAT);
+
+ return FIELD_GET(ASCFSTAT_TXFREEMASK, fstat);
+}
+
static void
lqasc_start_tx(struct uart_port *port)
{
@@ -228,8 +235,7 @@ lqasc_tx_chars(struct uart_port *port)
return;
}
- while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
- ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
+ while (lqasc_tx_ready(port)) {
if (port->x_char) {
writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
port->icount.tx++;
@@ -405,8 +411,8 @@ lqasc_shutdown(struct uart_port *port)
}
static void
-lqasc_set_termios(struct uart_port *port,
- struct ktermios *new, struct ktermios *old)
+lqasc_set_termios(struct uart_port *port, struct ktermios *new,
+ const struct ktermios *old)
{
unsigned int cflag;
unsigned int iflag;
@@ -600,15 +606,12 @@ static const struct uart_ops lqasc_pops = {
static void
lqasc_console_putchar(struct uart_port *port, unsigned char ch)
{
- int fifofree;
-
if (!port->membase)
return;
- do {
- fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
- & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
- } while (fifofree == 0);
+ while (!lqasc_tx_ready(port))
+ ;
+
writeb(ch, port->membase + LTQ_ASC_TBUF);
}
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 328b50521f14..4c0604325ee9 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -178,7 +178,7 @@ static void liteuart_shutdown(struct uart_port *port)
}
static void liteuart_set_termios(struct uart_port *port, struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud;
unsigned long flags;
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index 93140cac1ca1..ed47f4768338 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -278,6 +278,13 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
static void serial_lpc32xx_stop_tx(struct uart_port *port);
+static bool serial_lpc32xx_tx_ready(struct uart_port *port)
+{
+ u32 level = readl(LPC32XX_HSUART_LEVEL(port->membase));
+
+ return LPC32XX_HSU_TX_LEV(level) < 64;
+}
+
static void __serial_lpc32xx_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
@@ -293,8 +300,7 @@ static void __serial_lpc32xx_tx(struct uart_port *port)
goto exit_tx;
/* Transfer data */
- while (LPC32XX_HSU_TX_LEV(readl(
- LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
+ while (serial_lpc32xx_tx_ready(port)) {
writel((u32) xmit->buf[xmit->tail],
LPC32XX_HSUART_FIFO(port->membase));
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -493,7 +499,7 @@ static void serial_lpc32xx_shutdown(struct uart_port *port)
/* port->lock is not held. */
static void serial_lpc32xx_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, quot;
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 0b5f21fbb53d..c69602f356fd 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -418,7 +418,7 @@ static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void
max3100_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct max3100_port *s = container_of(port,
struct max3100_port,
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 7cf81f692ac4..fbf6e2b3161c 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -906,7 +906,7 @@ static void max310x_break_ctl(struct uart_port *port, int break_state)
static void max310x_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int lcr = 0, flow = 0;
int baud;
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index f4aaaadd0742..b1cd9a76dd93 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -192,7 +192,7 @@ static void mcf_shutdown(struct uart_port *port)
/****************************************************************************/
static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, baudclk;
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index 12117b596e73..3690f5cf0f43 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -646,8 +646,8 @@ static void men_z135_shutdown(struct uart_port *port)
}
static void men_z135_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
struct men_z135_port *uart = to_men_z135(port);
unsigned int baud;
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 6c8db19fd572..056243c12836 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -335,7 +335,7 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
static void meson_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int cflags, iflags, baud;
unsigned long flags;
@@ -667,29 +667,6 @@ static struct uart_driver meson_uart_driver = {
.cons = MESON_SERIAL_CONSOLE,
};
-static inline struct clk *meson_uart_probe_clock(struct device *dev,
- const char *id)
-{
- struct clk *clk = NULL;
- int ret;
-
- clk = devm_clk_get(dev, id);
- if (IS_ERR(clk))
- return clk;
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- dev_err(dev, "couldn't enable clk\n");
- return ERR_PTR(ret);
- }
-
- devm_add_action_or_reset(dev,
- (void(*)(void *))clk_disable_unprepare,
- clk);
-
- return clk;
-}
-
static int meson_uart_probe_clocks(struct platform_device *pdev,
struct uart_port *port)
{
@@ -697,15 +674,15 @@ static int meson_uart_probe_clocks(struct platform_device *pdev,
struct clk *clk_pclk = NULL;
struct clk *clk_baud = NULL;
- clk_pclk = meson_uart_probe_clock(&pdev->dev, "pclk");
+ clk_pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
if (IS_ERR(clk_pclk))
return PTR_ERR(clk_pclk);
- clk_xtal = meson_uart_probe_clock(&pdev->dev, "xtal");
+ clk_xtal = devm_clk_get_enabled(&pdev->dev, "xtal");
if (IS_ERR(clk_xtal))
return PTR_ERR(clk_xtal);
- clk_baud = meson_uart_probe_clock(&pdev->dev, "baud");
+ clk_baud = devm_clk_get_enabled(&pdev->dev, "baud");
if (IS_ERR(clk_baud))
return PTR_ERR(clk_baud);
diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c
index 347088bb380e..c15e0d84dc7e 100644
--- a/drivers/tty/serial/milbeaut_usio.c
+++ b/drivers/tty/serial/milbeaut_usio.c
@@ -298,7 +298,8 @@ static void mlb_usio_shutdown(struct uart_port *port)
}
static void mlb_usio_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned int escr, smr = MLB_USIO_SMR_SOE;
unsigned long flags, baud, quot;
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 3f1986c89694..73362d4bc45d 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -101,7 +101,7 @@ struct psc_ops {
void (*cw_restore_ints)(struct uart_port *port);
unsigned int (*set_baudrate)(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old);
+ const struct ktermios *old);
int (*clock_alloc)(struct uart_port *port);
void (*clock_relse)(struct uart_port *port);
int (*clock)(struct uart_port *port, int enable);
@@ -287,7 +287,7 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud;
unsigned int divisor;
@@ -305,7 +305,7 @@ static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port,
static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud;
unsigned int divisor;
@@ -533,7 +533,7 @@ static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud;
unsigned int divisor;
@@ -880,7 +880,7 @@ static inline void mpc5125_set_divisor(struct mpc5125_psc __iomem *psc,
static unsigned int mpc5125_psc_set_baudrate(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud;
unsigned int divisor;
@@ -1167,7 +1167,7 @@ mpc52xx_uart_shutdown(struct uart_port *port)
static void
mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned char mr1, mr2;
@@ -1364,7 +1364,7 @@ static const struct uart_ops mpc52xx_uart_ops = {
/* Interrupt handling */
/* ======================================================================== */
-static inline unsigned int
+static inline bool
mpc52xx_uart_int_rx_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
@@ -1425,7 +1425,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
return psc_ops->raw_rx_rdy(port);
}
-static inline int
+static inline bool
mpc52xx_uart_int_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
@@ -1435,13 +1435,13 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
psc_ops->write_char(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
- return 1;
+ return true;
}
/* Nothing to do ? */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
mpc52xx_uart_stop_tx(port);
- return 0;
+ return false;
}
/* Send chars */
@@ -1460,23 +1460,23 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
/* Maybe we're done after all */
if (uart_circ_empty(xmit)) {
mpc52xx_uart_stop_tx(port);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static irqreturn_t
mpc5xxx_uart_process_int(struct uart_port *port)
{
unsigned long pass = ISR_PASS_LIMIT;
- unsigned int keepgoing;
+ bool keepgoing;
u8 status;
/* While we have stuff to do, we continue */
do {
/* If we don't find anything to do, we stop */
- keepgoing = 0;
+ keepgoing = false;
psc_ops->rx_clr_irq(port);
if (psc_ops->rx_rdy(port))
@@ -1495,7 +1495,7 @@ mpc5xxx_uart_process_int(struct uart_port *port)
/* Limit number of iteration */
if (!(--pass))
- keepgoing = 0;
+ keepgoing = false;
} while (keepgoing);
diff --git a/drivers/tty/serial/mps2-uart.c b/drivers/tty/serial/mps2-uart.c
index 5e9429dcc51f..2e3e6cf16817 100644
--- a/drivers/tty/serial/mps2-uart.c
+++ b/drivers/tty/serial/mps2-uart.c
@@ -358,7 +358,7 @@ static void mps2_uart_shutdown(struct uart_port *port)
static void
mps2_uart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, bauddiv;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 3159889ddae1..7dd19a281579 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1263,7 +1263,7 @@ static void msm_shutdown(struct uart_port *port)
}
static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct msm_port *msm_port = to_msm_port(port);
struct msm_dma *dma = &msm_port->rx_dma;
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index 0ba0f4d9459d..ed0e763f622a 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -289,7 +289,7 @@ static void mux_shutdown(struct uart_port *port)
*/
static void
mux_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
}
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index 65eaecd10b7c..ba16e1da6bd3 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -564,7 +564,7 @@ static unsigned int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned in
static void mvebu_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned long flags;
unsigned int baud, min_baud, max_baud;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 1944daf8593a..d21a4f3ef2fe 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -959,7 +959,7 @@ err_out:
#define CTS_AT_AUART() !mctrl_gpio_to_gpiod(s->gpios, UART_GPIO_CTS)
static void mxs_auart_settermios(struct uart_port *u,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct mxs_auart_port *s = to_auart_port(u);
u32 ctrl, ctrl2, div;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0aa666e247d5..7d0d2718ef59 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -300,8 +300,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_OMAP_SCR, up->scr);
res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?
1 : 0;
- if (up->rts_gpiod &&
- gpiod_get_value(up->rts_gpiod) != res) {
+ if (gpiod_get_value(up->rts_gpiod) != res) {
if (port->rs485.delay_rts_after_send > 0)
mdelay(
port->rs485.delay_rts_after_send);
@@ -337,19 +336,24 @@ static void serial_omap_stop_rx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
+static void serial_omap_put_char(struct uart_omap_port *up, unsigned char ch)
+{
+ serial_out(up, UART_TX, ch);
+
+ if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
+ !(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
+ up->rs485_tx_filter_count++;
+}
+
static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
{
struct circ_buf *xmit = &up->port.state->xmit;
int count;
if (up->port.x_char) {
- serial_out(up, UART_TX, up->port.x_char);
+ serial_omap_put_char(up, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
- if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
- !(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
- up->rs485_tx_filter_count++;
-
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
@@ -358,12 +362,9 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
}
count = up->port.fifosize / 4;
do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ serial_omap_put_char(up, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->port.icount.tx++;
- if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
- !(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
- up->rs485_tx_filter_count++;
if (uart_circ_empty(xmit))
break;
@@ -397,7 +398,7 @@ static void serial_omap_start_tx(struct uart_port *port)
/* if rts not already enabled */
res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
- if (up->rts_gpiod && gpiod_get_value(up->rts_gpiod) != res) {
+ if (gpiod_get_value(up->rts_gpiod) != res) {
gpiod_set_value(up->rts_gpiod, res);
if (port->rs485.delay_rts_before_send > 0)
mdelay(port->rs485.delay_rts_before_send);
@@ -802,7 +803,7 @@ static void serial_omap_uart_qos_work(struct work_struct *work)
static void
serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char cval = 0;
@@ -1336,13 +1337,11 @@ serial_omap_config_rs485(struct uart_port *port, struct ktermios *termios,
up->ier = 0;
serial_out(up, UART_IER, 0);
- if (up->rts_gpiod) {
- /* enable / disable rts */
- val = (rs485->flags & SER_RS485_ENABLED) ?
- SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
- val = (rs485->flags & val) ? 1 : 0;
- gpiod_set_value(up->rts_gpiod, val);
- }
+ /* enable / disable rts */
+ val = (rs485->flags & SER_RS485_ENABLED) ?
+ SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
+ val = (rs485->flags & val) ? 1 : 0;
+ gpiod_set_value(up->rts_gpiod, val);
/* Enable interrupts */
up->ier = mode;
@@ -1547,11 +1546,13 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
ret = PTR_ERR(up->rts_gpiod);
if (ret == -EPROBE_DEFER)
return ret;
- /*
- * FIXME: the code historically ignored any other error than
- * -EPROBE_DEFER and just went on without GPIO.
- */
+
up->rts_gpiod = NULL;
+ up->port.rs485_supported = (const struct serial_rs485) { };
+ if (rs485conf->flags & SER_RS485_ENABLED) {
+ dev_err(dev, "disabling RS-485 (rts-gpio missing in device tree)\n");
+ memset(rs485conf, 0, sizeof(*rs485conf));
+ }
} else {
gpiod_set_consumer_name(up->rts_gpiod, "omap-serial");
}
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index 888e17e3f25f..fde39cc1145d 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -328,7 +328,7 @@ static void owl_uart_change_baudrate(struct owl_uart_port *owl_port,
static void owl_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct owl_uart_port *owl_port = to_owl_uart_port(port);
unsigned int baud;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 8a9065e4a903..c59ce7886579 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -898,9 +898,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
fifo_size--;
}
- bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
- UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
- xmit->tail, UART_XMIT_SIZE));
+ bytes = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (!bytes) {
dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__);
pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
@@ -1301,7 +1299,8 @@ static void pch_uart_shutdown(struct uart_port *port)
*bits. Update read_status_mask and ignore_status_mask to indicate
*the types of events we are interested in receiving. */
static void pch_uart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
int rtn;
unsigned int baud, parity, bits, stb;
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
index f418f1de66b3..2beada66c824 100644
--- a/drivers/tty/serial/pic32_uart.c
+++ b/drivers/tty/serial/pic32_uart.c
@@ -50,7 +50,7 @@
* @irq_rx_name: irq rx name
* @irq_tx: virtual tx interrupt number
* @irq_tx_name: irq tx name
- * @cts_gpio: clear to send gpio
+ * @cts_gpiod: clear to send GPIO
* @dev: device descriptor
**/
struct pic32_sport {
@@ -65,8 +65,7 @@ struct pic32_sport {
const char *irq_tx_name;
bool enable_tx_irq;
- bool hw_flow_ctrl;
- int cts_gpio;
+ struct gpio_desc *cts_gpiod;
struct clk *clk;
@@ -158,25 +157,16 @@ static void pic32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
PIC32_UART_MODE_LPBK);
}
-/* get the state of CTS input pin for this port */
-static unsigned int get_cts_state(struct pic32_sport *sport)
-{
- /* read and invert UxCTS */
- if (gpio_is_valid(sport->cts_gpio))
- return !gpio_get_value(sport->cts_gpio);
-
- return 1;
-}
-
/* serial core request to return the state of misc UART input pins */
static unsigned int pic32_uart_get_mctrl(struct uart_port *port)
{
struct pic32_sport *sport = to_pic32_sport(port);
unsigned int mctrl = 0;
- if (!sport->hw_flow_ctrl)
+ /* get the state of CTS input pin for this port */
+ if (!sport->cts_gpiod)
mctrl |= TIOCM_CTS;
- else if (get_cts_state(sport))
+ else if (gpiod_get_value(sport->cts_gpiod))
mctrl |= TIOCM_CTS;
/* DSR and CD are not supported in PIC32, so return 1
@@ -609,7 +599,7 @@ static void pic32_uart_shutdown(struct uart_port *port)
/* serial core request to change current uart setting */
static void pic32_uart_set_termios(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct pic32_sport *sport = to_pic32_sport(port);
unsigned int baud;
@@ -648,7 +638,7 @@ static void pic32_uart_set_termios(struct uart_port *port,
PIC32_UART_MODE_PDSEL0);
}
/* if hw flow ctrl, then the pins must be specified in device tree */
- if ((new->c_cflag & CRTSCTS) && sport->hw_flow_ctrl) {
+ if ((new->c_cflag & CRTSCTS) && sport->cts_gpiod) {
/* enable hardware flow control */
pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
PIC32_UART_MODE_UEN1);
@@ -875,7 +865,8 @@ static struct uart_driver pic32_uart_driver = {
static int pic32_uart_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
struct pic32_sport *sport;
int uart_idx = 0;
struct resource *res_mem;
@@ -904,25 +895,10 @@ static int pic32_uart_probe(struct platform_device *pdev)
/* Hardware flow control: gpios
* !Note: Basically, CTS is needed for reading the status.
*/
- sport->hw_flow_ctrl = false;
- sport->cts_gpio = of_get_named_gpio(np, "cts-gpios", 0);
- if (gpio_is_valid(sport->cts_gpio)) {
- sport->hw_flow_ctrl = true;
-
- ret = devm_gpio_request(sport->dev,
- sport->cts_gpio, "CTS");
- if (ret) {
- dev_err(&pdev->dev,
- "error requesting CTS GPIO\n");
- goto err;
- }
-
- ret = gpio_direction_input(sport->cts_gpio);
- if (ret) {
- dev_err(&pdev->dev, "error setting CTS GPIO\n");
- goto err;
- }
- }
+ sport->cts_gpiod = devm_gpiod_get_optional(dev, "cts", GPIOD_IN);
+ if (IS_ERR(sport->cts_gpiod))
+ return dev_err_probe(dev, PTR_ERR(sport->cts_gpiod), "error requesting CTS GPIO\n");
+ gpiod_set_consumer_name(sport->cts_gpiod, "CTS");
pic32_sports[uart_idx] = sport;
port = &sport->port;
@@ -943,7 +919,7 @@ static int pic32_uart_probe(struct platform_device *pdev)
}
#ifdef CONFIG_SERIAL_PIC32_CONSOLE
- if (uart_console(port) && (pic32_console.flags & CON_ENABLED)) {
+ if (uart_console_enabled(port)) {
/* The peripheral clock has been enabled by console_setup,
* so disable it till the port is used.
*/
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index f63257b8e872..fe2e4ec423f7 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1202,7 +1202,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned long baud;
@@ -1244,7 +1244,7 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
/* The port lock is not held. */
static void pmz_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned long flags;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9309ffd87c8e..2d25231fad84 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -423,7 +423,7 @@ static void serial_pxa_shutdown(struct uart_port *port)
static void
serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
unsigned char cval, fcr = 0;
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index f4698a064a4d..83b66b73303a 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <dt-bindings/interconnect/qcom,icc.h>
/* UART specific GENI registers */
#define SE_UART_LOOPBACK_CFG 0x22c
@@ -1005,7 +1006,8 @@ static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud,
}
static void qcom_geni_serial_set_termios(struct uart_port *uport,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned int baud;
u32 bits_per_char;
@@ -1524,7 +1526,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
* even with no_console_suspend
*/
if (uart_console(uport)) {
- geni_icc_set_tag(&port->se, 0x3);
+ geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ACTIVE_ONLY);
geni_icc_set_bw(&port->se);
}
return uart_suspend_port(private_data->drv, uport);
@@ -1539,7 +1541,7 @@ static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
ret = uart_resume_port(private_data->drv, uport);
if (uart_console(uport)) {
- geni_icc_set_tag(&port->se, 0x7);
+ geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS);
geni_icc_set_bw(&port->se);
}
return ret;
diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c
index feb2054aba37..0e387e2144fa 100644
--- a/drivers/tty/serial/rda-uart.c
+++ b/drivers/tty/serial/rda-uart.c
@@ -238,7 +238,7 @@ static void rda_uart_change_baudrate(struct rda_uart_port *rda_port,
static void rda_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct rda_uart_port *rda_port = to_rda_uart_port(port);
unsigned long flags;
diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c
index 6689d8add8f7..b81afb06f1f4 100644
--- a/drivers/tty/serial/rp2.c
+++ b/drivers/tty/serial/rp2.c
@@ -370,9 +370,8 @@ static void __rp2_uart_set_termios(struct rp2_uart_port *up,
up->ucode + RP2_RX_SWFLOW);
}
-static void rp2_uart_set_termios(struct uart_port *port,
- struct ktermios *new,
- struct ktermios *old)
+static void rp2_uart_set_termios(struct uart_port *port, struct ktermios *new,
+ const struct ktermios *old)
{
struct rp2_uart_port *up = port_to_up(port);
unsigned long flags;
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index e64e42a19d1a..dd9e3253cab4 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -409,7 +409,7 @@ static void sa1100_shutdown(struct uart_port *port)
static void
sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct sa1100_port *sport =
container_of(port, struct sa1100_port, port);
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index b7a4b47ce74e..77d1363029f5 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -1530,7 +1530,7 @@ static const u16 udivslot_table[16] = {
static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
const struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index 2cf8533ef760..c5d2b6cdcb4a 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -531,7 +531,7 @@ static void sbd_init_port(struct sbd_port *sport)
}
static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
+ const struct ktermios *old_termios)
{
struct sbd_port *sport = to_sport(uport);
unsigned int mode1 = 0, mode2 = 0, aux = 0;
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index d983692c59e0..524921360ca7 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1015,7 +1015,7 @@ static void sc16is7xx_break_ctl(struct uart_port *port, int break_state)
static void sc16is7xx_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index c56de2e104d4..dd98509f52e5 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -636,7 +636,8 @@ static void sccnxp_break_ctl(struct uart_port *port, int break_state)
}
static void sccnxp_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
unsigned long flags;
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index a5748e41483b..b7170cb9a544 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1270,14 +1270,14 @@ static void tegra_uart_enable_ms(struct uart_port *u)
}
static void tegra_uart_set_termios(struct uart_port *u,
- struct ktermios *termios, struct ktermios *oldtermios)
+ struct ktermios *termios,
+ const struct ktermios *oldtermios)
{
struct tegra_uart_port *tup = to_tegra_uport(u);
unsigned int baud;
unsigned long flags;
unsigned int lcr;
unsigned char char_bits;
- int symb_bit = 1;
struct clk *parent_clk = clk_get_parent(tup->uart_clk);
unsigned long parent_clk_rate = clk_get_rate(parent_clk);
int max_divider = (tup->cdata->support_clk_src_div) ? 0x7FFF : 0xFFFF;
@@ -1304,7 +1304,6 @@ static void tegra_uart_set_termios(struct uart_port *u,
termios->c_cflag &= ~CMSPAR;
if ((termios->c_cflag & PARENB) == PARENB) {
- symb_bit++;
if (termios->c_cflag & PARODD) {
lcr |= UART_LCR_PARITY;
lcr &= ~UART_LCR_EPAR;
@@ -1317,22 +1316,18 @@ static void tegra_uart_set_termios(struct uart_port *u,
}
char_bits = tty_get_char_size(termios->c_cflag);
- symb_bit += char_bits;
lcr &= ~UART_LCR_WLEN8;
lcr |= UART_LCR_WLEN(char_bits);
/* Stop bits */
- if (termios->c_cflag & CSTOPB) {
+ if (termios->c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
- symb_bit += 2;
- } else {
+ else
lcr &= ~UART_LCR_STOP;
- symb_bit++;
- }
tegra_uart_write(tup, lcr, UART_LCR);
tup->lcr_shadow = lcr;
- tup->symb_bit = symb_bit;
+ tup->symb_bit = tty_get_frame_size(termios->c_cflag);
/* Baud rate. */
baud = uart_get_baud_rate(u, termios, oldtermios,
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 12c87cd201a7..179ee199df34 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -49,7 +49,7 @@ static struct lock_class_key port_lock_key;
#define RS485_MAX_RTS_DELAY 100 /* msecs */
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
- struct ktermios *old_termios);
+ const struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
static void uart_change_pm(struct uart_state *state,
enum uart_pm_state pm_state);
@@ -158,15 +158,10 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
unsigned long flags;
unsigned int old;
- if (port->rs485.flags & SER_RS485_ENABLED) {
- set &= ~TIOCM_RTS;
- clear &= ~TIOCM_RTS;
- }
-
spin_lock_irqsave(&port->lock, flags);
old = port->mctrl;
port->mctrl = (old & ~clear) | set;
- if (old != port->mctrl)
+ if (old != port->mctrl && !(port->rs485.flags & SER_RS485_ENABLED))
port->ops->set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -380,7 +375,7 @@ EXPORT_SYMBOL(uart_update_timeout);
*/
unsigned int
uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old, unsigned int min, unsigned int max)
+ const struct ktermios *old, unsigned int min, unsigned int max)
{
unsigned int try;
unsigned int baud;
@@ -492,7 +487,7 @@ EXPORT_SYMBOL(uart_get_divisor);
/* Caller holds port mutex */
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
- struct ktermios *old_termios)
+ const struct ktermios *old_termios)
{
struct uart_port *uport = uart_port_check(state);
struct ktermios *termios;
@@ -1391,7 +1386,7 @@ static void uart_set_rs485_termination(struct uart_port *port,
!!(rs485->flags & SER_RS485_TERMINATE_BUS));
}
-int uart_rs485_config(struct uart_port *port)
+static int uart_rs485_config(struct uart_port *port)
{
struct serial_rs485 *rs485 = &port->rs485;
int ret;
@@ -1405,7 +1400,6 @@ int uart_rs485_config(struct uart_port *port)
return ret;
}
-EXPORT_SYMBOL_GPL(uart_rs485_config);
static int uart_get_rs485_config(struct uart_port *port,
struct serial_rs485 __user *rs485)
@@ -1444,8 +1438,13 @@ static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
ret = port->rs485_config(port, &tty->termios, &rs485);
- if (!ret)
+ if (!ret) {
port->rs485 = rs485;
+
+ /* Reset RTS and other mctrl lines when disabling RS485 */
+ if (!(rs485.flags & SER_RS485_ENABLED))
+ port->ops->set_mctrl(port, port->mctrl);
+ }
spin_unlock_irqrestore(&port->lock, flags);
if (ret)
return ret;
@@ -1619,7 +1618,7 @@ static void uart_set_ldisc(struct tty_struct *tty)
}
static void uart_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
+ const struct ktermios *old_termios)
{
struct uart_state *state = tty->driver_data;
struct uart_port *uport;
@@ -2352,7 +2351,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
spin_lock_irq(&uport->lock);
ops->stop_tx(uport);
- ops->set_mctrl(uport, 0);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, 0);
/* save mctrl so it can be restored on resume */
mctrl = uport->mctrl;
uport->mctrl = 0;
@@ -2440,7 +2440,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
uart_change_pm(state, UART_PM_STATE_ON);
spin_lock_irq(&uport->lock);
- ops->set_mctrl(uport, 0);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, 0);
spin_unlock_irq(&uport->lock);
if (console_suspend_enabled || !uart_console(uport)) {
/* Protected by port mutex for now */
@@ -2451,7 +2452,10 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
if (tty)
uart_change_speed(tty, state, NULL);
spin_lock_irq(&uport->lock);
- ops->set_mctrl(uport, uport->mctrl);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, uport->mctrl);
+ else
+ uart_rs485_config(uport);
ops->start_tx(uport);
spin_unlock_irq(&uport->lock);
tty_port_set_initialized(port, 1);
@@ -2497,7 +2501,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
"MMIO 0x%llx", (unsigned long long)port->mapbase);
break;
default:
- strlcpy(address, "*unknown*", sizeof(address));
+ strscpy(address, "*unknown*", sizeof(address));
break;
}
@@ -2558,10 +2562,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
*/
spin_lock_irqsave(&port->lock, flags);
port->mctrl &= TIOCM_DTR;
- if (port->rs485.flags & SER_RS485_ENABLED &&
- !(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
- port->mctrl |= TIOCM_RTS;
- port->ops->set_mctrl(port, port->mctrl);
+ if (!(port->rs485.flags & SER_RS485_ENABLED))
+ port->ops->set_mctrl(port, port->mctrl);
+ else
+ uart_rs485_config(port);
spin_unlock_irqrestore(&port->lock, flags);
/*
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 228e380db080..e12f1dc18c38 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -594,7 +594,7 @@ static void serial_txx9_shutdown(struct uart_port *up)
static void
serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int cval, fcr = 0;
unsigned long flags;
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 0075a1420005..62f773286d44 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1407,10 +1407,8 @@ static void sci_dma_tx_work_fn(struct work_struct *work)
spin_lock_irq(&port->lock);
head = xmit->head;
tail = xmit->tail;
- buf = s->tx_dma_addr + (tail & (UART_XMIT_SIZE - 1));
- s->tx_dma_len = min_t(unsigned int,
- CIRC_CNT(head, tail, UART_XMIT_SIZE),
- CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE));
+ buf = s->tx_dma_addr + tail;
+ s->tx_dma_len = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE);
if (!s->tx_dma_len) {
/* Transmit buffer has been flushed */
spin_unlock_irq(&port->lock);
@@ -2367,7 +2365,7 @@ static void sci_reset(struct uart_port *port)
}
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i, bits;
unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index 4b1d4fe8458e..7fb6760b5c37 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -646,7 +646,7 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,
static void sifive_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
unsigned long flags;
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 4329b9c9cbf0..342a87967631 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -771,9 +771,8 @@ static void sprd_shutdown(struct uart_port *port)
devm_free_irq(port->dev, port->irq, port);
}
-static void sprd_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
+static void sprd_set_termios(struct uart_port *port, struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned int baud, quot;
unsigned int lcr = 0, fc;
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index cce42f4c9bc2..fcecea689a0d 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -500,7 +500,7 @@ static void asc_pm(struct uart_port *port, unsigned int state,
}
static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct asc_port *ascport = to_asc_port(port);
struct gpio_desc *gpiod;
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 2c85dbf165c4..dfdbcf092fac 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -37,7 +37,7 @@
/* Register offsets */
-static struct stm32_usart_info stm32f4_info = {
+static struct stm32_usart_info __maybe_unused stm32f4_info = {
.ofs = {
.isr = 0x00,
.rdr = 0x04,
@@ -58,7 +58,7 @@ static struct stm32_usart_info stm32f4_info = {
}
};
-static struct stm32_usart_info stm32f7_info = {
+static struct stm32_usart_info __maybe_unused stm32f7_info = {
.ofs = {
.cr1 = 0x00,
.cr2 = 0x04,
@@ -80,7 +80,7 @@ static struct stm32_usart_info stm32f7_info = {
}
};
-static struct stm32_usart_info stm32h7_info = {
+static struct stm32_usart_info __maybe_unused stm32h7_info = {
.ofs = {
.cr1 = 0x00,
.cr2 = 0x04,
@@ -131,6 +131,53 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits)
writel_relaxed(val, port->membase + reg);
}
+static unsigned int stm32_usart_tx_empty(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
+ return TIOCSER_TEMT;
+
+ return 0;
+}
+
+static void stm32_usart_rs485_rts_enable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct serial_rs485 *rs485conf = &port->rs485;
+
+ if (stm32_port->hw_flow_control ||
+ !(rs485conf->flags & SER_RS485_ENABLED))
+ return;
+
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl | TIOCM_RTS);
+ } else {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl & ~TIOCM_RTS);
+ }
+}
+
+static void stm32_usart_rs485_rts_disable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct serial_rs485 *rs485conf = &port->rs485;
+
+ if (stm32_port->hw_flow_control ||
+ !(rs485conf->flags & SER_RS485_ENABLED))
+ return;
+
+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl & ~TIOCM_RTS);
+ } else {
+ mctrl_gpio_set(stm32_port->gpios,
+ stm32_port->port.mctrl | TIOCM_RTS);
+ }
+}
+
static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
u32 delay_DDE, u32 baud)
{
@@ -214,6 +261,12 @@ static int stm32_usart_config_rs485(struct uart_port *port, struct ktermios *ter
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+ /* Adjust RTS polarity in case it's driven in software */
+ if (stm32_usart_tx_empty(port))
+ stm32_usart_rs485_rts_disable(port);
+ else
+ stm32_usart_rs485_rts_enable(port);
+
return 0;
}
@@ -529,42 +582,6 @@ static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
}
-static void stm32_usart_rs485_rts_enable(struct uart_port *port)
-{
- struct stm32_port *stm32_port = to_stm32_port(port);
- struct serial_rs485 *rs485conf = &port->rs485;
-
- if (stm32_port->hw_flow_control ||
- !(rs485conf->flags & SER_RS485_ENABLED))
- return;
-
- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl | TIOCM_RTS);
- } else {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl & ~TIOCM_RTS);
- }
-}
-
-static void stm32_usart_rs485_rts_disable(struct uart_port *port)
-{
- struct stm32_port *stm32_port = to_stm32_port(port);
- struct serial_rs485 *rs485conf = &port->rs485;
-
- if (stm32_port->hw_flow_control ||
- !(rs485conf->flags & SER_RS485_ENABLED))
- return;
-
- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl & ~TIOCM_RTS);
- } else {
- mctrl_gpio_set(stm32_port->gpios,
- stm32_port->port.mctrl | TIOCM_RTS);
- }
-}
-
static void stm32_usart_transmit_chars_pio(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
@@ -807,17 +824,6 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
return IRQ_HANDLED;
}
-static unsigned int stm32_usart_tx_empty(struct uart_port *port)
-{
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-
- if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
- return TIOCSER_TEMT;
-
- return 0;
-}
-
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct stm32_port *stm32_port = to_stm32_port(port);
@@ -1089,7 +1095,7 @@ static void stm32_usart_shutdown(struct uart_port *port)
static void stm32_usart_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index eafada8fb6fa..1938ba5e98c0 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -323,7 +323,7 @@ static void sunhv_shutdown(struct uart_port *port)
/* port->lock is not held. */
static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
unsigned int quot = uart_get_divisor(port, baud);
diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c
index 60c73662f955..7afe61a0e72e 100644
--- a/drivers/tty/serial/sunplus-uart.c
+++ b/drivers/tty/serial/sunplus-uart.c
@@ -333,7 +333,7 @@ static void sunplus_shutdown(struct uart_port *port)
static void sunplus_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *oldtermios)
+ const struct ktermios *oldtermios)
{
u32 ext, div, div_l, div_h, baud, lcr;
u32 clk = port->uartclk;
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 6ea52293d9f3..99608b2a2b74 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -681,27 +681,23 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
unsigned int quot)
{
unsigned char dafo;
- int bits, n, m;
+ int n, m;
/* Byte size and parity */
switch (cflag & CSIZE) {
- case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
- case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
- case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
+ case CS5: dafo = SAB82532_DAFO_CHL5; break;
+ case CS6: dafo = SAB82532_DAFO_CHL6; break;
+ case CS7: dafo = SAB82532_DAFO_CHL7; break;
+ case CS8: dafo = SAB82532_DAFO_CHL8; break;
/* Never happens, but GCC is too dumb to figure it out */
- default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
+ default: dafo = SAB82532_DAFO_CHL5; break;
}
- if (cflag & CSTOPB) {
+ if (cflag & CSTOPB)
dafo |= SAB82532_DAFO_STOP;
- bits++;
- }
- if (cflag & PARENB) {
+ if (cflag & PARENB)
dafo |= SAB82532_DAFO_PARE;
- bits++;
- }
if (cflag & PARODD) {
dafo |= SAB82532_DAFO_PAR_ODD;
@@ -776,7 +772,7 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
/* port->lock is not held. */
static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_sunsab_port *up =
container_of(port, struct uart_sunsab_port, port);
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 84d545e5a8c7..9ea7e567540d 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -897,7 +897,7 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
static void
sunsu_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud, quot;
@@ -1217,13 +1217,13 @@ static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
serio->id.type = SERIO_RS232;
if (up->su_type == SU_PORT_KBD) {
serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "sukbd", sizeof(serio->name));
+ strscpy(serio->name, "sukbd", sizeof(serio->name));
} else {
serio->id.proto = SERIO_SUN;
serio->id.extra = 1;
- strlcpy(serio->name, "sums", sizeof(serio->name));
+ strscpy(serio->name, "sums", sizeof(serio->name));
}
- strlcpy(serio->phys,
+ strscpy(serio->phys,
(!(up->port.line & 1) ? "su/serio0" : "su/serio1"),
sizeof(serio->phys));
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index c14275d83b0b..87425290687d 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -938,7 +938,7 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
/* The port lock is not held. */
static void
sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct uart_sunzilog_port *up =
container_of(port, struct uart_sunzilog_port, port);
@@ -1307,13 +1307,13 @@ static void sunzilog_register_serio(struct uart_sunzilog_port *up)
serio->id.type = SERIO_RS232;
if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "zskbd", sizeof(serio->name));
+ strscpy(serio->name, "zskbd", sizeof(serio->name));
} else {
serio->id.proto = SERIO_SUN;
serio->id.extra = 1;
- strlcpy(serio->name, "zsms", sizeof(serio->name));
+ strscpy(serio->name, "zsms", sizeof(serio->name));
}
- strlcpy(serio->phys,
+ strscpy(serio->phys,
((up->flags & SUNZILOG_FLAG_CONS_KEYB) ?
"zs/serio0" : "zs/serio1"),
sizeof(serio->phys));
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
index 889b701ba7c6..23500b342da7 100644
--- a/drivers/tty/serial/tegra-tcu.c
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -126,7 +126,7 @@ static void tegra_tcu_uart_shutdown(struct uart_port *port)
static void tegra_tcu_uart_set_termios(struct uart_port *port,
struct ktermios *new,
- struct ktermios *old)
+ const struct ktermios *old)
{
}
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 08941eabe7b1..bb19ed012def 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -275,8 +275,8 @@ static int get_bindex(int baud)
}
static void timbuart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned int baud;
short bindex;
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 880e2afbb97b..eca41ac5477c 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -314,8 +314,9 @@ static void ulite_shutdown(struct uart_port *port)
clk_disable(pdata->clk);
}
-static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+static void ulite_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ const struct ktermios *old)
{
unsigned long flags;
struct uartlite_data *pdata = port->private_data;
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 3cc9ef08455c..82cf14dd3d43 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -843,7 +843,8 @@ static void qe_uart_shutdown(struct uart_port *port)
* Set the serial port parameters.
*/
static void qe_uart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
struct uart_qe_port *qe_port =
container_of(port, struct uart_qe_port, port);
@@ -853,13 +854,6 @@ static void qe_uart_set_termios(struct uart_port *port,
u16 upsmr = ioread16be(&uccp->upsmr);
struct ucc_uart_pram __iomem *uccup = qe_port->uccup;
u16 supsmr = ioread16be(&uccup->supsmr);
- u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */
-
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
/* byte size */
upsmr &= UCC_UART_UPSMR_CL_MASK;
@@ -869,22 +863,18 @@ static void qe_uart_set_termios(struct uart_port *port,
case CS5:
upsmr |= UCC_UART_UPSMR_CL_5;
supsmr |= UCC_UART_SUPSMR_CL_5;
- char_length += 5;
break;
case CS6:
upsmr |= UCC_UART_UPSMR_CL_6;
supsmr |= UCC_UART_SUPSMR_CL_6;
- char_length += 6;
break;
case CS7:
upsmr |= UCC_UART_UPSMR_CL_7;
supsmr |= UCC_UART_SUPSMR_CL_7;
- char_length += 7;
break;
default: /* case CS8 */
upsmr |= UCC_UART_UPSMR_CL_8;
supsmr |= UCC_UART_SUPSMR_CL_8;
- char_length += 8;
break;
}
@@ -892,13 +882,11 @@ static void qe_uart_set_termios(struct uart_port *port,
if (termios->c_cflag & CSTOPB) {
upsmr |= UCC_UART_UPSMR_SL;
supsmr |= UCC_UART_SUPSMR_SL;
- char_length++; /* + SL */
}
if (termios->c_cflag & PARENB) {
upsmr |= UCC_UART_UPSMR_PEN;
supsmr |= UCC_UART_SUPSMR_PEN;
- char_length++; /* + PEN */
if (!(termios->c_cflag & PARODD)) {
upsmr &= ~(UCC_UART_UPSMR_RPM_MASK |
@@ -953,7 +941,7 @@ static void qe_uart_set_termios(struct uart_port *port,
iowrite16be(upsmr, &uccp->upsmr);
if (soft_uart) {
iowrite16be(supsmr, &uccup->supsmr);
- iowrite8(char_length, &uccup->rx_length);
+ iowrite8(tty_get_frame_size(termios->c_cflag), &uccup->rx_length);
/* Soft-UART requires a 1X multiplier for TX */
qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 6f08136ce78a..10fbdb09965f 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -187,6 +187,13 @@ static void handle_rx(struct uart_port *port)
tty_flip_buffer_push(tport);
}
+static unsigned int vt8500_tx_empty(struct uart_port *port)
+{
+ unsigned int idx = vt8500_read(port, VT8500_URFIDX) & 0x1f;
+
+ return idx < 16 ? TIOCSER_TEMT : 0;
+}
+
static void handle_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
@@ -201,7 +208,7 @@ static void handle_tx(struct uart_port *port)
return;
}
- while ((vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16) {
+ while (vt8500_tx_empty(port)) {
if (uart_circ_empty(xmit))
break;
@@ -260,12 +267,6 @@ static irqreturn_t vt8500_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static unsigned int vt8500_tx_empty(struct uart_port *port)
-{
- return (vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16 ?
- TIOCSER_TEMT : 0;
-}
-
static unsigned int vt8500_get_mctrl(struct uart_port *port)
{
unsigned int usr;
@@ -355,7 +356,7 @@ static void vt8500_shutdown(struct uart_port *port)
static void vt8500_set_termios(struct uart_port *port,
struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
struct vt8500_port *vt8500_port =
container_of(port, struct vt8500_port, uart);
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 9e01fe6c0ab8..2eff7cff57c4 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -2,7 +2,7 @@
/*
* Cadence UART driver (found in Xilinx Zynq)
*
- * 2011 - 2014 (C) Xilinx Inc.
+ * Copyright (c) 2011 - 2014 Xilinx, Inc.
*
* This driver has originally been pushed by Xilinx using a Zynq-branding. This
* still shows in the naming of this file, the kconfig symbols and some symbols
@@ -361,6 +361,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
isrstatus &= ~CDNS_UART_IXR_TXEMPTY;
}
+ isrstatus &= port->read_status_mask;
+ isrstatus &= ~port->ignore_status_mask;
/*
* Skip RX processing if RX is disabled as RXEMPTY will never be set
* as read bytes will not be removed from the FIFO.
@@ -675,7 +677,8 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl)
* @old: Values of the previously saved termios structure
*/
static void cdns_uart_set_termios(struct uart_port *port,
- struct ktermios *termios, struct ktermios *old)
+ struct ktermios *termios,
+ const struct ktermios *old)
{
u32 cval = 0;
unsigned int baud, minbaud, maxbaud;
@@ -1130,8 +1133,35 @@ static struct uart_driver cdns_uart_uart_driver;
*/
static void cdns_uart_console_putchar(struct uart_port *port, unsigned char ch)
{
- while (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)
+ unsigned int ctrl_reg;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (1) {
+ ctrl_reg = readl(port->membase + CDNS_UART_CR);
+ if (!(ctrl_reg & CDNS_UART_CR_TX_DIS))
+ break;
+ if (time_after(jiffies, timeout)) {
+ dev_warn(port->dev,
+ "timeout waiting for Enable\n");
+ return;
+ }
+ cpu_relax();
+ }
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (1) {
+ ctrl_reg = readl(port->membase + CDNS_UART_SR);
+
+ if (!(ctrl_reg & CDNS_UART_SR_TXFULL))
+ break;
+ if (time_after(jiffies, timeout)) {
+ dev_warn(port->dev,
+ "timeout waiting for TX fifo\n");
+ return;
+ }
cpu_relax();
+ }
writel(ch, port->membase + CDNS_UART_FIFO);
}
@@ -1329,12 +1359,20 @@ static int cdns_uart_resume(struct device *device)
unsigned long flags;
u32 ctrl_reg;
int may_wake;
+ int ret;
may_wake = device_may_wakeup(device);
if (console_suspend_enabled && uart_console(port) && !may_wake) {
- clk_enable(cdns_uart->pclk);
- clk_enable(cdns_uart->uartclk);
+ ret = clk_enable(cdns_uart->pclk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(cdns_uart->uartclk);
+ if (ret) {
+ clk_disable(cdns_uart->pclk);
+ return ret;
+ }
spin_lock_irqsave(&port->lock, flags);
@@ -1383,9 +1421,17 @@ static int __maybe_unused cdns_runtime_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
struct cdns_uart *cdns_uart = port->private_data;
+ int ret;
- clk_enable(cdns_uart->pclk);
- clk_enable(cdns_uart->uartclk);
+ ret = clk_enable(cdns_uart->pclk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(cdns_uart->uartclk);
+ if (ret) {
+ clk_disable(cdns_uart->pclk);
+ return ret;
+ }
return 0;
};
@@ -1551,6 +1597,8 @@ static int cdns_uart_probe(struct platform_device *pdev)
port->dev = &pdev->dev;
port->uartclk = clk_get_rate(cdns_uart_data->uartclk);
port->private_data = cdns_uart_data;
+ port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG |
+ CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT;
cdns_uart_data->port = port;
platform_set_drvdata(pdev, port);
diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c
index 5bc58591665a..688db7d8b748 100644
--- a/drivers/tty/serial/zs.c
+++ b/drivers/tty/serial/zs.c
@@ -846,7 +846,7 @@ static void zs_reset(struct zs_port *zport)
}
static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
- struct ktermios *old_termios)
+ const struct ktermios *old_termios)
{
struct zs_port *zport = to_zport(uport);
struct zs_scc *scc = zport->scc;