summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c8
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c52
-rw-r--r--drivers/tty/serial/8250/8250_dma.c11
-rw-r--r--drivers/tty/serial/8250/8250_early.c2
-rw-r--r--drivers/tty/serial/8250/8250_exar.c37
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c2
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c28
-rw-r--r--drivers/tty/serial/8250/8250_mid.c43
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c4
-rw-r--r--drivers/tty/serial/8250/8250_omap.c16
-rw-r--r--drivers/tty/serial/8250/8250_port.c45
-rw-r--r--drivers/tty/serial/8250/8250_tegra.c2
-rw-r--r--drivers/tty/serial/8250/Kconfig16
13 files changed, 161 insertions, 105 deletions
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 2350fb3bb5e4..93fe10c680fb 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -82,7 +82,7 @@ static ssize_t lpc_address_show(struct device *dev,
addr = (aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRH) << 8) |
(aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRL));
- return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
+ return sysfs_emit(buf, "0x%x\n", addr);
}
static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
@@ -124,7 +124,7 @@ static ssize_t sirq_show(struct device *dev,
reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
+ return sysfs_emit(buf, "%u\n", reg);
}
static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
@@ -171,7 +171,7 @@ static ssize_t sirq_polarity_show(struct device *dev,
reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
+ return sysfs_emit(buf, "%u\n", reg ? 1 : 0);
}
static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
@@ -487,7 +487,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
port.port.irq = irq_of_parse_and_map(np, 0);
port.port.handle_irq = aspeed_vuart_handle_irq;
port.port.iotype = UPIO_MEM;
- port.port.type = PORT_16550A;
+ port.port.type = PORT_ASPEED_VUART;
port.port.uartclk = clk;
port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index fd95860cd661..2a1226a78a0c 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include "8250.h"
@@ -44,6 +45,10 @@ struct bcm2835aux_data {
u32 cntl;
};
+struct bcm2835_aux_serial_driver_data {
+ resource_size_t offset;
+};
+
static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
{
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -80,9 +85,12 @@ static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
static int bcm2835aux_serial_probe(struct platform_device *pdev)
{
+ const struct bcm2835_aux_serial_driver_data *bcm_data;
struct uart_8250_port up = { };
struct bcm2835aux_data *data;
+ resource_size_t offset = 0;
struct resource *res;
+ unsigned int uartclk;
int ret;
/* allocate the custom structure */
@@ -109,9 +117,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
/* get the clock - this also enables the HW */
- data->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(data->clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n");
+ data->clk = devm_clk_get_optional(&pdev->dev, NULL);
/* get the interrupt */
ret = platform_get_irq(pdev, 0);
@@ -125,8 +131,24 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "memory resource not found");
return -EINVAL;
}
- up.port.mapbase = res->start;
- up.port.mapsize = resource_size(res);
+
+ bcm_data = device_get_match_data(&pdev->dev);
+
+ /* Some UEFI implementations (e.g. tianocore/edk2 for the Raspberry Pi)
+ * describe the miniuart with a base address that encompasses the auxiliary
+ * registers shared between the miniuart and spi.
+ *
+ * This is due to historical reasons, see discussion here :
+ * https://edk2.groups.io/g/devel/topic/87501357#84349
+ *
+ * We need to add the offset between the miniuart and auxiliary
+ * registers to get the real miniuart base address.
+ */
+ if (bcm_data)
+ offset = bcm_data->offset;
+
+ up.port.mapbase = res->start + offset;
+ up.port.mapsize = resource_size(res) - offset;
/* Check for a fixed line number */
ret = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -141,12 +163,19 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
return ret;
}
+ uartclk = clk_get_rate(data->clk);
+ if (!uartclk) {
+ ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "could not get clk rate\n");
+ }
+
/* the HW-clock divider for bcm2835aux is 8,
* but 8250 expects a divider of 16,
* so we have to multiply the actual clock by 2
* to get identical baudrates.
*/
- up.port.uartclk = clk_get_rate(data->clk) * 2;
+ up.port.uartclk = uartclk * 2;
/* register the port */
ret = serial8250_register_8250_port(&up);
@@ -173,16 +202,27 @@ static int bcm2835aux_serial_remove(struct platform_device *pdev)
return 0;
}
+static const struct bcm2835_aux_serial_driver_data bcm2835_acpi_data = {
+ .offset = 0x40,
+};
+
static const struct of_device_id bcm2835aux_serial_match[] = {
{ .compatible = "brcm,bcm2835-aux-uart" },
{ },
};
MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match);
+static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
+ { "BCM2836", (kernel_ulong_t)&bcm2835_acpi_data },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
+
static struct platform_driver bcm2835aux_serial_driver = {
.driver = {
.name = "bcm2835-aux-uart",
.of_match_table = bcm2835aux_serial_match,
+ .acpi_match_table = bcm2835aux_serial_acpi_match,
},
.probe = bcm2835aux_serial_probe,
.remove = bcm2835aux_serial_remove,
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 890fa7ddaa7f..b3c3f7e5851a 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -64,10 +64,19 @@ int serial8250_tx_dma(struct uart_8250_port *p)
struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit;
struct dma_async_tx_descriptor *desc;
+ struct uart_port *up = &p->port;
int ret;
- if (dma->tx_running)
+ if (dma->tx_running) {
+ if (up->x_char) {
+ dmaengine_pause(dma->txchan);
+ uart_xchar_out(up, UART_TX);
+ dmaengine_resume(dma->txchan);
+ }
return 0;
+ } else if (up->x_char) {
+ uart_xchar_out(up, UART_TX);
+ }
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
/* We have been called from __dma_tx_complete() */
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index c171ce6db691..e52585064565 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -86,7 +86,7 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-static void serial_putc(struct uart_port *port, int c)
+static void serial_putc(struct uart_port *port, unsigned char c)
{
unsigned int status;
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index d502240bbcf2..7292917ac878 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -623,7 +623,12 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
maxnr = pci_resource_len(pcidev, bar) >> (board->reg_shift + 3);
- nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
+ if (pcidev->vendor == PCI_VENDOR_ID_ACCESSIO)
+ nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1);
+ else if (board->num_ports)
+ nr_ports = board->num_ports;
+ else
+ nr_ports = pcidev->device & 0x0f;
priv = devm_kzalloc(&pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL);
if (!priv)
@@ -722,22 +727,6 @@ static int __maybe_unused exar_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
-static const struct exar8250_board acces_com_2x = {
- .num_ports = 2,
- .setup = pci_xr17c154_setup,
-};
-
-static const struct exar8250_board acces_com_4x = {
- .num_ports = 4,
- .setup = pci_xr17c154_setup,
-};
-
-static const struct exar8250_board acces_com_8x = {
- .num_ports = 8,
- .setup = pci_xr17c154_setup,
-};
-
-
static const struct exar8250_board pbn_fastcom335_2 = {
.num_ports = 2,
.setup = pci_fastcom335_setup,
@@ -822,13 +811,13 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
}
static const struct pci_device_id exar_pci_tbl[] = {
- EXAR_DEVICE(ACCESSIO, COM_2S, acces_com_2x),
- EXAR_DEVICE(ACCESSIO, COM_4S, acces_com_4x),
- EXAR_DEVICE(ACCESSIO, COM_8S, acces_com_8x),
- EXAR_DEVICE(ACCESSIO, COM232_8, acces_com_8x),
- EXAR_DEVICE(ACCESSIO, COM_2SM, acces_com_2x),
- EXAR_DEVICE(ACCESSIO, COM_4SM, acces_com_4x),
- EXAR_DEVICE(ACCESSIO, COM_8SM, acces_com_8x),
+ EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM_4S, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM_8S, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM232_8, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM_2SM, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM_4SM, pbn_exar_XR17C15x),
+ EXAR_DEVICE(ACCESSIO, COM_8SM, pbn_exar_XR17C15x),
CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 65402d05eff9..cff91aa03f29 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -52,7 +52,7 @@ static void early_out(struct uart_port *port, int offset, uint8_t value)
writel(value, port->membase + (offset << 2));
}
-static void ingenic_early_console_putc(struct uart_port *port, int c)
+static void ingenic_early_console_putc(struct uart_port *port, unsigned char c)
{
uint8_t lsr;
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index d3bafec7619d..0f5af061e0b4 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -117,8 +117,7 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct dw_dma_slave *param = &lpss->dma_param;
struct pci_dev *pdev = to_pci_dev(port->dev);
- unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
+ struct pci_dev *dma_dev;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
@@ -137,6 +136,8 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return -EINVAL;
}
+ dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
+
param->dma_dev = &dma_dev->dev;
param->m_master = 0;
param->p_master = 1;
@@ -152,6 +153,14 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
+static void byt_serial_exit(struct lpss8250 *lpss)
+{
+ struct dw_dma_slave *param = &lpss->dma_param;
+
+ /* Paired with pci_get_slot() in the byt_serial_setup() above */
+ put_device(param->dma_dev);
+}
+
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct uart_8250_dma *dma = &lpss->data.dma;
@@ -170,6 +179,13 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
+static void ehl_serial_exit(struct lpss8250 *lpss)
+{
+ struct uart_8250_port *up = serial8250_get_port(lpss->data.line);
+
+ up->dma = NULL;
+}
+
#ifdef CONFIG_SERIAL_8250_DMA
static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
.nr_channels = 2,
@@ -344,8 +360,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_exit:
- if (lpss->board->exit)
- lpss->board->exit(lpss);
+ lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
return ret;
}
@@ -356,8 +371,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
serial8250_unregister_port(lpss->data.line);
- if (lpss->board->exit)
- lpss->board->exit(lpss);
+ lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
}
@@ -365,12 +379,14 @@ static const struct lpss8250_board byt_board = {
.freq = 100000000,
.base_baud = 2764800,
.setup = byt_serial_setup,
+ .exit = byt_serial_exit,
};
static const struct lpss8250_board ehl_board = {
.freq = 200000000,
.base_baud = 12500000,
.setup = ehl_serial_setup,
+ .exit = ehl_serial_exit,
};
static const struct lpss8250_board qrk_board = {
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index efa0515139f8..a2a03acb04ad 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -73,6 +73,11 @@ static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
return 0;
}
+static void pnw_exit(struct mid8250 *mid)
+{
+ pci_dev_put(mid->dma_dev);
+}
+
static int tng_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
@@ -124,6 +129,11 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
return 0;
}
+static void tng_exit(struct mid8250 *mid)
+{
+ pci_dev_put(mid->dma_dev);
+}
+
static int dnv_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
@@ -312,11 +322,9 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!uart.port.membase)
return -ENOMEM;
- if (mid->board->setup) {
- ret = mid->board->setup(mid, &uart.port);
- if (ret)
- return ret;
- }
+ ret = mid->board->setup(mid, &uart.port);
+ if (ret)
+ return ret;
ret = mid8250_dma_setup(mid, &uart);
if (ret)
@@ -330,9 +338,9 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, mid);
return 0;
+
err:
- if (mid->board->exit)
- mid->board->exit(mid);
+ mid->board->exit(mid);
return ret;
}
@@ -342,8 +350,7 @@ static void mid8250_remove(struct pci_dev *pdev)
serial8250_unregister_port(mid->line);
- if (mid->board->exit)
- mid->board->exit(mid);
+ mid->board->exit(mid);
}
static const struct mid8250_board pnw_board = {
@@ -351,6 +358,7 @@ static const struct mid8250_board pnw_board = {
.freq = 50000000,
.base_baud = 115200,
.setup = pnw_setup,
+ .exit = pnw_exit,
};
static const struct mid8250_board tng_board = {
@@ -358,6 +366,7 @@ static const struct mid8250_board tng_board = {
.freq = 38400000,
.base_baud = 1843200,
.setup = tng_setup,
+ .exit = tng_exit,
};
static const struct mid8250_board dnv_board = {
@@ -368,16 +377,14 @@ static const struct mid8250_board dnv_board = {
.exit = dnv_exit,
};
-#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
-
static const struct pci_device_id pci_ids[] = {
- MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART1, pnw_board),
- MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
- MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
- MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
- MID_DEVICE(PCI_DEVICE_ID_INTEL_CDF_UART, dnv_board),
- MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
- { },
+ { PCI_DEVICE_DATA(INTEL, PNW_UART1, &pnw_board) },
+ { PCI_DEVICE_DATA(INTEL, PNW_UART2, &pnw_board) },
+ { PCI_DEVICE_DATA(INTEL, PNW_UART3, &pnw_board) },
+ { PCI_DEVICE_DATA(INTEL, TNG_UART, &tng_board) },
+ { PCI_DEVICE_DATA(INTEL, CDF_UART, &dnv_board) },
+ { PCI_DEVICE_DATA(INTEL, DNV_UART, &dnv_board) },
+ { }
};
MODULE_DEVICE_TABLE(pci, pci_ids);
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index fb65dc601b23..f4a0caa56f84 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -289,10 +289,10 @@ static void
mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
- unsigned short fraction_L_mapping[] = {
+ static const unsigned short fraction_L_mapping[] = {
0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF
};
- unsigned short fraction_M_mapping[] = {
+ static const unsigned short fraction_M_mapping[] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3
};
struct uart_8250_port *up = up_to_u8250p(port);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 73e5f1dbd075..ac8bfa042391 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -357,21 +357,7 @@ static void omap_8250_set_termios(struct uart_port *port,
unsigned char cval = 0;
unsigned int baud;
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
+ cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 3b12bfc1ed67..318af6f13605 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -307,6 +307,14 @@ static const struct serial8250_config uart_config[] = {
.rxtrig_bytes = {1, 32, 64, 112},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
+ [PORT_ASPEED_VUART] = {
+ .name = "ASPEED VUART",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .rxtrig_bytes = {1, 4, 8, 14},
+ .flags = UART_CAP_FIFO,
+ },
};
/* Uart divisor latch read */
@@ -1615,6 +1623,18 @@ static inline void start_tx_rs485(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct uart_8250_em485 *em485 = up->em485;
+ /*
+ * While serial8250_em485_handle_stop_tx() is a noop if
+ * em485->active_timer != &em485->stop_tx_timer, it might happen that
+ * the timer is still armed and triggers only after the current bunch of
+ * chars is send and em485->active_timer == &em485->stop_tx_timer again.
+ * So cancel the timer. There is still a theoretical race condition if
+ * the timer is already running and only comes around to check for
+ * em485->active_timer when &em485->stop_tx_timer is armed again.
+ */
+ if (em485->active_timer == &em485->stop_tx_timer)
+ hrtimer_try_to_cancel(&em485->stop_tx_timer);
+
em485->active_timer = NULL;
if (em485->tx_stopped) {
@@ -1657,6 +1677,9 @@ static void serial8250_start_tx(struct uart_port *port)
serial8250_rpm_get_tx(up);
+ if (!port->x_char && uart_circ_empty(&port->state->xmit))
+ return;
+
if (em485 &&
em485->active_timer == &em485->start_tx_timer)
return;
@@ -1799,9 +1822,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
int count;
if (port->x_char) {
- serial_out(up, UART_TX, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
+ uart_xchar_out(port, UART_TX);
return;
}
if (uart_tx_stopped(port)) {
@@ -2582,21 +2603,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
{
unsigned char cval;
- switch (c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
+ cval = UART_LCR_WLEN(tty_get_char_size(c_cflag));
if (c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
@@ -3296,7 +3303,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults);
#ifdef CONFIG_SERIAL_8250_CONSOLE
-static void serial8250_console_putchar(struct uart_port *port, int ch)
+static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
{
struct uart_8250_port *up = up_to_u8250p(port);
diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c
index e13ae18b0713..e7cddeec9d8e 100644
--- a/drivers/tty/serial/8250/8250_tegra.c
+++ b/drivers/tty/serial/8250/8250_tegra.c
@@ -175,7 +175,7 @@ static const struct of_device_id tegra_uart_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_uart_of_match);
-static const struct acpi_device_id tegra_uart_acpi_match[] = {
+static const struct acpi_device_id tegra_uart_acpi_match[] __maybe_unused = {
{ "NVDA0100", 0 },
{ },
};
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 9d415a38cc71..cd93ea6eed65 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -479,11 +479,12 @@ config SERIAL_8250_LPSS
select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS)
select RATIONAL
help
- Selecting this option will enable handling of the extra features
- present on the UART found on various Intel platforms such as:
+ Selecting this option will enable handling of the UART found on
+ various Intel platforms such as:
- Intel Baytrail SoC
- Intel Braswell SoC
- Intel Quark X1000 SoC
+ that are not covered by the more generic SERIAL_8250_PCI option.
config SERIAL_8250_MID
tristate "Support for serial ports on Intel MID platforms"
@@ -494,17 +495,18 @@ config SERIAL_8250_MID
select HSU_DMA_PCI if (HSU_DMA && X86_INTEL_MID)
select RATIONAL
help
- Selecting this option will enable handling of the extra features
- present on the UART found on Intel Medfield SOC and various other
- Intel platforms.
+ Selecting this option will enable handling of the UART found on
+ Intel Medfield SOC and various other Intel platforms that is not
+ covered by the more generic SERIAL_8250_PCI option.
config SERIAL_8250_PERICOM
tristate "Support for Pericom and Acces I/O serial ports"
default SERIAL_8250
depends on SERIAL_8250 && PCI
help
- Selecting this option will enable handling of the extra features
- present on the Pericom and Acces I/O UARTs.
+ Selecting this option will enable handling of the Pericom and Acces
+ I/O UARTs that are not covered by the more generic SERIAL_8250_PCI
+ option.
config SERIAL_8250_PXA
tristate "PXA serial port support"