soc/mediatek/mt8186: Enable lastbus debug hardware

Lastbus is a bus debug tool. When the bus hangs, the bus transmission
information before resetting will be recorded.

The watchdog cannot clear it and it will be printed out for bus hanging
analysis.

TEST=build pass.
BUG=none

Signed-off-by: ot_zhenguo.li <ot_zhenguo.li@mediatek.corp-partner.google.com>
Change-Id: Iff39486dfad556a3104b2f2b6811c34c2ded6954
Reviewed-on: https://review.coreboot.org/c/coreboot/+/67437
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yidi Lin <yidilin@google.com>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
diff --git a/src/soc/mediatek/common/include/soc/lastbus.h b/src/soc/mediatek/common/include/soc/lastbus.h
new file mode 100644
index 0000000..3c93efb
--- /dev/null
+++ b/src/soc/mediatek/common/include/soc/lastbus.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_MEDIATEK_COMMON_LASTBUS_H
+#define SOC_MEDIATEK_COMMON_LASTBUS_H
+
+/* INFRA LASTBUS INFO */
+#define BUS_INFRA_SNAPSHOT	0xd00
+#define BUS_INFRA_CTRL		0xd04
+#define INFRASYS_CONFIG		0xffff000c
+#define INFRA_NUM		17
+
+/* PERI LASTBUS INFO */
+#define BUS_PERI_R0		0x500
+#define BUS_PERI_R1		0x504
+#define PERISYS_ENABLE		0xc
+#define PERISYS_TIMEOUT		0xffff
+#define PERI_NUM		18
+
+void lastbus_init(void);
+
+#endif
diff --git a/src/soc/mediatek/common/lastbus.c b/src/soc/mediatek/common/lastbus.c
new file mode 100644
index 0000000..cf4f8d1
--- /dev/null
+++ b/src/soc/mediatek/common/lastbus.c
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+#include <soc/lastbus.h>
+
+static unsigned long preisys_dump_offset[] = {
+	0x500, /* PERIBUS_DBG0 */
+	0x504, /* PERIBUS_DBG1 */
+	0x508, /* PERIBUS_DBG2 */
+	0x50C, /* PERIBUS_DBG3 */
+	0x510, /* PERIBUS_DBG4 */
+	0x514, /* PERIBUS_DBG5 */
+	0x518, /* PERIBUS_DBG6 */
+	0x51C, /* PERIBUS_DBG7 */
+	0x520, /* PERIBUS_DBG8 */
+	0x524, /* PERIBUS_DBG9 */
+	0x528, /* PERIBUS_DBG10 */
+	0x52C, /* PERIBUS_DBG11 */
+	0x530, /* PERIBUS_DBG12 */
+	0x534, /* PERIBUS_DBG13 */
+	0x538, /* PERIBUS_DBG14 */
+	0x53C, /* PERIBUS_DBG15 */
+	0x580, /* PERIBUS_DBG16 */
+	0x584, /* PERIBUS_DBG17 */
+};
+
+static void lastbus_setup(void)
+{
+	/* peri lastbus init */
+	write32p(PERICFG_BASE + BUS_PERI_R0, PERISYS_TIMEOUT);
+	write32p(PERICFG_BASE + BUS_PERI_R1, PERISYS_ENABLE);
+
+	/* infra lastbus init */
+	write32p(INFRACFG_AO_BASE + BUS_INFRA_CTRL, INFRASYS_CONFIG);
+}
+
+static void lastbus_dump(void)
+{
+	unsigned int i;
+	uintptr_t reg;
+
+	if (read32p(INFRACFG_AO_BASE + BUS_INFRA_CTRL) & 0x1) {
+		printk(BIOS_DEBUG, "** Dump lastbus infra debug registers start **\n");
+		for (i = 0; i < INFRA_NUM; i++) {
+			reg = INFRACFG_AO_BASE + BUS_INFRA_SNAPSHOT + 4 * i;
+			printk(BIOS_DEBUG, "%08x\n", read32p(reg));
+		}
+	}
+
+	if (read32p(PERICFG_BASE + BUS_PERI_R1) & 0x1) {
+		printk(BIOS_DEBUG, "** Dump lastbus peri debug registers start **\n");
+		for (i = 0; i < PERI_NUM; i++) {
+			reg = PERICFG_BASE + preisys_dump_offset[i];
+			printk(BIOS_DEBUG, "%08x\n", read32p(reg));
+		}
+	}
+}
+
+void lastbus_init(void)
+{
+	lastbus_dump();
+	lastbus_setup();
+}
diff --git a/src/soc/mediatek/mt8186/Makefile.inc b/src/soc/mediatek/mt8186/Makefile.inc
index bd1e560..724f80f 100644
--- a/src/soc/mediatek/mt8186/Makefile.inc
+++ b/src/soc/mediatek/mt8186/Makefile.inc
@@ -12,6 +12,7 @@
 bootblock-y += bootblock.c
 bootblock-y += ../common/eint_event.c
 bootblock-y += gic.c
+bootblock-y += ../common/lastbus.c
 bootblock-y += ../common/mmu_operations.c
 bootblock-y += ../common/tracker.c ../common/tracker_v1.c
 bootblock-y += ../common/wdt.c ../common/wdt_req.c wdt.c
diff --git a/src/soc/mediatek/mt8186/bootblock.c b/src/soc/mediatek/mt8186/bootblock.c
index e5d1e73..9b12e56 100644
--- a/src/soc/mediatek/mt8186/bootblock.c
+++ b/src/soc/mediatek/mt8186/bootblock.c
@@ -3,6 +3,7 @@
 #include <bootblock_common.h>
 #include <soc/eint_event.h>
 #include <soc/gic.h>
+#include <soc/lastbus.h>
 #include <soc/mmu_operations.h>
 #include <soc/pll.h>
 #include <soc/tracker_common.h>
@@ -12,6 +13,7 @@
 {
 	mtk_mmu_init();
 	bustracker_init();
+	lastbus_init();
 	mtk_wdt_init();
 	mt_pll_init();
 	unmask_eint_event_mask();