All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/2] SiFive UART support
@ 2018-12-05  6:29 Anup Patel
  2018-12-05  6:29 ` [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver Anup Patel
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-05  6:29 UTC (permalink / raw)
  To: u-boot

This patchset adds SiFive UART driver for SiFive UART
found on SiFive boards.

The driver is tested on QEMU sifive_u machine. In fact,
with this patchset same U-Boot binary boots on QEMU virt
machine and QEMU sifive_u machine in both M-mode and
S-mode.

The patches are based upon latest RISC-V UBoot tree
(git://git.denx.de/u-boot-riscv.git) at commit id
ce41c65382300b4be2b84df3c06c2aa6c591741d

Anup Patel (2):
  drivers: serial: Add SiFive UART driver
  riscv: qemu: Enable SiFive UART driver in defconfigs

 configs/qemu-riscv32_defconfig       |   1 +
 configs/qemu-riscv32_smode_defconfig |   1 +
 configs/qemu-riscv64_defconfig       |   1 +
 configs/qemu-riscv64_smode_defconfig |   1 +
 drivers/serial/Kconfig               |  13 ++
 drivers/serial/Makefile              |   1 +
 drivers/serial/serial_sifive.c       | 193 +++++++++++++++++++++++++++
 7 files changed, 211 insertions(+)
 create mode 100644 drivers/serial/serial_sifive.c

-- 
2.17.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
  2018-12-05  6:29 [U-Boot] [PATCH 0/2] SiFive UART support Anup Patel
@ 2018-12-05  6:29 ` Anup Patel
  2018-12-07 18:40   ` Palmer Dabbelt
  2018-12-10  1:54   ` Bin Meng
  2018-12-05  6:29 ` [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs Anup Patel
  2018-12-10  1:28 ` [U-Boot] [PATCH 0/2] SiFive UART support Bin Meng
  2 siblings, 2 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-05  6:29 UTC (permalink / raw)
  To: u-boot

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;
+}
+
+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
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs
  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-05  6:29 ` Anup Patel
  2018-12-07 18:41   ` Palmer Dabbelt
  2018-12-10  1:54   ` Bin Meng
  2018-12-10  1:28 ` [U-Boot] [PATCH 0/2] SiFive UART support Bin Meng
  2 siblings, 2 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-05  6:29 UTC (permalink / raw)
  To: u-boot

This patch enables SiFive UART driver in all QEMU RISC-V defconfigs.

Signed-off-by: Anup Patel <anup@brainfault.org>
---
 configs/qemu-riscv32_defconfig       | 1 +
 configs/qemu-riscv32_smode_defconfig | 1 +
 configs/qemu-riscv64_defconfig       | 1 +
 configs/qemu-riscv64_smode_defconfig | 1 +
 4 files changed, 4 insertions(+)

diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
index 6334d8c0fc..79c8d54cc7 100644
--- a/configs/qemu-riscv32_defconfig
+++ b/configs/qemu-riscv32_defconfig
@@ -7,3 +7,4 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
 # CONFIG_CMD_MII is not set
 CONFIG_OF_PRIOR_STAGE=y
+CONFIG_SIFIVE_SERIAL=y
diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig
index 0a84ec1874..b733dbed2f 100644
--- a/configs/qemu-riscv32_smode_defconfig
+++ b/configs/qemu-riscv32_smode_defconfig
@@ -8,3 +8,4 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
 # CONFIG_CMD_MII is not set
 CONFIG_OF_PRIOR_STAGE=y
+CONFIG_SIFIVE_SERIAL=y
diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
index 2d9ead93a2..a9d19a5574 100644
--- a/configs/qemu-riscv64_defconfig
+++ b/configs/qemu-riscv64_defconfig
@@ -8,3 +8,4 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
 # CONFIG_CMD_MII is not set
 CONFIG_OF_PRIOR_STAGE=y
+CONFIG_SIFIVE_SERIAL=y
diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig
index b012443370..8adc23f826 100644
--- a/configs/qemu-riscv64_smode_defconfig
+++ b/configs/qemu-riscv64_smode_defconfig
@@ -9,3 +9,4 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
 # CONFIG_CMD_MII is not set
 CONFIG_OF_PRIOR_STAGE=y
