On Tue, Aug 06, 2019 at 12:43:17PM +0300, Andy Shevchenko wrote: > Since we have a common library module for Synopsys DesignWare UART, > let us use it. > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> FWIW: Reviewed-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > --- > drivers/tty/serial/8250/8250_dw.c | 162 +++++------------------------- > drivers/tty/serial/8250/Kconfig | 1 + > 2 files changed, 28 insertions(+), 135 deletions(-) > > diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c > index 010d0a292e73..1c72fdc2dd37 100644 > --- a/drivers/tty/serial/8250/8250_dw.c > +++ b/drivers/tty/serial/8250/8250_dw.c > @@ -27,66 +27,36 @@ > > #include <asm/byteorder.h> > > -#include "8250.h" > +#include "8250_dwlib.h" > > /* Offsets for the DesignWare specific registers */ > #define DW_UART_USR 0x1f /* UART Status Register */ > -#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ > -#define DW_UART_CPR 0xf4 /* Component Parameter Register */ > -#define DW_UART_UCV 0xf8 /* UART Component Version */ > - > -/* Component Parameter Register bits */ > -#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) > -#define DW_UART_CPR_AFCE_MODE (1 << 4) > -#define DW_UART_CPR_THRE_MODE (1 << 5) > -#define DW_UART_CPR_SIR_MODE (1 << 6) > -#define DW_UART_CPR_SIR_LP_MODE (1 << 7) > -#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) > -#define DW_UART_CPR_FIFO_ACCESS (1 << 9) > -#define DW_UART_CPR_FIFO_STAT (1 << 10) > -#define DW_UART_CPR_SHADOW (1 << 11) > -#define DW_UART_CPR_ENCODED_PARMS (1 << 12) > -#define DW_UART_CPR_DMA_EXTRA (1 << 13) > -#define DW_UART_CPR_FIFO_MODE (0xff << 16) > -/* Helper for fifo size calculation */ > -#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) > > /* DesignWare specific register fields */ > #define DW_UART_MCR_SIRE BIT(6) > > struct dw8250_data { > + struct dw8250_port_data data; > + > u8 usr_reg; > - u8 dlf_size; > - int line; > int msr_mask_on; > int msr_mask_off; > struct clk *clk; > struct clk *pclk; > struct reset_control *rst; > - struct uart_8250_dma dma; > > unsigned int skip_autocfg:1; > unsigned int uart_16550_compatible:1; > }; > > -static inline u32 dw8250_readl_ext(struct uart_port *p, int offset) > +static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) > { > - if (p->iotype == UPIO_MEM32BE) > - return ioread32be(p->membase + offset); > - return readl(p->membase + offset); > -} > - > -static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg) > -{ > - if (p->iotype == UPIO_MEM32BE) > - iowrite32be(reg, p->membase + offset); > - else > - writel(reg, p->membase + offset); > + return container_of(data, struct dw8250_data, data); > } > > static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) > { > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > /* Override any modem control signals if needed */ > if (offset == UART_MSR) { > @@ -160,7 +130,7 @@ static void dw8250_tx_wait_empty(struct uart_port *p) > > static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) > { > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > /* Allow the TX to drain before we reconfigure */ > if (offset == UART_LCR) > @@ -175,7 +145,7 @@ static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) > > static void dw8250_serial_out(struct uart_port *p, int offset, int value) > { > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > writeb(value, p->membase + (offset << p->regshift)); > > @@ -202,7 +172,7 @@ 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; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > value &= 0xff; > __raw_writeq(value, p->membase + (offset << p->regshift)); > @@ -216,7 +186,7 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value) > > static void dw8250_serial_out32(struct uart_port *p, int offset, int value) > { > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > writel(value, p->membase + (offset << p->regshift)); > > @@ -233,7 +203,7 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) > > static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) > { > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > > iowrite32be(value, p->membase + (offset << p->regshift)); > > @@ -252,7 +222,7 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) > static int dw8250_handle_irq(struct uart_port *p) > { > struct uart_8250_port *up = up_to_u8250p(p); > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > unsigned int iir = p->serial_in(p, UART_IIR); > unsigned int status; > unsigned long flags; > @@ -306,7 +276,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, > struct ktermios *old) > { > unsigned int baud = tty_termios_baud_rate(termios); > - struct dw8250_data *d = p->private_data; > + struct dw8250_data *d = to_dw8250_data(p->private_data); > long rate; > int ret; > > @@ -368,37 +338,6 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param) > return param == chan->device->dev; > } > > -/* > - * divisor = div(I) + div(F) > - * "I" means integer, "F" means fractional > - * quot = div(I) = clk / (16 * baud) > - * frac = div(F) * 2^dlf_size > - * > - * let rem = clk % (16 * baud) > - * we have: div(F) * (16 * baud) = rem > - * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) > - */ > -static unsigned int dw8250_get_divisor(struct uart_port *p, > - unsigned int baud, > - unsigned int *frac) > -{ > - unsigned int quot, rem, base_baud = baud * 16; > - struct dw8250_data *d = p->private_data; > - > - quot = p->uartclk / base_baud; > - rem = p->uartclk % base_baud; > - *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); > - > - return quot; > -} > - > -static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, > - unsigned int quot, unsigned int quot_frac) > -{ > - dw8250_writel_ext(p, DW_UART_DLF, quot_frac); > - serial8250_do_set_divisor(p, baud, quot, quot_frac); > -} > - > static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) > { > if (p->dev->of_node) { > @@ -437,59 +376,12 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) > /* Platforms with iDMA 64-bit */ > if (platform_get_resource_byname(to_platform_device(p->dev), > IORESOURCE_MEM, "lpss_priv")) { > - data->dma.rx_param = p->dev->parent; > - data->dma.tx_param = p->dev->parent; > - data->dma.fn = dw8250_idma_filter; > + data->data.dma.rx_param = p->dev->parent; > + data->data.dma.tx_param = p->dev->parent; > + data->data.dma.fn = dw8250_idma_filter; > } > } > > -static void dw8250_setup_port(struct uart_port *p) > -{ > - struct uart_8250_port *up = up_to_u8250p(p); > - u32 reg; > - > - /* > - * If the Component Version Register returns zero, we know that > - * ADDITIONAL_FEATURES are not enabled. No need to go any further. > - */ > - reg = dw8250_readl_ext(p, 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); > - > - dw8250_writel_ext(p, DW_UART_DLF, ~0U); > - reg = dw8250_readl_ext(p, DW_UART_DLF); > - dw8250_writel_ext(p, DW_UART_DLF, 0); > - > - if (reg) { > - struct dw8250_data *d = p->private_data; > - > - d->dlf_size = fls(reg); > - p->get_divisor = dw8250_get_divisor; > - p->set_divisor = dw8250_set_divisor; > - } > - > - reg = dw8250_readl_ext(p, DW_UART_CPR); > - if (!reg) > - return; > - > - /* Select the type based on fifo */ > - if (reg & DW_UART_CPR_FIFO_MODE) { > - p->type = PORT_16550A; > - p->flags |= UPF_FIXED_TYPE; > - p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); > - up->capabilities = UART_CAP_FIFO; > - } > - > - if (reg & DW_UART_CPR_AFCE_MODE) > - up->capabilities |= UART_CAP_AFE; > - > - if (reg & DW_UART_CPR_SIR_MODE) > - up->capabilities |= UART_CAP_IRDA; > -} > - > static int dw8250_probe(struct platform_device *pdev) > { > struct uart_8250_port uart = {}, *up = &uart; > @@ -534,9 +426,9 @@ static int dw8250_probe(struct platform_device *pdev) > if (!data) > return -ENOMEM; > > - data->dma.fn = dw8250_fallback_dma_filter; > + data->data.dma.fn = dw8250_fallback_dma_filter; > data->usr_reg = DW_UART_USR; > - p->private_data = data; > + p->private_data = &data->data; > > data->uart_16550_compatible = device_property_read_bool(dev, > "snps,uart-16550-compatible"); > @@ -632,14 +524,14 @@ static int dw8250_probe(struct platform_device *pdev) > > /* If we have a valid fifosize, try hooking up DMA */ > if (p->fifosize) { > - data->dma.rxconf.src_maxburst = p->fifosize / 4; > - data->dma.txconf.dst_maxburst = p->fifosize / 4; > - up->dma = &data->dma; > + data->data.dma.rxconf.src_maxburst = p->fifosize / 4; > + data->data.dma.txconf.dst_maxburst = p->fifosize / 4; > + up->dma = &data->data.dma; > } > > - data->line = serial8250_register_8250_port(up); > - if (data->line < 0) { > - err = data->line; > + data->data.line = serial8250_register_8250_port(up); > + if (data->data.line < 0) { > + err = data->data.line; > goto err_reset; > } > > @@ -671,7 +563,7 @@ static int dw8250_remove(struct platform_device *pdev) > > pm_runtime_get_sync(dev); > > - serial8250_unregister_port(data->line); > + serial8250_unregister_port(data->data.line); > > reset_control_assert(data->rst); > > @@ -692,7 +584,7 @@ static int dw8250_suspend(struct device *dev) > { > struct dw8250_data *data = dev_get_drvdata(dev); > > - serial8250_suspend_port(data->line); > + serial8250_suspend_port(data->data.line); > > return 0; > } > @@ -701,7 +593,7 @@ static int dw8250_resume(struct device *dev) > { > struct dw8250_data *data = dev_get_drvdata(dev); > > - serial8250_resume_port(data->line); > + serial8250_resume_port(data->data.line); > > return 0; > } > diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig > index d628258fb4cf..90abf97b378d 100644 > --- a/drivers/tty/serial/8250/Kconfig > +++ b/drivers/tty/serial/8250/Kconfig > @@ -357,6 +357,7 @@ config SERIAL_8250_FSL > config SERIAL_8250_DW > tristate "Support for Synopsys DesignWare 8250 quirks" > depends on SERIAL_8250 > + select SERIAL_8250_DWLIB > help > Selecting this option will enable handling of the extra features > present in the Synopsys DesignWare APB UART. > -- > 2.20.1 -- heikki