[U-Boot] [PATCH 13/13] arm: zynq: Move serial driver to driver model

Michal Simek monstr at monstr.eu
Tue Sep 1 17:42:24 CEST 2015


On 08/29/2015 05:10 PM, Simon Glass wrote:
> Update this driver to use driver model and change all users.
> 
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
> 
>  arch/arm/Kconfig                |   1 +
>  drivers/serial/serial_zynq.c    | 162 ++++++++++++++++------------------------
>  include/configs/zynq_microzed.h |   1 -
>  include/configs/zynq_picozed.h  |   1 -
>  include/configs/zynq_zc70x.h    |   1 -
>  include/configs/zynq_zc770.h    |   6 --
>  include/configs/zynq_zed.h      |   1 -
>  include/configs/zynq_zybo.h     |   1 -
>  8 files changed, 65 insertions(+), 109 deletions(-)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index a82306e..7705e03 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -687,6 +687,7 @@ config ARCH_ZYNQ
>  	select DM
>  	select SPL_DM
>  	select DM_SPI
> +	select DM_SERIAL

Can you please keep DM_SPI and DM_SPI_FLASH together?

>  	select DM_SPI_FLASH
>  	select SPL_SEPARATE_BSS
>  
> diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
> index c39c1a9..7069afe 100644
> --- a/drivers/serial/serial_zynq.c
> +++ b/drivers/serial/serial_zynq.c
> @@ -6,6 +6,8 @@
>   */
>  
>  #include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
>  #include <errno.h>
>  #include <fdtdec.h>
>  #include <watchdog.h>
> @@ -18,6 +20,7 @@
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  #define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
> +#define ZYNQ_UART_SR_TXACTIVE	(1 << 11)  /* TX active */
>  #define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
>  
>  #define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
> @@ -38,9 +41,8 @@ struct uart_zynq {
>  	u32 baud_rate_divider; /* 0x34 - Baud Rate Divider [7:0] */
>  };
>  
> -static struct uart_zynq *uart_zynq_ports[2] = {
> -	[0] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR0,
> -	[1] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR1,
> +struct zynq_uart_priv {
> +	struct uart_zynq *regs;
>  };
>  
>  /* Set up the baud rate in gd struct */
> @@ -84,15 +86,6 @@ static void _uart_zynq_serial_setbrg(struct uart_zynq *regs,
>  	writel(bgen, &regs->baud_rate_gen);
>  }
>  
> -/* Set up the baud rate in gd struct */
> -static void uart_zynq_serial_setbrg(const int port)
> -{
> -	unsigned long clock = get_uart_clk(port);
> -	struct uart_zynq *regs = uart_zynq_ports[port];
> -
> -	return _uart_zynq_serial_setbrg(regs, clock, gd->baudrate);
> -}
> -
>  /* Initialize the UART, with...some settings. */
>  static void _uart_zynq_serial_init(struct uart_zynq *regs)
>  {
> @@ -102,20 +95,6 @@ static void _uart_zynq_serial_init(struct uart_zynq *regs)
>  	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
>  }
>  
> -/* Initialize the UART, with...some settings. */
> -static int uart_zynq_serial_init(const int port)
> -{
> -	struct uart_zynq *regs = uart_zynq_ports[port];
> -
> -	if (!regs)
> -		return -1;
> -
> -	_uart_zynq_serial_init(regs);
> -	uart_zynq_serial_setbrg(port);
> -
> -	return 0;
> -}
> -
>  static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
>  {
>  	if (readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL)
> @@ -126,103 +105,90 @@ static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
>  	return 0;
>  }
>  
> -static void uart_zynq_serial_putc(const char c, const int port)
> +int zynq_serial_setbrg(struct udevice *dev, int baudrate)
>  {
> -	struct uart_zynq *regs = uart_zynq_ports[port];
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
> +	unsigned long clock = get_uart_clk(0);
>  
> -	while (_uart_zynq_serial_putc(regs, c) == -EAGAIN)
> -		WATCHDOG_RESET();
> +	_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
>  
> -	if (c == '\n') {
> -		while (_uart_zynq_serial_putc(regs, '\r') == -EAGAIN)
> -			WATCHDOG_RESET();
> -	}
> +	return 0;
>  }
>  
> -static void uart_zynq_serial_puts(const char *s, const int port)
> +static int zynq_serial_probe(struct udevice *dev)
>  {
> -	while (*s)
> -		uart_zynq_serial_putc(*s++, port);
> -}
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
>  
> -static int uart_zynq_serial_tstc(const int port)
> -{
> -	struct uart_zynq *regs = uart_zynq_ports[port];
> +	_uart_zynq_serial_init(priv->regs);
>  
> -	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
> +	return 0;
>  }
>  
> -static int uart_zynq_serial_getc(const int port)
> +static int zynq_serial_getc(struct udevice *dev)
>  {
> -	struct uart_zynq *regs = uart_zynq_ports[port];
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
> +	struct uart_zynq *regs = priv->regs;
> +
> +	if (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
> +		return -EAGAIN;
>  
> -	while (!uart_zynq_serial_tstc(port))
> -		WATCHDOG_RESET();
>  	return readl(&regs->tx_rx_fifo);
>  }
>  
> -/* Multi serial device functions */
> -#define DECLARE_PSSERIAL_FUNCTIONS(port) \
> -	static int uart_zynq##port##_init(void) \
> -				{ return uart_zynq_serial_init(port); } \
> -	static void uart_zynq##port##_setbrg(void) \
> -				{ return uart_zynq_serial_setbrg(port); } \
> -	static int uart_zynq##port##_getc(void) \
> -				{ return uart_zynq_serial_getc(port); } \
> -	static int uart_zynq##port##_tstc(void) \
> -				{ return uart_zynq_serial_tstc(port); } \
> -	static void uart_zynq##port##_putc(const char c) \
> -				{ uart_zynq_serial_putc(c, port); } \
> -	static void uart_zynq##port##_puts(const char *s) \
> -				{ uart_zynq_serial_puts(s, port); }
> -
> -/* Serial device descriptor */
> -#define INIT_PSSERIAL_STRUCTURE(port, __name) {	\
> -	  .name   = __name,			\
> -	  .start  = uart_zynq##port##_init,	\
> -	  .stop   = NULL,			\
> -	  .setbrg = uart_zynq##port##_setbrg,	\
> -	  .getc   = uart_zynq##port##_getc,	\
> -	  .tstc   = uart_zynq##port##_tstc,	\
> -	  .putc   = uart_zynq##port##_putc,	\
> -	  .puts   = uart_zynq##port##_puts,	\
> -}
> +static int zynq_serial_putc(struct udevice *dev, const char ch)
> +{
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
>  
> -DECLARE_PSSERIAL_FUNCTIONS(0);
> -static struct serial_device uart_zynq_serial0_device =
> -	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
> -DECLARE_PSSERIAL_FUNCTIONS(1);
> -static struct serial_device uart_zynq_serial1_device =
> -	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
> +	return _uart_zynq_serial_putc(priv->regs, ch);
> +}
>  
> -__weak struct serial_device *default_serial_console(void)
> +static int zynq_serial_pending(struct udevice *dev, bool input)
>  {
> -	const void *blob = gd->fdt_blob;
> -	int node;
> -	unsigned int base_addr;
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
> +	struct uart_zynq *regs = priv->regs;
>  
> -	node = fdt_path_offset(blob, "serial0");
> -	if (node < 0)
> -		return NULL;
> +	if (input)
> +		return !(readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
> +	else
> +		return !!(readl(&regs->channel_sts) & ZYNQ_UART_SR_TXACTIVE);
> +}
>  
> -	base_addr = fdtdec_get_addr(blob, node, "reg");
> -	if (base_addr == FDT_ADDR_T_NONE)
> -		return NULL;
> +static int zynq_serial_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct zynq_uart_priv *priv = dev_get_priv(dev);
> +	fdt_addr_t addr;
>  
> -	if (base_addr == ZYNQ_SERIAL_BASEADDR0)
> -		return &uart_zynq_serial0_device;
> +	addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
>  
> -	if (base_addr == ZYNQ_SERIAL_BASEADDR1)
> -		return &uart_zynq_serial1_device;
> +	priv->regs = (struct uart_zynq *)addr;
>  
> -	return NULL;
> +	return 0;
>  }
>  
> -void zynq_serial_initialize(void)
> -{
> -	serial_register(&uart_zynq_serial0_device);
> -	serial_register(&uart_zynq_serial1_device);
> -}
> +static const struct dm_serial_ops zynq_serial_ops = {
> +	.putc = zynq_serial_putc,
> +	.pending = zynq_serial_pending,
> +	.getc = zynq_serial_getc,
> +	.setbrg = zynq_serial_setbrg,
> +};
> +
> +static const struct udevice_id zynq_serial_ids[] = {
> +	{ .compatible = "xlnx,xuartps" },

I would prefer to use
{ .compatible = "cdns,uart-r1p8" },
instead.
Or both.

The reason is that xlnx,xuartps compatible string is deprecated.
We switch to cadence compatible string.


> +	{ }
> +};
> +
> +U_BOOT_DRIVER(serial_s5p) = {

serial_zynq here

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150901/81fd229e/attachment.sig>


More information about the U-Boot mailing list