summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/mediatek/common/include/soc/lastbus_v1.h (renamed from src/soc/mediatek/common/include/soc/lastbus.h)4
-rw-r--r--src/soc/mediatek/common/include/soc/lastbus_v2.h40
-rw-r--r--src/soc/mediatek/common/lastbus_v1.c (renamed from src/soc/mediatek/common/lastbus.c)2
-rw-r--r--src/soc/mediatek/common/lastbus_v2.c112
-rw-r--r--src/soc/mediatek/mt8186/Makefile.inc2
-rw-r--r--src/soc/mediatek/mt8186/bootblock.c2
-rw-r--r--src/soc/mediatek/mt8188/Makefile.inc1
-rw-r--r--src/soc/mediatek/mt8188/bootblock.c2
-rw-r--r--src/soc/mediatek/mt8188/include/soc/addressmap.h6
-rw-r--r--src/soc/mediatek/mt8188/lastbus.c79
10 files changed, 245 insertions, 5 deletions
diff --git a/src/soc/mediatek/common/include/soc/lastbus.h b/src/soc/mediatek/common/include/soc/lastbus_v1.h
index 3c93efbf60..bd6cd86776 100644
--- a/src/soc/mediatek/common/include/soc/lastbus.h
+++ b/src/soc/mediatek/common/include/soc/lastbus_v1.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef SOC_MEDIATEK_COMMON_LASTBUS_H
-#define SOC_MEDIATEK_COMMON_LASTBUS_H
+#ifndef SOC_MEDIATEK_COMMON_LASTBUS_V1_H
+#define SOC_MEDIATEK_COMMON_LASTBUS_V1_H
/* INFRA LASTBUS INFO */
#define BUS_INFRA_SNAPSHOT 0xd00
diff --git a/src/soc/mediatek/common/include/soc/lastbus_v2.h b/src/soc/mediatek/common/include/soc/lastbus_v2.h
new file mode 100644
index 0000000000..d58da76b57
--- /dev/null
+++ b/src/soc/mediatek/common/include/soc/lastbus_v2.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_MEDIATEK_COMMON_LASTBUS_V2_H
+#define SOC_MEDIATEK_COMMON_LASTBUS_V2_H
+
+#define NR_MAX_LASTBUS_IDLE_MASK 8
+#define NR_MAX_LASTBUS_MONITOR 16
+#define TIMEOUT_THRES_SHIFT 16
+#define TIMEOUT_TYPE_SHIFT 1
+#define LASTBUS_TIMEOUT_CLR 0x0200
+#define LASTBUS_DEBUG_CKEN 0x0008
+#define LASTBUS_DEBUG_EN 0x0004
+#define LASTBUS_TIMEOUT 0x0001
+
+struct lastbus_idle_mask {
+ u32 reg_offset;
+ u32 reg_value;
+};
+
+struct lastbus_monitor {
+ const char *name;
+ uintptr_t base;
+ size_t num_ports;
+ u16 bus_freq_mhz;
+ size_t num_idle_mask;
+ struct lastbus_idle_mask idle_masks[NR_MAX_LASTBUS_IDLE_MASK];
+};
+
+struct lastbus_config {
+ const char *latch_platform;
+ unsigned int timeout_ms;
+ unsigned int timeout_type;
+ unsigned int num_used_monitors;
+ struct lastbus_monitor monitors[NR_MAX_LASTBUS_MONITOR];
+};
+
+void lastbus_init(void);
+extern const struct lastbus_config lastbus_cfg;
+
+#endif
diff --git a/src/soc/mediatek/common/lastbus.c b/src/soc/mediatek/common/lastbus_v1.c
index cf4f8d1a42..cf3fb1db39 100644
--- a/src/soc/mediatek/common/lastbus.c
+++ b/src/soc/mediatek/common/lastbus_v1.c
@@ -3,7 +3,7 @@
#include <console/console.h>
#include <device/mmio.h>
#include <soc/addressmap.h>
-#include <soc/lastbus.h>
+#include <soc/lastbus_v1.h>
static unsigned long preisys_dump_offset[] = {
0x500, /* PERIBUS_DBG0 */
diff --git a/src/soc/mediatek/common/lastbus_v2.c b/src/soc/mediatek/common/lastbus_v2.c
new file mode 100644
index 0000000000..2893c5a72a
--- /dev/null
+++ b/src/soc/mediatek/common/lastbus_v2.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+#include <soc/lastbus_v2.h>
+#include <timer.h>
+
+#define SYS_TIMER_0_OFFSET 0x400
+#define SYS_TIMER_1_OFFSET 0x404
+#define DEBUG_RESULT_OFFSET 0x408
+
+static bool lastbus_is_timeout(const struct lastbus_monitor *m)
+{
+ return read32p(m->base) & LASTBUS_TIMEOUT;
+}
+
+static uint64_t gray_code_to_binary(uint64_t gray_code)
+{
+ uint64_t value = 0;
+ while (gray_code) {
+ value ^= gray_code;
+ gray_code >>= 1;
+ }
+ return value;
+}
+
+static void lastbus_dump_monitor(const struct lastbus_monitor *m)
+{
+ int i;
+ uint64_t gray_code, bin_code;
+
+ printk(BIOS_INFO, "--- %s %#lx %ld ---\n", m->name, m->base, m->num_ports);
+
+ for (i = 0; i < m->num_ports; i++)
+ printk(BIOS_INFO, "%08x\n",
+ read32p(m->base + DEBUG_RESULT_OFFSET + (i * 4)));
+
+ gray_code = (uint64_t)read32p(m->base + SYS_TIMER_1_OFFSET) << 32 |
+ read32p(m->base + SYS_TIMER_0_OFFSET);
+ bin_code = gray_code_to_binary(gray_code);
+ printk(BIOS_INFO, "\ntimestamp: %#llx\n", bin_code);
+}
+
+static void lastbus_dump(void)
+{
+ const struct lastbus_monitor *m;
+ bool found = false;
+ int i;
+
+ for (i = 0; i < lastbus_cfg.num_used_monitors; i++) {
+ m = &lastbus_cfg.monitors[i];
+ if (!lastbus_is_timeout(m))
+ continue;
+
+ if (!found)
+ printk(BIOS_INFO,
+ "\n******************* %s lastbus ******************\n",
+ lastbus_cfg.latch_platform);
+ found = true;
+ lastbus_dump_monitor(m);
+ }
+}
+
+static u16 calculate_timeout_thres(u16 bus_freq_mhz, u32 timeout_ms)
+{
+ u64 value;
+ value = ((u64)timeout_ms * USECS_PER_MSEC * bus_freq_mhz) >> 10;
+ if (value >= UINT16_MAX)
+ return UINT16_MAX - 1;
+ return value >= 1 ? value - 1 : 0;
+}
+
+static void lastbus_init_monitor(const struct lastbus_monitor *m,
+ u32 timeout_ms, u32 timeout_type)
+{
+ u16 timeout_thres;
+ int i;
+
+ for (i = 0; i < m->num_idle_mask; i++)
+ write32p(m->base + m->idle_masks[i].reg_offset,
+ m->idle_masks[i].reg_value);
+
+ /* clear timeout status with DBG_CKEN */
+ write32p(m->base, LASTBUS_TIMEOUT_CLR | LASTBUS_DEBUG_CKEN);
+ /* de-assert clear bit */
+ clrbits32p(m->base, LASTBUS_TIMEOUT_CLR);
+
+ if (timeout_ms == UINT32_MAX)
+ timeout_thres = 0xFFFF;
+ else
+ timeout_thres = calculate_timeout_thres(m->bus_freq_mhz, timeout_ms);
+
+ setbits32p(m->base, (timeout_thres << TIMEOUT_THRES_SHIFT) |
+ (timeout_type << TIMEOUT_TYPE_SHIFT));
+ setbits32p(m->base, LASTBUS_DEBUG_EN);
+}
+
+static void lastbus_setup(void)
+{
+ int i;
+
+ for (i = 0; i < lastbus_cfg.num_used_monitors; i++)
+ lastbus_init_monitor(&lastbus_cfg.monitors[i], lastbus_cfg.timeout_ms,
+ lastbus_cfg.timeout_type);
+}
+
+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 d03ea0e791..04d047acf1 100644
--- a/src/soc/mediatek/mt8186/Makefile.inc
+++ b/src/soc/mediatek/mt8186/Makefile.inc
@@ -14,7 +14,7 @@ all-y += ../common/uart.c
bootblock-y += bootblock.c
bootblock-y += ../common/eint_event.c
bootblock-y += gic.c
-bootblock-y += ../common/lastbus.c
+bootblock-y += ../common/lastbus_v1.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 9b12e562a1..d06b11113b 100644
--- a/src/soc/mediatek/mt8186/bootblock.c
+++ b/src/soc/mediatek/mt8186/bootblock.c
@@ -3,7 +3,7 @@
#include <bootblock_common.h>
#include <soc/eint_event.h>
#include <soc/gic.h>
-#include <soc/lastbus.h>
+#include <soc/lastbus_v1.h>
#include <soc/mmu_operations.h>
#include <soc/pll.h>
#include <soc/tracker_common.h>
diff --git a/src/soc/mediatek/mt8188/Makefile.inc b/src/soc/mediatek/mt8188/Makefile.inc
index 95df6dc1d9..651cff0d5a 100644
--- a/src/soc/mediatek/mt8188/Makefile.inc
+++ b/src/soc/mediatek/mt8188/Makefile.inc
@@ -11,6 +11,7 @@ all-y += ../common/uart.c
bootblock-y += bootblock.c
bootblock-y += ../common/eint_event.c
+bootblock-y += ../common/lastbus_v2.c lastbus.c
bootblock-y += ../common/mmu_operations.c
bootblock-y += ../common/tracker.c ../common/tracker_v2.c
bootblock-y += ../common/wdt.c ../common/wdt_req.c wdt.c
diff --git a/src/soc/mediatek/mt8188/bootblock.c b/src/soc/mediatek/mt8188/bootblock.c
index 32ef4af2e3..f7b7849b36 100644
--- a/src/soc/mediatek/mt8188/bootblock.c
+++ b/src/soc/mediatek/mt8188/bootblock.c
@@ -4,6 +4,7 @@
#include <soc/eint_event.h>
#include <soc/mmu_operations.h>
#include <soc/pll.h>
+#include <soc/lastbus_v2.h>
#include <soc/tracker_common.h>
#include <soc/wdt.h>
@@ -11,6 +12,7 @@ void bootblock_soc_init(void)
{
mtk_mmu_init();
bustracker_init();
+ lastbus_init();
mtk_wdt_init();
mt_pll_init();
unmask_eint_event_mask();
diff --git a/src/soc/mediatek/mt8188/include/soc/addressmap.h b/src/soc/mediatek/mt8188/include/soc/addressmap.h
index 63f059616f..74489764f9 100644
--- a/src/soc/mediatek/mt8188/include/soc/addressmap.h
+++ b/src/soc/mediatek/mt8188/include/soc/addressmap.h
@@ -27,14 +27,20 @@ enum {
APMIXED_BASE = IO_PHYS + 0x0000C000,
SYSTIMER_BASE = IO_PHYS + 0x00017000,
INFRACFG_AO_BCRM_BASE = IO_PHYS + 0x00022000,
+ INFRA_AO_DBUG_BASE = IO_PHYS + 0x00023000,
PMIF_SPI_BASE = IO_PHYS + 0x00024000,
PMICSPI_MST_BASE = IO_PHYS + 0x00025000,
PMIF_SPMI_BASE = IO_PHYS + 0x00027000,
+ INFRA2_AO_DBUG_BASE = IO_PHYS + 0x00028000,
SPMI_MST_BASE = IO_PHYS + 0x00029000,
+ PERI_AO_BASE = IO_PHYS + 0x0002B000,
+ PERI_AO2_BASE = IO_PHYS + 0x0002E000,
DEVAPC_INFRA_AO_BASE = IO_PHYS + 0x00030000,
DEVAPC_PERI_AO_BASE = IO_PHYS + 0x00034000,
DEVAPC_PERI2_AO_BASE = IO_PHYS + 0x00038000,
DEVAPC_PERI_PAR_AO_BASE = IO_PHYS + 0x0003C000,
+ PERI_PAR_AO_BASE = IO_PHYS + 0x00040000,
+ FMEM_AO_BASE = IO_PHYS + 0x00042000,
DBG_TRACKER_BASE = IO_PHYS + 0x00208000,
PERI_TRACKER_BASE = IO_PHYS + 0x00218000,
EMI0_BASE = IO_PHYS + 0x00219000,
diff --git a/src/soc/mediatek/mt8188/lastbus.c b/src/soc/mediatek/mt8188/lastbus.c
new file mode 100644
index 0000000000..f2c0b0d57f
--- /dev/null
+++ b/src/soc/mediatek/mt8188/lastbus.c
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+#include <soc/lastbus_v2.h>
+
+const struct lastbus_config lastbus_cfg = {
+ .latch_platform = "MT8188",
+ .timeout_ms = 200,
+ .timeout_type = 0,
+ .num_used_monitors = 6,
+ .monitors = {
+ {
+ .name = "debug_ctrl_ao_INFRA_AO",
+ .base = INFRA_AO_DBUG_BASE,
+ .num_ports = 34,
+ .num_idle_mask = 2,
+ .idle_masks = {
+ {
+ .reg_offset = 0x04,
+ .reg_value = 0x2,
+ },
+ {
+ .reg_offset = 0x08,
+ .reg_value = 0x10000,
+ },
+ },
+ .bus_freq_mhz = 78,
+ },
+ {
+ .name = "debug_ctrl_ao_INFRA2_AO",
+ .base = INFRA2_AO_DBUG_BASE,
+ .num_ports = 9,
+ .num_idle_mask = 0,
+ .bus_freq_mhz = 78,
+ },
+ {
+ .name = "debug_ctrl_ao_PERI_AO",
+ .base = PERI_AO_BASE,
+ .num_ports = 25,
+ .num_idle_mask = 1,
+ .idle_masks = {
+ {
+ .reg_offset = 0x04,
+ .reg_value = 0x20000,
+ },
+ },
+ .bus_freq_mhz = 78,
+ },
+ {
+ .name = "debug_ctrl_ao_PERI_AO2",
+ .base = PERI_AO2_BASE,
+ .num_ports = 20,
+ .num_idle_mask = 0,
+ .bus_freq_mhz = 78,
+ },
+ {
+ .name = "debug_ctrl_ao_PERI_PAR_AO",
+ .base = PERI_PAR_AO_BASE,
+ .num_ports = 18,
+ .num_idle_mask = 0,
+ .bus_freq_mhz = 78,
+ },
+ {
+ .name = "debug_ctrl_ao_FMEM_AO",
+ .base = FMEM_AO_BASE,
+ .num_ports = 28,
+ .num_idle_mask = 1,
+ .idle_masks = {
+ {
+ .reg_offset = 0x14,
+ .reg_value = 0x204,
+ },
+ },
+ .bus_freq_mhz = 78,
+ },
+ },
+};