From 1e9ada4eb9b9ff6c36006ddb7ff10d5f3ce295fc Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Tue, 1 Feb 2022 11:35:13 -0600 Subject: [PATCH] dma: cavs: Add gpdma derivative of dw dma for cavs Intel's adsp needs to set, at a minimum, a clocking bit before the driver can initialize the designware dma controller. In many ways it is the designware dmac IP but with additional registers and functionality added on top of it. So the code structure here follows how the hardware appears to be designed, layered on top of the designware driver. Signed-off-by: Tom Burdick --- CODEOWNERS | 1 + .../intel_adsp_cavs25/Kconfig.defconfig | 4 - .../intel_adsp_cavs25/intel_adsp_cavs25.dts | 4 + .../intel_adsp_cavs25/intel_adsp_cavs25.yaml | 2 + drivers/dma/CMakeLists.txt | 1 + drivers/dma/Kconfig | 2 + drivers/dma/Kconfig.cavs_gpdma | 9 ++ drivers/dma/dma_cavs_gpdma.c | 139 ++++++++++++++++++ dts/bindings/dma/intel,cavs-gpdma.yaml | 13 ++ dts/xtensa/intel/intel_cavs25.dtsi | 24 +++ .../cavs_v25/Kconfig.defconfig.series | 4 + 11 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 drivers/dma/Kconfig.cavs_gpdma create mode 100644 drivers/dma/dma_cavs_gpdma.c create mode 100644 dts/bindings/dma/intel,cavs-gpdma.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8882c87689e..8efb8ca512f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -237,6 +237,7 @@ /drivers/dma/dma_stm32* @cybertale @lowlander /drivers/dma/*pl330* @raveenp /drivers/dma/*iproc_pax* @raveenp +/drivers/dma/*cavs* @teburd /drivers/ec_host_cmd_periph/ @jettr /drivers/edac/ @finikorg /drivers/eeprom/ @henrikbrixandersen diff --git a/boards/xtensa/intel_adsp_cavs25/Kconfig.defconfig b/boards/xtensa/intel_adsp_cavs25/Kconfig.defconfig index d21aa2710a2..564db9f040b 100644 --- a/boards/xtensa/intel_adsp_cavs25/Kconfig.defconfig +++ b/boards/xtensa/intel_adsp_cavs25/Kconfig.defconfig @@ -35,10 +35,6 @@ config 2ND_LVL_ISR_TBL_OFFSET config CAVS_ISR_TBL_OFFSET default 2ND_LVL_ISR_TBL_OFFSET -config DMA_DW - default y - depends on DMA - config I2S_CAVS default y depends on I2S diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts index d4c1cac454a..662e93d5296 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.dts @@ -12,6 +12,10 @@ model = "intel_adsp_cavs25"; compatible = "intel"; + aliases { + dma0 = &lpgpdma0; + }; + chosen { zephyr,sram = &sram0; }; diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml index 381cb61eae9..bce9412071d 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25.yaml @@ -5,6 +5,8 @@ arch: xtensa toolchain: - xcc - zephyr +supported: + - dma testing: ignore_tags: - net diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index 05335367619..9a47043f295 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -16,3 +16,4 @@ zephyr_library_sources_ifdef(CONFIG_DMA_MCUX_LPC dma_mcux_lpc.c) zephyr_library_sources_ifdef(CONFIG_DMA_PL330 dma_pl330.c) zephyr_library_sources_ifdef(CONFIG_DMA_IPROC_PAX dma_iproc_pax_v1.c) zephyr_library_sources_ifdef(CONFIG_DMA_IPROC_PAX_V2 dma_iproc_pax_v2.c) +zephyr_library_sources_ifdef(CONFIG_DMA_CAVS_GPDMA dma_cavs_gpdma.c dma_dw_common.c) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 8e6b047c79e..316f1600097 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -44,4 +44,6 @@ source "drivers/dma/Kconfig.dma_pl330" source "drivers/dma/Kconfig.iproc_pax" +source "drivers/dma/Kconfig.cavs_gpdma" + endif # DMA diff --git a/drivers/dma/Kconfig.cavs_gpdma b/drivers/dma/Kconfig.cavs_gpdma new file mode 100644 index 00000000000..1f41493b7e6 --- /dev/null +++ b/drivers/dma/Kconfig.cavs_gpdma @@ -0,0 +1,9 @@ +# cAVS GPDMA configuration options + +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config DMA_CAVS_GPDMA + bool "Enable cAVS GPDMA DMA driver" + help + Intel cAVS GPDMA DMA driver. diff --git a/drivers/dma/dma_cavs_gpdma.c b/drivers/dma/dma_cavs_gpdma.c new file mode 100644 index 00000000000..6efcafd4081 --- /dev/null +++ b/drivers/dma/dma_cavs_gpdma.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_cavs_gpdma + +#define GPDMA_CTL_OFFSET 0x004 +#define GPDMA_CTL_FDCGB BIT(0) + +#include "dma_dw_common.h" + +#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL +#include +LOG_MODULE_REGISTER(dma_cavs_gpdma); + + +/* Device run time data */ +struct cavs_gpdma_data { + struct dw_dma_dev_data dw_data; +}; + +/* Device constant configuration parameters */ +struct cavs_gpdma_cfg { + struct dw_dma_dev_cfg dw_cfg; + uint32_t shim; +}; + +/* Disables automatic clock gating (force disable clock gate) */ +static void cavs_gpdma_clock_enable(const struct device *dev) +{ + const struct cavs_gpdma_cfg *const dev_cfg = dev->config; + uint32_t reg = dev_cfg->shim + GPDMA_CTL_OFFSET; + + sys_write32(GPDMA_CTL_FDCGB, reg); +} + + +int cavs_gpdma_init(const struct device *dev) +{ + const struct cavs_gpdma_cfg *const dev_cfg = dev->config; + + /* Disable dynamic clock gating appropriately before initializing */ + cavs_gpdma_clock_enable(dev); + + /* Disable all channels and Channel interrupts */ + dw_dma_setup(dev); + + /* Configure interrupts */ + dev_cfg->dw_cfg.irq_config(); + + LOG_INF("Device %s initialized", dev->name); + + return 0; +} + + +static const struct dma_driver_api cavs_gpdma_driver_api = { + .config = dw_dma_config, + .reload = dw_dma_reload, + .start = dw_dma_transfer_start, + .stop = dw_dma_transfer_stop, +}; + + +#define CAVS_GPDMA_CHAN_ARB_DATA(inst) \ + static struct dw_drv_plat_data dmac##inst = { \ + .chan[0] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[1] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[2] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[3] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[4] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[5] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[6] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + .chan[7] = { \ + .class = 6, \ + .weight = 0, \ + }, \ + } + +#define CAVS_GPDMA_INIT(inst) \ + CAVS_GPDMA_CHAN_ARB_DATA(inst); \ + static void cavs_gpdma##inst##_irq_config(void); \ + \ + static const struct cavs_gpdma_cfg cavs_gpdma##inst##_config = { \ + .dw_cfg = { \ + .base = DT_INST_REG_ADDR(inst), \ + .irq_config = cavs_gpdma##inst##_irq_config, \ + }, \ + .shim = DT_INST_PROP_BY_IDX(inst, shim, 0), \ + }; \ + \ + static struct cavs_gpdma_data cavs_gpdma##inst##_data = { \ + .dw_data = { \ + .channel_data = &dmac##inst, \ + }, \ + }; \ + \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + &cavs_gpdma_init, \ + NULL, \ + &cavs_gpdma##inst##_data, \ + &cavs_gpdma##inst##_config, POST_KERNEL, \ + CONFIG_DMA_INIT_PRIORITY, \ + &cavs_gpdma_driver_api); \ + \ + static void cavs_gpdma##inst##_irq_config(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), \ + DT_INST_IRQ(inst, priority), dw_dma_isr, \ + DEVICE_DT_INST_GET(inst), \ + DT_INST_IRQ(inst, sense)); \ + irq_enable(DT_INST_IRQN(inst)); \ + } + +DT_INST_FOREACH_STATUS_OKAY(CAVS_GPDMA_INIT) diff --git a/dts/bindings/dma/intel,cavs-gpdma.yaml b/dts/bindings/dma/intel,cavs-gpdma.yaml new file mode 100644 index 00000000000..16394058f28 --- /dev/null +++ b/dts/bindings/dma/intel,cavs-gpdma.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2022 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Intel cAVS Designware based General Purpose DMA Controller node + +compatible: "intel,cavs-gpdma" + +include: snps,designware-dma.yaml + +properties: + shim: + type: array + required: true diff --git a/dts/xtensa/intel/intel_cavs25.dtsi b/dts/xtensa/intel/intel_cavs25.dtsi index a6d8acb6d3a..2aab5e60fbd 100644 --- a/dts/xtensa/intel/intel_cavs25.dtsi +++ b/dts/xtensa/intel/intel_cavs25.dtsi @@ -125,5 +125,29 @@ compatible = "intel,adsp-tlb"; reg = <0x3000 0x1000>; }; + + lpgpdma0: dma@7c000 { + compatible = "intel,cavs-gpdma"; + #dma-cells = <1>; + reg = <0x0007c000 0x1000>; + shim = <0x00078400 0x100>; + interrupts = <0x10 0 0>; + interrupt-parent = <&cavs3>; + label = "DMA_0"; + + status = "okay"; + }; + + lpgpdma1: dma@7d000 { + compatible = "intel,cavs-gpdma"; + #dma-cells = <1>; + reg = <0x0007d000 0x1000>; + shim = <0x00078500 0x100>; + interrupts = <0x0F 0 0>; + interrupt-parent = <&cavs3>; + label = "DMA_1"; + + status = "okay"; + }; }; }; diff --git a/soc/xtensa/intel_adsp/cavs_v25/Kconfig.defconfig.series b/soc/xtensa/intel_adsp/cavs_v25/Kconfig.defconfig.series index a9ef25ae126..fbc2841e235 100644 --- a/soc/xtensa/intel_adsp/cavs_v25/Kconfig.defconfig.series +++ b/soc/xtensa/intel_adsp/cavs_v25/Kconfig.defconfig.series @@ -72,4 +72,8 @@ config KERNEL_VM_SIZE endif +config DMA_CAVS_GPDMA + default y + depends on DMA + endif # SOC_SERIES_INTEL_CAVS_V25