diff options
-rw-r--r-- | arch/arm/boot/dts/armada-38x.dtsi | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 31 |
2 files changed, 29 insertions, 6 deletions
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 4cc09e43eea2..6916d7532ad2 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -163,7 +163,7 @@ }; uart0: serial@12000 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart"; reg = <0x12000 0x100>; reg-shift = <2>; interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; @@ -173,7 +173,7 @@ }; uart1: serial@12100 { - compatible = "snps,dw-apb-uart"; + compatible = "marvell,armada-38x-uart"; reg = <0x12100 0x100>; reg-shift = <2>; interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 6fcdb90f616a..0529b5cc094b 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -121,25 +121,44 @@ static void dw8250_check_lcr(struct uart_port *p, int value) } /* Returns once the transmitter is empty or we run out of retries */ -static void dw8250_tx_wait_empty(struct uart_port *p, int tries) +static void dw8250_tx_wait_empty(struct uart_port *p) { + unsigned int tries = 20000; + unsigned int delay_threshold = tries - 1000; unsigned int lsr; while (tries--) { lsr = readb (p->membase + (UART_LSR << p->regshift)); if (lsr & UART_LSR_TEMT) break; - udelay (10); + + /* The device is first given a chance to empty without delay, + * to avoid slowdowns at high bitrates. If after 1000 tries + * the buffer has still not emptied, allow more time for low- + * speed links. */ + if (tries < delay_threshold) + udelay (1); } } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; /* Allow the TX to drain before we reconfigure */ if (offset == UART_LCR) - dw8250_tx_wait_empty(p, 1000); + dw8250_tx_wait_empty(p); + + writeb(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + + +static void dw8250_serial_out(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; writeb(value, p->membase + (offset << p->regshift)); @@ -357,6 +376,9 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) p->serial_in = dw8250_serial_in32be; p->serial_out = dw8250_serial_out32be; } + if (of_device_is_compatible(np, "marvell,armada-38x-uart")) + p->serial_out = dw8250_serial_out38x; + } else if (acpi_dev_present("APMC0D08", NULL, -1)) { p->iotype = UPIO_MEM32; p->regshift = 2; @@ -666,6 +688,7 @@ static const struct dev_pm_ops dw8250_pm_ops = { static const struct of_device_id dw8250_of_match[] = { { .compatible = "snps,dw-apb-uart" }, { .compatible = "cavium,octeon-3860-uart" }, + { .compatible = "marvell,armada-38x-uart" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dw8250_of_match); |