Skip to content

Commit 1b030ce

Browse files
platform: add ACP_7_X platform support for native Zephyr
Add ACP_7_X platform support for native Zephyr drivers. Changes include: - Add platform-specific files for ACP_7_X native Zephyr support - Add ACP_7_X in zephyr/CMakeLists.txt with platform sources, include directories and PLATFORM variable - Add app/boards/acp_7_x_adsp.conf with ACP_7_X Kconfig options for native Zephyr drivers (DMA, DAI, interrupts) Signed-off-by: Sneha Voona <sneha.voona@amd.com> Co-authored-by: DineshKumar Kalva <DineshKumar.Kalva@amd.com>
1 parent 3abe29b commit 1b030ce

20 files changed

Lines changed: 4008 additions & 0 deletions

File tree

app/boards/acp_7_x_adsp.conf

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
CONFIG_ACP_7_X=y
2+
CONFIG_HAVE_AGENT=n
3+
CONFIG_DCACHE_LINE_SIZE_DETECT=n
4+
CONFIG_DCACHE_LINE_SIZE=128
5+
CONFIG_DYNAMIC_INTERRUPTS=y
6+
CONFIG_SHARED_INTERRUPTS=n
7+
CONFIG_ZEPHYR_LOG=y
8+
CONFIG_LOG_MODE_DEFERRED=n
9+
CONFIG_LOG_MODE_MINIMAL=y
10+
CONFIG_DMA=y
11+
CONFIG_DMA_DOMAIN=n
12+
CONFIG_ZEPHYR_NATIVE_DRIVERS=y
13+
CONFIG_INTC_AMD_ACP=y
14+
CONFIG_DMA_AMD_ACP_HOST=y
15+
CONFIG_DMA_AMD_ACP_SDW=y
16+
CONFIG_DAI_AMD_SDW=y
17+
CONFIG_AMS=n
18+
CONFIG_WRAP_ACTUAL_POSITION=y
19+
CONFIG_TRACE=n
20+
CONFIG_COMP_VOLUME=y
21+
CONFIG_COMP_SRC=n
22+
CONFIG_COMP_FIR=n
23+
CONFIG_COMP_IIR=n
24+
CONFIG_COMP_DCBLOCK=n
25+
CONFIG_COMP_CROSSOVER=n
26+
CONFIG_COMP_DRC=n
27+
CONFIG_COMP_MULTIBAND_DRC=n
28+
CONFIG_COMP_TONE=n
29+
CONFIG_COMP_KPB=n
30+
CONFIG_MAXIM_DSM=n
31+
CONFIG_COMP_ASRC=n
32+
CONFIG_COMP_IGO_NR=n
33+
CONFIG_COMP_COPIER=n
34+
CONFIG_COMP_RTNR=n
35+
CONFIG_COMP_ARIA=n
36+
CONFIG_COMP_BASEFW_IPC4=n
37+
CONFIG_COMP_UP_DOWN_MIXER=n
38+
CONFIG_COMP_TDFB=n
39+
CONFIG_COMP_SEL=n
40+
CONFIG_COMP_MIXER=n
41+
CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000=n
42+
CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000=n
43+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000=n
44+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025=n
45+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000=n
46+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000=n
47+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050=n
48+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000=n
49+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000=n
50+
CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100=n
51+
CONFIG_CORE_COUNT=1
52+
CONFIG_FORMAT_CONVERT_HIFI3=n
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
3+
add_local_sources(sof
4+
ipc.c
5+
)

