From 2f320730a15fa0e555bf5ec7e15b6a328db18665 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 6 Apr 2022 17:26:33 -0500 Subject: [PATCH] dma/cavs_hda: Adds link in/link out compatibles Adds hda link in and out drivers. The link in and link out channels of HDA have small differences with the host channels. Updates the existing cavs_hda drivers and code to account for these differences. Signed-off-by: Tom Burdick --- drivers/dma/dma_cavs_hda.c | 77 ++++++++++++++++++- drivers/dma/dma_cavs_hda.h | 13 +++- drivers/dma/dma_cavs_hda_link_in.c | 38 +++++++++ drivers/dma/dma_cavs_hda_link_out.c | 38 +++++++++ dts/bindings/dma/intel,cavs-hda-link-in.yaml | 8 ++ dts/bindings/dma/intel,cavs-hda-link-out.yaml | 8 ++ dts/xtensa/intel/intel_cavs.dtsi | 21 +++++ .../intel_adsp/common/include/cavs_hda.h | 30 ++++++-- tests/boards/intel_adsp/hda/src/smoke.c | 4 +- 9 files changed, 225 insertions(+), 12 deletions(-) create mode 100644 drivers/dma/dma_cavs_hda_link_in.c create mode 100644 drivers/dma/dma_cavs_hda_link_out.c create mode 100644 dts/bindings/dma/intel,cavs-hda-link-in.yaml create mode 100644 dts/bindings/dma/intel,cavs-hda-link-out.yaml diff --git a/drivers/dma/dma_cavs_hda.c b/drivers/dma/dma_cavs_hda.c index a3590250735..9c6f3db8406 100644 --- a/drivers/dma/dma_cavs_hda.c +++ b/drivers/dma/dma_cavs_hda.c @@ -98,6 +98,81 @@ int cavs_hda_dma_host_out_config(const struct device *dev, return res; } +int cavs_hda_dma_link_in_config(const struct device *dev, + uint32_t channel, + struct dma_config *dma_cfg) +{ + const struct cavs_hda_dma_cfg *const cfg = dev->config; + struct dma_block_config *blk_cfg; + uint8_t *buf; + int res; + + __ASSERT(channel < cfg->dma_channels, "Channel does not exist"); + __ASSERT(dma_cfg->block_count == 1, + "HDA does not support scatter gather or chained " + "block transfers."); + __ASSERT(dma_cfg->channel_direction == cfg->direction, + "Unexpected channel direction, HDA link in supports " + "PERIPHERAL_TO_MEMORY"); + + blk_cfg = dma_cfg->head_block; + buf = (uint8_t *)(uintptr_t)(blk_cfg->source_address); + res = cavs_hda_set_buffer(cfg->base, channel, buf, + blk_cfg->block_size); + + if (res == 0 && dma_cfg->source_data_size <= 3) { + /* set the sample container set bit to 16bits */ + *DGCS(cfg->base, channel) |= DGCS_SCS; + } + + return res; +} + + +int cavs_hda_dma_link_out_config(const struct device *dev, + uint32_t channel, + struct dma_config *dma_cfg) +{ + const struct cavs_hda_dma_cfg *const cfg = dev->config; + struct dma_block_config *blk_cfg; + uint8_t *buf; + int res; + + __ASSERT(channel < cfg->dma_channels, "Channel does not exist"); + __ASSERT(dma_cfg->block_count == 1, + "HDA does not support scatter gather or chained " + "block transfers."); + __ASSERT(dma_cfg->channel_direction == cfg->direction, + "Unexpected channel direction, HDA link out supports " + "MEMORY_TO_PERIPHERAL"); + + blk_cfg = dma_cfg->head_block; + buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address); + + res = cavs_hda_set_buffer(cfg->base, channel, buf, + blk_cfg->block_size); + + if (res == 0 && dma_cfg->dest_data_size <= 3) { + /* set the sample container set bit to 16bits */ + *DGCS(cfg->base, channel) |= DGCS_SCS; + } + + return res; +} + + +int cavs_hda_dma_link_reload(const struct device *dev, uint32_t channel, + uint32_t src, uint32_t dst, size_t size) +{ + const struct cavs_hda_dma_cfg *const cfg = dev->config; + + __ASSERT(channel < cfg->dma_channels, "Channel does not exist"); + + cavs_hda_link_commit(cfg->base, channel, size); + + return 0; +} + int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel, uint32_t src, uint32_t dst, size_t size) { @@ -105,7 +180,7 @@ int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel, __ASSERT(channel < cfg->dma_channels, "Channel does not exist"); - cavs_hda_commit(cfg->base, channel, size); + cavs_hda_host_commit(cfg->base, channel, size); return 0; } diff --git a/drivers/dma/dma_cavs_hda.h b/drivers/dma/dma_cavs_hda.h index 971fdda86b2..4915ff87655 100644 --- a/drivers/dma/dma_cavs_hda.h +++ b/drivers/dma/dma_cavs_hda.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_DRIVERS_DMA_DMA_CAVS_HDA_COMMON_H_ #define ZEPHYR_DRIVERS_DMA_DMA_CAVS_HDA_COMMON_H_ -#define CAVS_HDA_MAX_CHANNELS 32 +#define CAVS_HDA_MAX_CHANNELS DT_PROP(DT_NODELABEL(hda_host_out), dma_channels) #include @@ -31,6 +31,17 @@ int cavs_hda_dma_host_out_config(const struct device *dev, uint32_t channel, struct dma_config *dma_cfg); +int cavs_hda_dma_link_in_config(const struct device *dev, + uint32_t channel, + struct dma_config *dma_cfg); + +int cavs_hda_dma_link_out_config(const struct device *dev, + uint32_t channel, + struct dma_config *dma_cfg); + +int cavs_hda_dma_link_reload(const struct device *dev, uint32_t channel, + uint32_t src, uint32_t dst, size_t size); + int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel, uint32_t src, uint32_t dst, size_t size); diff --git a/drivers/dma/dma_cavs_hda_link_in.c b/drivers/dma/dma_cavs_hda_link_in.c new file mode 100644 index 00000000000..4878b240cf9 --- /dev/null +++ b/drivers/dma/dma_cavs_hda_link_in.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_cavs_hda_link_in + +#include +#include "dma_cavs_hda.h" + +#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL +#include +LOG_MODULE_REGISTER(dma_cavs_hda_dma_link_in); + +static const struct dma_driver_api cavs_hda_dma_link_in_api = { + .config = cavs_hda_dma_link_in_config, + .reload = cavs_hda_dma_link_reload, + .start = cavs_hda_dma_start, + .stop = cavs_hda_dma_stop, + .get_status = cavs_hda_dma_status, + .chan_filter = cavs_hda_dma_chan_filter, +}; + +#define CAVS_HDA_DMA_LINK_IN_INIT(inst) \ + static const struct cavs_hda_dma_cfg cavs_hda_dma##inst##_config = { \ + .base = DT_INST_REG_ADDR(inst), \ + .dma_channels = DT_INST_PROP(inst, dma_channels), \ + .direction = MEMORY_TO_HOST \ + }; \ + \ + static struct cavs_hda_dma_data cavs_hda_dma##inst##_data = {}; \ + \ + DEVICE_DT_INST_DEFINE(inst, &cavs_hda_dma_init, NULL, &cavs_hda_dma##inst##_data, \ + &cavs_hda_dma##inst##_config, POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \ + &cavs_hda_dma_link_in_api); + +DT_INST_FOREACH_STATUS_OKAY(CAVS_HDA_DMA_LINK_IN_INIT) diff --git a/drivers/dma/dma_cavs_hda_link_out.c b/drivers/dma/dma_cavs_hda_link_out.c new file mode 100644 index 00000000000..007a2fdfb68 --- /dev/null +++ b/drivers/dma/dma_cavs_hda_link_out.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_cavs_hda_link_out + +#include +#include "dma_cavs_hda.h" + +#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL +#include +LOG_MODULE_REGISTER(dma_cavs_hda_dma_link_out); + +static const struct dma_driver_api cavs_hda_dma_link_out_api = { + .config = cavs_hda_dma_link_out_config, + .reload = cavs_hda_dma_link_reload, + .start = cavs_hda_dma_start, + .stop = cavs_hda_dma_stop, + .get_status = cavs_hda_dma_status, + .chan_filter = cavs_hda_dma_chan_filter, +}; + +#define CAVS_HDA_DMA_LINK_OUT_INIT(inst) \ + static const struct cavs_hda_dma_cfg cavs_hda_dma##inst##_config = { \ + .base = DT_INST_REG_ADDR(inst), \ + .dma_channels = DT_INST_PROP(inst, dma_channels), \ + .direction = MEMORY_TO_HOST \ + }; \ + \ + static struct cavs_hda_dma_data cavs_hda_dma##inst##_data = {}; \ + \ + DEVICE_DT_INST_DEFINE(inst, &cavs_hda_dma_init, NULL, &cavs_hda_dma##inst##_data, \ + &cavs_hda_dma##inst##_config, POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \ + &cavs_hda_dma_link_out_api); + +DT_INST_FOREACH_STATUS_OKAY(CAVS_HDA_DMA_LINK_OUT_INIT) diff --git a/dts/bindings/dma/intel,cavs-hda-link-in.yaml b/dts/bindings/dma/intel,cavs-hda-link-in.yaml new file mode 100644 index 00000000000..c15b341c272 --- /dev/null +++ b/dts/bindings/dma/intel,cavs-hda-link-in.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Intel cAVS HDA Link In controller + +compatible: "intel,cavs-hda-link-in" + +include: intel,cavs-hda.yaml diff --git a/dts/bindings/dma/intel,cavs-hda-link-out.yaml b/dts/bindings/dma/intel,cavs-hda-link-out.yaml new file mode 100644 index 00000000000..ba31ca704e2 --- /dev/null +++ b/dts/bindings/dma/intel,cavs-hda-link-out.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Intel cAVS HDA Link Out controller + +compatible: "intel,cavs-hda-link-out" + +include: intel,cavs-hda.yaml diff --git a/dts/xtensa/intel/intel_cavs.dtsi b/dts/xtensa/intel/intel_cavs.dtsi index 33c368b245f..aa587045d68 100644 --- a/dts/xtensa/intel/intel_cavs.dtsi +++ b/dts/xtensa/intel/intel_cavs.dtsi @@ -31,6 +31,25 @@ status = "okay"; }; + hda_link_out: dma@72400 { + compatible = "intel,cavs-hda-link-out"; + #dma-cells = <1>; + reg = <0x00072400 0x40>; + dma-channels = <7>; + label = "HDA_LINK_OUT"; + + status = "okay"; + }; + + hda_link_in: dma@72600 { + compatible = "intel,cavs-hda-link-in"; + #dma-cells = <1>; + reg = <0x00072600 0x40>; + dma-channels = <7>; + label = "HDA_LINK_IN"; + + status = "okay"; + }; hda_host_out: dma@72800 { compatible = "intel,cavs-hda-host-out"; @@ -51,5 +70,7 @@ status = "okay"; }; + + }; }; diff --git a/soc/xtensa/intel_adsp/common/include/cavs_hda.h b/soc/xtensa/intel_adsp/common/include/cavs_hda.h index 16aca9179e2..2b3d0b7405b 100644 --- a/soc/xtensa/intel_adsp/common/include/cavs_hda.h +++ b/soc/xtensa/intel_adsp/common/include/cavs_hda.h @@ -241,7 +241,7 @@ static inline uint32_t cavs_hda_unused(uint32_t base, uint32_t sid) } /** - * @brief Commit a number of bytes that have been transferred + * @brief Commit a number of bytes that have been transferred to/from host * * Writes the length to BFPI. For host transfers LLPI and LPIB are * also written to with the given length. @@ -259,13 +259,27 @@ static inline uint32_t cavs_hda_unused(uint32_t base, uint32_t sid) * @param sid Stream ID within the register block * @param len Len to increment postion by */ -static inline void cavs_hda_commit(uint32_t base, uint32_t sid, uint32_t len) +static inline void cavs_hda_host_commit(uint32_t base, uint32_t sid, uint32_t len) +{ + *DGBFPI(base, sid) = len; + *DGLLPI(base, sid) = len; + *DGLPIBI(base, sid) = len; +} + +/** + * @brief Commit a number of bytes that have been transferred to/from link + * + * Writes the length to BFPI. + * + * @seealso cavs_hda_host_commit + * + * @param base Base address of the IP register block + * @param sid Stream ID within the register block + * @param len Len to increment postion by + */ +static inline void cavs_hda_link_commit(uint32_t base, uint32_t sid, uint32_t len) { *DGBFPI(base, sid) = len; - if (base == HDA_HOST_IN_BASE || base == HDA_HOST_OUT_BASE) { - *DGLLPI(base, sid) = len; - *DGLPIBI(base, sid) = len; - } } /** @@ -287,8 +301,8 @@ static inline bool cavs_hda_buf_full(uint32_t base, uint32_t sid) * For HDA this does not mean that the buffer is full or empty * there are bit flags for those cases. * - * This can let you wait on the hardware to catch up to your - * reads or writes (ex after a cavs_hda_commit) + * Useful for waiting on the hardware to catch up to + * reads or writes (e.g. after a cavs_hda_commit) * * @param dev HDA Stream device * @param sid Stream ID diff --git a/tests/boards/intel_adsp/hda/src/smoke.c b/tests/boards/intel_adsp/hda/src/smoke.c index 4f8818fc38a..e2ed657e2e2 100644 --- a/tests/boards/intel_adsp/hda/src/smoke.c +++ b/tests/boards/intel_adsp/hda/src/smoke.c @@ -90,7 +90,7 @@ void test_hda_host_in_smoke(void) cavs_hda_dbg("host_in", HDA_HOST_IN_BASE, STREAM_ID); for (uint32_t i = 0; i < TRANSFER_COUNT; i++) { - cavs_hda_commit(HDA_HOST_IN_BASE, STREAM_ID, HDA_BUF_SIZE); + cavs_hda_host_commit(HDA_HOST_IN_BASE, STREAM_ID, HDA_BUF_SIZE); printk("dsp inc_pos: "); cavs_hda_dbg("host_in", HDA_HOST_IN_BASE, STREAM_ID); WAIT_FOR(cavs_hda_wp_rp_eq(HDA_HOST_IN_BASE, STREAM_ID), 10000, k_msleep(1)); @@ -186,7 +186,7 @@ void test_hda_host_out_smoke(void) } zassert_true(is_ramp, "Expected data to be a ramp"); - cavs_hda_commit(HDA_HOST_OUT_BASE, STREAM_ID, HDA_BUF_SIZE); + cavs_hda_host_commit(HDA_HOST_OUT_BASE, STREAM_ID, HDA_BUF_SIZE); printk("dsp inc pos: "); cavs_hda_dbg("host_out", HDA_HOST_OUT_BASE, STREAM_ID); }