Message ID | 20220310161650.289387-7-miquel.raynal@bootlin.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Series | RZN1 UART DMA support | expand |
On Thu, Mar 10, 2022 at 05:16:49PM +0100, Miquel Raynal wrote: > From: Phil Edworthy <phil.edworthy@renesas.com> > > The Renesas RZ/N1 devices have a modified Synopsys DW UART. The > modifications are mostly related to the DMA handlnig, and so this patch > adds support for DMA. > The RZ/N1 UART must be used with the peripheral as the flow > controller. (1) > This means the DMA length should also be programmed into > UART registers. (2) Hmm... DMA controller vs. Peripheral flow control is about signalling on the HW level on who starts the transaction. This is programmed in the DMA controller device driver. Is it what you do in DesignWare DMA patch series? Ah, I see now, you set fc here. But still it's not clear how (2) and (1) are related. > Aside from this, there are some points to note about DMA burst sizes. > First, DMA must not remove all of the data from the rx FIFO. Otherwise, > we do not get a 'character timeout' interrupt, and so do not know that > we should push data up the serial stack. Therefore, we have the rx > threshold for generating an interrupt set to half the FIFO depth (this > is the default for 16550A), and set the DMA burst size when reading the > FIFO to a quarter of the FIFO depth. > > Second, when transmitting data using DMA, the burst size must be limited > to 1 byte to handle then case when transmitting just 1 byte. Otherwise > the DMA doesn't complete the burst, and nothing happens. ... > +/* Offsets for the Renesas RZ/N1 DesignWare specific registers */ > +/* DMA Software Ack */ > +#define RZN1_UART_DMASA 0xa8 Is it specific to Renesas? IIRC it's Synopsys DesignWare register, makes sense to use appropriate prefix or no prefix. ... > +#define RZN1_UART_xDMACR_1_WORD_BURST 0 > +#define RZN1_UART_xDMACR_4_WORD_BURST BIT(1) > +#define RZN1_UART_xDMACR_8_WORD_BURST (BIT(1) | BIT(2)) This looks like incorrect use of BIT() macro. Please, use plain decimal integers. Something like 1 (0 << 1) 4 (1 << 1) 8 (3 << 1) If I'm mistaken, describe the meaning of each bit there. ... > +static void rzn1_8250_handle_irq(struct uart_port *port, unsigned int iir) > +{ > + struct uart_8250_port *up = up_to_u8250p(port); > + struct uart_8250_dma *dma = up->dma; > + unsigned char status; > + if (up->dma && dma->rx_running) { With if (!)up->dma && dma->rx_running)) return; maybe easier to read the rest. > + status = port->serial_in(port, UART_LSR); > + if (status & (UART_LSR_DR | UART_LSR_BI)) { > + /* Stop the DMA transfer */ > + writel(0, port->membase + RZN1_UART_RDMACR); > + writel(1, port->membase + RZN1_UART_DMASA); > + } > + } > +} ... > + if (d->is_rzn1 && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) > + rzn1_8250_handle_irq(p, iir); A few years ago it was a discussion about broken timeout on some platforms with Synopsys DesignWare UART + DMA. Can it be that this is actually required for all of them that uses same combination of IPs? ... > +static u32 rzn1_get_dmacr_burst(int max_burst) > +{ > + u32 val = 0; Redundant assignment and variable itself. Use return statements directly. > + if (max_burst >= 8) > + val = RZN1_UART_xDMACR_8_WORD_BURST; > + else if (max_burst >= 4) > + val = RZN1_UART_xDMACR_4_WORD_BURST; > + else > + val = RZN1_UART_xDMACR_1_WORD_BURST; > + > + return val; > +} ... > +static int rzn1_dw8250_tx_dma(struct uart_8250_port *p) > +{ > + struct uart_port *up = &p->port; > + struct uart_8250_dma *dma = p->dma; > + struct circ_buf *xmit = &p->port.state->xmit; > + int tx_size; > + u32 val; > + > + if (uart_tx_stopped(&p->port) || dma->tx_running || > + uart_circ_empty(xmit)) > + return 0; > + > + tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); > + writel(0, up->membase + RZN1_UART_TDMACR); > + val = rzn1_get_dmacr_burst(dma->txconf.dst_maxburst); > + val |= tx_size << RZN1_UART_xDMACR_BLK_SZ_OFFSET; > + val |= RZN1_UART_xDMACR_DMA_EN; > + writel(val, up->membase + RZN1_UART_TDMACR); Can this be added as a callback to the serial8250_tx_dma()? Ditto for Rx counterpart. > + return serial8250_tx_dma(p); > +} ... > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); Device property API. > /* Always ask for fixed clock rate from a property. */ > device_property_read_u32(dev, "clock-frequency", &p->uartclk);
Hi Andy, andriy.shevchenko@linux.intel.com wrote on Thu, 10 Mar 2022 20:25:52 +0200: > On Thu, Mar 10, 2022 at 05:16:49PM +0100, Miquel Raynal wrote: > > From: Phil Edworthy <phil.edworthy@renesas.com> > > > > The Renesas RZ/N1 devices have a modified Synopsys DW UART. The > > modifications are mostly related to the DMA handlnig, and so this patch > > adds support for DMA. > > > The RZ/N1 UART must be used with the peripheral as the flow > > controller. > > (1) > > > This means the DMA length should also be programmed into > > UART registers. > > (2) > > Hmm... DMA controller vs. Peripheral flow control is about signalling on the HW > level on who starts the transaction. This is programmed in the DMA controller > device driver. Is it what you do in DesignWare DMA patch series? > > Ah, I see now, you set fc here. > > But still it's not clear how (2) and (1) are related. Both come from the system manual: (1) table 11.45 "Flow Control Combinations" states that using UART with DMA requires setting the DMA in the peripheral flow controller mode regardless of the direction. (2) chapter 11.6.1.3 "Basic Interface Definitions" explains that the burst size in the above case must be configured in the peripheral's register DEST/SRC_BURST_SIZE. > > Aside from this, there are some points to note about DMA burst sizes. > > First, DMA must not remove all of the data from the rx FIFO. Otherwise, > > we do not get a 'character timeout' interrupt, and so do not know that > > we should push data up the serial stack. Therefore, we have the rx > > threshold for generating an interrupt set to half the FIFO depth (this > > is the default for 16550A), and set the DMA burst size when reading the > > FIFO to a quarter of the FIFO depth. > > > > Second, when transmitting data using DMA, the burst size must be limited > > to 1 byte to handle then case when transmitting just 1 byte. Otherwise > > the DMA doesn't complete the burst, and nothing happens. > > ... > > > +/* Offsets for the Renesas RZ/N1 DesignWare specific registers */ > > +/* DMA Software Ack */ > > +#define RZN1_UART_DMASA 0xa8 > > Is it specific to Renesas? IIRC it's Synopsys DesignWare register, makes > sense to use appropriate prefix or no prefix. I have no idea, I can use a more common prefix. > > ... > > > +#define RZN1_UART_xDMACR_1_WORD_BURST 0 > > +#define RZN1_UART_xDMACR_4_WORD_BURST BIT(1) > > +#define RZN1_UART_xDMACR_8_WORD_BURST (BIT(1) | BIT(2)) > > This looks like incorrect use of BIT() macro. > Please, use plain decimal integers. Something like > > 1 (0 << 1) > 4 (1 << 1) > 8 (3 << 1) > > If I'm mistaken, describe the meaning of each bit there. Matter of taste, I believe, whatever. > > ... > > > +static void rzn1_8250_handle_irq(struct uart_port *port, unsigned int iir) > > +{ > > + struct uart_8250_port *up = up_to_u8250p(port); > > + struct uart_8250_dma *dma = up->dma; > > + unsigned char status; > > > + if (up->dma && dma->rx_running) { > > With > > if (!)up->dma && dma->rx_running)) > return; > > maybe easier to read the rest. > > > + status = port->serial_in(port, UART_LSR); > > + if (status & (UART_LSR_DR | UART_LSR_BI)) { > > + /* Stop the DMA transfer */ > > + writel(0, port->membase + RZN1_UART_RDMACR); > > + writel(1, port->membase + RZN1_UART_DMASA); > > + } > > + } > > +} > > ... > > > + if (d->is_rzn1 && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) > > + rzn1_8250_handle_irq(p, iir); > > A few years ago it was a discussion about broken timeout on some platforms > with Synopsys DesignWare UART + DMA. Can it be that this is actually required > for all of them that uses same combination of IPs? I am not sure because I went through the fix for this issue and for me there are two different things > > ... > > > +static u32 rzn1_get_dmacr_burst(int max_burst) > > +{ > > > + u32 val = 0; > > Redundant assignment and variable itself. Use return statements directly. > > > + if (max_burst >= 8) > > + val = RZN1_UART_xDMACR_8_WORD_BURST; > > + else if (max_burst >= 4) > > + val = RZN1_UART_xDMACR_4_WORD_BURST; > > + else > > + val = RZN1_UART_xDMACR_1_WORD_BURST; > > + > > + return val; > > +} > > ... > > > +static int rzn1_dw8250_tx_dma(struct uart_8250_port *p) > > +{ > > + struct uart_port *up = &p->port; > > + struct uart_8250_dma *dma = p->dma; > > + struct circ_buf *xmit = &p->port.state->xmit; > > + int tx_size; > > + u32 val; > > + > > + if (uart_tx_stopped(&p->port) || dma->tx_running || > > + uart_circ_empty(xmit)) > > + return 0; > > + > > + tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); > > > + writel(0, up->membase + RZN1_UART_TDMACR); > > + val = rzn1_get_dmacr_burst(dma->txconf.dst_maxburst); > > + val |= tx_size << RZN1_UART_xDMACR_BLK_SZ_OFFSET; > > + val |= RZN1_UART_xDMACR_DMA_EN; > > + writel(val, up->membase + RZN1_UART_TDMACR); > > Can this be added as a callback to the serial8250_tx_dma()? > Ditto for Rx counterpart. Fair enough. > > > + return serial8250_tx_dma(p); > > +} > > ... > > > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); > > Device property API. I'm not sure to get what you mean here again. The Information is in the device tree, the compatible string already gives us what we need, why would we need a device property? (or perhaps I misunderstand what "device property API" means) > > > /* Always ask for fixed clock rate from a property. */ > > device_property_read_u32(dev, "clock-frequency", &p->uartclk); > Thanks, Miquèl
Hi Miquel, On Thu, Mar 10, 2022 at 5:17 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote: > From: Phil Edworthy <phil.edworthy@renesas.com> > > The Renesas RZ/N1 devices have a modified Synopsys DW UART. The > modifications are mostly related to the DMA handlnig, and so this patch > adds support for DMA. > > The RZ/N1 UART must be used with the peripheral as the flow > controller. This means the DMA length should also be programmed into > UART registers. > > Aside from this, there are some points to note about DMA burst sizes. > First, DMA must not remove all of the data from the rx FIFO. Otherwise, > we do not get a 'character timeout' interrupt, and so do not know that > we should push data up the serial stack. Therefore, we have the rx > threshold for generating an interrupt set to half the FIFO depth (this > is the default for 16550A), and set the DMA burst size when reading the > FIFO to a quarter of the FIFO depth. > > Second, when transmitting data using DMA, the burst size must be limited > to 1 byte to handle then case when transmitting just 1 byte. Otherwise > the DMA doesn't complete the burst, and nothing happens. > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Thanks for your patch! > --- a/drivers/tty/serial/8250/8250_dma.c > +++ b/drivers/tty/serial/8250/8250_dma.c > @@ -501,6 +589,8 @@ static int dw8250_probe(struct platform_device *pdev) > data->msr_mask_off |= UART_MSR_TERI; > } > > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); Explicit checks for compatible values are frowned upon if you have a match table. Please handle this through of_device.data, cfr. the various quirks. Please rename "is_rzn1" to something that describes the feature. > + > /* Always ask for fixed clock rate from a property. */ > device_property_read_u32(dev, "clock-frequency", &p->uartclk); Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Hi Miquel, CC esmil On Fri, Mar 11, 2022 at 10:39 AM Geert Uytterhoeven <geert@linux-m68k.org> wrote: > > Hi Miquel, > > On Thu, Mar 10, 2022 at 5:17 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote: > > From: Phil Edworthy <phil.edworthy@renesas.com> > > > > The Renesas RZ/N1 devices have a modified Synopsys DW UART. The > > modifications are mostly related to the DMA handlnig, and so this patch > > adds support for DMA. > > > > The RZ/N1 UART must be used with the peripheral as the flow > > controller. This means the DMA length should also be programmed into > > UART registers. > > > > Aside from this, there are some points to note about DMA burst sizes. > > First, DMA must not remove all of the data from the rx FIFO. Otherwise, > > we do not get a 'character timeout' interrupt, and so do not know that > > we should push data up the serial stack. Therefore, we have the rx > > threshold for generating an interrupt set to half the FIFO depth (this > > is the default for 16550A), and set the DMA burst size when reading the > > FIFO to a quarter of the FIFO depth. > > > > Second, when transmitting data using DMA, the burst size must be limited > > to 1 byte to handle then case when transmitting just 1 byte. Otherwise > > the DMA doesn't complete the burst, and nothing happens. > > > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > > Thanks for your patch! > > > --- a/drivers/tty/serial/8250/8250_dma.c > > +++ b/drivers/tty/serial/8250/8250_dma.c > > > @@ -501,6 +589,8 @@ static int dw8250_probe(struct platform_device *pdev) > > data->msr_mask_off |= UART_MSR_TERI; > > } > > > > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); > > Explicit checks for compatible values are frowned upon if you have > a match table. > Please handle this through of_device.data, cfr. the various quirks. Oops, these are not yet upstream, but present in my tree due to including support for StarLight, cfr. https://github.com/esmil/linux/commits/visionfive/drivers/tty/serial/8250/8250_dw.c But you do already have: + { .compatible = "renesas,rzn1-uart", .data = &rzn1_pdata }, since "[PATCH 4/7] serial: 8250_dw: Provide the RZN1 CPR register value". > Please rename "is_rzn1" to something that describes the feature. > > > + > > /* Always ask for fixed clock rate from a property. */ > > device_property_read_u32(dev, "clock-frequency", &p->uartclk); Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Hi Geert, geert@linux-m68k.org wrote on Fri, 11 Mar 2022 10:51:53 +0100: > Hi Miquel, > > CC esmil > > > > --- a/drivers/tty/serial/8250/8250_dma.c > > > +++ b/drivers/tty/serial/8250/8250_dma.c > > > > > @@ -501,6 +589,8 @@ static int dw8250_probe(struct platform_device *pdev) > > > data->msr_mask_off |= UART_MSR_TERI; > > > } > > > > > > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); > > > > Explicit checks for compatible values are frowned upon if you have > > a match table. > > Please handle this through of_device.data, cfr. the various quirks. > > Oops, these are not yet upstream, but present in my tree due to including > support for StarLight, cfr. > https://github.com/esmil/linux/commits/visionfive/drivers/tty/serial/8250/8250_dw.c Oh thanks for pointing it! Too bad that these quirks were not introduced inside a wider structure, I think it's always a must even if there is only one parameter there. Anyway, I'll introduce a wider specific structure and use it. > But you do already have: > > + { .compatible = "renesas,rzn1-uart", .data = &rzn1_pdata }, > > since "[PATCH 4/7] serial: 8250_dw: Provide the RZN1 CPR register value". > > > Please rename "is_rzn1" to something that describes the feature. > > > > > + > > > /* Always ask for fixed clock rate from a property. */ > > > device_property_read_u32(dev, "clock-frequency", &p->uartclk); > > Gr{oetje,eeting}s, > > Geert Thanks, Miquèl
On Thu, Mar 10, 2022 at 08:27:43PM +0100, Miquel Raynal wrote: > andriy.shevchenko@linux.intel.com wrote on Thu, 10 Mar 2022 20:25:52 > +0200: > > On Thu, Mar 10, 2022 at 05:16:49PM +0100, Miquel Raynal wrote: ... > > > +/* Offsets for the Renesas RZ/N1 DesignWare specific registers */ > > > +/* DMA Software Ack */ > > > +#define RZN1_UART_DMASA 0xa8 > > > > Is it specific to Renesas? IIRC it's Synopsys DesignWare register, makes > > sense to use appropriate prefix or no prefix. > > I have no idea, I can use a more common prefix. It's a register described in Synopsys DesignWare specification. It's not related to Renesas IP integration. ... > > > +#define RZN1_UART_xDMACR_1_WORD_BURST 0 > > > +#define RZN1_UART_xDMACR_4_WORD_BURST BIT(1) > > > +#define RZN1_UART_xDMACR_8_WORD_BURST (BIT(1) | BIT(2)) > > > > This looks like incorrect use of BIT() macro. > > Please, use plain decimal integers. Something like > > > > 1 (0 << 1) > > 4 (1 << 1) > > 8 (3 << 1) > > > > If I'm mistaken, describe the meaning of each bit there. > > Matter of taste, I believe, whatever. Actually no, when one uses BIT() masks it implies that in the datasheet each bit is meaningful. So, please clarify this and update accordingly. ... > > > + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); > > > > Device property API. > > I'm not sure to get what you mean here again. The Information is in the > device tree, the compatible string already gives us what we need, why > would we need a device property? (or perhaps I misunderstand what > "device property API" means) Use non-OF APIs, which usually starts with device_property_ or fwnode_. But Geert already suggested something better. > > > /* Always ask for fixed clock rate from a property. */ > > > device_property_read_u32(dev, "clock-frequency", &p->uartclk);
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index a0563f2341ac..0858c0b988a2 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -105,6 +105,7 @@ int serial8250_tx_dma(struct uart_8250_port *p) dma->tx_err = 1; return ret; } +EXPORT_SYMBOL_GPL(serial8250_tx_dma); int serial8250_rx_dma(struct uart_8250_port *p) { @@ -130,6 +131,7 @@ int serial8250_rx_dma(struct uart_8250_port *p) return 0; } +EXPORT_SYMBOL_GPL(serial8250_rx_dma); void serial8250_rx_dma_flush(struct uart_8250_port *p) { diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index c0f54284bc70..04e05fc939df 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -37,6 +37,20 @@ /* DesignWare specific register fields */ #define DW_UART_MCR_SIRE BIT(6) +/* Offsets for the Renesas RZ/N1 DesignWare specific registers */ +/* DMA Software Ack */ +#define RZN1_UART_DMASA 0xa8 +/* DMA Control Register Transmit Mode */ +#define RZN1_UART_TDMACR 0x10c +/* DMA Control Register Receive Mode */ +#define RZN1_UART_RDMACR 0x110 + +#define RZN1_UART_xDMACR_DMA_EN BIT(0) +#define RZN1_UART_xDMACR_1_WORD_BURST 0 +#define RZN1_UART_xDMACR_4_WORD_BURST BIT(1) +#define RZN1_UART_xDMACR_8_WORD_BURST (BIT(1) | BIT(2)) +#define RZN1_UART_xDMACR_BLK_SZ_OFFSET 3 + static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) { return container_of(data, struct dw8250_data, data); @@ -217,6 +231,22 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) } +static void rzn1_8250_handle_irq(struct uart_port *port, unsigned int iir) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_dma *dma = up->dma; + unsigned char status; + + if (up->dma && dma->rx_running) { + status = port->serial_in(port, UART_LSR); + if (status & (UART_LSR_DR | UART_LSR_BI)) { + /* Stop the DMA transfer */ + writel(0, port->membase + RZN1_UART_RDMACR); + writel(1, port->membase + RZN1_UART_DMASA); + } + } +} + static int dw8250_handle_irq(struct uart_port *p) { struct uart_8250_port *up = up_to_u8250p(p); @@ -245,6 +275,9 @@ static int dw8250_handle_irq(struct uart_port *p) spin_unlock_irqrestore(&p->lock, flags); } + if (d->is_rzn1 && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) + rzn1_8250_handle_irq(p, iir); + if (serial8250_handle_irq(p, iir)) return 1; @@ -368,6 +401,61 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param) return param == chan->device->dev; } +static u32 rzn1_get_dmacr_burst(int max_burst) +{ + u32 val = 0; + + if (max_burst >= 8) + val = RZN1_UART_xDMACR_8_WORD_BURST; + else if (max_burst >= 4) + val = RZN1_UART_xDMACR_4_WORD_BURST; + else + val = RZN1_UART_xDMACR_1_WORD_BURST; + + return val; +} + +static int rzn1_dw8250_tx_dma(struct uart_8250_port *p) +{ + struct uart_port *up = &p->port; + struct uart_8250_dma *dma = p->dma; + struct circ_buf *xmit = &p->port.state->xmit; + int tx_size; + u32 val; + + if (uart_tx_stopped(&p->port) || dma->tx_running || + uart_circ_empty(xmit)) + return 0; + + tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + + writel(0, up->membase + RZN1_UART_TDMACR); + val = rzn1_get_dmacr_burst(dma->txconf.dst_maxburst); + val |= tx_size << RZN1_UART_xDMACR_BLK_SZ_OFFSET; + val |= RZN1_UART_xDMACR_DMA_EN; + writel(val, up->membase + RZN1_UART_TDMACR); + + return serial8250_tx_dma(p); +} + +static int rzn1_dw8250_rx_dma(struct uart_8250_port *p) +{ + struct uart_port *up = &p->port; + struct uart_8250_dma *dma = p->dma; + u32 val; + + if (dma->rx_running) + return 0; + + writel(0, up->membase + RZN1_UART_RDMACR); + val = rzn1_get_dmacr_burst(dma->rxconf.src_maxburst); + val |= dma->rx_size << RZN1_UART_xDMACR_BLK_SZ_OFFSET; + val |= RZN1_UART_xDMACR_DMA_EN; + writel(val, up->membase + RZN1_UART_RDMACR); + + return serial8250_rx_dma(p); +} + static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) { struct device_node *np = p->dev->of_node; @@ -501,6 +589,8 @@ static int dw8250_probe(struct platform_device *pdev) data->msr_mask_off |= UART_MSR_TERI; } + data->is_rzn1 = of_device_is_compatible(dev->of_node, "renesas,rzn1-uart"); + /* Always ask for fixed clock rate from a property. */ device_property_read_u32(dev, "clock-frequency", &p->uartclk); @@ -561,6 +651,13 @@ static int dw8250_probe(struct platform_device *pdev) data->data.dma.rxconf.src_maxburst = p->fifosize / 4; data->data.dma.txconf.dst_maxburst = p->fifosize / 4; up->dma = &data->data.dma; + + if (data->is_rzn1) { + data->data.dma.txconf.device_fc = 1; + data->data.dma.rxconf.device_fc = 1; + uart.dma->tx_dma = rzn1_dw8250_tx_dma; + uart.dma->rx_dma = rzn1_dw8250_rx_dma; + } } data->data.line = serial8250_register_8250_port(up); diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h index 900b2321aff0..014005c170e4 100644 --- a/drivers/tty/serial/8250/8250_dwlib.h +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -35,6 +35,7 @@ struct dw8250_data { unsigned int skip_autocfg:1; unsigned int uart_16550_compatible:1; unsigned int dma_capable:1; + unsigned int is_rzn1:1; }; void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);