Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/boards/imx8mp_evk_mimx8ml8_adsp.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ CONFIG_DMA=y
CONFIG_DMA_NXP_SDMA=y
CONFIG_DAI_NXP_MICFIL=y
CONFIG_TRACE=n
CONFIG_PROBE=y
CONFIG_PROBE_POINTS_MAX=16
CONFIG_SHARED_INTERRUPTS=y
CONFIG_ZEPHYR_NATIVE_DRIVERS=y
CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y
Expand Down
87 changes: 82 additions & 5 deletions src/probe/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,17 @@ LOG_MODULE_REGISTER(probe, CONFIG_SOF_LOG_LEVEL);
#define PROBE_POINT_INVALID 0xFFFFFFFF

#define PROBE_BUFFER_LOCAL_SIZE 8192
/* host buffer layout: u32 write counter in the first bytes, ring data after the header */
#define PROBE_HOST_HDR_SIZE 4096
#define DMA_ELEM_SIZE 32

/* i.MX IPC3: the DSP writes extraction data straight into the host ring */
#if CONFIG_IPC_MAJOR_3 && CONFIG_ZEPHYR_NATIVE_DRIVERS && CONFIG_IMX
#define PROBE_HOST_RING 1
#else
#define PROBE_HOST_RING 0
#endif

/**
* DMA buffer
*/
Expand All @@ -74,6 +83,11 @@ struct probe_dma_ext {
struct dma_sg_config config; /**< DMA SG config */
struct probe_dma_buf dmapb; /**< DMA buffer pointer */
struct dma_copy dc; /**< DMA copy */
#if PROBE_HOST_RING
uintptr_t host_base; /**< host buffer: header + ring (IPC3) */
uint32_t host_size; /**< host ring size in bytes (IPC3) */
uint32_t host_wr; /**< total bytes written to host ring (IPC3) */
#endif
};

/**
Expand Down Expand Up @@ -195,13 +209,18 @@ __cold static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction)
{
uint32_t addr_align;
uint32_t channel;
struct dma_config dma_cfg;
struct dma_block_config dma_block_cfg;
struct dma_config dma_cfg = {0};
struct dma_block_config dma_block_cfg = {0};
int err = 0;

assert_can_be_cold();

#if CONFIG_IPC_MAJOR_3
/* IPC3: stream_tag carries the host buffer address; use host DMA channel 0 */
channel = 0;
#else
channel = ((union ipc4_connector_node_id)dma->stream_tag).f.v_index;
#endif

/* request DMA in the dir LMEM->HMEM with shared access */
dma->dc.dmac = sof_dma_get(direction, 0, SOF_DMA_DEV_HOST,
Expand Down Expand Up @@ -259,6 +278,10 @@ __cold static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction)
case SOF_DMA_DIR_LMEM_TO_HMEM:
dma_cfg.channel_direction = MEMORY_TO_HOST;
dma_block_cfg.source_address = (uint32_t)dma->dmapb.addr;
#if PROBE_HOST_RING
/* never transferred, probe_host_write() copies; driver wants non-zero */
dma_block_cfg.dest_address = (uint32_t)dma->dmapb.addr;
#endif
break;
case SOF_DMA_DIR_HMEM_TO_LMEM:
dma_cfg.channel_direction = HOST_TO_MEMORY;
Expand Down Expand Up @@ -320,6 +343,42 @@ __cold static int probe_dma_deinit(struct probe_dma_ext *dma)
return 0;
}

