[coreboot-gerrit] Change in coreboot[master]: drivers/uart: Add a driver for SiFive's UART

Jonathan Neuschäfer (Code Review) gerrit at coreboot.org
Sun Apr 22 00:30:35 CEST 2018


Jonathan Neuschäfer has uploaded this change for review. ( https://review.coreboot.org/25768


Change subject: drivers/uart: Add a driver for SiFive's UART
......................................................................

drivers/uart: Add a driver for SiFive's UART

This UART is used in the SiFive FU540 SoC.

Change-Id: I915edf39666b7a5f9550e3b7e743e97fe3cacfd3
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer at gmx.net>
---
M src/drivers/uart/Kconfig
M src/drivers/uart/Makefile.inc
A src/drivers/uart/sifive.c
3 files changed, 125 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/25768/1

diff --git a/src/drivers/uart/Kconfig b/src/drivers/uart/Kconfig
index 54f591d..bfc5cce 100644
--- a/src/drivers/uart/Kconfig
+++ b/src/drivers/uart/Kconfig
@@ -61,6 +61,11 @@
 	default n
 	select HAVE_UART_SPECIAL
 
+config DRIVERS_UART_SIFIVE
+	bool
+	select HAVE_UART_SPECIAL
+	select UART_OVERRIDE_INPUT_CLOCK_DIVIDER
+
 config UART_USE_REFCLK_AS_INPUT_CLOCK
 	bool
 	default n
diff --git a/src/drivers/uart/Makefile.inc b/src/drivers/uart/Makefile.inc
index ebaa5d4..c7aa1ae 100644
--- a/src/drivers/uart/Makefile.inc
+++ b/src/drivers/uart/Makefile.inc
@@ -42,4 +42,11 @@
 verstage-y += pl011.c
 endif
 
+ifeq ($(CONFIG_DRIVERS_UART_SIFIVE),y)
+bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += sifive.c
+romstage-y += sifive.c
+postcar-y += sifive.c
+ramstage-y += sifive.c
+endif
+
 endif
diff --git a/src/drivers/uart/sifive.c b/src/drivers/uart/sifive.c
new file mode 100644
index 0000000..8e54d16
--- /dev/null
+++ b/src/drivers/uart/sifive.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Jonathan Neuschäfer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <boot/coreboot_tables.h>
+#include <console/uart.h>
+#include <types.h>
+
+/*
+ * This is a driver for SiFive's own UART, documented in the FU540 manual:
+ * https://www.sifive.com/documentation/chips/freedom-u540-c000-manual/
+ */
+
+struct sifive_uart_registers {
+	uint32_t txdata;	/* Transmit data register */
+	uint32_t rxdata;	/* Receive data register */
+	uint32_t txctrl;	/* Transmit control register */
+	uint32_t rxctrl;	/* Receive control register */
+	uint32_t ie;		/* UART interrupt enable */
+	uint32_t ip;		/* UART interrupt pending */
+	uint32_t div;		/* Baud rate divisor */
+};
+
+#define TXDATA_FULL		BIT(31)
+#define RXDATA_EMPTY		BIT(31)
+#define TXCTRL_TXEN		BIT(0)
+#define TXCTRL_NSTOP_SHIFT	1
+#define TXCTRL_NSTOP(x)		(((x)-1) << TXCTRL_NSTOP_SHIFT)
+#define TXCTRL_TXCNT_SHIFT	16
+#define TXCTRL_TXCNT(x)		((x) << TXCTRL_TXCNT_SHIFT)
+#define RXCTRL_RXEN		BIT(0)
+#define RXCTRL_RXCNT_SHIFT	16
+#define RXCTRL_RXCNT(x)		((x) << RXCTRL_RXCNT_SHIFT)
+#define IP_TXWM			BIT(0)
+#define IP_RXWM			BIT(1)
+
+void uart_init(int idx)
+{
+	struct sifive_uart_registers *regs = uart_platform_baseptr(idx);
+
+	/* TODO: Configure the divisor */
+
+	/* Enable transmission, one stop bit, transmit watermark at 1 */
+	write32(&regs->txctrl, TXCTRL_TXEN|TXCTRL_NSTOP(1)|TXCTRL_TXCNT(1));
+
+	/* Enable reception, receive watermark at 0 */
+	write32(&regs->rxctrl, RXCTRL_RXEN|RXCTRL_RXCNT(0));
+}
+
+static bool uart_can_tx(struct sifive_uart_registers *regs)
+{
+	return !(read32(&regs->txdata) & TXDATA_FULL);
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+	struct sifive_uart_registers *regs = uart_platform_baseptr(idx);
+
+	while (!uart_can_tx(regs))
+		; /* TODO: implement a timeout */
+
+	write32(&regs->txdata, data);
+}
+
+void uart_tx_flush(int idx)
+{
+	struct sifive_uart_registers *regs = uart_platform_baseptr(idx);
+	uint32_t ip;
+
+	/* Use the TX watermark bit to find out if the TX FIFO is empty */
+	do {
+		ip = read32(&regs->ip);
+	} while(!(ip & IP_TXWM));
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+	struct sifive_uart_registers *regs = uart_platform_baseptr(idx);
+	uint32_t rxdata = read32(&regs->rxdata);
+
+	if (rxdata & RXDATA_EMPTY)
+		return 0;
+	else
+		return rxdata & 0xff;
+}
+
+unsigned int uart_input_clock_divider(void)
+{
+	/*
+	 * The SiFive UART handles oversampling internally. The divided clock
+	 * is the baud clock.
+	 */
+	return 1;
+}
+
+#ifndef __PRE_RAM__
+void uart_fill_lb(void *data)
+{
+	/* TODO */
+}
+#endif

-- 
To view, visit https://review.coreboot.org/25768
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I915edf39666b7a5f9550e3b7e743e97fe3cacfd3
Gerrit-Change-Number: 25768
Gerrit-PatchSet: 1
Gerrit-Owner: Jonathan Neuschäfer <j.neuschaefer at gmx.net>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180421/71977f83/attachment-0001.html>


More information about the coreboot-gerrit mailing list