Skip to content

Commit

Permalink
boards/mediatek: Add mt8196_adsp
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
andyross committed Nov 14, 2024
1 parent 2c47dce commit 9ab079b
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 6 deletions.
5 changes: 5 additions & 0 deletions boards/mediatek/mt8196_adsp/Kconfig.mt8196_adsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2024 The ChromiumOS Authors
# SPDX-License-Identifier: Apache-2.0

config BOARD_MT8196_ADSP
select SOC_MT8196_ADSP
5 changes: 5 additions & 0 deletions boards/mediatek/mt8196_adsp/board.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
boards:
- name: mt8196_adsp
vendor: mediatek
socs:
- name: mt8196_adsp
109 changes: 109 additions & 0 deletions boards/mediatek/mt8196_adsp/mt8196_adsp.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* 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@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 { };

};
5 changes: 5 additions & 0 deletions drivers/timer/mtk_adsp_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions soc/mediatek/mtk_adsp/Kconfig.soc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
10 changes: 10 additions & 0 deletions soc/mediatek/mtk_adsp/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
18 changes: 18 additions & 0 deletions soc/mediatek/mtk_adsp/mt8196_adsp/Kconfig.defconfig
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions soc/mediatek/mtk_adsp/mt8196_adsp/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Copyright 2024 The ChromiumOS Authors
* SPDX-License-Identifier: Apache-2.0
*/

#include "../linker.ld"
10 changes: 10 additions & 0 deletions soc/mediatek/mtk_adsp/mt8196_adsp/soc.h
Original file line number Diff line number Diff line change
@@ -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 */
21 changes: 15 additions & 6 deletions soc/mediatek/mtk_adsp/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 */
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions soc/mediatek/mtk_adsp/soc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ family:
socs:
- name: mt8186_adsp
- name: mt8188_adsp
- name: mt8196_adsp
socs:
- name: mt8196_adsp

0 comments on commit 9ab079b

Please sign in to comment.