[coreboot-gerrit] Change in coreboot[master]: drivers/uart: Add helper function to allow bit-banging

Julius Werner (Code Review) gerrit at coreboot.org
Wed Apr 25 01:42:57 CEST 2018


Julius Werner has uploaded this change for review. ( https://review.coreboot.org/25812


Change subject: drivers/uart: Add helper function to allow bit-banging
......................................................................

drivers/uart: Add helper function to allow bit-banging

In some cases it may be useful to be able to bitbang a UART, such as
during early bring-up when a driver for the actual controller isn't
available yet. On some platforms we may even want to use this
permanently, such as on the SDM845 where the hardware UART controller
needs to have firmware loaded and is thus unavailable for most of the
bootblock.

This patch adds some helper code that makes it easy to implement this on
a platform, you just have to pass it a function to control the Tx pin
state and it will do the rest. It relies on the mono_time API and is
thus bound to microsecond timing granularity, but that seems to be
barely good enough for 115200 baud if the bit times are calculated
carefully.

Change-Id: If7dcecc7b8a95ec15f456efd2ec1f1e0dde239b4
Signed-off-by: Julius Werner <jwerner at chromium.org>
---
M src/drivers/uart/util.c
M src/include/console/uart.h
2 files changed, 32 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/12/25812/1

diff --git a/src/drivers/uart/util.c b/src/drivers/uart/util.c
index c7b9ab2..d38f688 100644
--- a/src/drivers/uart/util.c
+++ b/src/drivers/uart/util.c
@@ -13,6 +13,8 @@
 
 #include <console/console.h>
 #include <console/uart.h>
+#include <types.h>
+#include <timer.h>
 
 /* Calculate divisor. Do not floor but round to nearest integer. */
 unsigned int uart_baudrate_divisor(unsigned int baudrate,
@@ -53,3 +55,30 @@
 	return 115200 * 16;
 }
 #endif
+
+/* Helper function to allow bitbanging an 8n1 UART. */
+void uart_bitbang_tx_byte(unsigned char data, void (*set_tx)(int line_state))
+{
+	const int baud_rate = get_uart_baudrate();
+	int i;
+	struct stopwatch sw;
+	stopwatch_init(&sw);
+
+	/* Send start bit */
+	set_tx(0);
+	while (stopwatch_duration_usecs(&sw) < MHz / baud_rate)
+		stopwatch_tick(&sw);
+
+	/* 'i' counts the total bits sent at the end of the loop */
+	for (i = 2; i < 10; i++) {
+		set_tx(data & 1);
+		data >>= 1;
+		while (stopwatch_duration_usecs(&sw) < i * MHz / baud_rate)
+			stopwatch_tick(&sw);
+	}
+
+	/* Send stop bit */
+	set_tx(1);
+	while (stopwatch_duration_usecs(&sw) < i * MHz / baud_rate)
+		stopwatch_tick(&sw);
+}
diff --git a/src/include/console/uart.h b/src/include/console/uart.h
index 3bd390e..2e9c7b8 100644
--- a/src/include/console/uart.h
+++ b/src/include/console/uart.h
@@ -46,6 +46,9 @@
  */
 unsigned int uart_input_clock_divider(void);
 
+/* Bitbang out one byte on an 8n1 UART through the output function set_tx(). */
+void uart_bitbang_tx_byte(unsigned char data, void (*set_tx)(int line_state));
+
 void uart_init(int idx);
 void uart_tx_byte(int idx, unsigned char data);
 void uart_tx_flush(int idx);

-- 
To view, visit https://review.coreboot.org/25812
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: If7dcecc7b8a95ec15f456efd2ec1f1e0dde239b4
Gerrit-Change-Number: 25812
Gerrit-PatchSet: 1
Gerrit-Owner: Julius Werner <jwerner at chromium.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180424/f4e0f53a/attachment-0001.html>


More information about the coreboot-gerrit mailing list