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 <thomas.burdick@intel.com>
This commit is contained in:
parent
f9acacfd11
commit
1e9ada4eb9
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -12,6 +12,10 @@
|
||||
model = "intel_adsp_cavs25";
|
||||
compatible = "intel";
|
||||
|
||||
aliases {
|
||||
dma0 = &lpgpdma0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram0;
|
||||
};
|
||||
|
||||
@ -5,6 +5,8 @@ arch: xtensa
|
||||
toolchain:
|
||||
- xcc
|
||||
- zephyr
|
||||
supported:
|
||||
- dma
|
||||
testing:
|
||||
ignore_tags:
|
||||
- net
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -44,4 +44,6 @@ source "drivers/dma/Kconfig.dma_pl330"
|
||||
|
||||
source "drivers/dma/Kconfig.iproc_pax"
|
||||
|
||||
source "drivers/dma/Kconfig.cavs_gpdma"
|
||||
|
||||
endif # DMA
|
||||
|
||||
9
drivers/dma/Kconfig.cavs_gpdma
Normal file
9
drivers/dma/Kconfig.cavs_gpdma
Normal file
@ -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.
|
||||
139
drivers/dma/dma_cavs_gpdma.c
Normal file
139
drivers/dma/dma_cavs_gpdma.c
Normal file
@ -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 <logging/log.h>
|
||||
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)
|
||||
13
dts/bindings/dma/intel,cavs-gpdma.yaml
Normal file
13
dts/bindings/dma/intel,cavs-gpdma.yaml
Normal file
@ -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
|
||||
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -72,4 +72,8 @@ config KERNEL_VM_SIZE
|
||||
|
||||
endif
|
||||
|
||||
config DMA_CAVS_GPDMA
|
||||
default y
|
||||
depends on DMA
|
||||
|
||||
endif # SOC_SERIES_INTEL_CAVS_V25
|
||||
|
||||
Loading…
Reference in New Issue
Block a user