soc: boards: Add Mediatek MT8186 and MT8188 audio DSPs
These are very similar devices to mt8195, minimal changes needed beyond boilerplate configuration. In the process, this reworks the board/soc layout to be HWMv2 compliant, with "adsp" becoming a CPU cluster beneath the SOC. So the name of the boards to west become e.g. "mt8195/mt8195/adsp" (which can be shortened to "mt8195//adsp" if desired). Note that the cpuclk driver is not yet ported, it works only with 8195 (the clocking/power architecture seems similar between the parts, but the graph of wells and clocks is different and historically these have been three separate drivers in SOF). The biggest changes are in the image/loader scripts, which needed some rework for cross-device portability. Signed-off-by: Andy Ross <andyross@google.com>
This commit is contained in:
parent
cdd4cbcc67
commit
5364783ba1
39 changed files with 709 additions and 322 deletions
5
boards/mediatek/mt8186/Kconfig.mt8186
Normal file
5
boards/mediatek/mt8186/Kconfig.mt8186
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright 2024 The ChromiumOS Authors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_MT8186
|
||||
select SOC_MT8186
|
5
boards/mediatek/mt8186/board.yml
Normal file
5
boards/mediatek/mt8186/board.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
boards:
|
||||
- name: mt8186
|
||||
vendor: mediatek
|
||||
socs:
|
||||
- name: mt8186
|
80
boards/mediatek/mt8186/mt8186_adsp.dts
Normal file
80
boards/mediatek/mt8186/mt8186_adsp.dts
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* Copyright 2024 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <mem.h>
|
||||
|
||||
/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 { };
|
||||
};
|
5
boards/mediatek/mt8188/Kconfig.mt8188
Normal file
5
boards/mediatek/mt8188/Kconfig.mt8188
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright 2024 The ChromiumOS Authors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_MT8188
|
||||
select SOC_MT8188
|
5
boards/mediatek/mt8188/board.yml
Normal file
5
boards/mediatek/mt8188/board.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
boards:
|
||||
- name: mt8188
|
||||
vendor: mediatek
|
||||
socs:
|
||||
- name: mt8188
|
81
boards/mediatek/mt8188/mt8188_adsp.dts
Normal file
81
boards/mediatek/mt8188/mt8188_adsp.dts
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Copyright 2024 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <mem.h>
|
||||
|
||||
/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 { };
|
||||
};
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
boards:
|
||||
- name: mt8195_adsp
|
||||
- name: mt8195
|
||||
full_name: MT8195 ADSP
|
||||
vendor: mediatek
|
||||
socs:
|
||||
- name: mt8195_adsp
|
||||
- name: mt8195
|
94
boards/mediatek/mt8195/mt8195_adsp.dts
Normal file
94
boards/mediatek/mt8195/mt8195_adsp.dts
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* Copyright 2023 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <mem.h>
|
||||
|
||||
/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 { };
|
||||
};
|
|
@ -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
|
|
@ -1,95 +0,0 @@
|
|||
/* Copyright 2023 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <mem.h>
|
||||
|
||||
/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 { };
|
||||
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
# Copyright 2023 The ChromiumOS Authors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=13000000
|
|
@ -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 "")
|
||||
|
|
@ -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
|
|
@ -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
|
34
soc/mediatek/mt8xxx/Kconfig.soc
Normal file
34
soc/mediatek/mt8xxx/Kconfig.soc
Normal file
|
@ -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
|
|
@ -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("<III", FILE_MAGIC, len(sram), boot_vector))
|
|
@ -16,6 +16,7 @@ void intc_mtk_adsp_set_enable(const struct device *dev, int irq, bool val);
|
|||
*/
|
||||
static const struct device *irq_dev(unsigned int *irq_inout)
|
||||
{
|
||||
#ifdef CONFIG_SOC_SERIES_MT8195
|
||||
/* Controller 0 is on Xtensa vector 1, controller 1 on vector 23. */
|
||||
if ((*irq_inout & 0xff) == 1) {
|
||||
*irq_inout >>= 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)
|
|
@ -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 <zephyr/linker/llext-sections.ld>
|
||||
#endif
|
||||
|
||||
} /* SECTIONS */
|
|
@ -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 {
|
13
soc/mediatek/mt8xxx/mt8186/Kconfig.defconfig
Normal file
13
soc/mediatek/mt8xxx/mt8186/Kconfig.defconfig
Normal file
|
@ -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
|
5
soc/mediatek/mt8xxx/mt8186/linker.ld
Normal file
5
soc/mediatek/mt8xxx/mt8186/linker.ld
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* Copyright 2024 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "../linker.ld"
|
10
soc/mediatek/mt8xxx/mt8186/soc.h
Normal file
10
soc/mediatek/mt8xxx/mt8186/soc.h
Normal file
|
@ -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 */
|
12
soc/mediatek/mt8xxx/mt8188/Kconfig.defconfig
Normal file
12
soc/mediatek/mt8xxx/mt8188/Kconfig.defconfig
Normal file
|
@ -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
|
5
soc/mediatek/mt8xxx/mt8188/linker.ld
Normal file
5
soc/mediatek/mt8xxx/mt8188/linker.ld
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* Copyright 2024 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "../linker.ld"
|
10
soc/mediatek/mt8xxx/mt8188/soc.h
Normal file
10
soc/mediatek/mt8xxx/mt8188/soc.h
Normal file
|
@ -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 */
|
|
@ -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
|
5
soc/mediatek/mt8xxx/mt8195/linker.ld
Normal file
5
soc/mediatek/mt8xxx/mt8195/linker.ld
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* Copyright 2024 The ChromiumOS Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "../linker.ld"
|
10
soc/mediatek/mt8xxx/mt8195/soc.h
Normal file
10
soc/mediatek/mt8xxx/mt8195/soc.h
Normal file
|
@ -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 */
|
227
soc/mediatek/mt8xxx/mtk_adsp_load.py
Executable file
227
soc/mediatek/mt8xxx/mtk_adsp_load.py
Executable file
|
@ -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("<I", bstr)[0]
|
||||
|
||||
def main():
|
||||
dsp = detect()
|
||||
assert dsp
|
||||
|
||||
# Probe devicetree for mappable memory regions
|
||||
mmio = mappings()
|
||||
|
||||
# Open device and establish mappings
|
||||
devmem_fd = open("/dev/mem", "wb+")
|
||||
for mp in mmio:
|
||||
paddr = mmio[mp][0]
|
||||
mapsz = mmio[mp][1]
|
||||
mapsz = int((mapsz + 4095) / 4096) * 4096
|
||||
maps[mp] = mmap.mmap(devmem_fd.fileno(), mapsz, offset=paddr,
|
||||
flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE|mmap.PROT_READ)
|
||||
|
||||
if dsp == "mt8195":
|
||||
dev = MT8195(maps)
|
||||
elif dsp in ("mt8186", "mt8188"):
|
||||
dev = MT818x(maps)
|
||||
|
||||
if sys.argv[1] == "load":
|
||||
dat = open(sys.argv[2], "rb").read()
|
||||
assert le4(dat[0:4])== FILE_MAGIC
|
||||
sram_len = le4(dat[4:8])
|
||||
boot_vector = le4(dat[8:12])
|
||||
sram = dat[12:12+sram_len]
|
||||
dram = dat[12 + sram_len:]
|
||||
assert len(sram) <= mmio["sram"][1]
|
||||
assert len(dram) <= mmio["dram1"][1]
|
||||
|
||||
# Stop the device and write the regions. Note that we don't
|
||||
# zero-fill SRAM, as that's been observed to reboot the host
|
||||
# (!!) on mt8186 when the writes near the end of the 512k
|
||||
# region.
|
||||
# pylint: disable=consider-using-enumerate
|
||||
for i in range(sram_len):
|
||||
maps["sram"][i] = sram[i]
|
||||
#for i in range(sram_len, mmio["sram"][1]):
|
||||
# maps["sram"][i] = 0
|
||||
for i in range(len(dram)):
|
||||
maps["dram1"][i] = dram[i]
|
||||
for i in range(len(dram), mmio["dram1"][1]):
|
||||
maps["dram1"][i] = 0
|
||||
dev.start(boot_vector)
|
||||
log()
|
||||
|
||||
elif sys.argv[1] == "log":
|
||||
log()
|
||||
|
||||
elif sys.argv[1] == "dump":
|
||||
sz = mmio[sys.argv[2]][1]
|
||||
mm = maps[sys.argv[2]]
|
||||
sys.stdout.buffer.write(mm[0:sz])
|
||||
|
||||
else:
|
||||
print(f"Usage: {sys.argv[0]} log | load <file>")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -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
|
|
@ -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 <zephyr/device.h>
|
||||
|
||||
|
@ -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 */
|
16
soc/mediatek/mt8xxx/soc.yml
Normal file
16
soc/mediatek/mt8xxx/soc.yml
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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("<I", bstr)[0]
|
||||
|
||||
def main():
|
||||
# Open device and establish mappings
|
||||
devmem_fd = open("/dev/mem", "wb+")
|
||||
for mp in MAPPINGS:
|
||||
paddr = MAPPINGS[mp][0]
|
||||
mapsz = MAPPINGS[mp][1]
|
||||
maps[mp] = mmap.mmap(devmem_fd.fileno(), mapsz, offset=paddr,
|
||||
flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE|mmap.PROT_READ)
|
||||
|
||||
# Create a Regs object for the registers
|
||||
cfg = Regs(ctypes.addressof(ctypes.c_int.from_buffer(maps["regs"])))
|
||||
cfg.ALTRESETVEC = 0x0004 # Xtensa boot address
|
||||
cfg.RESET_SW = 0x0024 # Xtensa halt/reset/boot control
|
||||
cfg.PDEBUGBUS0 = 0x000c # Unclear, enabled by host, unused by SOF?
|
||||
cfg.SRAM_POOL_CON = 0x0930 # SRAM power control: low 4 bits (banks?) enable
|
||||
cfg.EMI_MAP_ADDR = 0x981c # == host SRAM mapping - 0x40000000 (controls MMIO map?)
|
||||
cfg.freeze()
|
||||
|
||||
if sys.argv[1] == "load":
|
||||
dat = open(sys.argv[2], "rb").read()
|
||||
assert le4(dat[0:4])== FILE_MAGIC
|
||||
sram_len = le4(dat[4:8])
|
||||
boot_vector = le4(dat[8:12])
|
||||
sram = dat[12:12+sram_len]
|
||||
dram = dat[12 + sram_len:]
|
||||
assert len(sram) <= MAPPINGS["sram"][1]
|
||||
assert len(dram) <= MAPPINGS["dram"][1]
|
||||
for i in range(sram_len):
|
||||
maps["sram"][i] = sram[i]
|
||||
for i in range(sram_len, MAPPINGS["sram"][1]):
|
||||
maps["sram"][i] = 0
|
||||
for i in range(len(dram)):
|
||||
maps["dram"][i] = dram[i]
|
||||
for i in range(len(dram), MAPPINGS["dram"][1]):
|
||||
maps["dram"][i] = 0
|
||||
start(cfg, boot_vector)
|
||||
|
||||
elif sys.argv[1] == "log":
|
||||
log()
|
||||
|
||||
else:
|
||||
print(f"Usage: {sys.argv[0]} log | load <file>")
|
||||
|
||||
# (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()
|
|
@ -1,6 +0,0 @@
|
|||
family:
|
||||
- name: mtk_adsp
|
||||
series:
|
||||
- name: mtk_adsp
|
||||
socs:
|
||||
- name: mt8195_adsp
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue