tegra124: Add a test function which spams exclamation points on the UART.
This function spews characters on the console and, until we have a working
console, is an easy way to see whether the system boots to a particular point.
For some reason waiting for transmitter to be empty hangs, but transmitting
characters still works.
BUG=None
TEST=Enabled the function and saw the UART output.
BRANCH=None
Change-Id: I1622c8a58849f4b8bdcaa67500b81042d7346df4
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: https://chromium-review.googlesource.com/171030
Reviewed-by: Ronald Minnich <rminnich@chromium.org>
Commit-Queue: Gabe Black <gabeblack@chromium.org>
Tested-by: Gabe Black <gabeblack@chromium.org>
diff --git a/src/soc/nvidia/tegra124/bootblock.c b/src/soc/nvidia/tegra124/bootblock.c
index 97180a0..46997b9 100644
--- a/src/soc/nvidia/tegra124/bootblock.c
+++ b/src/soc/nvidia/tegra124/bootblock.c
@@ -18,14 +18,100 @@
*/
#include <arch/hlt.h>
+#include <arch/io.h>
#include <arch/stages.h>
#include <cbfs.h>
#include <console/console.h>
+#include <stdint.h>
+
+#define UART_TEST 0
+
+static uint8_t readr(int reg)
+{
+ return read8((void *)(0x70000000 + 0x6000 + 4 * reg));
+}
+
+static void writer(int reg, uint8_t val)
+{
+ write8(val, (void *)(0x70000000 + 0x6000 + 4 * reg));
+}
+
+static int test_func(void)
+{
+ unsigned divisor = 221;
+ int i;
+
+ /*
+ * On poweron, AVP clock source (also called system clock) is set to
+ * PLLP_out0 with frequency set at 1MHz. Before initializing PLLP, we
+ * need to move the system clock's source to CLK_M temporarily. And
+ * then switch it to PLLP_out4 (204MHz) at a later time.
+ */
+ write32((0 << 12) | (0 << 8) | (0 << 4) | (0 << 0) | (2 << 28),
+ (void *)(0x60006000 + 0x28));
+
+ // wait a little bit (nominally 2-3 us)
+ for (i = 0; i < 0x10000; i++)
+ __asm__ __volatile__("");
+
+ // Set function.
+ setbits_le32((void *)(0x70000000 + 0x3000 + 0x2e0), 3 << 0);
+ setbits_le32((void *)(0x70000000 + 0x3000 + 0x2e4), 3 << 0);
+
+ // Output.
+ clrbits_le32((void *)(0x70000000 + 0x3000 + 0x2e0), 1 << 5);
+ // Input.
+ setbits_le32((void *)(0x70000000 + 0x3000 + 0x2e4), 1 << 5);
+
+ // Disable tristate.
+ clrbits_le32((void *)(0x70000000 + 0x3000 + 0x2e0), 1 << 4);
+ clrbits_le32((void *)(0x70000000 + 0x3000 + 0x2e4), 1 << 4);
+
+ // Assert UART reset and enable clock.
+ setbits_le32((void *)(0x60006000 + 4 + 0), 1 << 6);
+
+ // Enable the clock.
+ setbits_le32((void *)(0x60006000 + 4 * 4 + 0), 1 << 6);
+
+ // Set the clock source.
+ clrbits_le32((void *)(0x60006000 + 0x100 + 4 * 0x1e), 3 << 30);
+
+ // wait a little bit (nominally 2us?)
+ for (i = 0; i < 0x10000; i++)
+ __asm__ __volatile__("");
+
+ // De-assert reset to UART.
+ clrbits_le32((void *)(0x60006000 + 4 + 0), 1 << 6);
+
+ // This is supposed to wait for the transmitter to be empty, but it
+ // never completes for some reason.
+ if (0)
+ while (!(readr(5) & 0x40));
+
+ writer(1, 0);
+ writer(3, 0x80 | 0x3);
+ writer(0, 0);
+ writer(1, 0);
+ writer(3, 0x3);
+ writer(2, 0x01 | 0x2 | 0x4);
+ writer(3, 0x80 | 0x3);
+ writer(0, divisor & 0xff);
+ writer(1, (divisor >> 8) & 0xff);
+ writer(3, 0x3);
+
+ for (;;) {
+ writer(0, '!');
+ }
+ return 0;
+}
void main(void)
{
void *entry;
+ if (UART_TEST)
+ test_func();
+
if (CONFIG_BOOTBLOCK_CONSOLE)
console_init();