+CONFIG_SIFIVE_SERIAL=y
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
  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
  2018-12-11 14:56     ` Anup Patel
  2018-12-10  1:54   ` Bin Meng
  1 sibling, 1 reply; 11+ messages in thread
From: Palmer Dabbelt @ 2018-12-07 18:40 UTC (permalink / raw)
  To: u-boot

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!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs
  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
  1 sibling, 0 replies; 11+ messages in thread
From: Palmer Dabbelt @ 2018-12-07 18:41 UTC (permalink / raw)
  To: u-boot

On Tue, 04 Dec 2018 22:29:24 PST (-0800), anup at brainfault.org wrote:
> This patch enables SiFive UART driver in all QEMU RISC-V defconfigs.
>
> Signed-off-by: Anup Patel <anup@brainfault.org>
> ---
>  configs/qemu-riscv32_defconfig       | 1 +
>  configs/qemu-riscv32_smode_defconfig | 1 +
>  configs/qemu-riscv64_defconfig       | 1 +
>  configs/qemu-riscv64_smode_defconfig | 1 +
>  4 files changed, 4 insertions(+)
>
> diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
> index 6334d8c0fc..79c8d54cc7 100644
> --- a/configs/qemu-riscv32_defconfig
> +++ b/configs/qemu-riscv32_defconfig
> @@ -7,3 +7,4 @@ CONFIG_DISPLAY_CPUINFO=y
>  CONFIG_DISPLAY_BOARDINFO=y
>  # CONFIG_CMD_MII is not set
>  CONFIG_OF_PRIOR_STAGE=y
> +CONFIG_SIFIVE_SERIAL=y
> diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig
> index 0a84ec1874..b733dbed2f 100644
> --- a/configs/qemu-riscv32_smode_defconfig
> +++ b/configs/qemu-riscv32_smode_defconfig
> @@ -8,3 +8,4 @@ CONFIG_DISPLAY_CPUINFO=y
>  CONFIG_DISPLAY_BOARDINFO=y
>  # CONFIG_CMD_MII is not set
>  CONFIG_OF_PRIOR_STAGE=y
> +CONFIG_SIFIVE_SERIAL=y
> diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
> index 2d9ead93a2..a9d19a5574 100644
> --- a/configs/qemu-riscv64_defconfig
> +++ b/configs/qemu-riscv64_defconfig
> @@ -8,3 +8,4 @@ CONFIG_DISPLAY_CPUINFO=y
>  CONFIG_DISPLAY_BOARDINFO=y
>  # CONFIG_CMD_MII is not set
>  CONFIG_OF_PRIOR_STAGE=y
> +CONFIG_SIFIVE_SERIAL=y
> diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig
> index b012443370..8adc23f826 100644
> --- a/configs/qemu-riscv64_smode_defconfig
> +++ b/configs/qemu-riscv64_smode_defconfig
> @@ -9,3 +9,4 @@ CONFIG_DISPLAY_CPUINFO=y
>  CONFIG_DISPLAY_BOARDINFO=y
>  # CONFIG_CMD_MII is not set
>  CONFIG_OF_PRIOR_STAGE=y
> +CONFIG_SIFIVE_SERIAL=y

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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 0/2] SiFive UART support
  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-05  6:29 ` [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs Anup Patel
@ 2018-12-10  1:28 ` Bin Meng
  2 siblings, 0 replies; 11+ messages in thread
From: Bin Meng @ 2018-12-10  1:28 UTC (permalink / raw)
  To: u-boot

Hi Anup,

On Wed, Dec 5, 2018 at 2:29 PM Anup Patel <anup@brainfault.org> wrote:
>
> This patchset adds SiFive UART driver for SiFive UART
> found on SiFive boards.
>
> The driver is tested on QEMU sifive_u machine. In fact,
> with this patchset same U-Boot binary boots on QEMU virt
> machine and QEMU sifive_u machine in both M-mode and
> S-mode.
>

I was unable to get this working with QEMU sifive_u target. I am using:

$ qemu-system-riscv64 -nographic -M sifive_u -kernel u-boot

with QEMU version 3.0.50

