From 9ab079b75720c329d67aacf92827448b80512c17 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Wed, 30 Oct 2024 11:06:05 -0700 Subject: [PATCH] boards/mediatek: Add mt8196_adsp Add Zephyr support for the Audio DSP on the MT8196 SOC. This is a very similar device to previous designs. Most of this patch is just DTS. The biggest delta is the more complicated second level interrupt controller, though it is still able to be represented using some vaguely clever DTS config over the older intc_mtk_adsp driver. Also the memory layout is slightly different, requiring a little indirection to set the initial boot stack address and log output buffer. And the timer "irq_ack" register bits moved. Signed-off-by: Andy Ross --- .../mediatek/mt8196_adsp/Kconfig.mt8196_adsp | 5 + boards/mediatek/mt8196_adsp/board.yml | 5 + boards/mediatek/mt8196_adsp/mt8196_adsp.dts | 109 ++++++++++++++++++ drivers/timer/mtk_adsp_timer.c | 5 + soc/mediatek/mtk_adsp/Kconfig.soc | 11 ++ soc/mediatek/mtk_adsp/irq.c | 10 ++ .../mtk_adsp/mt8196_adsp/Kconfig.defconfig | 18 +++ soc/mediatek/mtk_adsp/mt8196_adsp/linker.ld | 5 + soc/mediatek/mtk_adsp/mt8196_adsp/soc.h | 10 ++ soc/mediatek/mtk_adsp/soc.c | 21 +++- soc/mediatek/mtk_adsp/soc.yml | 3 + 11 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 boards/mediatek/mt8196_adsp/Kconfig.mt8196_adsp create mode 100644 boards/mediatek/mt8196_adsp/board.yml create mode 100644 boards/mediatek/mt8196_adsp/mt8196_adsp.dts create mode 100644 soc/mediatek/mtk_adsp/mt8196_adsp/Kconfig.defconfig create mode 100644 soc/mediatek/mtk_adsp/mt8196_adsp/linker.ld create mode 100644 soc/mediatek/mtk_adsp/mt8196_adsp/soc.h diff --git a/boards/mediatek/mt8196_adsp/Kconfig.mt8196_adsp b/boards/mediatek/mt8196_adsp/Kconfig.mt8196_adsp new file mode 100644 index 000000000000000..ad94da1428090ff --- /dev/null +++ b/boards/mediatek/mt8196_adsp/Kconfig.mt8196_adsp @@ -0,0 +1,5 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MT8196_ADSP + select SOC_MT8196_ADSP diff --git a/boards/mediatek/mt8196_adsp/board.yml b/boards/mediatek/mt8196_adsp/board.yml new file mode 100644 index 000000000000000..8d6c0cb9c6e23e3 --- /dev/null +++ b/boards/mediatek/mt8196_adsp/board.yml @@ -0,0 +1,5 @@ +boards: + - name: mt8196_adsp + vendor: mediatek + socs: + - name: mt8196_adsp diff --git a/boards/mediatek/mt8196_adsp/mt8196_adsp.dts b/boards/mediatek/mt8196_adsp/mt8196_adsp.dts new file mode 100644 index 000000000000000..1cc43225f709ab8 --- /dev/null +++ b/boards/mediatek/mt8196_adsp/mt8196_adsp.dts @@ -0,0 +1,109 @@ +/* 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@90000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x90000000 DT_SIZE_M(6)>; +}; + +dram1: memory@90700000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x90700000 DT_SIZE_M(1)>; +}; + +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>; + }; + + /* The 8196 interrupt controller is actually more complicated + * than the driver here supports. There are 64 total + * interrupt inputs, each of which is a associated with one of + * 16 "groups", each of which is wired to a separate Xtensa + * architectural interrupt. (Whether the mapping of external + * interrupts to groups is mutable is an open question, the + * values here appear to be hardware defaults). We represent + * each group (strictly each of the high and low 32 interrupts + * of each group) as a separate adsp_intc controller, pointing + * at the same status and enable registers, but with disjoint + * masks. Note that this disallows configurations where a + * single controller needs to manage interrupts in both the + * high and low 32 bits of the set, but no current drivers + * rely on such a configuration. + */ + + intc_g1: intc_g1@1a014010 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x1a014010 4>; + status-reg = <0x1a014008>; + mask = <0x00007f3f>; + interrupts = <1 0 0>; + interrupt-parent = <&core_intc>; + }; + + intc_g2: intc_g2@1a014010 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x1a014010 4>; + status-reg = <0x1a014008>; + mask = <0x000000c0>; + interrupts = <2 0 0>; + interrupt-parent = <&core_intc>; + }; + + ostimer64: ostimer64@1a00b080 { + compatible = "mediatek,ostimer64"; + reg = <0x1a00b080 28>; + }; + + ostimer0: ostimer@1a00b000 { + compatible = "mediatek,ostimer"; + reg = <0x1a00b000 16>; + interrupt-parent = <&intc_g1>; + interrupts = <8 0 0>; + }; + + mbox0: mbox@1a360100 { + compatible = "mediatek,mbox"; + reg = <0x1a360100 16>; + interrupt-parent = <&intc_g2>; + interrupts = <6 0 0>; + }; + + mbox1: mbox@1a370100 { + compatible = "mediatek,mbox"; + reg = <0x1a370100 16>; + interrupt-parent = <&intc_g2>; + interrupts = <7 0 0>; + }; +}; /* soc */ + +chosen { }; +aliases { }; + +}; diff --git a/drivers/timer/mtk_adsp_timer.c b/drivers/timer/mtk_adsp_timer.c index 7a6c06d9e61ac1d..9be3122efaa2faf 100644 --- a/drivers/timer/mtk_adsp_timer.c +++ b/drivers/timer/mtk_adsp_timer.c @@ -56,8 +56,13 @@ struct mtk_ostimer64 { #define OSTIMER_CON_CLKSRC_BCLK 0x20 /* CPU speed, 720 MHz */ #define OSTIMER_CON_CLKSRC_PCLK 0x30 /* ~312 MHz experimentally */ +#ifndef CONFIG_SOC_MT8196_ADSP #define OSTIMER_IRQ_ACK_ENABLE BIT(4) /* read = status, write = enable */ #define OSTIMER_IRQ_ACK_CLEAR BIT(5) +#else +#define OSTIMER_IRQ_ACK_ENABLE BIT(0) +#define OSTIMER_IRQ_ACK_CLEAR BIT(5) +#endif #define OST64_HZ 13000000U #define OST_HZ 26000000U diff --git a/soc/mediatek/mtk_adsp/Kconfig.soc b/soc/mediatek/mtk_adsp/Kconfig.soc index 970847dde5cd3f3..03eb15a93248e99 100644 --- a/soc/mediatek/mtk_adsp/Kconfig.soc +++ b/soc/mediatek/mtk_adsp/Kconfig.soc @@ -16,6 +16,12 @@ config SOC_SERIES_MT818X_ADSP help Mediatek MT818x Audio DSPs +config SOC_SERIES_MT8196_ADSP + bool + select SOC_FAMILY_MTK_ADSP + help + Mediatek MT8196 Audio DSPs + config SOC_MT8195_ADSP bool select SOC_SERIES_MT8195_ADSP @@ -28,7 +34,12 @@ config SOC_MT8188_ADSP bool select SOC_SERIES_MT818X_ADSP +config SOC_MT8196_ADSP + bool + select SOC_SERIES_MT8196_ADSP + config SOC default "mt8195_adsp" if SOC_MT8195_ADSP default "mt8186_adsp" if SOC_MT8186_ADSP default "mt8188_adsp" if SOC_MT8188_ADSP + default "mt8196_adsp" if SOC_MT8196_ADSP diff --git a/soc/mediatek/mtk_adsp/irq.c b/soc/mediatek/mtk_adsp/irq.c index 17467f965d782b2..a3a5a195d050c82 100644 --- a/soc/mediatek/mtk_adsp/irq.c +++ b/soc/mediatek/mtk_adsp/irq.c @@ -25,6 +25,16 @@ 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)); +#elif defined(CONFIG_SOC_SERIES_MT8196_ADSP) + /* Two subcontrollers on core IRQs 1 and 2 */ + uint32_t lvl1 = *irq_inout & 0xff; + + *irq_inout = (*irq_inout >> 8) - 1; + if (lvl1 == 1) { + return DEVICE_DT_GET(DT_INST(0, mediatek_adsp_intc)); + } + __ASSERT_NO_MSG(lvl1 == 2); + 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)); diff --git a/soc/mediatek/mtk_adsp/mt8196_adsp/Kconfig.defconfig b/soc/mediatek/mtk_adsp/mt8196_adsp/Kconfig.defconfig new file mode 100644 index 000000000000000..143b4f7ecf8d72c --- /dev/null +++ b/soc/mediatek/mtk_adsp/mt8196_adsp/Kconfig.defconfig @@ -0,0 +1,18 @@ +# Copyright 2024 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MT8196_ADSP + +config LEGACY_MULTI_LEVEL_TABLE_GENERATION + default n + +config NUM_2ND_LEVEL_AGGREGATORS + default 2 + +config 2ND_LVL_INTR_00_OFFSET + default 1 + +config 2ND_LVL_INTR_01_OFFSET + default 2 + +endif diff --git a/soc/mediatek/mtk_adsp/mt8196_adsp/linker.ld b/soc/mediatek/mtk_adsp/mt8196_adsp/linker.ld new file mode 100644 index 000000000000000..3d086aecb1abc7a --- /dev/null +++ b/soc/mediatek/mtk_adsp/mt8196_adsp/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/mtk_adsp/mt8196_adsp/soc.h b/soc/mediatek/mtk_adsp/mt8196_adsp/soc.h new file mode 100644 index 000000000000000..c316ceaafcbf2fa --- /dev/null +++ b/soc/mediatek/mtk_adsp/mt8196_adsp/soc.h @@ -0,0 +1,10 @@ +/* Copyright 2024 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_MT8196_ADSP_SOC_H +#define ZEPHYR_SOC_MT8196_ADSP_SOC_H + +#include "../soc.h" + +#endif /* ZEPHYR_SOC_MT8196_ADSP_SOC_H */ diff --git a/soc/mediatek/mtk_adsp/soc.c b/soc/mediatek/mtk_adsp/soc.c index 23acb56aa53a5c7..deb7eb4162210bb 100644 --- a/soc/mediatek/mtk_adsp/soc.c +++ b/soc/mediatek/mtk_adsp/soc.c @@ -19,14 +19,23 @@ extern char _mtk_adsp_dram_end[]; #define DRAM_SIZE DT_REG_SIZE(DT_NODELABEL(dram0)) #define DRAM_END (DRAM_START + DRAM_SIZE) +#ifdef CONFIG_SOC_MT8196_ADSP +#define INIT_STACK "0x90400000" +#define LOG_BASE 0x90580000 +#define LOG_LEN 0x80000 +#else +#define INIT_STACK "0x60e00000" +#define LOG_BASE 0x60700000 +#define LOG_LEN 0x100000 +#endif + /* This is the true boot vector. This device allows for direct * setting of the alternate reset vector, so we let it link wherever * 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). 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]. + * really this should move to the arch layer). The initial stack + * really should be the end of _interrupt_stacks[0] */ __asm__(".align 4\n\t" ".global mtk_adsp_boot_entry\n\t" @@ -38,7 +47,7 @@ __asm__(".align 4\n\t" " movi a0, 1\n\t" " wsr a0, WINDOWSTART\n\t" " rsync\n\t" - " movi a1, 0x60e00000\n\t" + " movi a1, " INIT_STACK "\n\t" " call4 c_boot\n\t"); /* Initial MPU configuration, needed to enable caching */ @@ -109,8 +118,8 @@ static void enable_mpu(void) */ int arch_printk_char_out(int c) { - char volatile * const buf = (void *)0x60700000; - const size_t max = 0x100000 - 4; + char volatile * const buf = (void *)LOG_BASE; + const size_t max = LOG_LEN - 4; int volatile * const len = (int *)&buf[max]; if (*len < max) { diff --git a/soc/mediatek/mtk_adsp/soc.yml b/soc/mediatek/mtk_adsp/soc.yml index d7a9658cb6dabc0..9a3e6289788c5cb 100644 --- a/soc/mediatek/mtk_adsp/soc.yml +++ b/soc/mediatek/mtk_adsp/soc.yml @@ -8,3 +8,6 @@ family: socs: - name: mt8186_adsp - name: mt8188_adsp + - name: mt8196_adsp + socs: + - name: mt8196_adsp