diff --git a/boards/mediatek/mt8186/Kconfig.mt8186 b/boards/mediatek/mt8186/Kconfig.mt8186 new file mode 100644 index 00000000000..9b54fdd9f62 --- /dev/null +++ b/boards/mediatek/mt8186/Kconfig.mt8186 @@ -0,0 +1,5 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MT8186 + select SOC_MT8186 diff --git a/boards/mediatek/mt8186/board.yml b/boards/mediatek/mt8186/board.yml new file mode 100644 index 00000000000..04582e157f7 --- /dev/null +++ b/boards/mediatek/mt8186/board.yml @@ -0,0 +1,5 @@ +boards: + - name: mt8186 + vendor: mediatek + socs: + - name: mt8186 diff --git a/boards/mediatek/mt8186/mt8186_adsp.dts b/boards/mediatek/mt8186/mt8186_adsp.dts new file mode 100644 index 00000000000..a04aac1ffbf --- /dev/null +++ b/boards/mediatek/mt8186/mt8186_adsp.dts @@ -0,0 +1,80 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@4e100000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x4e100000 DT_SIZE_K(1024)>; + }; + + dram0: memory@60000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x60000000 DT_SIZE_M(16)>; + }; + + dram1: memory@61000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x61000000 DT_SIZE_K(1024)>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0 4>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + intc2: intc@10680010 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x10680010 4>; + status-reg = <0x10680050>; + interrupts = <2 0 0>; + mask = <0x3f>; + interrupt-parent = <&core_intc>; + }; + + ostimer64: ostimer64@10683080 { + compatible = "mediatek,ostimer64"; + reg = <0x10683080 28>; + }; + + ostimer0: ostimer@10683000 { + compatible = "mediatek,ostimer"; + reg = <0x10683000 16>; + interrupt-parent = <&core_intc>; + interrupts = <18 0 0>; + }; + + mbox0: mbox@10686100 { + compatible = "mediatek,mbox"; + reg = <0x10686100 16>; + interrupt-parent = <&intc2>; + interrupts = <1 0 0>; + }; + + mbox1: mbox@10687100 { + compatible = "mediatek,mbox"; + reg = <0x10687100 16>; + interrupt-parent = <&intc2>; + interrupts = <2 0 0>; + }; + }; /* soc */ + + chosen { }; + aliases { }; +}; diff --git a/boards/mediatek/mt8188/Kconfig.mt8188 b/boards/mediatek/mt8188/Kconfig.mt8188 new file mode 100644 index 00000000000..cc549945b91 --- /dev/null +++ b/boards/mediatek/mt8188/Kconfig.mt8188 @@ -0,0 +1,5 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MT8188 + select SOC_MT8188 diff --git a/boards/mediatek/mt8188/board.yml b/boards/mediatek/mt8188/board.yml new file mode 100644 index 00000000000..f50e9227a82 --- /dev/null +++ b/boards/mediatek/mt8188/board.yml @@ -0,0 +1,5 @@ +boards: + - name: mt8188 + vendor: mediatek + socs: + - name: mt8188 diff --git a/boards/mediatek/mt8188/mt8188_adsp.dts b/boards/mediatek/mt8188/mt8188_adsp.dts new file mode 100644 index 00000000000..1796bb7f447 --- /dev/null +++ b/boards/mediatek/mt8188/mt8188_adsp.dts @@ -0,0 +1,81 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/dts-v1/; +/ { + + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@4e100000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x4e100000 DT_SIZE_K(512)>; + }; + + dram0: memory@60000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x60000000 DT_SIZE_M(15)>; + }; + + dram1: memory@61000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x61000000 DT_SIZE_K(1024)>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0 4>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + intc2: intc@10b80010 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x10b80010 4>; + status-reg = <0x10b80050>; + interrupts = <2 0 0>; + mask = <0x3f>; + interrupt-parent = <&core_intc>; + }; + + ostimer64: ostimer64@10b83080 { + compatible = "mediatek,ostimer64"; + reg = <0x10b83080 28>; + }; + + ostimer0: ostimer@10b83000 { + compatible = "mediatek,ostimer"; + reg = <0x10b83000 16>; + interrupt-parent = <&core_intc>; + interrupts = <18 0 0>; + }; + + mbox0: mbox@10b86100 { + compatible = "mediatek,mbox"; + reg = <0x10b86100 16>; + interrupt-parent = <&intc2>; + interrupts = <1 0 0>; + }; + + mbox1: mbox@10b87100 { + compatible = "mediatek,mbox"; + reg = <0x10b87100 16>; + interrupt-parent = <&intc2>; + interrupts = <2 0 0>; + }; + }; /* soc */ + + chosen { }; + aliases { }; +}; diff --git a/boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp b/boards/mediatek/mt8195/Kconfig.mt8195 similarity index 71% rename from boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp rename to boards/mediatek/mt8195/Kconfig.mt8195 index 43a3a49f9e1..0fb211185c9 100644 --- a/boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp +++ b/boards/mediatek/mt8195/Kconfig.mt8195 @@ -1,7 +1,7 @@ # Copyright 2023 The ChromiumOS Authors # SPDX-License-Identifier: Apache-2.0 -config BOARD_MT8195_ADSP - select SOC_MT8195_ADSP +config BOARD_MT8195 + select SOC_MT8195 help Board with Mediatek MT8195 Audio DSP diff --git a/boards/mediatek/mt8195_adsp/board.yml b/boards/mediatek/mt8195/board.yml similarity index 57% rename from boards/mediatek/mt8195_adsp/board.yml rename to boards/mediatek/mt8195/board.yml index a58b33ecf8d..7a9bb707c1d 100644 --- a/boards/mediatek/mt8195_adsp/board.yml +++ b/boards/mediatek/mt8195/board.yml @@ -1,6 +1,6 @@ boards: - - name: mt8195_adsp + - name: mt8195 full_name: MT8195 ADSP vendor: mediatek socs: - - name: mt8195_adsp + - name: mt8195 diff --git a/boards/mediatek/mt8195/mt8195_adsp.dts b/boards/mediatek/mt8195/mt8195_adsp.dts new file mode 100644 index 00000000000..a21d81693fa --- /dev/null +++ b/boards/mediatek/mt8195/mt8195_adsp.dts @@ -0,0 +1,94 @@ +/* Copyright 2023 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/dts-v1/; +/ { + + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@40000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x40000000 DT_SIZE_K(256)>; + }; + + dram0: memory@60000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x60000000 DT_SIZE_M(17)>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + cpuclk: cpuclk@10000000 { + compatible = "mediatek,mt8195_cpuclk"; + reg = <0x10000000 380>; + cg_reg = <0x10720180>; + pll_ctrl_reg = <0x1000c7e0>; + freqs_mhz = <26 370 540 720>; + }; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0 4>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + intc1: intc@10680130 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x10680130 4>; + status-reg = <0x10680150>; + interrupts = <1 0 0>; + mask = <0x3ffffff0>; + interrupt-parent = <&core_intc>; + }; + + intc23: intc@108030f4 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x108030f4 4>; + status-reg = <0x108030fc>; + interrupts = <23 0 0>; + mask = <0xffff>; + interrupt-parent = <&core_intc>; + }; + + ostimer64: ostimer64@1080d080 { + compatible = "mediatek,ostimer64"; + reg = <0x1080d080 28>; + }; + + ostimer0: ostimer@1080d000 { + compatible = "mediatek,ostimer"; + reg = <0x1080d000 16>; + interrupt-parent = <&intc23>; + interrupts = <11 0 0>; + }; + + mbox0: mbox@10816000 { + compatible = "mediatek,mbox"; + reg = <0x10816000 56>; + interrupt-parent = <&intc23>; + interrupts = <0 0 0>; + }; + + mbox1: mbox@10817000 { + compatible = "mediatek,mbox"; + reg = <0x10817000 56>; + interrupt-parent = <&intc23>; + interrupts = <1 0 0>; + }; + }; /* soc */ + + chosen { }; + aliases { }; +}; diff --git a/boards/mediatek/mt8195_adsp/Kconfig.defconfig b/boards/mediatek/mt8195_adsp/Kconfig.defconfig deleted file mode 100644 index 31f557670b1..00000000000 --- a/boards/mediatek/mt8195_adsp/Kconfig.defconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2023 The ChromiumOS Authors -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MT8195_ADSP - -config BOARD - default "mt8195_adsp" - -endif # BOARD_MT8195_ADSP diff --git a/boards/mediatek/mt8195_adsp/mt8195_adsp.dts b/boards/mediatek/mt8195_adsp/mt8195_adsp.dts deleted file mode 100644 index c26e2dd0f40..00000000000 --- a/boards/mediatek/mt8195_adsp/mt8195_adsp.dts +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright 2023 The ChromiumOS Authors - * SPDX-License-Identifier: Apache-2.0 - */ -#include - -/dts-v1/; -/ { - -#address-cells = <1>; -#size-cells = <1>; - -sram0: memory@40000000 { - device_type = "memory"; - compatible = "mmio-sram"; - reg = <0x40000000 DT_SIZE_K(256)>; -}; - -dram0: memory@60000000 { - device_type = "memory"; - compatible = "mmio-sram"; - reg = <0x60000000 DT_SIZE_M(17)>; -}; - -soc { - #address-cells = <1>; - #size-cells = <1>; - - cpuclk: cpuclk@10000000 { - compatible = "mediatek,mt8195_cpuclk"; - reg = <0x10000000 380>; - cg_reg = <0x10720180>; - pll_ctrl_reg = <0x1000c7e0>; - freqs_mhz = <26 370 540 720>; - }; - - core_intc: core_intc@0 { - compatible = "cdns,xtensa-core-intc"; - reg = <0 4>; - interrupt-controller; - #interrupt-cells = <3>; - }; - - intc1: intc@10680130 { - compatible = "mediatek,adsp_intc"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <0x10680130 4>; - status-reg = <0x10680150>; - interrupts = <1 0 0>; - mask = <0x3ffffff0>; - interrupt-parent = <&core_intc>; - }; - - intc23: intc@108030f4 { - compatible = "mediatek,adsp_intc"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <0x108030f4 4>; - status-reg = <0x108030fc>; - interrupts = <23 0 0>; - mask = <0xffff>; - interrupt-parent = <&core_intc>; - }; - - ostimer64: ostimer64@1080d080 { - compatible = "mediatek,ostimer64"; - reg = <0x1080d080 28>; - }; - - ostimer0: ostimer@1080d000 { - compatible = "mediatek,ostimer"; - reg = <0x1080d000 16>; - interrupt-parent = <&intc23>; - interrupts = <11 0 0>; - }; - - mbox0: mbox@10816000 { - compatible = "mediatek,mbox"; - reg = <0x10816000 56>; - interrupt-parent = <&intc23>; - interrupts = <0 0 0>; - }; - - mbox1: mbox@10817000 { - compatible = "mediatek,mbox"; - reg = <0x10817000 56>; - interrupt-parent = <&intc23>; - interrupts = <1 0 0>; - }; -}; /* soc */ - -chosen { }; -aliases { }; - -}; diff --git a/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig b/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig deleted file mode 100644 index 1110a4cfeb1..00000000000 --- a/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2023 The ChromiumOS Authors -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=13000000 diff --git a/soc/mediatek/mtk_adsp/CMakeLists.txt b/soc/mediatek/mt8xxx/CMakeLists.txt similarity index 78% rename from soc/mediatek/mtk_adsp/CMakeLists.txt rename to soc/mediatek/mt8xxx/CMakeLists.txt index fb2d3b5933d..96d0ae468b1 100644 --- a/soc/mediatek/mtk_adsp/CMakeLists.txt +++ b/soc/mediatek/mt8xxx/CMakeLists.txt @@ -1,7 +1,9 @@ # Copyright 2023 The ChromiumOS Authors # SPDX-License-Identifier: Apache-2.0 -zephyr_library_sources(soc.c irq.c cpuclk.c mbox.c) +zephyr_library_sources(soc.c irq.c mbox.c) + +zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_MT8195 cpuclk.c) set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_SOC}/linker.ld CACHE INTERNAL "") diff --git a/soc/mediatek/mtk_adsp/Kconfig b/soc/mediatek/mt8xxx/Kconfig similarity index 81% rename from soc/mediatek/mtk_adsp/Kconfig rename to soc/mediatek/mt8xxx/Kconfig index a2887dff328..87f4f24faec 100644 --- a/soc/mediatek/mtk_adsp/Kconfig +++ b/soc/mediatek/mt8xxx/Kconfig @@ -1,6 +1,6 @@ # Copyright 2024 The ChromiumOS Authors # SPDX-License-Identifier: Apache-2.0 -config SOC_FAMILY_MTK_ADSP +config SOC_FAMILY_MTK select XTENSA select XTENSA_GEN_HANDLERS diff --git a/soc/mediatek/mtk_adsp/Kconfig.defconfig b/soc/mediatek/mt8xxx/Kconfig.defconfig similarity index 76% rename from soc/mediatek/mtk_adsp/Kconfig.defconfig rename to soc/mediatek/mt8xxx/Kconfig.defconfig index b25781651b4..b2796b8889d 100644 --- a/soc/mediatek/mtk_adsp/Kconfig.defconfig +++ b/soc/mediatek/mt8xxx/Kconfig.defconfig @@ -3,7 +3,7 @@ orsource "*/Kconfig.defconfig" -if SOC_FAMILY_MTK_ADSP +if SOC_FAMILY_MTK config INTC_MTK_ADSP default y @@ -23,11 +23,22 @@ config MAX_IRQ_PER_AGGREGATOR config 2ND_LVL_ISR_TBL_OFFSET default 32 +# The 8186/8188 core has only one software interrupt that lives at +# level 2, underneath other hardware interrupts like timer, so it +# can't reliably do this. Unselect so the tests don't try to exercise +# it. +config IRQ_OFFLOAD_NESTED + default n if SOC_SERIES_MT818X + default y + config MTK_ADSP_TIMER default y config XTENSA_TIMER default n +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 13000000 + config MAIN_STACK_SIZE default 2048 @@ -48,7 +59,8 @@ config XTENSA_HAL default y config SOC_TOOLCHAIN_NAME - default "mtk_mt8195_adsp" + default "mtk_mt8195_adsp" if SOC_SERIES_MT8195 + default "mtk_mt818x_adsp" if SOC_SERIES_MT818X config XTENSA_RESET_VECTOR default n @@ -69,4 +81,4 @@ config GEN_SW_ISR_TABLE config GEN_IRQ_VECTOR_TABLE default n -endif # SOC_FAMILY_MTK_ADSP +endif # SOC_FAMILY_MTK diff --git a/soc/mediatek/mt8xxx/Kconfig.soc b/soc/mediatek/mt8xxx/Kconfig.soc new file mode 100644 index 00000000000..0b26f92abc7 --- /dev/null +++ b/soc/mediatek/mt8xxx/Kconfig.soc @@ -0,0 +1,34 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_MTK + bool + +config SOC_SERIES_MT8195 + bool + select SOC_FAMILY_MTK + help + Mediatek MT8195 Audio DSP + +config SOC_SERIES_MT818X + bool + select SOC_FAMILY_MTK + help + Mediatek MT818x Audio DSPs + +config SOC_MT8195 + bool + select SOC_SERIES_MT8195 + +config SOC_MT8186 + bool + select SOC_SERIES_MT818X + +config SOC_MT8188 + bool + select SOC_SERIES_MT818X + +config SOC + default "mt8195" if SOC_MT8195 + default "mt8186" if SOC_MT8186 + default "mt8188" if SOC_MT8188 diff --git a/soc/mediatek/mtk_adsp/cpuclk.c b/soc/mediatek/mt8xxx/cpuclk.c similarity index 100% rename from soc/mediatek/mtk_adsp/cpuclk.c rename to soc/mediatek/mt8xxx/cpuclk.c diff --git a/soc/mediatek/mtk_adsp/gen_img.py b/soc/mediatek/mt8xxx/gen_img.py similarity index 71% rename from soc/mediatek/mtk_adsp/gen_img.py rename to soc/mediatek/mt8xxx/gen_img.py index 5d14f5e9d13..b004ccfb7ba 100755 --- a/soc/mediatek/mtk_adsp/gen_img.py +++ b/soc/mediatek/mt8xxx/gen_img.py @@ -21,8 +21,6 @@ import elftools.elf.sections FILE_MAGIC = 0xe463be95 -SRAM_START = 0x40000000 -SRAM_END = 0x40040000 DRAM_START = 0x60000000 DRAM_END = 0x61100000 @@ -34,12 +32,31 @@ ef = elftools.elf.elffile.ELFFile(open(elf_file, "rb")) sram = bytearray() dram = bytearray() + +# Returns the offset of a segment within the sram region, or -1 if it +# doesn't appear to be SRAM. SRAM is mapped differently for different +# SOCs, but it's always a <=1M region in 0x4xxxxxxx. Just use what we +# get, but validate that it fits. +sram_block = 0 +def sram_off(addr): + global sram_block + if addr < 0x40000000 or addr >= 0x50000000: + return -1 + block = addr & ~0xfffff + assert sram_block in (0, block) + + sram_block = block + off = addr - sram_block + assert off < 0x100000 + return off + for seg in ef.iter_segments(): h = seg.header if h.p_type == "PT_LOAD": - if h.p_paddr in range(SRAM_START, SRAM_END): + soff = sram_off(h.p_paddr) + if soff >= 0: buf = sram - off = h.p_paddr - SRAM_START + off = soff elif h.p_paddr in range(DRAM_START, DRAM_END): buf = dram off = h.p_paddr - DRAM_START @@ -52,6 +69,7 @@ for seg in ef.iter_segments(): if end > len(buf): buf.extend(b'\x00' * (end - len(buf))) + # pylint: disable=consider-using-enumerate for i in range(len(dat)): buf[i + off] = dat[i] @@ -61,9 +79,8 @@ for sec in ef.iter_sections(): if sym.name == "mtk_adsp_boot_entry": boot_vector = sym.entry['st_value'] -assert len(sram) < SRAM_END - SRAM_START assert len(dram) < DRAM_END - DRAM_START -assert (SRAM_START <= boot_vector < SRAM_END) or (DRAM_START <= boot_vector < DRAM_END) +assert (sram_off(boot_vector) >= 0) or (DRAM_START <= boot_vector < DRAM_END) of = open(out_file, "wb") of.write(struct.pack(">= 8; @@ -24,6 +25,10 @@ static const struct device *irq_dev(unsigned int *irq_inout) __ASSERT_NO_MSG((*irq_inout & 0xff) == 23); *irq_inout = (*irq_inout >> 8) - 1; return DEVICE_DT_GET(DT_INST(1, mediatek_adsp_intc)); +#else + /* Only one on 818x */ + return DEVICE_DT_GET(DT_INST(0, mediatek_adsp_intc)); +#endif } void z_soc_irq_enable(unsigned int irq) diff --git a/soc/mediatek/mtk_adsp/mt8195_adsp/linker.ld b/soc/mediatek/mt8xxx/linker.ld similarity index 98% rename from soc/mediatek/mtk_adsp/mt8195_adsp/linker.ld rename to soc/mediatek/mt8xxx/linker.ld index b58b91e5dc9..faa58ec8763 100644 --- a/soc/mediatek/mtk_adsp/mt8195_adsp/linker.ld +++ b/soc/mediatek/mt8xxx/linker.ld @@ -1,4 +1,4 @@ -/* Copyright 2023 The ChromiumOS Authors +/* Copyright 2024 The ChromiumOS Authors * SPDX-License-Identifier: Apache-2.0 */ @@ -139,4 +139,5 @@ SECTIONS { #ifdef CONFIG_LLEXT #include #endif + } /* SECTIONS */ diff --git a/soc/mediatek/mtk_adsp/mbox.c b/soc/mediatek/mt8xxx/mbox.c similarity index 83% rename from soc/mediatek/mtk_adsp/mbox.c rename to soc/mediatek/mt8xxx/mbox.c index 70acbd24612..69fc7b08393 100644 --- a/soc/mediatek/mtk_adsp/mbox.c +++ b/soc/mediatek/mt8xxx/mbox.c @@ -28,20 +28,31 @@ * * In practice: The first device (mbox0) is for IPC commands in both * directions. The cmd register is written with a 1 ("IPI_OP_REQ") - * and the command is placed in shared DRAM. The message registers - * are ignored. The second device (mbox1) is for responses to IPC - * commands, writing a 2 (IPI_OP_RSP) to the command register. (Yes, - * this is redundant, and the actual value is ignored by the ISRs on - * both sides). + * and the command is placed in shared DRAM. + * + * Note that the 8195 has ten "msg" registers. These only exist on + * this version of the hardware, and act as uninspected r/w scratch + * registers to both the host and DSP, with no other behavior. They + * aren't used by the Linux kernel at all (which has a single driver + * for all these DSPs), so are described here for completeness but + * otherwise ignored. In practice they don't do anything that simple + * shared memory can't. */ struct mtk_mbox { +#ifdef SOC_SERIES_MT8195 uint32_t in_cmd; uint32_t in_cmd_clr; uint32_t in_msg[5]; uint32_t out_cmd; uint32_t out_cmd_clr; uint32_t out_msg[5]; +#else + uint32_t in_cmd; + uint32_t out_cmd; + uint32_t in_cmd_clr; + uint32_t out_cmd_clr; +#endif }; struct mbox_cfg { diff --git a/soc/mediatek/mt8xxx/mt8186/Kconfig.defconfig b/soc/mediatek/mt8xxx/mt8186/Kconfig.defconfig new file mode 100644 index 00000000000..763e0c2ddd0 --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8186/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MT8186 + +# FIXME: move this to 818x series code to share w/8188 +config NUM_2ND_LEVEL_AGGREGATORS + default 1 + +config 2ND_LVL_INTR_00_OFFSET + default 2 + +endif diff --git a/soc/mediatek/mt8xxx/mt8186/linker.ld b/soc/mediatek/mt8xxx/mt8186/linker.ld new file mode 100644 index 00000000000..3d086aecb1a --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8186/linker.ld @@ -0,0 +1,5 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../linker.ld" diff --git a/soc/mediatek/mt8xxx/mt8186/soc.h b/soc/mediatek/mt8xxx/mt8186/soc.h new file mode 100644 index 00000000000..5b5613517fb --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8186/soc.h @@ -0,0 +1,10 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_MT8186_SOC_H +#define ZEPHYR_SOC_MT8186_SOC_H + +#include "../soc.h" + +#endif /* ZEPHYR_SOC_MT8186_SOC_H */ diff --git a/soc/mediatek/mt8xxx/mt8188/Kconfig.defconfig b/soc/mediatek/mt8xxx/mt8188/Kconfig.defconfig new file mode 100644 index 00000000000..b79e1caac36 --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8188/Kconfig.defconfig @@ -0,0 +1,12 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MT8188 + +config NUM_2ND_LEVEL_AGGREGATORS + default 1 + +config 2ND_LVL_INTR_00_OFFSET + default 2 + +endif diff --git a/soc/mediatek/mt8xxx/mt8188/linker.ld b/soc/mediatek/mt8xxx/mt8188/linker.ld new file mode 100644 index 00000000000..3d086aecb1a --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8188/linker.ld @@ -0,0 +1,5 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../linker.ld" diff --git a/soc/mediatek/mt8xxx/mt8188/soc.h b/soc/mediatek/mt8xxx/mt8188/soc.h new file mode 100644 index 00000000000..381f5686c8f --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8188/soc.h @@ -0,0 +1,10 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_MT8188_SOC_H +#define ZEPHYR_SOC_MT8188_SOC_H + +#include "../soc.h" + +#endif /* ZEPHYR_SOC_MT8188_SOC_H */ diff --git a/soc/mediatek/mtk_adsp/mt8195_adsp/Kconfig.defconfig b/soc/mediatek/mt8xxx/mt8195/Kconfig.defconfig similarity index 78% rename from soc/mediatek/mtk_adsp/mt8195_adsp/Kconfig.defconfig rename to soc/mediatek/mt8xxx/mt8195/Kconfig.defconfig index e50e98f004c..15e030beb35 100644 --- a/soc/mediatek/mtk_adsp/mt8195_adsp/Kconfig.defconfig +++ b/soc/mediatek/mt8xxx/mt8195/Kconfig.defconfig @@ -1,7 +1,7 @@ # Copyright 2023 The ChromiumOS Authors # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_MT8195_ADSP +if SOC_SERIES_MT8195 config NUM_2ND_LEVEL_AGGREGATORS default 2 @@ -10,4 +10,4 @@ config 2ND_LVL_INTR_00_OFFSET config 2ND_LVL_INTR_01_OFFSET default 23 -endif # SOC_SERIES_MT8195_ADSP +endif # SOC_SERIES_MT8195 diff --git a/soc/mediatek/mt8xxx/mt8195/linker.ld b/soc/mediatek/mt8xxx/mt8195/linker.ld new file mode 100644 index 00000000000..3d086aecb1a --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8195/linker.ld @@ -0,0 +1,5 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../linker.ld" diff --git a/soc/mediatek/mt8xxx/mt8195/soc.h b/soc/mediatek/mt8xxx/mt8195/soc.h new file mode 100644 index 00000000000..cfd8c56ad5e --- /dev/null +++ b/soc/mediatek/mt8xxx/mt8195/soc.h @@ -0,0 +1,10 @@ +/* Copyright 2023 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_MT8195_SOC_H +#define ZEPHYR_SOC_MT8195_SOC_H + +#include "../soc.h" + +#endif /* ZEPHYR_SOC_MT8195_SOC_H */ diff --git a/soc/mediatek/mt8xxx/mtk_adsp_load.py b/soc/mediatek/mt8xxx/mtk_adsp_load.py new file mode 100755 index 00000000000..ebd22d4beeb --- /dev/null +++ b/soc/mediatek/mt8xxx/mtk_adsp_load.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 +import ctypes +import sys +import mmap +import time +import struct +from glob import glob +import re + +# MT8195 audio firmware load/debug gadget + +# Note that the hardware handling here is only partial: in practice +# the audio DSP depends on clock and power well devices whose drivers +# live elsewhere in the kernel. Those aren't duplicated here. Make +# sure the DSP has been started by a working kernel driver first. +# +# See gen_img.py for docs on the image format itself. The way this +# script works is to map the device memory regions and registers via +# /dev/mem and copy the two segments while resetting the DSP. +# +# In the kernel driver, the address/size values come from devicetree. +# But currently the MediaTek architecture is one kernel driver per SOC +# (i.e. the devicetree values in the kenrel source are tied to the +# specific SOC anyway), so it really doesn't matter and we hard-code +# the addresses for simplicity. +# +# (For future reference: in /proc/device-tree on current ChromeOS +# kernels, the host registers are a "cfg" platform resource on the +# "adsp@10803000" node. The sram is likewise the "sram" resource on +# that device node, and the two dram areas are "memory-region" +# phandles pointing to "adsp_mem_region" and "adsp_dma_mem_region" +# nodes under "/reserved-memory"). + +FILE_MAGIC = 0xe463be95 + +# Runtime mmap objects for each MAPPINGS entry +maps = {} + +# Returns a string (e.g. "mt8195", "mt8186", "mt8188") if a supported +# adsp is detected, or None if not +def detect(): + compat = readfile(glob("/proc/device-tree/**/adsp@*/compatible", + recursive=True)[0], "r") + m = re.match(r'.*(mt\d{4})-dsp', compat) + if m: + return m.group(1) + +# Parse devicetree to find the MMIO mappings: there is an "adsp" node +# (in various locations) with an array of named "reg" mappings. It +# also refers by reference to reserved-memory regions of system +# DRAM. Those don't have names, call them dram0/1 (dram1 is the main +# region to which code is linked, dram0 is presumably a dma pool but +# unused by current firmware). Returns a dict mapping name to a +# (addr, size) tuple. +def mappings(): + path = glob("/proc/device-tree/**/adsp@*/", recursive=True)[0] + rnames = readfile(path + "reg-names", "r").split('\0')[:-1] + regs = struct.unpack(f">{2 * len(rnames)}Q", readfile(path + "reg")) + maps = { n : (regs[2*i], regs[2*i+1]) for i, n in enumerate(rnames) } + for i, ph in enumerate(struct.unpack(">II", readfile(path + "memory-region"))): + for rmem in glob("/proc/device-tree/reserved-memory/*/"): + if struct.unpack(">I", readfile(rmem + "phandle"))[0] == ph: + (addr, sz) = struct.unpack(">QQ", readfile(rmem + "reg")) + maps[f"dram{i}"] = (addr, sz) + break + return maps + +# Register API for 8195 +class MT8195(): + def __init__(self, maps): + # Create a Regs object for the registers + r = Regs(ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"]))) + r.ALTRESETVEC = 0x0004 # Xtensa boot address + r.RESET_SW = 0x0024 # Xtensa halt/reset/boot control + r.PDEBUGBUS0 = 0x000c # Unclear, enabled by host, unused by SOF? + r.SRAM_POOL_CON = 0x0930 # SRAM power control: low 4 bits (banks?) enable + r.EMI_MAP_ADDR = 0x981c # == host SRAM mapping - 0x40000000 (controls MMIO map?) + r.freeze() + self.cfg = r + + def stop(self): + self.cfg.RESET_SW |= 8 # Set RUNSTALL: halt CPU + self.cfg.RESET_SW |= 3 # Set low two bits: "BRESET|DRESET" + + def start(self, boot_vector): + self.stop() + self.cfg.RESET_SW |= 0x10 # Enable "alternate reset" boot vector + self.cfg.ALTRESETVEC = boot_vector + self.cfg.RESET_SW &= ~3 # Release reset bits + self.cfg.RESET_SW &= ~8 # Clear RUNSTALL: go! + +# Register API for 8186/8188 +class MT818x(): + def __init__(self, maps): + # These have registers spread across two blocks + cfg_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"])) + sec_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["sec"])) + self.cfg = Regs(cfg_base) + self.cfg.SW_RSTN = 0x00 + self.cfg.IO_CONFIG = 0x0c + self.cfg.freeze() + self.sec = Regs(sec_base) + self.sec.ALTVEC_C0 = 0x04 + self.sec.ALTVECSEL = 0x0c + self.sec.freeze() + + def stop(self): + self.cfg.IO_CONFIG |= (1<<31) # Set RUNSTALL to stop core + time.sleep(0.1) + self.cfg.SW_RSTN |= 0x11 # Assert reset: SW_RSTN_C0|SW_DBG_RSTN_C0 + + # Note: 8186 and 8188 use different bits in ALTVECSEC, but + # it's safe to write both to enable the alternate boot vector + def start(self, boot_vector): + self.cfg.IO_CONFIG |= (1<<31) # Set RUNSTALL + self.sec.ALTVEC_C0 = boot_vector + self.sec.ALTVECSEL = 0x03 # Enable alternate vector + self.cfg.SW_RSTN |= 0x00000011 # Assert reset + self.cfg.SW_RSTN &= 0xffffffee # Release reset + self.cfg.IO_CONFIG &= 0x7fffffff # Clear RUNSTALL + +# Temporary logging protocol: watch the 1M null-terminated log +# 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(): + msg = b'' + dram = maps["dram1"] + for i in range(0x700000, 0x800000): + x = dram[i] + if x == 0: + sys.stdout.buffer.write(msg) + sys.stdout.buffer.flush() + msg = b'' + while x == 0: + time.sleep(0.1) + x = dram[i] + msg += x.to_bytes(1, "little") + sys.stdout.buffer.write(msg) + sys.stdout.buffer.flush() + +# (Cribbed from cavstool.py) +class Regs: + def __init__(self, base_addr): + vars(self)["base_addr"] = base_addr + vars(self)["ptrs"] = {} + vars(self)["frozen"] = False + def freeze(self): + vars(self)["frozen"] = True + def __setattr__(self, name, val): + if not self.frozen and name not in self.ptrs: + addr = self.base_addr + val + self.ptrs[name] = ctypes.c_uint32.from_address(addr) + else: + self.ptrs[name].value = val + def __getattr__(self, name): + return self.ptrs[name].value + +def readfile(f, mode="rb"): + return open(f, mode).read() + +def le4(bstr): + assert len(bstr) == 4 + return struct.unpack("") + +if __name__ == "__main__": + main() diff --git a/soc/mediatek/mtk_adsp/soc.c b/soc/mediatek/mt8xxx/soc.c similarity index 96% rename from soc/mediatek/mtk_adsp/soc.c rename to soc/mediatek/mt8xxx/soc.c index 83e8de52344..211e68d8427 100644 --- a/soc/mediatek/mtk_adsp/soc.c +++ b/soc/mediatek/mt8xxx/soc.c @@ -24,7 +24,9 @@ extern char _mtk_adsp_dram_end[]; * it lands and extract its address in the loader. This represents * the minimum amount of effort required to successfully call a C * function (and duplicates a few versions elsewhere in the tree: - * really this should move to the arch layer). + * really this should move to the arch layer). Note that the stack + * used is 15MB into the DRAM region and safe/unused by all devices. + * But really this should be z_interrupt_stacks[0]. */ __asm__(".align 4\n\t" ".global mtk_adsp_boot_entry\n\t" @@ -36,7 +38,7 @@ __asm__(".align 4\n\t" " movi a0, 1\n\t" " wsr a0, WINDOWSTART\n\t" " rsync\n\t" - " movi a1, 0x40040000\n\t" + " movi a1, 0x60e00000\n\t" " call4 c_boot\n\t"); /* Initial MPU configuration, needed to enable caching */ @@ -148,7 +150,9 @@ void c_boot(void) */ __asm__ volatile("wsr %0, VECBASE; rsync" :: "r"(&z_xtensa_vecbase)); +#ifdef CONFIG_SOC_SERIES_MT8195 mtk_adsp_cpu_freq_init(); +#endif /* Likewise, memory power is external to the device, and the * kernel SOF loader doesn't zero it, so zero our unlinked diff --git a/soc/mediatek/mtk_adsp/soc.h b/soc/mediatek/mt8xxx/soc.h similarity index 87% rename from soc/mediatek/mtk_adsp/soc.h rename to soc/mediatek/mt8xxx/soc.h index 5543efd46b6..6857547ea2a 100644 --- a/soc/mediatek/mtk_adsp/soc.h +++ b/soc/mediatek/mt8xxx/soc.h @@ -2,8 +2,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_SOC_MTK_ADSP_SOC_H -#define ZEPHYR_SOC_MTK_ADSP_SOC_H +#ifndef ZEPHYR_SOC_MTK_SOC_H +#define ZEPHYR_SOC_MTK_SOC_H #include @@ -26,4 +26,4 @@ void mtk_adsp_mbox_set_handler(const struct device *mbox, uint32_t chan, /* Signal an interrupt on the specified channel for the other side */ void mtk_adsp_mbox_signal(const struct device *mbox, uint32_t chan); -#endif /* ZEPHYR_SOC_MTK_ADSP_SOC_H */ +#endif /* ZEPHYR_SOC_MTK_SOC_H */ diff --git a/soc/mediatek/mt8xxx/soc.yml b/soc/mediatek/mt8xxx/soc.yml new file mode 100644 index 00000000000..2f8e56639bb --- /dev/null +++ b/soc/mediatek/mt8xxx/soc.yml @@ -0,0 +1,16 @@ +family: + - name: mt8xxx + series: + - name: mt8195 + socs: + - name: mt8195 + cpuclusters: + - name: adsp + - name: mt818x + socs: + - name: mt8186 + cpuclusters: + - name: adsp + - name: mt8188 + cpuclusters: + - name: adsp diff --git a/soc/mediatek/mtk_adsp/Kconfig.soc b/soc/mediatek/mtk_adsp/Kconfig.soc deleted file mode 100644 index 37e4f452287..00000000000 --- a/soc/mediatek/mtk_adsp/Kconfig.soc +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2024 The ChromiumOS Authors -# SPDX-License-Identifier: Apache-2.0 - -config SOC_FAMILY_MTK_ADSP - bool - help - Mediatek MT8xxx Series Audio DSPs - -config SOC_SERIES_MT8195_ADSP - bool - select SOC_FAMILY_MTK_ADSP - help - Mediatek MT8195 Audio DSP - -config SOC_MT8195_ADSP - bool - select SOC_SERIES_MT8195_ADSP - -config SOC_FAMILY - default "mtk_adsp" if SOC_FAMILY_MTK_ADSP - -config SOC_SERIES - default "mt8195_adsp" if SOC_SERIES_MT8195_ADSP - -config SOC - default "mt8195_adsp" if SOC_MT8195_ADSP diff --git a/soc/mediatek/mtk_adsp/mt8195_adsp/soc.h b/soc/mediatek/mtk_adsp/mt8195_adsp/soc.h deleted file mode 100644 index fc66e0e6582..00000000000 --- a/soc/mediatek/mtk_adsp/mt8195_adsp/soc.h +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright 2023 The ChromiumOS Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_MT8195_ADSP_SOC_H -#define ZEPHYR_SOC_MT8195_ADSP_SOC_H - -#include "../soc.h" - -#endif /* ZEPHYR_SOC_MT8195_ADSP_SOC_H */ diff --git a/soc/mediatek/mtk_adsp/mtk_adsp_load.py b/soc/mediatek/mtk_adsp/mtk_adsp_load.py deleted file mode 100755 index 461b9061e65..00000000000 --- a/soc/mediatek/mtk_adsp/mtk_adsp_load.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python -# Copyright 2023 The ChromiumOS Authors -# SPDX-License-Identifier: Apache-2.0 -import ctypes -import sys -import mmap -import time -import struct - -# MT8195 audio firmware load/debug gadget - -# Note that the hardware handling here is only partial: in practice -# the audio DSP depends on clock and power well devices whose drivers -# live elsewhere in the kernel. Those aren't duplicated here. Make -# sure the DSP has been started by a working kernel driver first. -# -# See gen_img.py for docs on the image format itself. The way this -# script works is to map the device memory regions and registers via -# /dev/mem and copy the two segments while resetting the DSP. -# -# In the kernel driver, the address/size values come from devicetree. -# But currently the MediaTek architecture is one kernel driver per SOC -# (i.e. the devicetree values in the kenrel source are tied to the -# specific SOC anyway), so it really doesn't matter and we hard-code -# the addresses for simplicity. -# -# (For future reference: in /proc/device-tree on current ChromeOS -# kernels, the host registers are a "cfg" platform resource on the -# "adsp@10803000" node. The sram is likewise the "sram" resource on -# that device node, and the two dram areas are "memory-region" -# phandles pointing to "adsp_mem_region" and "adsp_dma_mem_region" -# nodes under "/reserved-memory"). - -FILE_MAGIC = 0xe463be95 - -MAPPINGS = { "regs" : (0x10803000, 0xa000), - "sram" : (0x10840000, 0x40000), - "dram" : (0x60000000, 0x1000000) } - -# Runtime mmap objects for each MAPPINGS entry -maps = {} - -def stop(cfg): - cfg.RESET_SW |= 8 # Set RUNSTALL: halt CPU - cfg.RESET_SW |= 3 # Set low two bits: "BRESET|DRESET" - -def start(cfg, boot_vector): - stop(cfg) - - cfg.RESET_SW |= 0x10 # Enable "alternate reset" boot vector - cfg.ALTRESETVEC = boot_vector - - cfg.RESET_SW &= ~3 # Release reset bits - cfg.RESET_SW &= ~8 # Clear RUNSTALL: go! - -# Temporary logging protocol: watch the 1M null-terminated log -# 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(): - msg = b'' - dram = maps["dram"] - for i in range(0x700000, 0x800000): - x = dram[i] - if x == 0: - sys.stdout.buffer.write(msg) - sys.stdout.buffer.flush() - msg = b'' - while x == 0: - time.sleep(0.1) - x = dram[i] - msg += x.to_bytes(1, "little") - sys.stdout.buffer.write(msg) - sys.stdout.buffer.flush() - -def le4(bstr): - assert len(bstr) == 4 - return struct.unpack("") - -# (Cribbed from cavstool.py) -class Regs: - def __init__(self, base_addr): - vars(self)["base_addr"] = base_addr - vars(self)["ptrs"] = {} - vars(self)["frozen"] = False - def freeze(self): - vars(self)["frozen"] = True - def __setattr__(self, name, val): - if not self.frozen and name not in self.ptrs: - addr = self.base_addr + val - self.ptrs[name] = ctypes.c_uint32.from_address(addr) - else: - self.ptrs[name].value = val - def __getattr__(self, name): - return self.ptrs[name].value - -if __name__ == "__main__": - main() diff --git a/soc/mediatek/mtk_adsp/soc.yml b/soc/mediatek/mtk_adsp/soc.yml deleted file mode 100644 index c042b9bd2ae..00000000000 --- a/soc/mediatek/mtk_adsp/soc.yml +++ /dev/null @@ -1,6 +0,0 @@ -family: - - name: mtk_adsp - series: - - name: mtk_adsp - socs: - - name: mt8195_adsp diff --git a/tests/boards/mtk_adsp/src/main.c b/tests/boards/mtk_adsp/src/main.c index 487f8dd74c8..95efbffd47c 100644 --- a/tests/boards/mtk_adsp/src/main.c +++ b/tests/boards/mtk_adsp/src/main.c @@ -35,6 +35,7 @@ static uint32_t cpu_hz(void) ZTEST(mtk_adsp, cpu_freq) { +#ifdef CONFIG_SOC_SERIES_MT8195 int freqs[] = { 26, 370, 540, 720 }; for (int i = 0; i < ARRAY_SIZE(freqs); i++) { @@ -49,6 +50,9 @@ ZTEST(mtk_adsp, cpu_freq) zassert_true(err > 200); } +#else + (void)cpu_hz(); +#endif } #define MBOX0 DEVICE_DT_GET(DT_INST(0, mediatek_mbox)) @@ -71,9 +75,9 @@ static void mbox_fn(const struct device *mbox, void *arg) * on mbox1 after receiving a "command" on mbox0 (you can also see it * whine about the invalid IPC message in the kernel logs). * - * Note that there's a catch: SOF's "reply" comes after a timeout - * (it's an invalid command, afterall) which is 165 seconds! But the - * test does pass. + * Note that there's a catch: on older kernels, SOF's "reply" comes + * after a timeout (it's an invalid command, afterall) which is 165 + * seconds! But the test does pass. */ ZTEST(mtk_adsp, mbox) {