[PATCH v3 2/2] serial: fsl_lpuart: add DMA support

Arnd Bergmann arnd at arndb.de
Wed Jan 15 04:25:34 EST 2014


On Wednesday 15 January 2014, Yuan Yao wrote:
> Add dma support for lpuart. This function depend on DMA driver. 
> You can turn on it by SERIAL_FSL_LPUART_DMA=y. And It works if dts node has dma properties.
> 
> Signed-off-by: Yuan Yao <yao.yuan at freescale.com>

Most of the changes you did look good, but I have to say I'm not a fan of
the #ifdef you added. I don't think you actually need to have the compile-time
selection, and it would be best to just drop that part.

If you have a good reason to keep it, please change the code to
more readable "if (IS_ENABLED(CONFIG_FSL_LPUART_DMA))" constructs.
If you decide to do this, you will find that you need far fewer
such conditionals because a lot of the code will automatically
get dropped by the compiler.
  
>  uart0: serial at 40027000 {
> -	       compatible = "fsl,vf610-lpuart";
> -	       reg = <0x40027000 0x1000>;
> -	       interrupts = <0 61 0x00>;
> -       };
> +		compatible = "fsl,vf610-lpuart";
> +		reg = <0x40027000 0x1000>;
> +		interrupts = <0 61 0x00>;
> +		clocks = <&clks VF610_CLK_UART0>;
> +		clock-names = "ipg";
> +		dma-names = "lpuart-tx","lpuart-rx";
> +		dmas = <&edma0 0 VF610_EDMA_MUXID0_UART0_TX>,
> +			<&edma0 0 VF610_EDMA_MUXID0_UART0_RX>;
> +	};

You still haven't addressed my comment about removing the VF610_EDMA_MUXID0_UART0_TX
macros.

>  
> +#ifdef CONFIG_SERIAL_FSL_LPUART_DMA
> +#define DMA_MAXBURST		16
> +#define DMA_MAXBURST_MASK	(DMA_MAXBURST - 1)
> +#define FSL_UART_RX_DMA_BUFFER_SIZE	64
> +#endif

For this part there was no need for the #ifdef to start with.

>  #define DRIVER_NAME	"fsl-lpuart"
>  #define DEV_NAME	"ttyLP"
>  #define UART_NR		6
> @@ -121,6 +132,26 @@ struct lpuart_port {
>  	struct clk		*clk;
>  	unsigned int		txfifo_size;
>  	unsigned int		rxfifo_size;
> +
> +#ifdef CONFIG_SERIAL_FSL_LPUART_DMA
> +	bool			lpuart_dma_use;
> +	struct dma_chan		*dma_tx_chan;
> +	struct dma_chan		*dma_rx_chan;
> +	struct dma_async_tx_descriptor  *dma_tx_desc;
> +	struct dma_async_tx_descriptor  *dma_rx_desc;
> +	dma_addr_t		dma_tx_buf_bus;
> +	dma_addr_t		dma_rx_buf_bus;
> +	dma_cookie_t		dma_tx_cookie;
> +	dma_cookie_t		dma_rx_cookie;
> +	unsigned char		*dma_tx_buf_virt;
> +	unsigned char		*dma_rx_buf_virt;
> +	unsigned int		dma_tx_bytes;
> +	unsigned int		dma_rx_bytes;
> +	int			dma_tx_in_progress;
> +	int			dma_rx_in_progress;
> +	unsigned int		dma_rx_timeout;
> +	struct timer_list	lpuart_timer;
> +#endif
>  };

This part will result in a slight increase in data size even if
dma support is turned off at compile time.

>  
>  	temp = readb(port->membase + UARTCR2);
>  	writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
>  
> +#ifdef CONFIG_SERIAL_FSL_LPUART_DMA
> +	if (sport->lpuart_dma_use) {
> +		if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
> +			lpuart_prepare_tx(sport);
> +	} else {
> +		if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
> +			lpuart_transmit_buffer(sport);
> +	}
> +#else
>  	if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
>  		lpuart_transmit_buffer(sport);
> +#endif
>  }

So this can simply become

+	if (IS_ENABLED(CONFIG_SERIAL_FSL_LPUART_DMA) && sport->lpuart_dma_use) {
+		if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
+			lpuart_prepare_tx(sport);
+	} else {
+		if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
+			lpuart_trans	mit_buffer(sport);
+	}

and the compiler will silently drop the lpuart_prepare_tx() function and everything
it calls that isn't used elsewhere.


> +
> +#ifdef CONFIG_SERIAL_FSL_LPUART_DMA
> +	struct platform_device *pdev = to_platform_device(port->dev);
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	if (of_get_property(np, "dmas", NULL)) {
> +		sport->lpuart_dma_use = true;
> +		lpuart_dma_tx_request(port);
> +		lpuart_dma_rx_request(port);
> +		temp = readb(port->membase + UARTCR5);
> +		writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
> +	} else
> +		sport->lpuart_dma_use = false;	
> +#endif

Same here.

> @@ -854,6 +1291,10 @@ static int __init lpuart_serial_init(void)
>  
>  	pr_info("serial: Freescale lpuart driver\n");
>  
> +#ifdef CONFIG_SERIAL_FSL_LPUART_DMA
> +	pr_info("serial: Freescale lpuart dma support\n");
> +#endif
> +

This message is not helpful in the long run, I'd rather see you drop the
other one as well. Note that this function is called on *all* platforms
when the driver is enabled, not just on those that actually have the uart.

	Arnd



More information about the linux-arm-kernel mailing list