@@ -634,6 +634,14 @@ config SYS_STDIO_DEREGISTER
removed (for example a USB keyboard) then this option can be
enabled to ensure this is handled correctly.
+config BCM_ELOG
+ bool "Broadcom error logging support"
+ default n
+ help
+ Enables broadcom error logging support to be used with brcm
+ platforms, say Y to this option to enable the logging support.
+ If unsure, say N.
+
endmenu
menu "Logging"
@@ -95,6 +95,7 @@ else
obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o
endif
else
+obj-$(CONFIG_BCM_ELOG) += bcm_elog.o
obj-y += console.o
endif # CONFIG_SPL_BUILD
new file mode 100644
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Broadcom.
+ */
+
+#include <bcm_elog.h>
+
+/* Log one character */
+int log2ddr(const char ch)
+{
+ u32 offset, len;
+ uintptr_t base = BCM_ELOG_UBOOT_BASE;
+
+ offset = readl(base + BCM_ELOG_OFF_OFFSET);
+ len = readl(base + BCM_ELOG_LEN_OFFSET);
+ writeb(ch, base + offset);
+ offset++;
+
+ /* log buffer is now full and need to wrap around */
+ if (offset >= BCM_ELOG_UBOOT_SIZE)
+ offset = BCM_ELOG_HEADER_LEN;
+
+ /* only increment length when log buffer is not full */
+ if (len < BCM_ELOG_UBOOT_SIZE - BCM_ELOG_HEADER_LEN)
+ len++;
+
+ writel(offset, base + BCM_ELOG_OFF_OFFSET);
+ writel(len, base + BCM_ELOG_LEN_OFFSET);
+
+ return 0;
+}
+
+/* Routine to initialize error logging */
+void bcm_elog_init(uintptr_t base, uint32_t size)
+{
+ u32 val;
+
+ /*
+ * If a valid signature is found, it means logging is already
+ * initialize. In this case, we should not re-initialize the entry
+ * header in the designated memory
+ */
+ val = readl(base + BCM_ELOG_SIG_OFFSET);
+ if (val != BCM_ELOG_SIG_VAL) {
+ writel(base + BCM_ELOG_SIG_OFFSET, BCM_ELOG_SIG_VAL);
+ writel(base + BCM_ELOG_OFF_OFFSET, BCM_ELOG_HEADER_LEN);
+ writel(base + BCM_ELOG_LEN_OFFSET, 0);
+ }
+}
@@ -20,6 +20,10 @@
#include <env_internal.h>
#include <watchdog.h>
+#ifdef CONFIG_BCM_ELOG
+#include <bcm_elog.h>
+#endif
+
DECLARE_GLOBAL_DATA_PTR;
static int on_console(const char *name, const char *value, enum env_op op,
@@ -536,6 +540,9 @@ void putc(const char c)
if (!gd->have_console)
return pre_console_putc(c);
+#ifdef CONFIG_BCM_ELOG
+ log2ddr(c);
+#endif
if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */
fputc(stdout, c);
@@ -587,6 +594,17 @@ void puts(const char *s)
if (!gd->have_console)
return pre_console_puts(s);
+#ifdef CONFIG_BCM_ELOG
+ {
+ const char *tmp = s;
+
+ while (*tmp) {
+ int c = *tmp++;
+
+ log2ddr(c);
+ }
+ }
+#endif
if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */
fputs(stdout, s);
@@ -790,6 +808,10 @@ int console_init_f(void)
print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
+#ifdef CONFIG_BCM_ELOG
+ bcm_elog_init(BCM_ELOG_UBOOT_BASE, BCM_ELOG_UBOOT_SIZE);
+#endif
+
return 0;
}
@@ -15,6 +15,7 @@ CONFIG_LOGLEVEL=7
CONFIG_SILENT_CONSOLE=y
CONFIG_SILENT_U_BOOT_ONLY=y
# CONFIG_SILENT_CONSOLE_UPDATE_ON_SET is not set
+CONFIG_BCM_ELOG=y
CONFIG_SUPPORT_RAW_INITRD=y
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_HUSH_PARSER=y
@@ -46,11 +47,11 @@ CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550=y
-CONFIG_FAT_WRITE=y
CONFIG_TEE=y
CONFIG_OPTEE=y
# CONFIG_OPTEE_TA_AVB is not set
# CONFIG_WATCHDOG is not set
CONFIG_WDT=y
CONFIG_WDT_SP805=y
+CONFIG_FAT_WRITE=y
CONFIG_SPL_OF_LIBFDT=y
new file mode 100644
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 Broadcom.
+ *
+ */
+
+#ifndef __BCM_ELOG_H__
+#define __BCM_ELOG_H__
+
+#include <asm/io.h>
+#include <linux/types.h>
+
+/* Default AP error logging base address */
+#ifndef ELOG_AP_UART_LOG_BASE
+#define ELOG_AP_UART_LOG_BASE 0x8f110000
+#endif
+
+/* Reserve 16K to store error logs */
+#define BCM_ELOG_UBOOT_BASE ELOG_AP_UART_LOG_BASE
+#define BCM_ELOG_UBOOT_SIZE 0x4000
+
+/* error logging signature */
+#define BCM_ELOG_SIG_OFFSET 0x0000
+#define BCM_ELOG_SIG_VAL 0x75767971
+
+/* current logging offset that points to where new logs should be added */
+#define BCM_ELOG_OFF_OFFSET 0x0004
+
+/* current logging length (excluding header) */
+#define BCM_ELOG_LEN_OFFSET 0x0008
+
+#define BCM_ELOG_HEADER_LEN 12
+
+int log2ddr(const char ch);
+void bcm_elog_init(uintptr_t base, uint32_t size);
+
+#endif /* __BCM_ELOG_H__ */