#if PROBE_HOST_RING
/*
* Copy extraction data straight into the host ring and publish the new
* write counter. The i.MX host DMA driver can only memcpy inside DSP
* memory, so the DSP writes to the host buffer itself and flushes its
* data cache.
*/
static int probe_host_write(struct probe_dma_ext *dma, const void *src, uint32_t bytes)
{
uint8_t *ring = (uint8_t *)dma->host_base + PROBE_HOST_HDR_SIZE;
uint32_t off, head;

if (!dma->host_base || !dma->host_size)
return -EINVAL;

off = dma->host_wr % dma->host_size;
Comment thread
ursus161 marked this conversation as resolved.
Resolved
head = MIN(bytes, dma->host_size - off);

memcpy(ring + off, src, head);
dcache_writeback_region((__sparse_force void __sparse_cache *)(ring + off), head);
if (bytes > head) {
memcpy(ring, (const uint8_t *)src + head, bytes - head);
dcache_writeback_region((__sparse_force void __sparse_cache *)ring,
bytes - head);
}

/* host_wr wraps at 2^32; kernel side casts its counter to u32 before subtracting */
dma->host_wr += bytes;
*(volatile uint32_t *)dma->host_base = dma->host_wr;
dcache_writeback_region((__sparse_force void __sparse_cache *)dma->host_base,
sizeof(uint32_t));

return 0;
}
#endif

/*
* \brief Probe task for extraction.
*
Expand Down Expand Up @@ -351,7 +410,10 @@ static enum task_state probe_task(void *data)
avail = _probe->ext_dma.dmapb.end_addr - _probe->ext_dma.dmapb.r_ptr;

if (avail > 0)
#if CONFIG_ZEPHYR_NATIVE_DRIVERS
#if PROBE_HOST_RING
err = probe_host_write(&_probe->ext_dma,
(void *)_probe->ext_dma.dmapb.r_ptr, avail);
#elif CONFIG_ZEPHYR_NATIVE_DRIVERS
err = dma_reload(_probe->ext_dma.dc.dmac->z_dev,
_probe->ext_dma.dc.chan->index, 0, 0, avail);
#else
Expand Down Expand Up @@ -417,6 +479,15 @@ __cold int probe_init(const struct probe_dma *probe_dma)
return -EINVAL;
}

#if PROBE_HOST_RING
/* ring must hold a full local buffer and wrap cleanly at 2^32 */
if (probe_dma && (probe_dma->dma_buffer_size < PROBE_BUFFER_LOCAL_SIZE ||
(probe_dma->dma_buffer_size & (probe_dma->dma_buffer_size - 1)))) {
tr_err(&pr_tr, "bad host ring size %u", probe_dma->dma_buffer_size);
return -EINVAL;
}
#endif

/* alloc probes main struct */
sof_get()->probe = rzalloc(SOF_MEM_FLAG_USER,
sizeof(*_probe));
Expand Down Expand Up @@ -446,6 +517,12 @@ __cold int probe_init(const struct probe_dma *probe_dma)

_probe->ext_dma.stream_tag = probe_dma->stream_tag;
_probe->ext_dma.dma_buffer_size = probe_dma->dma_buffer_size;
#if PROBE_HOST_RING
/* i.MX: stream_tag holds the physical address of the host ring buffer */
_probe->ext_dma.host_base = probe_dma->stream_tag;
_probe->ext_dma.host_size = probe_dma->dma_buffer_size;
_probe->ext_dma.host_wr = 0;
#endif

err = probe_dma_init(&_probe->ext_dma, SOF_DMA_DIR_LMEM_TO_HMEM);
if (err < 0) {
Expand Down Expand Up @@ -1249,7 +1326,7 @@ __cold int probe_point_add(uint32_t count, const struct probe_point *probe)
#elif CONFIG_AMD_ACP_HOST_DMA_PROBE
dev = ipc_get_buffer_by_id(ipc_get(), buf_id->full_id);
#else
dev = ipc_get_comp_by_id(ipc_get(), buf_id->full_id);
dev = ipc_get_comp_dev(ipc_get(), COMP_TYPE_ANY, buf_id->full_id);
#endif
/* check if buffer exists */
if (!dev) {
Expand Down Expand Up @@ -1512,7 +1589,7 @@ __cold int probe_point_remove(uint32_t count, const uint32_t *buffer_id)
#if CONFIG_AMD_ACP_HOST_DMA_PROBE
dev = ipc_get_buffer_by_id(ipc_get(), buffer_id[i]);
#else
dev = ipc_get_comp_by_id(ipc_get(), buffer_id[i]);
dev = ipc_get_comp_dev(ipc_get(), COMP_TYPE_ANY, buffer_id[i]);
#endif
if (dev) {
struct comp_buffer *probe_buf =
Expand Down
Loading