[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(®s->txctrl, TXCTRL_TXEN|TXCTRL_NSTOP(1)|TXCTRL_TXCNT(1));
+
+ /* Enable reception, receive watermark at 0 */
+ write32(®s->rxctrl, RXCTRL_RXEN|RXCTRL_RXCNT(0));
+}
+
+static bool uart_can_tx(struct sifive_uart_registers *regs)
+{
+ return !(read32(®s->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(®s->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(®s->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(®s->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