> The patches are based upon latest RISC-V UBoot tree
> (git://git.denx.de/u-boot-riscv.git) at commit id
> ce41c65382300b4be2b84df3c06c2aa6c591741d
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
  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
@ 2018-12-10  1:54   ` Bin Meng
  2018-12-10 12:59     ` Anup Patel
  1 sibling, 1 reply; 11+ messages in thread
From: Bin Meng @ 2018-12-10  1:54 UTC (permalink / raw)
  To: u-boot

Hi Anup,

On Wed, Dec 5, 2018 at 2:29 PM Anup Patel <anup@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.

nits: pls update the copyright notice

> + */
> +
> +#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;
> +}
> +
> +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),

This is not used anywhere in this driver.

> +};
> +
> +#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
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs
  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
  1 sibling, 1 reply; 11+ messages in thread
From: Bin Meng @ 2018-12-10  1:54 UTC (permalink / raw)
  To: u-boot

Hi Anup,

On Wed, Dec 5, 2018 at 2:29 PM Anup Patel <anup@brainfault.org> wrote:
>
> This patch enables SiFive UART driver in all QEMU RISC-V defconfigs.
>
> Signed-off-by: Anup Patel <anup@brainfault.org>
> ---
>  configs/qemu-riscv32_defconfig       | 1 +
>  configs/qemu-riscv32_smode_defconfig | 1 +
>  configs/qemu-riscv64_defconfig       | 1 +
>  configs/qemu-riscv64_smode_defconfig | 1 +
>  4 files changed, 4 insertions(+)
>

Can we "imply SIFIVE_SERIAL" in BOARD_SPECIFIC_OPTIONS in
board/emulation/qemu-riscv/Kconfig instead?

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
  2018-12-10  1:54   ` Bin Meng
@ 2018-12-10 12:59     ` Anup Patel
  0 siblings, 0 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-10 12:59 UTC (permalink / raw)
  To: u-boot

On Mon, Dec 10, 2018 at 7:25 AM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Anup,
>
> On Wed, Dec 5, 2018 at 2:29 PM Anup Patel <anup@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.
>
> nits: pls update the copyright notice

Thanks for catching it. I will update it.

>
> > + */
> > +
> > +#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;
> > +}
> > +
> > +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),
>
> This is not used anywhere in this driver.

Ok, I will remove priv_auto_alloc_size.

>
> > +};
> > +
> > +#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
> > --
>
> Regards,
> Bin

Regards,
Anup

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 2/2] riscv: qemu: Enable SiFive UART driver in defconfigs
  2018-12-10  1:54   ` Bin Meng
@ 2018-12-10 13:00     ` Anup Patel
  0 siblings, 0 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-10 13:00 UTC (permalink / raw)
  To: u-boot

On Mon, Dec 10, 2018 at 7:25 AM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Anup,
>
> On Wed, Dec 5, 2018 at 2:29 PM Anup Patel <anup@brainfault.org> wrote:
> >
> > This patch enables SiFive UART driver in all QEMU RISC-V defconfigs.
> >
> > Signed-off-by: Anup Patel <anup@brainfault.org>
> > ---
> >  configs/qemu-riscv32_defconfig       | 1 +
> >  configs/qemu-riscv32_smode_defconfig | 1 +
> >  configs/qemu-riscv64_defconfig       | 1 +
> >  configs/qemu-riscv64_smode_defconfig | 1 +
> >  4 files changed, 4 insertions(+)
> >
>
> Can we "imply SIFIVE_SERIAL" in BOARD_SPECIFIC_OPTIONS in
> board/emulation/qemu-riscv/Kconfig instead?

Sure, will do. If it works then I will drop this patch.

Regards,
Anup

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/2] drivers: serial: Add SiFive UART driver
  2018-12-07 18:40   ` Palmer Dabbelt
@ 2018-12-11 14:56     ` Anup Patel
  0 siblings, 0 replies; 11+ messages in thread
From: Anup Patel @ 2018-12-11 14:56 UTC (permalink / raw)
  To: u-boot

On Sat, Dec 8, 2018 at 12:10 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>
> 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.

Ohh yes, u-boot serial drivers usually don't drain TX FIFO.

If required we can add it via separate patch.

>
> > +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,
Anup

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-12-11 14:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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.