All of lore.kernel.org
 help / color / mirror / Atom feed
From: Palmer Dabbelt <palmer@sifive.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
Date: Fri, 07 Dec 2018 10:40:58 -0800 (PST)	[thread overview]
Message-ID: <mhng-e96d2ba6-4a54-4dd9-9763-01dafb9d6125@palmer-si-x1c4> (raw)
In-Reply-To: <20181205062924.26640-2-anup@brainfault.org>

On Tue, 04 Dec 2018 22:29:23 PST (-0800), anup at brainfault.org wrote:
> This patch adds SiFive UART driver. The driver is 100% DM driver
> and it determines input clock using clk framework.
>
> Signed-off-by: Anup Patel <anup@brainfault.org>
> ---
>  drivers/serial/Kconfig         |  13 +++
>  drivers/serial/Makefile        |   1 +
>  drivers/serial/serial_sifive.c | 193 +++++++++++++++++++++++++++++++++
>  3 files changed, 207 insertions(+)
>  create mode 100644 drivers/serial/serial_sifive.c
>
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 3bcc61e731..30f7e00557 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -343,6 +343,13 @@ config DEBUG_UART_SANDBOX
>  	  start up driver model. The driver will be available until the real
>  	  driver model serial is running.
>
> +config DEBUG_UART_SIFIVE
> +	bool "SiFive UART"
> +	help
> +	  Select this to enable a debug UART using the serial_sifive driver. You
> +	  will need to provide parameters to make this work. The driver will
> +	  be available until the real driver-model serial is running.
> +
>  config DEBUG_UART_STM32
>  	bool "STMicroelectronics STM32"
>  	depends on STM32_SERIAL
> @@ -685,6 +692,12 @@ config PXA_SERIAL
>  	  If you have a machine based on a Marvell XScale PXA2xx CPU you
>  	  can enable its onboard serial ports by enabling this option.
>
> +config SIFIVE_SERIAL
> +	bool "SiFive UART support"
> +	depends on DM_SERIAL
> +	help
> +	  This driver supports the SiFive UART. If unsure say N.
> +
>  config STI_ASC_SERIAL
>  	bool "STMicroelectronics on-chip UART"
>  	depends on DM_SERIAL && ARCH_STI
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index b6377b1076..b6781535a8 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
>  obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
>  obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
>  obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
> +obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
>
>  ifndef CONFIG_SPL_BUILD
>  obj-$(CONFIG_USB_TTY) += usbtty.o
> diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
> new file mode 100644
> index 0000000000..cce05d5a01
> --- /dev/null
> +++ b/drivers/serial/serial_sifive.c
> @@ -0,0 +1,193 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
> + */
> +
> +#include <clk.h>
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <watchdog.h>
> +#include <asm/io.h>
> +#include <linux/compiler.h>
> +#include <serial.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define UART_TXFIFO_FULL	0x80000000
> +#define UART_RXFIFO_EMPTY	0x80000000
> +#define UART_RXFIFO_DATA	0x000000ff
> +#define UART_TXCTRL_TXEN	0x1
> +#define UART_RXCTRL_RXEN	0x1
> +
> +struct uart_sifive {
> +	u32 txfifo;
> +	u32 rxfifo;
> +	u32 txctrl;
> +	u32 rxctrl;
> +	u32 ie;
> +	u32 ip;
> +	u32 div;
> +};
> +
> +struct sifive_uart_platdata {
> +	unsigned int clock;
> +	struct uart_sifive *regs;
> +};
> +
> +/* Set up the baud rate in gd struct */
> +static void _sifive_serial_setbrg(struct uart_sifive *regs,
> +				  unsigned long clock, unsigned long baud)
> +{
> +	writel((u32)((clock / baud) - 1), &regs->div);
> +}
> +
> +static void _sifive_serial_init(struct uart_sifive *regs)
> +{
> +	writel(UART_TXCTRL_TXEN, &regs->txctrl);
> +	writel(UART_RXCTRL_RXEN, &regs->rxctrl);
> +	writel(0, &regs->ie);
> +}
> +
> +static int _sifive_serial_putc(struct uart_sifive *regs, const char c)
> +{
> +	if (readl(&regs->txfifo) & UART_TXFIFO_FULL)
> +		return -EAGAIN;
> +
> +	writel(c, &regs->txfifo);
> +
> +	return 0;
> +}
> +
> +static int _sifive_serial_getc(struct uart_sifive *regs)
> +{
> +	int ch = readl(&regs->rxfifo);
> +
> +	if (ch & UART_RXFIFO_EMPTY)
> +		return -EAGAIN;
> +	ch &= UART_RXFIFO_DATA;
> +
> +	return (!ch) ? -EAGAIN : ch;
> +}
> +
> +static int sifive_serial_setbrg(struct udevice *dev, int baudrate)
> +{
> +	int err;
> +	struct clk clk;
> +	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
> +
> +	err = clk_get_by_index(dev, 0, &clk);
> +	if (!err) {
> +		err = clk_get_rate(&clk);
> +		if (!IS_ERR_VALUE(err))
> +			platdata->clock = err;
> +	} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
> +		debug("SiFive UART failed to get clock\n");
> +		return err;
> +	}
> +
> +	if (!platdata->clock)
> +		platdata->clock = dev_read_u32_default(dev, "clock-frequency", 0);
> +	if (!platdata->clock) {
> +		debug("SiFive UART clock not defined\n");
> +		return -EINVAL;
> +	}
> +
> +	_sifive_serial_setbrg(platdata->regs, platdata->clock, baudrate);
> +
> +	return 0;
> +}