src/drivers/amd/acp_7_x/ipc.c

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* Copyright(c) 2026 AMD. All rights reserved.
4+
*
5+
* Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com>
6+
* Sneha Voona <sneha.voona@amd.com>
7+
* DineshKumar Kalva <DineshKumar.Kalva@amd.com>
8+
*/
9+
10+
#include <rtos/panic.h>
11+
#include <rtos/interrupt.h>
12+
#include <sof/ipc/driver.h>
13+
#include <sof/ipc/msg.h>
14+
#include <sof/ipc/schedule.h>
15+
#include <rtos/alloc.h>
16+
#include <sof/lib/dma.h>
17+
#include <sof/lib/mailbox.h>
18+
#include <sof/lib/memory.h>
19+
#include <sof/lib/uuid.h>
20+
#include <rtos/wait.h>
21+
#include <sof/list.h>
22+
#include <sof/platform.h>
23+
#include <sof/schedule/edf_schedule.h>
24+
#include <sof/schedule/schedule.h>
25+
#include <rtos/task.h>
26+
#include <rtos/spinlock.h>
27+
#include <ipc/header.h>
28+
#include <ipc/topology.h>
29+
#include <errno.h>
30+
#include <stddef.h>
31+
#include <stdint.h>
32+
#include <platform/platform.h>
33+
#include <platform/ipc.h>
34+
#include <zephyr/logging/log.h>
35+
36+
volatile acp_scratch_mem_config_t *pscratch_mem_cfg =
37+
(volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE +
38+
SCRATCH_REG_OFFSET);
39+
40+
SOF_DEFINE_REG_UUID(ipc_task_amd);
41+
LOG_MODULE_REGISTER(ipc_handler_file, LOG_LEVEL_DBG);
42+
43+
#define HOST_TO_DSP_INTR 1
44+
#define INTERRUPT_DISABLE 0
45+
#define IRQ_NUM_EXT_LEVEL3 3
46+
#define IRQ_EXT_IPC_LEVEL_3 3
47+
48+
/* This function triggers a host interrupt from ACP DSP */
49+
void acp_dsp_to_host_intr_trig(void)
50+
{
51+
acp_sw_intr_trig_t sw_intr_trig;
52+
/* Read the Software Interrupt controller register and update */
53+
sw_intr_trig = (acp_sw_intr_trig_t) io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
54+
/* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */
55+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE;
56+
/* Write the Software Interrupt controller register */
57+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
58+
}
59+
60+
/* Clear the Acknowledge ( status) for the host to DSP interrupt */
61+
static void acp_ack_intr_from_host(void)
62+
{
63+
/* acknowledge the host interrupt */
64+
acp_dsp_sw_intr_stat_t sw_intr_stat;
65+
66+
sw_intr_stat.u32all = 0;
67+
sw_intr_stat.bits.host_to_dsp0_intr1_stat = INTERRUPT_ENABLE;
68+
io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT), sw_intr_stat.u32all);
69+
}
70+
71+
inline uint32_t sof_ipc_host_status(void)
72+
{
73+
return (pscratch_mem_cfg->acp_host_ack_write | pscratch_mem_cfg->acp_host_msg_write);
74+
}
75+
76+
inline uint32_t sof_ipc_host_msg_flag(void)
77+
{
78+
return pscratch_mem_cfg->acp_host_msg_write;
79+
}
80+
81+
inline uint32_t sof_ipc_host_ack_flag(void)
82+
{
83+
return pscratch_mem_cfg->acp_host_ack_write;
84+
}
85+
86+
inline uint32_t sof_ipc_dsp_status(void)
87+
{
88+
return (pscratch_mem_cfg->acp_dsp_msg_write | pscratch_mem_cfg->acp_dsp_ack_write);
89+
}
90+
91+
inline void sof_ipc_host_ack_clear(void)
92+
{
93+
pscratch_mem_cfg->acp_host_ack_write = 0;
94+
}
95+
96+
inline void sof_ipc_host_msg_clear(void)
97+
{
98+
pscratch_mem_cfg->acp_host_msg_write = 0;
99+
}
100+
101+
inline void sof_ipc_dsp_ack_set(void)
102+
{
103+
pscratch_mem_cfg->acp_dsp_ack_write = 1;
104+
}
105+
106+
inline void sof_ipc_dsp_msg_set(void)
107+
{
108+
pscratch_mem_cfg->acp_dsp_msg_write = 1;
109+
}
110+
111+
enum task_state ipc_platform_do_cmd(struct ipc *ipc)
112+
{
113+
struct ipc_cmd_hdr *hdr;
114+
115+
hdr = mailbox_validate();
116+
ipc_cmd(hdr);
117+
return SOF_TASK_STATE_COMPLETED;
118+
}
119+
120+
int platform_ipc_init(struct ipc *ipc)
121+
{
122+
ipc_set_drvdata(ipc, NULL);
123+
/* schedule */
124+
schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_amd_uuid),
125+
&ipc_task_ops, ipc, 0, 0);
126+
interrupt_disable(IRQ_EXT_IPC_LEVEL_3, ipc);
127+
interrupt_unregister(IRQ_EXT_IPC_LEVEL_3, ipc);
128+
interrupt_register(IRQ_EXT_IPC_LEVEL_3, amd_irq_handler, ipc);
129+
/* Enabling software interuppts */
130+
interrupt_enable(IRQ_EXT_IPC_LEVEL_3, ipc);
131+
return 0;
132+
}
133+
134+
void amd_irq_handler(void *arg)
135+
{
136+
struct ipc *ipc = arg;
137+
uint32_t status;
138+
uint32_t lock;
139+
acp_dsp_sw_intr_stat_t swintrstat;
140+
acp_sw_intr_trig_t swintrtrig;
141+
142+
swintrstat = (acp_dsp_sw_intr_stat_t)io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT);
143+
status = swintrstat.u32all & HOST_TO_DSP_INTR;
144+
if (status) {
145+
/* Interrupt source */
146+
lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0);
147+
/* Removed unbounded while(lock) loop - using bounded loop below instead */
148+
int timeout = 20000;
149+
150+
while (lock && --timeout > 0) {
151+
lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0);
152+
}
153+
if (timeout == 0) {
154+
/* Give up, don't block forever */
155+
LOG_ERR("ACP semaphore timeout in IRQ handler");
156+
return;
157+
}
158+
/***************************************************** */
159+
/* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */
160+
swintrtrig = (acp_sw_intr_trig_t)
161+
io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
162+
swintrtrig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE;
163+
swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
164+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG),
165+
swintrtrig.u32all);
166+
167+
/* Clear the Host to DSP Status Register */
168+
acp_ack_intr_from_host();
169+
/********************************************* */
170+
171+
if (sof_ipc_host_status()) {
172+
if (sof_ipc_host_ack_flag()) {
173+
/* Clear the ACK from host */
174+
sof_ipc_host_ack_clear();
175+
}
176+
/* Check if new message from host */
177+
if (sof_ipc_host_msg_flag()) {
178+
/* Clear the msg bit from host*/
179+
sof_ipc_host_msg_clear();
180+
ipc_schedule_process(ipc);
181+
}
182+
} else {
183+
tr_err(&ipc_tr, "IPC:interrupt without setting flags host status 0x%x", sof_ipc_host_status());
184+
io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), 0);
185+
}
186+
}
187+
}
188+
189+
void ipc_platform_complete_cmd(struct ipc *ipc)
190+
{
191+
acp_sw_intr_trig_t sw_intr_trig;
192+
193+
/* Set Dsp Ack for msg from host */
194+
sof_ipc_dsp_ack_set();
195+
/* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */
196+
sw_intr_trig = (acp_sw_intr_trig_t)
197+
io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
198+
sw_intr_trig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE;
199+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
200+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
201+
/* now interrupt host to tell it we have sent a message */
202+
acp_dsp_to_host_intr_trig();
203+
/* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */
204+
sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
205+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
206+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
207+
io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), 0);
208+
LOG_DBG("IPC cmd completed");
209+
if (ipc->pm_prepare_D3) {
210+
while (1) {
211+
wait_for_interrupt(0);
212+
}
213+
}
214+
}
215+
216+
int ipc_platform_send_msg(const struct ipc_msg *msg)
217+
{
218+
int ret = 0;
219+
acp_sw_intr_trig_t sw_intr_trig;
220+
acp_dsp_sw_intr_stat_t sw_intr_stat;
221+
uint32_t status;
222+
uint32_t lock;
223+
/* Check if host cleared the status for previous messages */
224+
sw_intr_stat = (acp_dsp_sw_intr_stat_t)
225+
io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT);
226+
status = sw_intr_stat.bits.dsp0_to_host_intr_stat;
227+
if (sof_ipc_dsp_status() || status) {
228+
return -EBUSY;
229+
}
230+
lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0);
231+
int timeout = 20000;
232+
233+
while (lock && --timeout > 0) {
234+
lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0);
235+
}
236+
if (timeout == 0) {
237+
/* Give up, don't block forever */
238+
LOG_ERR("ACP semaphore timeout in IPC send");
239+
return -EBUSY;
240+
}
241+
242+
/* Write new message in the mailbox */
243+
mailbox_dspbox_write(0, msg->tx_data, msg->tx_size);
244+
/* Need to set DSP message flag */
245+
sof_ipc_dsp_msg_set();
246+
/* Trigger host interrupt to notify new message from DSP */
247+
/* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */
248+
sw_intr_trig = (acp_sw_intr_trig_t)
249+
io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
250+
sw_intr_trig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE;
251+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
252+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
253+
acp_dsp_to_host_intr_trig();
254+
/* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */
255+
sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
256+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
257+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
258+
io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock);
259+
return ret;
260+
}
261+
262+
void ipc_platform_send_msg_direct(const struct ipc_msg *msg)
263+
{
264+
acp_sw_intr_trig_t sw_intr_trig;
265+
266+
/* Write message directly to mailbox - no status checks for emergency */
267+
mailbox_dspbox_write(0, msg->tx_data, msg->tx_size);
268+
269+
/* Set DSP message flag */
270+
sof_ipc_dsp_msg_set();
271+
272+
/* Interrupt host immediately */
273+
acp_dsp_to_host_intr_trig();
274+
275+
/* Disable the trigger bit */
276+
sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG);
277+
sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE;
278+
io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all);
279+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
3+
add_subdirectory(lib)
4+
add_local_sources(sof platform.c)

0 commit comments

Comments
 (0)