diff --git a/soc/mediatek/mt8xxx/Kconfig.defconfig b/soc/mediatek/mt8xxx/Kconfig.defconfig index 415e8d2af57..d8ebe43c402 100644 --- a/soc/mediatek/mt8xxx/Kconfig.defconfig +++ b/soc/mediatek/mt8xxx/Kconfig.defconfig @@ -48,6 +48,15 @@ config MTK_ADSP_TIMER config XTENSA_TIMER default n +config CONSOLE + default y +config WINSTREAM_CONSOLE + default y +config WINSTREAM + default y +config LOG_BACKEND_ADSP + default y if LOG + config XTENSA_CCOUNT_HZ default 720000000 if SOC_MT8195 default 400000000 if SOC_MT8186 diff --git a/soc/mediatek/mt8xxx/mtk_adsp_load.py b/soc/mediatek/mt8xxx/mtk_adsp_load.py index 40db3436486..aa4b45f4b87 100755 --- a/soc/mediatek/mt8xxx/mtk_adsp_load.py +++ b/soc/mediatek/mt8xxx/mtk_adsp_load.py @@ -171,7 +171,7 @@ class MT8196: # stream at 0x60700000 -- the top of the linkable region of # existing SOF firmware, before the heap. Nothing uses this # currently. Will be replaced by winstream very soon. -def log(dev): +def old_log(dev): msg = b'' dram = maps["dram1"] for i in dev.logrange(): @@ -218,6 +218,93 @@ def le4(bstr): return struct.unpack(" 0x2000000 or (r.START >= r.WLEN) or (r.END >= r.WLEN): + raise RuntimeError("Invalid winstream") + self.regs = r + self.data = (ctypes.c_char * r.WLEN).from_address(addr + 16) + self.msg = bytearray(r.WLEN) + self.seq = 0 + + def read(self): + ws, msg, data = self.regs, self.msg, self.data + last_seq = self.seq + wlen = ws.WLEN + while True: + start, end, seq = ws.START, ws.END, ws.SEQ + self.seq = seq + if seq == last_seq or start == end: + return "" + behind = seq - last_seq + if behind > ((end - start) % wlen): + return "" + copy = (end - behind) % wlen + suffix = min(behind, wlen - copy) + for i in range(suffix): + msg[i] = data[copy + i][0] + msglen = suffix + l2 = behind - suffix + if l2 > 0: + for i in range(l2): + msg[msglen + i] = data[i][0] + msglen += l2 + if start == ws.START and seq == ws.SEQ: + return msg[0:msglen].decode("utf-8", "replace") + + +# Locates a winstream descriptor in the firmware via its 96-bit magic +# number and returns the address and size fields it finds there. +def find_winstream(maps): + magic = b'\x74\x5f\x6a\xd0\x79\xe2\x4f\x00\xcd\xb8\xbd\xf9' + for m in maps: + if "ram" in m: + magoff = maps[m].find(magic) + if magoff >= 0: + addr = le4(maps[m][magoff + 12 : magoff + 16]) + return addr + raise RuntimeError("Cannot find winstream descriptor in firmware runtime") + + +def winstream_localaddr(globaddr, mmio, maps): + for m in mmio: + off = globaddr - mmio[m][0] + if 0 <= off < mmio[m][1]: + return ctypes.addressof(ctypes.c_int.from_buffer(maps[m])) + off + raise RuntimeError("Winstream address not inside DSP memory") + + +def winstream_log(mmio, maps): + physaddr = find_winstream(maps) + regsbase = winstream_localaddr(physaddr, mmio, maps) + ws = Winstream(regsbase) + while True: + msg = ws.read() + if msg: + sys.stdout.write(msg) + sys.stdout.flush() + else: + time.sleep(0.1) + + def main(): dsp = detect() assert dsp @@ -272,14 +359,17 @@ def main(): for i in range(len(dram), mmio["dram1"][1]): maps["dram1"][i] = 0 dev.start(boot_vector) - log(dev) + winstream_log(mmio, maps) elif sys.argv[1] == "log": - log(dev) + winstream_log(mmio, maps) + + elif sys.argv[1] == "oldlog": + old_log(dev) elif sys.argv[1] == "mem": print("Memory Regions:") - for m in mmio.keys(): + for m in mmio: print(f" {m}: {mmio[m][1]} @ 0x{mmio[m][0]:08x}") elif sys.argv[1] == "dump": diff --git a/soc/mediatek/mt8xxx/soc.c b/soc/mediatek/mt8xxx/soc.c index aaf893953ff..2b375ccf395 100644 --- a/soc/mediatek/mt8xxx/soc.c +++ b/soc/mediatek/mt8xxx/soc.c @@ -251,6 +251,7 @@ static void enable_mpu(void) * dram clear and also set buf[0] to 0 manually (as it isn't affected * by device reset). */ +#ifndef CONFIG_WINSTREAM_CONSOLE int arch_printk_char_out(int c) { char volatile * const buf = (void *)LOG_BASE; @@ -263,6 +264,10 @@ int arch_printk_char_out(int c) } return 0; } +#endif + +/* Define this here as a simple uncached array, no special linkage requirements */ +__nocache char _winstream_console_buf[CONFIG_WINSTREAM_CONSOLE_STATIC_SIZE]; void c_boot(void) {