I don't see anything that ensures the TX FIFO is drained before changing the 
baud rate.  I don't know anything about u-boot so I'm not sure if that's 
expected.

> +static int sifive_serial_probe(struct udevice *dev)
> +{
> +	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
> +
> +	/* No need to reinitialize the UART after relocation */
> +	if (gd->flags & GD_FLG_RELOC)
> +		return 0;
> +
> +	_sifive_serial_init(platdata->regs);
> +
> +	return 0;
> +}
> +
> +static int sifive_serial_getc(struct udevice *dev)
> +{
> +	int c;
> +	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
> +	struct uart_sifive *regs = platdata->regs;
> +
> +	while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
> +
> +	return c;
> +}
> +
> +static int sifive_serial_putc(struct udevice *dev, const char ch)
> +{
> +	int rc;
> +	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
> +
> +	while ((rc = _sifive_serial_putc(platdata->regs, ch)) == -EAGAIN) ;
> +
> +	return rc;
> +}
> +
> +static int sifive_serial_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
> +
> +	platdata->regs = (struct uart_sifive *)dev_read_addr(dev);
> +	if (IS_ERR(platdata->regs))
> +		return PTR_ERR(platdata->regs);
> +
> +	return 0;
> +}
> +
> +static const struct dm_serial_ops sifive_serial_ops = {
> +	.putc = sifive_serial_putc,
> +	.getc = sifive_serial_getc,
> +	.setbrg = sifive_serial_setbrg,
> +};
> +
> +static const struct udevice_id sifive_serial_ids[] = {
> +	{ .compatible = "sifive,uart0" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(serial_sifive) = {
> +	.name	= "serial_sifive",
> +	.id	= UCLASS_SERIAL,
> +	.of_match = sifive_serial_ids,
> +	.ofdata_to_platdata = sifive_serial_ofdata_to_platdata,
> +	.platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata),
> +	.probe = sifive_serial_probe,
> +	.ops	= &sifive_serial_ops,
> +	.priv_auto_alloc_size	= sizeof(struct sifive_uart_platdata),
> +};
> +
> +#ifdef CONFIG_DEBUG_UART_SIFIVE
> +static inline void _debug_uart_init(void)
> +{
> +	struct uart_sifive *regs =
> +			(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
> +
> +	_sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
> +			      CONFIG_BAUDRATE);
> +	_sifive_serial_init(regs);
> +}
> +
> +static inline void _debug_uart_putc(int ch)
> +{
> +	struct uart_sifive *regs =
> +			(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
> +
> +	while (_sifive_serial_putc(regs, ch) == -EAGAIN)
> +		WATCHDOG_RESET();
> +}
> +
> +DEBUG_UART_FUNCS
> +
> +#endif

Reviewed-by: Palmer Dabbelt <palmer@sifive.com>

Thanks!

  reply	other threads:[~2018-12-07 18:40 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-05  6:29 [U-Boot] [PATCH 0/2] SiFive UART support Anup Patel
2018-12-05  6:29 ` [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver Anup Patel
2018-12-07 18:40   ` Palmer Dabbelt [this message]
2018-12-11 14:56     ` Anup Patel
2018-12-10  1:54   ` Bin Meng
2018-12-10 12:59     ` Anup Patel
2018-12-05  6:29 ` [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs Anup Patel
2018-12-07 18:41   ` Palmer Dabbelt
2018-12-10  1:54   ` Bin Meng
2018-12-10 13:00     ` Anup Patel
2018-12-10  1:28 ` [U-Boot] [PATCH 0/2] SiFive UART support Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=mhng-e96d2ba6-4a54-4dd9-9763-01dafb9d6125@palmer-si-x1c4 \
    --to=palmer@sifive.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.