From cdcea058e51008479545f29201b4fa577c59733c Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:25 +0200 Subject: serial: 8250_dw: Avoid serial_outx code duplicate with new dw8250_check_lcr() With the help of Heikki we take common code that makes sure LCR write wasn't ignored and put it in new function called dw8250_check_lcr(). This function serves 3 serial_out routines: dw8250_serial_out(), dw8250_serial_out32(), and dw8250_serial_outq(). This patch only brings better code reuse. Signed-off-by: Noam Camus Cc: Heikki Krogerus Cc: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 91 ++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 49 deletions(-) (limited to 'drivers/tty/serial/8250/8250_dw.c') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index a5d319e4aae6..ffe5e0cb1f05 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -95,25 +95,43 @@ static void dw8250_force_idle(struct uart_port *p) (void)p->serial_in(p, UART_RX); } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_check_lcr(struct uart_port *p, int value) { - writeb(value, p->membase + (offset << p->regshift)); + void __iomem *offset = p->membase + (UART_LCR << p->regshift); + int tries = 1000; /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writeb(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ + while (tries--) { + unsigned int lcr = p->serial_in(p, UART_LCR); + + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) + return; + + dw8250_force_idle(p); + +#ifdef CONFIG_64BIT + __raw_writeq(value & 0xff, offset); +#else + if (p->iotype == UPIO_MEM32) + writel(value, offset); + else + writeb(value, offset); +#endif } + /* + * FIXME: this deadlocks if port->lock is already held + * dev_err(p->dev, "Couldn't set LCR to %d\n", 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)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) @@ -135,49 +153,26 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) static void dw8250_serial_outq(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); /* Read back to ensure register write ordering. */ __raw_readq(p->membase + (UART_LCR << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - __raw_writeq(value & 0xff, - p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } #endif /* CONFIG_64BIT */ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + writel(value, p->membase + (offset << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writel(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) @@ -463,10 +458,8 @@ static int dw8250_probe(struct platform_device *pdev) dw8250_quirks(p, data); /* If the Busy Functionality is not implemented, don't handle it */ - if (data->uart_16550_compatible) { - p->serial_out = NULL; + if (data->uart_16550_compatible) p->handle_irq = NULL; - } if (!data->skip_autocfg) dw8250_setup_port(p); -- cgit v1.2.3 From 4625090187768bc776d69dfaa6a1f79b1125debe Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:26 +0200 Subject: serial: 8250_dw: Add support for big-endian MMIO accesses Add support for UPIO_MEM32BE in addition to UPIO_MEM32. For big endian we use 2 new accessors similar to little endian, called dw8250_serial_out32be() and dw8250_serial_in32be(). Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/tty/serial/8250/8250_dw.c') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index ffe5e0cb1f05..92c4a9bc2e6d 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -182,6 +182,24 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) return dw8250_modify_msr(p, offset, value); } +static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + iowrite32be(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + +static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) +{ + unsigned int value = ioread32be(p->membase + (offset << p->regshift)); + + return dw8250_modify_msr(p, offset, value); +} + + static int dw8250_handle_irq(struct uart_port *p) { struct dw8250_data *d = p->private_data; @@ -276,6 +294,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) data->skip_autocfg = true; } #endif + if (of_device_is_big_endian(p->dev->of_node)) { + p->iotype = UPIO_MEM32BE; + p->serial_in = dw8250_serial_in32be; + p->serial_out = dw8250_serial_out32be; + } } else if (has_acpi_companion(p->dev)) { p->iotype = UPIO_MEM32; p->regshift = 2; -- cgit v1.2.3 From 5a43140cc4a59eda4549cc3b74989efa77973158 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:27 +0200 Subject: serial: 8250_dw: Do not use readl/writel before checking port iotype Direct call to readl()/writel() is checked against iotype and in case of UPIO_MEM32BE we use ioread32be()/iowrite32be() instead of them. Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial/8250/8250_dw.c') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 92c4a9bc2e6d..30810acf7f96 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -114,6 +114,8 @@ static void dw8250_check_lcr(struct uart_port *p, int value) #else if (p->iotype == UPIO_MEM32) writel(value, offset); + else if (p->iotype == UPIO_MEM32BE) + iowrite32be(value, offset); else writeb(value, offset); #endif @@ -327,14 +329,20 @@ static void dw8250_setup_port(struct uart_port *p) * If the Component Version Register returns zero, we know that * ADDITIONAL_FEATURES are not enabled. No need to go any further. */ - reg = readl(p->membase + DW_UART_UCV); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_UCV); + else + reg = readl(p->membase + DW_UART_UCV); if (!reg) return; dev_dbg(p->dev, "Designware UART version %c.%c%c\n", (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - reg = readl(p->membase + DW_UART_CPR); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_CPR); + else + reg = readl(p->membase + DW_UART_CPR); if (!reg) return; -- cgit v1.2.3 From 34eefb595c10eb9a6dc99a82f7333c86dfe61337 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Feb 2016 17:38:45 +0200 Subject: serial: 8250_dw: remove redundant 'else' keyword When the main branch contains return statement the 'else' keyword is not needed. Remove it here. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial/8250/8250_dw.c') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 30810acf7f96..d190d6953281 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -207,9 +207,10 @@ static int dw8250_handle_irq(struct uart_port *p) struct dw8250_data *d = p->private_data; unsigned int iir = p->serial_in(p, UART_IIR); - if (serial8250_handle_irq(p, iir)) { + if (serial8250_handle_irq(p, iir)) return 1; - } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { + + if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR */ (void)p->serial_in(p, d->usr_reg); -- cgit v1.2.3 From 31f28cc2a2458708514ec77eac59dd3d19a57a7e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Feb 2016 17:46:55 +0200 Subject: serial: 8250_dw: remove leftover definitions The clocks are managed through clk-fractional-divider.c module, and thus CLK framework takes care about it. Remove letfovers from this driver. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/tty/serial/8250/8250_dw.c') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d190d6953281..a3fb95d85d7c 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -68,12 +68,6 @@ struct dw8250_data { unsigned int uart_16550_compatible:1; }; -#define BYT_PRV_CLK 0x800 -#define BYT_PRV_CLK_EN (1 << 0) -#define BYT_PRV_CLK_M_VAL_SHIFT 1 -#define BYT_PRV_CLK_N_VAL_SHIFT 16 -#define BYT_PRV_CLK_UPDATE (1 << 31) - static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; -- cgit v1.2.3