Skip to content

Commit 318fba6

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 c90bc6f commit 318fba6

20 files changed

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