aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c54
-rw-r--r--drivers/tty/serial/8250/8250_core.c27
-rw-r--r--drivers/tty/serial/8250/8250_exar.c20
-rw-r--r--drivers/tty/serial/8250/8250_of.c4
-rw-r--r--drivers/tty/serial/8250/8250_omap.c22
-rw-r--r--drivers/tty/serial/8250/8250_pci.c172
-rw-r--r--drivers/tty/serial/8250/8250_port.c57
-rw-r--r--drivers/tty/serial/8250/serial_cs.c13
-rw-r--r--drivers/tty/serial/Kconfig1
-rw-r--r--drivers/tty/serial/amba-pl011.c2
-rw-r--r--drivers/tty/serial/arc_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c2
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c19
-rw-r--r--drivers/tty/serial/dz.c4
-rw-r--r--drivers/tty/serial/fsl_lpuart.c135
-rw-r--r--drivers/tty/serial/icom.c2
-rw-r--r--drivers/tty/serial/imx.c27
-rw-r--r--drivers/tty/serial/ip22zilog.c2
-rw-r--r--drivers/tty/serial/kgdb_nmi.c4
-rw-r--r--drivers/tty/serial/liteuart.c21
-rw-r--r--drivers/tty/serial/max310x.c40
-rw-r--r--drivers/tty/serial/meson_uart.c8
-rw-r--r--drivers/tty/serial/mux.c2
-rw-r--r--drivers/tty/serial/mvebu-uart.c21
-rw-r--r--drivers/tty/serial/mxs-auart.c26
-rw-r--r--drivers/tty/serial/omap-serial.c10
-rw-r--r--drivers/tty/serial/pmac_zilog.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c22
-rw-r--r--drivers/tty/serial/samsung_tty.c3
-rw-r--r--drivers/tty/serial/sb1250-duart.c2
-rw-r--r--drivers/tty/serial/sc16is7xx.c26
-rw-r--r--drivers/tty/serial/serial_core.c58
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c41
-rw-r--r--drivers/tty/serial/sh-sci.h1
-rw-r--r--drivers/tty/serial/st-asc.c4
-rw-r--r--drivers/tty/serial/stm32-usart.c197
-rw-r--r--drivers/tty/serial/sunsab.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/sunzilog.c2
-rw-r--r--drivers/tty/serial/tegra-tcu.c26
-rw-r--r--drivers/tty/serial/uartlite.c27
-rw-r--r--drivers/tty/serial/ucc_uart.c2
-rw-r--r--drivers/tty/serial/vr41xx_siu.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c12
45 files changed, 588 insertions, 542 deletions
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index d035d08cb987..4caab8714e2c 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -34,7 +34,6 @@
struct aspeed_vuart {
struct device *dev;
- void __iomem *regs;
struct clk *clk;
int line;
struct timer_list unthrottle_timer;
@@ -64,14 +63,24 @@ static const int unthrottle_timeout = HZ/10;
* different system (though most of them use 3f8/4).
*/
+static inline u8 aspeed_vuart_readb(struct aspeed_vuart *vuart, u8 reg)
+{
+ return readb(vuart->port->port.membase + reg);
+}
+
+static inline void aspeed_vuart_writeb(struct aspeed_vuart *vuart, u8 val, u8 reg)
+{
+ writeb(val, vuart->port->port.membase + reg);
+}
+
static ssize_t lpc_address_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
u16 addr;
- addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) |
- (readb(vuart->regs + ASPEED_VUART_ADDRL));
+ 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);
}
@@ -81,8 +90,8 @@ static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
if (addr > U16_MAX)
return -EINVAL;
- writeb(addr >> 8, vuart->regs + ASPEED_VUART_ADDRH);
- writeb(addr >> 0, vuart->regs + ASPEED_VUART_ADDRL);
+ aspeed_vuart_writeb(vuart, addr >> 8, ASPEED_VUART_ADDRH);
+ aspeed_vuart_writeb(vuart, addr >> 0, ASPEED_VUART_ADDRL);
return 0;
}
@@ -111,7 +120,7 @@ static ssize_t sirq_show(struct device *dev,
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
u8 reg;
- reg = readb(vuart->regs + ASPEED_VUART_GCRB);
+ reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB);
reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
@@ -128,10 +137,10 @@ static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
- reg = readb(vuart->regs + ASPEED_VUART_GCRB);
+ reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB);
reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
reg |= sirq;
- writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
+ aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRB);
return 0;
}
@@ -159,7 +168,7 @@ static ssize_t sirq_polarity_show(struct device *dev,
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
u8 reg;
- reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+ 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);
@@ -168,14 +177,14 @@ static ssize_t sirq_polarity_show(struct device *dev,
static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
bool polarity)
{
- u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+ u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
if (polarity)
reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
else
reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
- writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
+ aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
}
static ssize_t sirq_polarity_store(struct device *dev,
@@ -210,14 +219,14 @@ static const struct attribute_group aspeed_vuart_attr_group = {
static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled)
{
- u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+ u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
if (enabled)
reg |= ASPEED_VUART_GCRA_VUART_EN;
else
reg &= ~ASPEED_VUART_GCRA_VUART_EN;
- writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
+ aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
}
static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
@@ -225,7 +234,7 @@ static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
{
u8 reg;
- reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+ reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
/* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
if (!discard)
@@ -233,7 +242,7 @@ static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
else
reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
- writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
+ aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
}
static int aspeed_vuart_startup(struct uart_port *uart_port)
@@ -320,7 +329,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir, lsr;
- int space, count;
+ unsigned int space, count;
iir = serial_port_in(port, UART_IIR);
@@ -339,14 +348,12 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
struct aspeed_vuart *vuart = port->private_data;
__aspeed_vuart_set_throttle(up, true);
- if (!timer_pending(&vuart->unthrottle_timer)) {
- vuart->port = up;
+ if (!timer_pending(&vuart->unthrottle_timer))
mod_timer(&vuart->unthrottle_timer,
jiffies + unthrottle_timeout);
- }
} else {
- count = min(space, 256);
+ count = min(space, 256U);
do {
serial8250_read_char(up, lsr);
@@ -421,13 +428,9 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- vuart->regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(vuart->regs))
- return PTR_ERR(vuart->regs);
memset(&port, 0, sizeof(port));
port.port.private_data = vuart;
- port.port.membase = vuart->regs;
port.port.mapbase = res->start;
port.port.mapsize = resource_size(res);
port.port.startup = aspeed_vuart_startup;
@@ -485,7 +488,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
port.port.iotype = UPIO_MEM;
port.port.type = PORT_16550A;
port.port.uartclk = clk;
- port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
+ port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
if (of_property_read_bool(np, "no-loopback-test"))
@@ -502,6 +505,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
goto err_clk_disable;
vuart->line = rc;
+ vuart->port = serial8250_get_port(vuart->line);
rc = of_parse_phandle_with_fixed_args(
np, "aspeed,sirq-polarity-sense", 2, 0,
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index cae61d1ebec5..1ce193daea7f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -172,7 +172,6 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
static int serial_link_irq_chain(struct uart_8250_port *up)
{
struct hlist_head *h;
- struct hlist_node *n;
struct irq_info *i;
int ret;
@@ -180,13 +179,11 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
+ hlist_for_each_entry(i, h, node)
if (i->irq == up->port.irq)
break;
- }
- if (n == NULL) {
+ if (i == NULL) {
i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
if (i == NULL) {
mutex_unlock(&hash_mutex);
@@ -220,25 +217,18 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
- /*
- * yes, some broken gcc emit "warning: 'i' may be used uninitialized"
- * but no, we are not going to take a patch that assigns NULL below.
- */
struct irq_info *i;
- struct hlist_node *n;
struct hlist_head *h;
mutex_lock(&hash_mutex);
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
- hlist_for_each(n, h) {
- i = hlist_entry(n, struct irq_info, node);
+ hlist_for_each_entry(i, h, node)
if (i->irq == up->port.irq)
break;
- }
- BUG_ON(n == NULL);
+ BUG_ON(i == NULL);
BUG_ON(i->head == NULL);
if (list_empty(i->head))
@@ -331,9 +321,9 @@ static int univ8250_setup_irq(struct uart_8250_port *up)
* hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0.
*/
- if (!port->irq) {
+ if (!port->irq)
mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
- } else
+ else
retval = serial_link_irq_chain(up);
return retval;
@@ -762,6 +752,7 @@ void serial8250_suspend_port(int line)
if (!console_suspend_enabled && uart_console(port) &&
port->type != PORT_8250) {
unsigned char canary = 0xa5;
+
serial_out(up, UART_SCR, canary);
if (serial_in(up, UART_SCR) == canary)
up->canary = canary;
@@ -915,7 +906,7 @@ static struct platform_device *serial8250_isa_devs;
*/
static DEFINE_MUTEX(serial_mutex);
-static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
+static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_port *port)
{
int i;
@@ -980,7 +971,7 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work)
*
* On success the port is ready to use and the line number is returned.
*/
-int serial8250_register_8250_port(struct uart_8250_port *up)
+int serial8250_register_8250_port(const struct uart_8250_port *up)
{
struct uart_8250_port *uart;
int ret = -ENOSPC;
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index bd4e9f6ac29c..3ffeedc29c83 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -501,23 +501,27 @@ static const struct dmi_system_id exar_platforms[] = {
{}
};
+static const struct exar8250_platform *exar_get_platform(void)
+{
+ const struct dmi_system_id *dmi_match;
+
+ dmi_match = dmi_first_match(exar_platforms);
+ if (dmi_match)
+ return dmi_match->driver_data;
+
+ return &exar8250_default_platform;
+}
+
static int
pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
struct uart_8250_port *port, int idx)
{
- const struct exar8250_platform *platform;
- const struct dmi_system_id *dmi_match;
+ const struct exar8250_platform *platform = exar_get_platform();
unsigned int offset = idx * 0x400;
unsigned int baud = 7812500;
u8 __iomem *p;
int ret;
- dmi_match = dmi_first_match(exar_platforms);
- if (dmi_match)
- platform = dmi_match->driver_data;
- else
- platform = &exar8250_default_platform;
-
port->port.uartclk = baud * 16;
port->port.rs485_config = platform->rs485_config;
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 0b077b45d6a9..bce28729dd7b 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -192,6 +192,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
u32 tx_threshold;
int ret;
+ if (IS_ENABLED(CONFIG_SERIAL_8250_BCM7271) &&
+ of_device_is_compatible(ofdev->dev.of_node, "brcm,bcm7271-uart"))
+ return -ENODEV;
+
port_type = (unsigned long)of_device_get_match_data(&ofdev->dev);
if (port_type == PORT_UNKNOWN)
return -EINVAL;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 8ac11eaeca51..79418d4beb48 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -43,6 +43,7 @@
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
#define UART_HAS_EFR2 BIT(4)
#define UART_HAS_RHR_IT_DIS BIT(5)
+#define UART_RX_TIMEOUT_QUIRK BIT(6)
#define OMAP_UART_FCR_RX_TRIG 6
#define OMAP_UART_FCR_TX_TRIG 4
@@ -104,6 +105,9 @@
#define UART_OMAP_EFR2 0x23
#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6)
+/* RX FIFO occupancy indicator */
+#define UART_OMAP_RX_LVL 0x64
+
struct omap8250_priv {
int line;
u8 habit;
@@ -611,6 +615,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port);
static irqreturn_t omap8250_irq(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
+ struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir;
int ret;
@@ -625,6 +630,18 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
serial8250_rpm_get(up);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
+
+ /*
+ * On K3 SoCs, it is observed that RX TIMEOUT is signalled after
+ * FIFO has been drained, in which case a dummy read of RX FIFO
+ * is required to clear RX TIMEOUT condition.
+ */
+ if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
+ (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
+ serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
+ serial_port_in(port, UART_RX);
+ }
+
serial8250_rpm_put(up);
return IRQ_RETVAL(ret);
@@ -813,7 +830,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
poll_count--)
cpu_relax();
- if (!poll_count)
+ if (poll_count == -1)
dev_err(p->port.dev, "teardown incomplete\n");
}
}
@@ -1218,7 +1235,8 @@ static struct omap8250_dma_params am33xx_dma = {
static struct omap8250_platdata am654_platdata = {
.dma_params = &am654_dma,
- .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS,
+ .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS |
+ UART_RX_TIMEOUT_QUIRK,
};
static struct omap8250_platdata am33xx_platdata = {
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 780cc99732b6..75827b608fdb 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -2851,7 +2851,7 @@ enum pci_board_num_t {
pbn_b0_2_1843200,
pbn_b0_4_1843200,
- pbn_b0_1_4000000,
+ pbn_b0_1_3906250,
pbn_b0_bt_1_115200,
pbn_b0_bt_2_115200,
@@ -2931,10 +2931,10 @@ enum pci_board_num_t {
pbn_plx_romulus,
pbn_endrun_2_4000000,
pbn_oxsemi,
- pbn_oxsemi_1_4000000,
- pbn_oxsemi_2_4000000,
- pbn_oxsemi_4_4000000,
- pbn_oxsemi_8_4000000,
+ pbn_oxsemi_1_3906250,
+ pbn_oxsemi_2_3906250,
+ pbn_oxsemi_4_3906250,
+ pbn_oxsemi_8_3906250,
pbn_intel_i960,
pbn_sgi_ioc3,
pbn_computone_4,
@@ -2972,6 +2972,10 @@ enum pci_board_num_t {
pbn_sunix_pci_4s,
pbn_sunix_pci_8s,
pbn_sunix_pci_16s,
+ pbn_titan_1_4000000,
+ pbn_titan_2_4000000,
+ pbn_titan_4_4000000,
+ pbn_titan_8_4000000,
pbn_moxa8250_2p,
pbn_moxa8250_4p,
pbn_moxa8250_8p,
@@ -3077,10 +3081,10 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8,
},
- [pbn_b0_1_4000000] = {
+ [pbn_b0_1_3906250] = {
.flags = FL_BASE0,
.num_ports = 1,
- .base_baud = 4000000,
+ .base_baud = 3906250,
.uart_offset = 8,
},
@@ -3475,31 +3479,31 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 115200,
.uart_offset = 8,
},
- [pbn_oxsemi_1_4000000] = {
+ [pbn_oxsemi_1_3906250] = {
.flags = FL_BASE0,
.num_ports = 1,
- .base_baud = 4000000,
+ .base_baud = 3906250,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_2_4000000] = {
+ [pbn_oxsemi_2_3906250] = {
.flags = FL_BASE0,
.num_ports = 2,
- .base_baud = 4000000,
+ .base_baud = 3906250,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_4_4000000] = {
+ [pbn_oxsemi_4_3906250] = {
.flags = FL_BASE0,
.num_ports = 4,
- .base_baud = 4000000,
+ .base_baud = 3906250,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
- [pbn_oxsemi_8_4000000] = {
+ [pbn_oxsemi_8_3906250] = {
.flags = FL_BASE0,
.num_ports = 8,
- .base_baud = 4000000,
+ .base_baud = 3906250,
.uart_offset = 0x200,
.first_offset = 0x1000,
},
@@ -3759,6 +3763,34 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 921600,
.uart_offset = 0x8,
},
+ [pbn_titan_1_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_titan_2_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_titan_4_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_titan_8_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
[pbn_moxa8250_2p] = {
.flags = FL_BASE1,
.num_ports = 2,
@@ -4478,158 +4510,158 @@ static const struct pci_device_id serial_pci_tbl[] = {
*/
{ PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_b0_1_4000000 },
+ pbn_b0_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_oxsemi_2_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_oxsemi_2_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
+ pbn_oxsemi_4_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
+ pbn_oxsemi_4_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
+ pbn_oxsemi_8_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
+ pbn_oxsemi_8_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
/*
* Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
*/
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_oxsemi_1_3906250 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_oxsemi_2_3906250 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
- pbn_oxsemi_4_4000000 },
+ pbn_oxsemi_4_3906250 },
{ PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
- pbn_oxsemi_8_4000000 },
+ pbn_oxsemi_8_3906250 },
/*
* Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
*/
{ PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_oxsemi_2_3906250 },
/*
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
@@ -4703,22 +4735,22 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_b0_4_921600 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_1_4000000 },
+ pbn_titan_1_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_titan_2_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_4_4000000 },
+ pbn_titan_4_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_8_4000000 },
+ pbn_titan_8_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_titan_2_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_oxsemi_2_4000000 },
+ pbn_titan_2_4000000 },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200V3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_921600 },
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index fc5ab2032282..2164290cbd31 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2512,19 +2512,45 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
unsigned int baud,
unsigned int *frac)
{
+ upf_t magic_multiplier = port->flags & UPF_MAGIC_MULTIPLIER;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int quot;
/*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
+ * Handle magic divisors for baud rates above baud_base on SMSC
+ * Super I/O chips. We clamp custom rates from clk/6 and clk/12
+ * up to clk/4 (0x8001) and clk/8 (0x8002) respectively. These
+ * magic divisors actually reprogram the baud rate generator's
+ * reference clock derived from chips's 14.318MHz clock input.
*
+ * Documentation claims that with these magic divisors the base
+ * frequencies of 7.3728MHz and 3.6864MHz are used respectively
+ * for the extra baud rates of 460800bps and 230400bps rather
+ * than the usual base frequency of 1.8462MHz. However empirical
+ * evidence contradicts that.
+ *
+ * Instead bit 7 of the DLM register (bit 15 of the divisor) is
+ * effectively used as a clock prescaler selection bit for the
+ * base frequency of 7.3728MHz, always used. If set to 0, then
+ * the base frequency is divided by 4 for use by the Baud Rate
+ * Generator, for the usual arrangement where the value of 1 of
+ * the divisor produces the baud rate of 115200bps. Conversely,
+ * if set to 1 and high-speed operation has been enabled with the
+ * Serial Port Mode Register in the Device Configuration Space,
+ * then the base frequency is supplied directly to the Baud Rate
+ * Generator, so for the divisor values of 0x8001, 0x8002, 0x8003,
+ * 0x8004, etc. the respective baud rates produced are 460800bps,
+ * 230400bps, 153600bps, 115200bps, etc.
+ *
+ * In all cases only low 15 bits of the divisor are used to divide
+ * the baud base and therefore 32767 is the maximum divisor value
+ * possible, even though documentation says that the programmable
+ * Baud Rate Generator is capable of dividing the internal PLL
+ * clock by any divisor from 1 to 65535.
*/
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
+ if (magic_multiplier && baud >= port->uartclk / 6)
quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
+ else if (magic_multiplier && baud >= port->uartclk / 12)
quot = 0x8002;
else if (up->port.type == PORT_NPCM)
quot = npcm_get_divisor(up, baud);
@@ -2629,6 +2655,21 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
struct ktermios *old)
{
unsigned int tolerance = port->uartclk / 100;
+ unsigned int min;
+ unsigned int max;
+
+ /*
+ * Handle magic divisors for baud rates above baud_base on SMSC
+ * Super I/O chips. Enable custom rates of clk/4 and clk/8, but
+ * disable divisor values beyond 32767, which are unavailable.
+ */
+ if (port->flags & UPF_MAGIC_MULTIPLIER) {
+ min = port->uartclk / 16 / UART_DIV_MAX >> 1;
+ max = (port->uartclk + tolerance) / 4;
+ } else {
+ min = port->uartclk / 16 / UART_DIV_MAX;
+ max = (port->uartclk + tolerance) / 16;
+ }
/*
* Ask the core to calculate the divisor for us.
@@ -2636,9 +2677,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
* slower than nominal still match standard baud rates without
* causing transmission errors.
*/
- return uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / UART_DIV_MAX,
- (port->uartclk + tolerance) / 16);
+ return uart_get_baud_rate(port, termios, old, min, max);
}
/*
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 63ea9c4da3d5..dc2ef05a10eb 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -306,6 +306,7 @@ static int serial_resume(struct pcmcia_device *link)
static int serial_probe(struct pcmcia_device *link)
{
struct serial_info *info;
+ int ret;
dev_dbg(&link->dev, "serial_attach()\n");
@@ -320,7 +321,15 @@ static int serial_probe(struct pcmcia_device *link)
if (do_sound)
link->config_flags |= CONF_ENABLE_SPKR;
- return serial_config(link);
+ ret = serial_config(link);
+ if (ret)
+ goto free_info;
+
+ return 0;
+
+free_info:
+ kfree(info);
+ return ret;
}
static void serial_detach(struct pcmcia_device *link)
@@ -777,6 +786,7 @@ static const struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
+ PCMCIA_DEVICE_PROD_ID12("Option International", "GSM-Ready 56K/ISDN", 0x9d7cd6f5, 0xb23844aa),
PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
@@ -804,7 +814,6 @@ static const struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b),
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83),
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490),
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 682f9171c82c..24282ad99d85 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1553,6 +1553,7 @@ config SERIAL_LITEUART_CONSOLE
bool "LiteUART serial port console support"
depends on SERIAL_LITEUART=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
Say 'Y' or 'M' here if you wish to use the FPGA-based LiteUART serial
controller from LiteX SoC builder as the system console
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 78682c12156a..e14f3378b8a0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1062,7 +1062,7 @@ static void pl011_dma_rx_poll(struct timer_list *t)
struct tty_port *port = &uap->port.state->port;
struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = uap->dmarx.chan;
- unsigned long flags = 0;
+ unsigned long flags;
unsigned int dmataken = 0;
unsigned int size = 0;
struct pl011_sgbuf *sgbuf;
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 1a9444b6b57e..596217d10d5c 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -149,7 +149,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
/*
* Driver internal routine, used by both tty(serial core) as well as tx-isr
* -Called under spinlock in either cases
- * -also tty->stopped has already been checked
+ * -also tty->flow.stopped has already been checked
* = by uart_start( ) before calling us
* = tx_ist checks that too before calling
*/
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 058886d9045b..249ea35088d2 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -30,9 +30,9 @@
#include <linux/irq.h>
#include <linux/suspend.h>
#include <linux/mm.h>
+#include <linux/io.h>
#include <asm/div64.h>
-#include <asm/io.h>
#include <asm/ioctls.h>
#define PDC_BUFFER_SIZE 512
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 58aaa533203b..c719aa2b1832 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -524,24 +524,7 @@ static void cpm_uart_set_termios(struct uart_port *port,
scval = 0;
/* byte size */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits = 5;
- break;
- case CS6:
- bits = 6;
- break;
- case CS7:
- bits = 7;
- break;
- case CS8:
- bits = 8;
- break;
- /* Never happens, but GCC is too dumb to figure it out */
- default:
- bits = 8;
- break;
- }
+ bits = tty_get_char_size(termios->c_cflag);
sbits = bits - 5;
if (termios->c_cflag & CSTOPB) {
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c
index 4552742c3859..e9edabc5a211 100644
--- a/drivers/tty/serial/dz.c
+++ b/drivers/tty/serial/dz.c
@@ -47,8 +47,8 @@
#include <linux/tty_flip.h>
#include <linux/atomic.h>
+#include <linux/io.h>
#include <asm/bootinfo.h>
-#include <asm/io.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/kn01.h>
@@ -115,7 +115,7 @@ static void dz_out(struct dz_port *dport, unsigned offset, u16 value)
* rs_stop () and rs_start ()
*
* These routines are called before setting or resetting
- * tty->stopped. They enable or disable transmitter interrupts,
+ * tty->flow.stopped. They enable or disable transmitter interrupts,
* as necessary.
* ------------------------------------------------------------
*/
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 794035041744..508128ddfa01 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -824,21 +824,18 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
static void lpuart_txint(struct lpuart_port *sport)
{
- unsigned long flags;
-
- spin_lock_irqsave(&sport->port.lock, flags);
+ spin_lock(&sport->port.lock);
lpuart_transmit_buffer(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ spin_unlock(&sport->port.lock);
}
static void lpuart_rxint(struct lpuart_port *sport)
{
unsigned int flg, ignored = 0, overrun = 0;
struct tty_port *port = &sport->port.state->port;
- unsigned long flags;
unsigned char rx, sr;
- spin_lock_irqsave(&sport->port.lock, flags);
+ spin_lock(&sport->port.lock);
while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) {
flg = TTY_NORMAL;
@@ -850,7 +847,7 @@ static void lpuart_rxint(struct lpuart_port *sport)
sr = readb(sport->port.membase + UARTSR1);
rx = readb(sport->port.membase + UARTDR);
- if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
+ if (uart_prepare_sysrq_char(&sport->port, rx))
continue;
if (sr & (UARTSR1_PE | UARTSR1_OR | UARTSR1_FE)) {
@@ -896,28 +893,26 @@ out:
writeb(UARTSFIFO_RXOF, sport->port.membase + UARTSFIFO);
}
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ uart_unlock_and_check_sysrq(&sport->port);
tty_flip_buffer_push(port);
}
static void lpuart32_txint(struct lpuart_port *sport)
{
- unsigned long flags;
-
- spin_lock_irqsave(&sport->port.lock, flags);
+ spin_lock(&sport->port.lock);
lpuart32_transmit_buffer(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ spin_unlock(&sport->port.lock);
}
static void lpuart32_rxint(struct lpuart_port *sport)
{
unsigned int flg, ignored = 0;
struct tty_port *port = &sport->port.state->port;
- unsigned long flags;
unsigned long rx, sr;
+ bool is_break;
- spin_lock_irqsave(&sport->port.lock, flags);
+ spin_lock(&sport->port.lock);
while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) {
flg = TTY_NORMAL;
@@ -928,16 +923,29 @@ static void lpuart32_rxint(struct lpuart_port *sport)
*/
sr = lpuart32_read(&sport->port, UARTSTAT);
rx = lpuart32_read(&sport->port, UARTDATA);
- rx &= 0x3ff;
+ rx &= UARTDATA_MASK;
+
+ /*
+ * The LPUART can't distinguish between a break and a framing error,
+ * thus we assume it is a break if the received data is zero.
+ */
+ is_break = (sr & UARTSTAT_FE) && !rx;
- if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
+ if (is_break && uart_handle_break(&sport->port))
+ continue;
+
+ if (uart_prepare_sysrq_char(&sport->port, rx))
continue;
if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) {
- if (sr & UARTSTAT_PE)
- sport->port.icount.parity++;
- else if (sr & UARTSTAT_FE)
+ if (sr & UARTSTAT_PE) {
+ if (is_break)
+ sport->port.icount.brk++;
+ else
+ sport->port.icount.parity++;
+ } else if (sr & UARTSTAT_FE) {
sport->port.icount.frame++;
+ }
if (sr & UARTSTAT_OR)
sport->port.icount.overrun++;
@@ -950,22 +958,24 @@ static void lpuart32_rxint(struct lpuart_port *sport)
sr &= sport->port.read_status_mask;
- if (sr & UARTSTAT_PE)
- flg = TTY_PARITY;
- else if (sr & UARTSTAT_FE)
+ if (sr & UARTSTAT_PE) {
+ if (is_break)
+ flg = TTY_BREAK;
+ else
+ flg = TTY_PARITY;
+ } else if (sr & UARTSTAT_FE) {
flg = TTY_FRAME;
+ }
if (sr & UARTSTAT_OR)
flg = TTY_OVERRUN;
-
- sport->port.sysrq = 0;
}
tty_insert_flip_char(port, rx, flg);
}
out:
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ uart_unlock_and_check_sysrq(&sport->port);
tty_flip_buffer_push(port);
}
@@ -1393,58 +1403,54 @@ static int lpuart32_config_rs485(struct uart_port *port,
static unsigned int lpuart_get_mctrl(struct uart_port *port)
{
- unsigned int temp = 0;
- unsigned char reg;
-
- reg = readb(port->membase + UARTMODEM);
- if (reg & UARTMODEM_TXCTSE)
- temp |= TIOCM_CTS;
+ unsigned int mctrl = 0;
+ u8 reg;
- if (reg & UARTMODEM_RXRTSE)
- temp |= TIOCM_RTS;
+ reg = readb(port->membase + UARTCR1);
+ if (reg & UARTCR1_LOOPS)
+ mctrl |= TIOCM_LOOP;
- return temp;
+ return mctrl;
}
static unsigned int lpuart32_get_mctrl(struct uart_port *port)
{
- unsigned int temp = 0;
- unsigned long reg;
-
- reg = lpuart32_read(port, UARTMODIR);
- if (reg & UARTMODIR_TXCTSE)
- temp |= TIOCM_CTS;
+ unsigned int mctrl = 0;
+ u32 reg;
- if (reg & UARTMODIR_RXRTSE)
- temp |= TIOCM_RTS;
+ reg = lpuart32_read(port, UARTCTRL);
+ if (reg & UARTCTRL_LOOPS)
+ mctrl |= TIOCM_LOOP;
- return temp;
+ return mctrl;
}
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- unsigned char temp;
- struct lpuart_port *sport = container_of(port,
- struct lpuart_port, port);
+ u8 reg;
- /* Make sure RXRTSE bit is not set when RS485 is enabled */
- if (!(sport->port.rs485.flags & SER_RS485_ENABLED)) {
- temp = readb(sport->port.membase + UARTMODEM) &
- ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
+ reg = readb(port->membase + UARTCR1);
- if (mctrl & TIOCM_RTS)
- temp |= UARTMODEM_RXRTSE;
+ /* for internal loopback we need LOOPS=1 and RSRC=0 */
+ reg &= ~(UARTCR1_LOOPS | UARTCR1_RSRC);
+ if (mctrl & TIOCM_LOOP)
+ reg |= UARTCR1_LOOPS;
- if (mctrl & TIOCM_CTS)
- temp |= UARTMODEM_TXCTSE;
-
- writeb(temp, port->membase + UARTMODEM);
- }
+ writeb(reg, port->membase + UARTCR1);
}
static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ u32 reg;
+
+ reg = lpuart32_read(port, UARTCTRL);
+ /* for internal loopback we need LOOPS=1 and RSRC=0 */
+ reg &= ~(UARTCTRL_LOOPS | UARTCTRL_RSRC);
+ if (mctrl & TIOCM_LOOP)
+ reg |= UARTCTRL_LOOPS;
+
+ lpuart32_write(port, reg, UARTCTRL);
}
static void lpuart_break_ctl(struct uart_port *port, int break_state)
@@ -1581,6 +1587,9 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport)
u32 uartbaud;
int ret;
+ if (uart_console(&sport->port))
+ goto err;
+
if (!sport->dma_tx_chan)
goto err;
@@ -1610,6 +1619,9 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport)
int ret;
unsigned char cr3;
+ if (uart_console(&sport->port))
+ goto err;
+
if (!sport->dma_rx_chan)
goto err;
@@ -1625,7 +1637,7 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport)
sport->lpuart_dma_rx_use = true;
rx_dma_timer_init(sport);
- if (sport->port.has_sysrq) {
+ if (sport->port.has_sysrq && !lpuart_is_32(sport)) {
cr3 = readb(sport->port.membase + UARTCR3);
cr3 |= UARTCR3_FEIE;
writeb(cr3, sport->port.membase + UARTCR3);
@@ -2278,7 +2290,7 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
unsigned long flags;
int locked = 1;
- if (sport->port.sysrq || oops_in_progress)
+ if (oops_in_progress)
locked = spin_trylock_irqsave(&sport->port.lock, flags);
else
spin_lock_irqsave(&sport->port.lock, flags);
@@ -2308,7 +2320,7 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
unsigned long flags;
int locked = 1;
- if (sport->port.sysrq || oops_in_progress)
+ if (oops_in_progress)
locked = spin_trylock_irqsave(&sport->port.lock, flags);
else
spin_lock_irqsave(&sport->port.lock, flags);
@@ -2414,6 +2426,9 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
bd = lpuart32_read(&sport->port, UARTBAUD);
bd &= UARTBAUD_SBR_MASK;
+ if (!bd)
+ return;
+
sbr = bd;
uartclk = lpuart_get_baud_clk_rate(sport);
/*
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 9e9abfc4824a..03a2fe9f4c9a 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -37,7 +37,7 @@
#include <linux/firmware.h>
#include <linux/bitops.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <linux/uaccess.h>
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 7d5a8dfa3e91..8b121cd869e9 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -225,6 +225,8 @@ struct imx_port {
struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf;
struct circ_buf rx_ring;
+ unsigned int rx_buf_size;
+ unsigned int rx_period_length;
unsigned int rx_periods;
dma_cookie_t rx_cookie;
unsigned int tx_bytes;
@@ -1183,10 +1185,6 @@ static void imx_uart_dma_rx_callback(void *data)
}
}
-/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 16
-#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4)
-
static int imx_uart_start_rx_dma(struct imx_port *sport)
{
struct scatterlist *sgl = &sport->rx_sgl;
@@ -1197,9 +1195,8 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
- sport->rx_periods = RX_DMA_PERIODS;
- sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+ sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
@@ -1316,7 +1313,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
goto err;
}
- sport->rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL);
+ sport->rx_buf_size = sport->rx_period_length * sport->rx_periods;
+ sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
if (!sport->rx_buf) {
ret = -ENOMEM;
goto err;
@@ -1975,8 +1973,8 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
{
struct imx_port *sport = imx_uart_ports[co->index];
struct imx_port_ucrs old_ucr;
+ unsigned long flags;
unsigned int ucr1;
- unsigned long flags = 0;
int locked = 1;
if (sport->port.sysrq)
@@ -2179,11 +2177,16 @@ static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
return HRTIMER_NORESTART;
}
+/* Default RX DMA buffer configuration */
+#define RX_DMA_PERIODS 16
+#define RX_DMA_PERIOD_LEN (PAGE_SIZE / 4)
+
static int imx_uart_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct imx_port *sport;
void __iomem *base;
+ u32 dma_buf_conf[2];
int ret = 0;
u32 ucr1;
struct resource *res;
@@ -2218,6 +2221,14 @@ static int imx_uart_probe(struct platform_device *pdev)
if (of_get_property(np, "fsl,inverted-rx", NULL))
sport->inverted_rx = 1;
+ if (!of_property_read_u32_array(np, "fsl,dma-info", dma_buf_conf, 2)) {
+ sport->rx_period_length = dma_buf_conf[0];
+ sport->rx_periods = dma_buf_conf[1];
+ } else {
+ sport->rx_period_length = RX_DMA_PERIOD_LEN;
+ sport->rx_periods = RX_DMA_PERIODS;
+ }
+
if (sport->port.line >= ARRAY_SIZE(imx_uart_ports)) {
dev_err(&pdev->dev, "serial%d out of range\n",
sport->port.line);
diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c
index 86fff69d7e7c..f4dc5fe4ba92 100644
--- a/drivers/tty/serial/ip22zilog.c
+++ b/drivers/tty/serial/ip22zilog.c
@@ -31,7 +31,7 @@
#include <linux/spinlock.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/sgialib.h>
#include <asm/sgi/ioc.h>
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index db059b66438e..3e7c6ee8e4b3 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -115,7 +115,7 @@ static void kgdb_tty_recv(int ch)
static int kgdb_nmi_poll_one_knock(void)
{
static int n;
- int c = -1;
+ int c;
const char *magic = kgdb_nmi_magic;
size_t m = strlen(magic);
bool printch = false;
@@ -298,7 +298,7 @@ static void kgdb_nmi_tty_hangup(struct tty_struct *tty)
tty_port_hangup(&priv->port);
}
-static int kgdb_nmi_tty_write_room(struct tty_struct *tty)
+static unsigned int kgdb_nmi_tty_write_room(struct tty_struct *tty)
{
/* Actually, we can handle any amount as we use polled writes. */
return 2048;
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 0b06770642cb..dbc0559a9157 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -370,6 +370,27 @@ static int __init liteuart_console_init(void)
return 0;
}
console_initcall(liteuart_console_init);
+
+static void early_liteuart_write(struct console *console, const char *s,
+ unsigned int count)
+{
+ struct earlycon_device *device = console->data;
+ struct uart_port *port = &device->port;
+
+ uart_console_write(port, s, count, liteuart_putchar);
+}
+
+static int __init early_liteuart_setup(struct earlycon_device *device,
+ const char *options)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = early_liteuart_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(liteuart, "litex,liteuart", early_liteuart_setup);
#endif /* CONFIG_SERIAL_LITEUART_CONSOLE */
static int __init liteuart_init(void)
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 3cbc757d7be7..0c1e4df52215 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -552,7 +552,7 @@ static int max310x_update_best_err(unsigned long f, long *besterr)
return 1;
}
-static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
+static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
unsigned long freq, bool xtal)
{
unsigned int div, clksrc, pllcfg = 0;
@@ -618,7 +618,7 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
}
}
- return (int)bestfreq;
+ return bestfreq;
}
static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
@@ -1253,9 +1253,10 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype,
struct regmap *regmap, int irq)
{
- int i, ret, fmin, fmax, freq, uartclk;
+ int i, ret, fmin, fmax, freq;
struct max310x_port *s;
- bool xtal = false;
+ u32 uartclk = 0;
+ bool xtal;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -1267,24 +1268,20 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
return -ENOMEM;
}
+ /* Always ask for fixed clock rate from a property. */
+ device_property_read_u32(dev, "clock-frequency", &uartclk);
+
s->clk = devm_clk_get_optional(dev, "osc");
if (IS_ERR(s->clk))
return PTR_ERR(s->clk);
if (s->clk) {
- fmin = 500000;
- fmax = 35000000;
+ xtal = false;
} else {
s->clk = devm_clk_get_optional(dev, "xtal");
if (IS_ERR(s->clk))
return PTR_ERR(s->clk);
- if (s->clk) {
- fmin = 1000000;
- fmax = 4000000;
- xtal = true;
- } else {
- dev_err(dev, "Cannot get clock\n");
- return -EINVAL;
- }
+
+ xtal = true;
}
ret = clk_prepare_enable(s->clk);
@@ -1292,6 +1289,21 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
return ret;
freq = clk_get_rate(s->clk);
+ if (freq == 0)
+ freq = uartclk;
+ if (freq == 0) {
+ dev_err(dev, "Cannot get clock rate\n");
+ return -EINVAL;
+ }
+
+ if (xtal) {
+ fmin = 1000000;
+ fmax = 4000000;
+ } else {
+ fmin = 500000;
+ fmax = 35000000;
+ }
+
/* Check frequency limits */
if (freq < fmin || freq > fmax) {
ret = -ERANGE;
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 529cd0289056..efee3935917f 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -715,13 +715,15 @@ static int meson_uart_probe(struct platform_device *pdev)
{
struct resource *res_mem, *res_irq;
struct uart_port *port;
+ u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */
int ret = 0;
- int id = -1;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
if (pdev->id < 0) {
+ int id;
+
for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
if (!meson_ports[id]) {
pdev->id = id;
@@ -741,6 +743,8 @@ static int meson_uart_probe(struct platform_device *pdev)
if (!res_irq)
return -ENODEV;
+ of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize);
+
if (meson_ports[pdev->id]) {
dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
return -EBUSY;
@@ -770,7 +774,7 @@ static int meson_uart_probe(struct platform_device *pdev)
port->type = PORT_MESON;
port->x_char = 0;
port->ops = &meson_uart_ops;
- port->fifosize = 64;
+ port->fifosize = fifosize;
meson_ports[pdev->id] = port;
platform_set_drvdata(pdev, port);
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index 47ab280f553b..be640d9863cd 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -21,7 +21,7 @@
#include <linux/console.h>
#include <linux/delay.h> /* for udelay */
#include <linux/device.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/parisc-device.h>
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index 51b0ecabf2ec..231de29a6452 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -128,7 +128,6 @@ struct mvebu_uart {
struct uart_port *port;
struct clk *clk;
int irq[UART_IRQ_COUNT];
- unsigned char __iomem *nb;
struct mvebu_uart_driver_data *data;
#if defined(CONFIG_PM)
struct mvebu_uart_pm_regs pm_regs;
@@ -445,12 +444,11 @@ static void mvebu_uart_shutdown(struct uart_port *port)
static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
{
- struct mvebu_uart *mvuart = to_mvuart(port);
unsigned int d_divisor, m_divisor;
u32 brdv, osamp;
- if (IS_ERR(mvuart->clk))
- return -PTR_ERR(mvuart->clk);
+ if (!port->uartclk)
+ return -EOPNOTSUPP;
/*
* The baudrate is derived from the UART clock thanks to two divisors:
@@ -463,7 +461,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
* makes use of D to configure the desired baudrate.
*/
m_divisor = OSAMP_DEFAULT_DIVISOR;
- d_divisor = DIV_ROUND_UP(port->uartclk, baud * m_divisor);
+ d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor);
brdv = readl(port->membase + UART_BRDV);
brdv &= ~BRDV_BAUD_MASK;
@@ -482,7 +480,7 @@ static void mvebu_uart_set_termios(struct uart_port *port,
struct ktermios *old)
{
unsigned long flags;
- unsigned int baud;
+ unsigned int baud, min_baud, max_baud;
spin_lock_irqsave(&port->lock, flags);
@@ -501,16 +499,21 @@ static void mvebu_uart_set_termios(struct uart_port *port,
port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR;
/*
+ * Maximal divisor is 1023 * 16 when using default (x16) scheme.
* Maximum achievable frequency with simple baudrate divisor is 230400.
* Since the error per bit frame would be of more than 15%, achieving
* higher frequencies would require to implement the fractional divisor
* feature.
*/
- baud = uart_get_baud_rate(port, termios, old, 0, 230400);
+ min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16);
+ max_baud = 230400;
+
+ baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud);
if (mvebu_uart_baud_rate_set(port, baud)) {
/* No clock available, baudrate cannot be changed */
if (old)
- baud = uart_get_baud_rate(port, old, NULL, 0, 230400);
+ baud = uart_get_baud_rate(port, old, NULL,
+ min_baud, max_baud);
} else {
tty_termios_encode_baud_rate(termios, baud, baud);
uart_update_timeout(port, termios->c_cflag, baud);
@@ -617,7 +620,7 @@ static void mvebu_uart_putc(struct uart_port *port, int c)
static void mvebu_uart_putc_early_write(struct console *con,
const char *s,
- unsigned n)
+ unsigned int n)
{
struct earlycon_device *dev = con->data;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index f414d6acad69..ac45f3386e97 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -87,7 +87,7 @@
#define AUART_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8)
#define AUART_LINECTRL_SPS (1 << 7)
#define AUART_LINECTRL_WLEN_MASK 0x00000060
-#define AUART_LINECTRL_WLEN(v) (((v) & 0x3) << 5)
+#define AUART_LINECTRL_WLEN(v) ((((v) - 5) & 0x3) << 5)
#define AUART_LINECTRL_FEN (1 << 4)
#define AUART_LINECTRL_STP2 (1 << 3)
#define AUART_LINECTRL_EPS (1 << 2)
@@ -962,7 +962,7 @@ static void mxs_auart_settermios(struct uart_port *u,
struct ktermios *old)
{
struct mxs_auart_port *s = to_auart_port(u);
- u32 bm, ctrl, ctrl2, div;
+ u32 ctrl, ctrl2, div;
unsigned int cflag, baud, baud_min, baud_max;
cflag = termios->c_cflag;
@@ -970,25 +970,7 @@ static void mxs_auart_settermios(struct uart_port *u,
ctrl = AUART_LINECTRL_FEN;
ctrl2 = mxs_read(s, REG_CTRL2);
- /* byte size */
- switch (cflag & CSIZE) {
- case CS5:
- bm = 0;
- break;
- case CS6:
- bm = 1;
- break;
- case CS7:
- bm = 2;
- break;
- case CS8:
- bm = 3;
- break;
- default:
- return;
- }
-
- ctrl |= AUART_LINECTRL_WLEN(bm);
+ ctrl |= AUART_LINECTRL_WLEN(tty_get_char_size(cflag));
/* parity */
if (cflag & PARENB) {
@@ -1403,7 +1385,7 @@ auart_console_get_options(struct mxs_auart_port *s, int *baud,
*parity = 'o';
}
- if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2))
+ if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(7))
*bits = 7;
else
*bits = 8;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 84e8158088cd..9e81b09ba08e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -626,7 +626,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
static unsigned int serial_omap_tx_empty(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- unsigned long flags = 0;
+ unsigned long flags;
unsigned int ret = 0;
pm_runtime_get_sync(up->dev);
@@ -704,7 +704,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- unsigned long flags = 0;
+ unsigned long flags;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
pm_runtime_get_sync(up->dev);
@@ -722,7 +722,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
static int serial_omap_startup(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- unsigned long flags = 0;
+ unsigned long flags;
int retval;
/*
@@ -797,7 +797,7 @@ static int serial_omap_startup(struct uart_port *port)
static void serial_omap_shutdown(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- unsigned long flags = 0;
+ unsigned long flags;
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
@@ -845,7 +845,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char cval = 0;
- unsigned long flags = 0;
+ unsigned long flags;
unsigned int baud, quot;
switch (termios->c_cflag & CSIZE) {
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index d6aef8a1f0a4..12ce150b0ad4 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -47,7 +47,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/sections.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#ifdef CONFIG_PPC_PMAC
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 23d729ed3bf6..aedc38893e6c 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1050,21 +1050,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
}
/* bits per char */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits_per_char = 5;
- break;
- case CS6:
- bits_per_char = 6;
- break;
- case CS7:
- bits_per_char = 7;
- break;
- case CS8:
- default:
- bits_per_char = 8;
- break;
- }
+ bits_per_char = tty_get_char_size(termios->c_cflag);
/* stop bits */
if (termios->c_cflag & CSTOPB)
@@ -1338,7 +1324,7 @@ static const struct uart_ops qcom_geni_uart_pops = {
static int qcom_geni_serial_probe(struct platform_device *pdev)
{
int ret = 0;
- int line = -1;
+ int line;
struct qcom_geni_serial_port *port;
struct uart_port *uport;
struct resource *res;
@@ -1354,7 +1340,9 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
line = of_alias_get_id(pdev->dev.of_node, "serial");
} else {
drv = &qcom_geni_uart_driver;
- line = of_alias_get_id(pdev->dev.of_node, "hsuart");
+ line = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (line == -ENODEV) /* compat with non-standard aliases */
+ line = of_alias_get_id(pdev->dev.of_node, "hsuart");
}
port = get_port_from_line(line, console);
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index d9e4b67a12a0..9fbc61151c2e 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -2220,8 +2220,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
default:
dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
prop);
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
}
}
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index 22c7bc90b104..738df6d9c0d9 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -34,7 +34,7 @@
#include <linux/types.h>
#include <linux/refcount.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_uart.h>
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 9adb8362578c..acbb615dd28f 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1208,8 +1208,16 @@ static int sc16is7xx_probe(struct device *dev,
/* Always ask for fixed clock rate from a property. */
device_property_read_u32(dev, "clock-frequency", &uartclk);
- s->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(s->clk)) {
+ s->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(s->clk))
+ return PTR_ERR(s->clk);
+
+ ret = clk_prepare_enable(s->clk);
+ if (ret)
+ return ret;
+
+ freq = clk_get_rate(s->clk);
+ if (freq == 0) {
if (uartclk)
freq = uartclk;
if (pfreq)
@@ -1217,13 +1225,7 @@ static int sc16is7xx_probe(struct device *dev,
if (freq)
dev_dbg(dev, "Clock frequency: %luHz\n", freq);
else
- return PTR_ERR(s->clk);
- } else {
- ret = clk_prepare_enable(s->clk);
- if (ret)
- return ret;
-
- freq = clk_get_rate(s->clk);
+ return -EINVAL;
}
s->regmap = regmap;
@@ -1358,8 +1360,7 @@ out_thread:
kthread_stop(s->kworker_task);
out_clk:
- if (!IS_ERR(s->clk))
- clk_disable_unprepare(s->clk);
+ clk_disable_unprepare(s->clk);
return ret;
}
@@ -1383,8 +1384,7 @@ static int sc16is7xx_remove(struct device *dev)
kthread_flush_worker(&s->kworker);
kthread_stop(s->kworker_task);
- if (!IS_ERR(s->clk))
- clk_disable_unprepare(s->clk);
+ clk_disable_unprepare(s->clk);
return 0;
}
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 18ff85a83f80..69092deba11f 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -184,8 +184,8 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
int init_hw)
{
struct uart_port *uport = uart_port_check(state);
+ unsigned long flags;
unsigned long page;
- unsigned long flags = 0;
int retval = 0;
if (uport->type == PORT_UNKNOWN)
@@ -275,7 +275,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
{
struct uart_port *uport = uart_port_check(state);
struct tty_port *port = &state->port;
- unsigned long flags = 0;
+ unsigned long flags;
char *xmit_buf = NULL;
/*
@@ -334,39 +334,15 @@ void
uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int baud)
{
- unsigned int bits;
+ unsigned int size;
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break; /* CS8 */
- }
-
- if (cflag & CSTOPB)
- bits++;
- if (cflag & PARENB)
- bits++;
-
- /*
- * The total number of bits to be transmitted in the fifo.
- */
- bits = bits * port->fifosize;
+ size = tty_get_frame_size(cflag) * port->fifosize;
/*
* Figure the timeout to send the above number of bits.
* Add .02 seconds of slop
*/
- port->timeout = (HZ * bits) / baud + HZ/50;
+ port->timeout = (HZ * size) / baud + HZ/50;
}
EXPORT_SYMBOL(uart_update_timeout);
@@ -616,12 +592,12 @@ static int uart_write(struct tty_struct *tty,
return ret;
}
-static int uart_write_room(struct tty_struct *tty)
+static unsigned int uart_write_room(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port;
unsigned long flags;
- int ret;
+ unsigned int ret;
port = uart_port_lock(state, flags);
ret = uart_circ_chars_free(&state->xmit);
@@ -629,12 +605,12 @@ static int uart_write_room(struct tty_struct *tty)
return ret;
}
-static int uart_chars_in_buffer(struct tty_struct *tty)
+static unsigned int uart_chars_in_buffer(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port;
unsigned long flags;
- int ret;
+ unsigned int ret;
port = uart_port_lock(state, flags);
ret = uart_circ_chars_pending(&state->xmit);
@@ -3029,26 +3005,28 @@ out:
/*
* Are the two ports equivalent?
*/
-int uart_match_port(struct uart_port *port1, struct uart_port *port2)
+bool uart_match_port(const struct uart_port *port1,
+ const struct uart_port *port2)
{
if (port1->iotype != port2->iotype)
- return 0;
+ return false;
switch (port1->iotype) {
case UPIO_PORT:
- return (port1->iobase == port2->iobase);
+ return port1->iobase == port2->iobase;
case UPIO_HUB6:
- return (port1->iobase == port2->iobase) &&
- (port1->hub6 == port2->hub6);
+ return port1->iobase == port2->iobase &&
+ port1->hub6 == port2->hub6;
case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
case UPIO_TSI:
- return (port1->mapbase == port2->mapbase);
+ return port1->mapbase == port2->mapbase;
}
- return 0;
+
+ return false;
}
EXPORT_SYMBOL(uart_match_port);
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 0a7e5b74bc1d..aaca4fe38486 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -24,7 +24,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <asm/io.h>
+#include <linux/io.h>
static char *serial_version = "1.11";
static char *serial_name = "TX39/49 Serial driver";
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 4baf1316ea72..07eb56294371 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -289,7 +289,7 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
},
/*
- * The "SCIFA" that is in RZ/T and RZ/A2.
+ * The "SCIFA" that is in RZ/A2, RZ/G2L and RZ/T.
* It looks like a normal SCIF with FIFO data, but with a
* compressed address space. Also, the break out of interrupts
* are different: ERI/BRI, RXI, TXI, TEI, DRI.
@@ -306,6 +306,7 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
[SCFDR] = { 0x0E, 16 },
[SCSPTR] = { 0x10, 16 },
[SCLSR] = { 0x12, 16 },
+ [SEMR] = { 0x14, 8 },
},
.fifosize = 16,
.overrun_reg = SCLSR,
@@ -610,6 +611,14 @@ static void sci_stop_tx(struct uart_port *port)
ctrl &= ~SCSCR_TIE;
serial_port_out(port, SCSCR, ctrl);
+
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ if (to_sci_port(port)->chan_tx &&
+ !dma_submit_error(to_sci_port(port)->cookie_tx)) {
+ dmaengine_terminate_async(to_sci_port(port)->chan_tx);
+ to_sci_port(port)->cookie_tx = -EINVAL;
+ }
+#endif
}
static void sci_start_rx(struct uart_port *port)
@@ -840,9 +849,6 @@ static void sci_transmit_chars(struct uart_port *port)
}
-/* On SH3, SCIF may read end-of-break as a space->mark char */
-#define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); })
-
static void sci_receive_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
@@ -2494,25 +2500,10 @@ done:
uart_update_timeout(port, termios->c_cflag, baud);
/* byte size and parity */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break;
- }
+ bits = tty_get_frame_size(termios->c_cflag);
- if (termios->c_cflag & CSTOPB)
- bits++;
- if (termios->c_cflag & PARENB)
- bits++;
+ if (sci_getreg(port, SEMR)->size)
+ serial_port_out(port, SEMR, 0);
if (best_clk >= 0) {
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
@@ -3170,6 +3161,10 @@ static const struct of_device_id of_sci_match[] = {
.compatible = "renesas,scif-r7s9210",
.data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE),
},
+ {
+ .compatible = "renesas,scif-r9a07g044",
+ .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE),
+ },
/* Family-specific types */
{
.compatible = "renesas,rcar-gen1-scif",
@@ -3452,6 +3447,7 @@ static int __init rzscifa_early_console_setup(struct earlycon_device *device,
port_cfg.regtype = SCIx_RZ_SCIFA_REGTYPE;
return early_console_setup(device, PORT_SCIF);
}
+
static int __init scifa_early_console_setup(struct earlycon_device *device,
const char *opt)
{
@@ -3471,6 +3467,7 @@ static int __init hscif_early_console_setup(struct earlycon_device *device,
OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup);
OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup);
OF_EARLYCON_DECLARE(scif, "renesas,scif-r7s9210", rzscifa_early_console_setup);
+OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a07g044", rzscifa_early_console_setup);
OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup);
OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup);
OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup);
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index c0dfe4382898..c0ae78632dda 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -31,6 +31,7 @@ enum {
SCCKS, /* BRG Clock Select Register */
HSRTRGR, /* Rx FIFO Data Count Trigger Register */
HSTTRGR, /* Tx FIFO Data Count Trigger Register */
+ SEMR, /* Serial extended mode register */
SCIx_NR_REGS,
};
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index e7048515a79c..87e480cc8206 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -65,7 +65,7 @@ static struct uart_driver asc_uart_driver;
/* ASC_RXBUF */
#define ASC_RXBUF_PE 0x100
#define ASC_RXBUF_FE 0x200
-/**
+/*
* Some of status comes from higher bits of the character and some come from
* the status register. Combining both of them in to single status using dummy
* bits.
@@ -478,7 +478,7 @@ static void asc_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct asc_port *ascport = to_asc_port(port);
- unsigned long flags = 0;
+ unsigned long flags;
u32 ctl;
switch (state) {
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index c2ae7b392b86..ef793b3b4591 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -718,36 +718,6 @@ static void stm32_usart_shutdown(struct uart_port *port)
free_irq(port->irq, port);
}
-static unsigned int stm32_usart_get_databits(struct ktermios *termios)
-{
- unsigned int bits;
-
- tcflag_t cflag = termios->c_cflag;
-
- switch (cflag & CSIZE) {
- /*
- * CSIZE settings are not necessarily supported in hardware.
- * CSIZE unsupported configurations are handled here to set word length
- * to 8 bits word as default configuration and to print debug message.
- */
- case CS5:
- bits = 5;
- break;
- case CS6:
- bits = 6;
- break;
- case CS7:
- bits = 7;
- break;
- /* default including CS8 */
- default:
- bits = 8;
- break;
- }
-
- return bits;
-}
-
static void stm32_usart_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
@@ -805,7 +775,7 @@ static void stm32_usart_set_termios(struct uart_port *port,
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
- bits = stm32_usart_get_databits(termios);
+ bits = tty_get_char_size(cflag);
stm32_port->rdr_mask = (BIT(bits) - 1);
if (cflag & PARENB) {
@@ -980,7 +950,7 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state,
struct stm32_port, port);
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
const struct stm32_usart_config *cfg = &stm32port->info->cfg;
- unsigned long flags = 0;
+ unsigned long flags;
switch (state) {
case UART_PM_STATE_ON:
@@ -1182,6 +1152,14 @@ static const struct of_device_id stm32_match[] = {
MODULE_DEVICE_TABLE(of, stm32_match);
#endif
+static void stm32_usart_of_dma_rx_remove(struct stm32_port *stm32port,
+ struct platform_device *pdev)
+{
+ if (stm32port->rx_buf)
+ dma_free_coherent(&pdev->dev, RX_BUF_L, stm32port->rx_buf,
+ stm32port->rx_dma_buf);
+}
+
static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct platform_device *pdev)
{
@@ -1199,19 +1177,11 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
if (uart_console(port))
return -ENODEV;
- /* Request DMA RX channel */
- stm32port->rx_ch = dma_request_slave_channel(dev, "rx");
- if (!stm32port->rx_ch) {
- dev_info(dev, "rx dma alloc failed\n");
- return -ENODEV;
- }
stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L,
&stm32port->rx_dma_buf,
GFP_KERNEL);
- if (!stm32port->rx_buf) {
- ret = -ENOMEM;
- goto alloc_err;
- }
+ if (!stm32port->rx_buf)
+ return -ENOMEM;
/* Configure DMA channel */
memset(&config, 0, sizeof(config));
@@ -1221,8 +1191,8 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
ret = dmaengine_slave_config(stm32port->rx_ch, &config);
if (ret < 0) {
dev_err(dev, "rx dma channel config failed\n");
- ret = -ENODEV;
- goto config_err;
+ stm32_usart_of_dma_rx_remove(stm32port, pdev);
+ return ret;
}
/* Prepare a DMA cyclic transaction */
@@ -1232,8 +1202,8 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(dev, "rx dma prep cyclic failed\n");
- ret = -ENODEV;
- goto config_err;
+ stm32_usart_of_dma_rx_remove(stm32port, pdev);
+ return -ENODEV;
}
/* No callback as dma buffer is drained on usart interrupt */
@@ -1244,24 +1214,22 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
ret = dma_submit_error(dmaengine_submit(desc));
if (ret) {
dmaengine_terminate_sync(stm32port->rx_ch);
- goto config_err;
+ stm32_usart_of_dma_rx_remove(stm32port, pdev);
+ return ret;
}
/* Issue pending DMA requests */
dma_async_issue_pending(stm32port->rx_ch);
return 0;
+}
-config_err:
- dma_free_coherent(&pdev->dev,
- RX_BUF_L, stm32port->rx_buf,
- stm32port->rx_dma_buf);
-
-alloc_err:
- dma_release_channel(stm32port->rx_ch);
- stm32port->rx_ch = NULL;
-
- return ret;
+static void stm32_usart_of_dma_tx_remove(struct stm32_port *stm32port,
+ struct platform_device *pdev)
+{
+ if (stm32port->tx_buf)
+ dma_free_coherent(&pdev->dev, TX_BUF_L, stm32port->tx_buf,
+ stm32port->tx_dma_buf);
}
static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
@@ -1275,19 +1243,11 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
stm32port->tx_dma_busy = false;
- /* Request DMA TX channel */
- stm32port->tx_ch = dma_request_slave_channel(dev, "tx");
- if (!stm32port->tx_ch) {
- dev_info(dev, "tx dma alloc failed\n");
- return -ENODEV;
- }
stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L,
&stm32port->tx_dma_buf,
GFP_KERNEL);
- if (!stm32port->tx_buf) {
- ret = -ENOMEM;
- goto alloc_err;
- }
+ if (!stm32port->tx_buf)
+ return -ENOMEM;
/* Configure DMA channel */
memset(&config, 0, sizeof(config));
@@ -1297,22 +1257,11 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
ret = dmaengine_slave_config(stm32port->tx_ch, &config);
if (ret < 0) {
dev_err(dev, "tx dma channel config failed\n");
- ret = -ENODEV;
- goto config_err;
+ stm32_usart_of_dma_tx_remove(stm32port, pdev);
+ return ret;
}
return 0;
-
-config_err:
- dma_free_coherent(&pdev->dev,
- TX_BUF_L, stm32port->tx_buf,
- stm32port->tx_dma_buf);
-
-alloc_err:
- dma_release_channel(stm32port->tx_ch);
- stm32port->tx_ch = NULL;
-
- return ret;
}
static int stm32_usart_serial_probe(struct platform_device *pdev)
@@ -1336,16 +1285,43 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
if (ret)
- goto err_nowup;
+ goto err_deinit_port;
}
- ret = stm32_usart_of_dma_rx_probe(stm32port, pdev);
- if (ret)
- dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n");
+ stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx");
+ if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_wakeirq;
+ }
+ /* Fall back in interrupt mode for any non-deferral error */
+ if (IS_ERR(stm32port->rx_ch))
+ stm32port->rx_ch = NULL;
+
+ stm32port->tx_ch = dma_request_chan(&pdev->dev, "tx");
+ if (PTR_ERR(stm32port->tx_ch) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_dma_rx;
+ }
+ /* Fall back in interrupt mode for any non-deferral error */
+ if (IS_ERR(stm32port->tx_ch))
+ stm32port->tx_ch = NULL;
- ret = stm32_usart_of_dma_tx_probe(stm32port, pdev);
- if (ret)
- dev_info(&pdev->dev, "interrupt mode used for tx (no dma)\n");
+ if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) {
+ /* Fall back in interrupt mode */
+ dma_release_channel(stm32port->rx_ch);
+ stm32port->rx_ch = NULL;
+ }
+
+ if (stm32port->tx_ch && stm32_usart_of_dma_tx_probe(stm32port, pdev)) {
+ /* Fall back in interrupt mode */
+ dma_release_channel(stm32port->tx_ch);
+ stm32port->tx_ch = NULL;
+ }
+
+ if (!stm32port->rx_ch)
+ dev_info(&pdev->dev, "interrupt mode for rx (no dma)\n");
+ if (!stm32port->tx_ch)
+ dev_info(&pdev->dev, "interrupt mode for tx (no dma)\n");
platform_set_drvdata(pdev, &stm32port->port);
@@ -1366,30 +1342,23 @@ err_port:
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
- if (stm32port->rx_ch) {
- dmaengine_terminate_async(stm32port->rx_ch);
- dma_release_channel(stm32port->rx_ch);
- }
-
- if (stm32port->rx_dma_buf)
- dma_free_coherent(&pdev->dev,
- RX_BUF_L, stm32port->rx_buf,
- stm32port->rx_dma_buf);
-
if (stm32port->tx_ch) {
- dmaengine_terminate_async(stm32port->tx_ch);
+ stm32_usart_of_dma_tx_remove(stm32port, pdev);
dma_release_channel(stm32port->tx_ch);
}
- if (stm32port->tx_dma_buf)
- dma_free_coherent(&pdev->dev,
- TX_BUF_L, stm32port->tx_buf,
- stm32port->tx_dma_buf);
+ if (stm32port->rx_ch)
+ stm32_usart_of_dma_rx_remove(stm32port, pdev);
+
+err_dma_rx:
+ if (stm32port->rx_ch)
+ dma_release_channel(stm32port->rx_ch);
+err_wakeirq:
if (stm32port->wakeup_src)
dev_pm_clear_wake_irq(&pdev->dev);
-err_nowup:
+err_deinit_port:
if (stm32port->wakeup_src)
device_set_wakeup_capable(&pdev->dev, false);
@@ -1416,28 +1385,20 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
+ if (stm32_port->tx_ch) {
+ dmaengine_terminate_async(stm32_port->tx_ch);
+ stm32_usart_of_dma_tx_remove(stm32_port, pdev);
+ dma_release_channel(stm32_port->tx_ch);
+ }
+
if (stm32_port->rx_ch) {
dmaengine_terminate_async(stm32_port->rx_ch);
+ stm32_usart_of_dma_rx_remove(stm32_port, pdev);
dma_release_channel(stm32_port->rx_ch);
}
- if (stm32_port->rx_dma_buf)
- dma_free_coherent(&pdev->dev,
- RX_BUF_L, stm32_port->rx_buf,
- stm32_port->rx_dma_buf);
-
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- if (stm32_port->tx_ch) {
- dmaengine_terminate_async(stm32_port->tx_ch);
- dma_release_channel(stm32_port->tx_ch);
- }
-
- if (stm32_port->tx_dma_buf)
- dma_free_coherent(&pdev->dev,
- TX_BUF_L, stm32_port->tx_buf,
- stm32_port->tx_dma_buf);
-
if (stm32_port->wakeup_src) {
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index bab551f46963..92e572634009 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -35,7 +35,7 @@
#include <linux/init.h>
#include <linux/of_device.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/setup.h>
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 12c2468f2b0e..425a016f9db7 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -39,7 +39,7 @@
#include <linux/delay.h>
#include <linux/of_device.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/setup.h>
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 001e19d7c17d..1a54e3e52ed6 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -35,7 +35,7 @@
#include <linux/init.h>
#include <linux/of_device.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/setup.h>
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
index 52687c65ad74..4877c54c613d 100644
--- a/drivers/tty/serial/tegra-tcu.c
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -195,13 +195,6 @@ static int tegra_tcu_probe(struct platform_device *pdev)
return err;
}
- tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx");
- if (IS_ERR(tcu->rx)) {
- err = PTR_ERR(tcu->rx);
- dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err);
- goto free_tx;
- }
-
#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
/* setup the console */
strcpy(tcu->console.name, "ttyTCU");
@@ -226,7 +219,7 @@ static int tegra_tcu_probe(struct platform_device *pdev)
if (err) {
dev_err(&pdev->dev, "failed to register UART driver: %d\n",
err);
- goto free_rx;
+ goto free_tx;
}
/* setup the port */
@@ -246,6 +239,17 @@ static int tegra_tcu_probe(struct platform_device *pdev)
goto unregister_uart;
}
+ /*
+ * Request RX channel after creating port to ensure tcu->port
+ * is ready for any immediate incoming bytes.
+ */
+ tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx");
+ if (IS_ERR(tcu->rx)) {
+ err = PTR_ERR(tcu->rx);
+ dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err);
+ goto remove_uart_port;
+ }
+
platform_set_drvdata(pdev, tcu);
#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
register_console(&tcu->console);
@@ -253,10 +257,10 @@ static int tegra_tcu_probe(struct platform_device *pdev)
return 0;
+remove_uart_port:
+ uart_remove_one_port(&tcu->driver, &tcu->port);
unregister_uart:
uart_unregister_driver(&tcu->driver);
-free_rx:
- mbox_free_channel(tcu->rx);
free_tx:
mbox_free_channel(tcu->tx);
@@ -270,9 +274,9 @@ static int tegra_tcu_remove(struct platform_device *pdev)
#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
unregister_console(&tcu->console);
#endif
+ mbox_free_channel(tcu->rx);
uart_remove_one_port(&tcu->driver, &tcu->port);
uart_unregister_driver(&tcu->driver);
- mbox_free_channel(tcu->rx);
mbox_free_channel(tcu->tx);
return 0;
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index f42ccc40ffa6..a5f15f22d9ef 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -505,21 +505,23 @@ static void ulite_console_write(struct console *co, const char *s,
static int ulite_console_setup(struct console *co, char *options)
{
- struct uart_port *port;
+ struct uart_port *port = NULL;
int baud = 9600;
int bits = 8;
int parity = 'n';
int flow = 'n';
-
- port = console_port;
+ if (co->index >= 0 && co->index < ULITE_NR_UARTS)
+ port = ulite_ports + co->index;
/* Has the device been initialized yet? */
- if (!port->mapbase) {
+ if (!port || !port->mapbase) {
pr_debug("console on ttyUL%i not present\n", co->index);
return -ENODEV;
}
+ console_port = port;
+
/* not initialized yet? */
if (!port->membase) {
if (ulite_request_port(port))
@@ -655,17 +657,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
dev_set_drvdata(dev, port);
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
- /*
- * If console hasn't been found yet try to assign this port
- * because it is required to be assigned for console setup function.
- * If register_console() don't assign value, then console_port pointer
- * is cleanup.
- */
- if (ulite_uart_driver.cons->index == -1)
- console_port = port;
-#endif
-
/* Register the port */
rc = uart_add_one_port(&ulite_uart_driver, port);
if (rc) {
@@ -675,12 +666,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
return rc;
}
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
- /* This is not port which is used for console that's why clean it up */
- if (ulite_uart_driver.cons->index == -1)
- console_port = NULL;
-#endif
-
return 0;
}
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index f81261cb52b8..6000853973c1 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1227,7 +1227,7 @@ static int soft_uart_init(struct platform_device *ofdev)
* kernel, then we use it.
*/
ret = request_firmware_nowait(THIS_MODULE,
- FW_ACTION_HOTPLUG, filename, &ofdev->dev,
+ FW_ACTION_UEVENT, filename, &ofdev->dev,
GFP_KERNEL, &ofdev->dev, uart_firmware_cont);
if (ret) {
dev_err(&ofdev->dev,
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
index eeb4b6568776..647198b1e2b9 100644
--- a/drivers/tty/serial/vr41xx_siu.c
+++ b/drivers/tty/serial/vr41xx_siu.c
@@ -20,7 +20,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/vr41xx/siu.h>
#include <asm/vr41xx/vr41xx.h>
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 67a2db621e2b..962e522ccc45 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -484,7 +484,7 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port,
#ifdef CONFIG_COMMON_CLK
/**
- * cdns_uart_clk_notitifer_cb - Clock notifier callback
+ * cdns_uart_clk_notifier_cb - Clock notifier callback
* @nb: Notifier block
* @event: Notify event
* @data: Notifier data
@@ -497,8 +497,8 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
struct uart_port *port;
int locked = 0;
struct clk_notifier_data *ndata = data;
- unsigned long flags = 0;
struct cdns_uart *cdns_uart = to_cdns_uart(nb);
+ unsigned long flags;
port = cdns_uart->port;
if (port->suspended)
@@ -1149,7 +1149,7 @@ static void cdns_uart_console_putchar(struct uart_port *port, int ch)
}
static void cdns_early_write(struct console *con, const char *s,
- unsigned n)
+ unsigned int n)
{
struct earlycon_device *dev = con->data;
@@ -1210,7 +1210,7 @@ static void cdns_uart_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_port *port = console_port;
- unsigned long flags = 0;
+ unsigned long flags;
unsigned int imr, ctrl;
int locked = 1;
@@ -1308,7 +1308,7 @@ static int cdns_uart_suspend(struct device *device)
may_wake = device_may_wakeup(device);
if (console_suspend_enabled && uart_console(port) && may_wake) {
- unsigned long flags = 0;
+ unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/* Empty the receive FIFO 1st before making changes */
@@ -1339,7 +1339,7 @@ static int cdns_uart_resume(struct device *device)
{
struct uart_port *port = dev_get_drvdata(device);
struct cdns_uart *cdns_uart = port->private_data;
- unsigned long flags = 0;
+ unsigned long flags;
u32 ctrl_reg;
int may_wake;