drivers: dma: dma_intel_lpss: Added intel LPSS DMA interface
Added intel LPSS DMA interface using dw common to support usage of internal DMA in LPSS UART, SPI and I2C for transfer and receive operations. Signed-off-by: Anisetti Avinash Krishna <anisetti.avinash.krishna@intel.com>
This commit is contained in:
parent
c828e8cd02
commit
5925a4670b
|
@ -23,6 +23,7 @@ zephyr_library_sources_ifdef(CONFIG_DMA_INTEL_ADSP_HDA_HOST_OUT dma_intel_adsp_h
|
|||
zephyr_library_sources_ifdef(CONFIG_DMA_INTEL_ADSP_HDA_LINK_IN dma_intel_adsp_hda_link_in.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_INTEL_ADSP_HDA_LINK_OUT dma_intel_adsp_hda_link_out.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_INTEL_ADSP_GPDMA dma_intel_adsp_gpdma.c dma_dw_common.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_INTEL_LPSS dma_intel_lpss.c dma_dw_common.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_GD32 dma_gd32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_ESP32 dma_esp32_gdma.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DMA_MCHP_XEC dma_mchp_xec.c)
|
||||
|
|
|
@ -58,4 +58,5 @@ source "drivers/dma/Kconfig.xmc4xxx"
|
|||
|
||||
source "drivers/dma/Kconfig.rpi_pico"
|
||||
|
||||
source "drivers/dma/Kconfig.intel_lpss"
|
||||
endif # DMA
|
||||
|
|
|
@ -38,3 +38,9 @@ config DMA_DW_HOST_MASK
|
|||
help
|
||||
Some instances of the DesignWare DMAC require a mask applied to source/destination
|
||||
addresses to signifiy the memory space the address is in.
|
||||
|
||||
config DMA_DW_CHANNEL_COUNT
|
||||
int "dw max channel count"
|
||||
default 8
|
||||
help
|
||||
Channel count for designware DMA instances.
|
||||
|
|
17
drivers/dma/Kconfig.intel_lpss
Normal file
17
drivers/dma/Kconfig.intel_lpss
Normal file
|
@ -0,0 +1,17 @@
|
|||
# LPSS DMA configuration options
|
||||
|
||||
# Copyright (c) 2023 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config DMA_INTEL_LPSS
|
||||
bool "INTEL LPSS DMA driver"
|
||||
default n
|
||||
depends on DT_HAS_INTEL_LPSS_ENABLED
|
||||
help
|
||||
INTEL LPSS DMA driver.
|
||||
|
||||
if DMA_INTEL_LPSS
|
||||
|
||||
source "drivers/dma/Kconfig.dw_common"
|
||||
|
||||
endif # DMA_INTEL_LPSS
|
|
@ -132,7 +132,7 @@ int dw_dma_config(const struct device *dev, uint32_t channel,
|
|||
uint32_t msize = 3;/* default msize, 8 bytes */
|
||||
int ret = 0;
|
||||
|
||||
if (channel >= DW_MAX_CHAN) {
|
||||
if (channel >= DW_CHAN_COUNT) {
|
||||
LOG_ERR("%s: invalid dma channel %d", __func__, channel);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
@ -444,7 +444,7 @@ int dw_dma_start(const struct device *dev, uint32_t channel)
|
|||
int ret = 0;
|
||||
|
||||
/* validate channel */
|
||||
if (channel >= DW_MAX_CHAN) {
|
||||
if (channel >= DW_CHAN_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -492,10 +492,10 @@ int dw_dma_start(const struct device *dev, uint32_t channel)
|
|||
|
||||
/* channel needs to start from scratch, so write SAR and DAR */
|
||||
#ifdef CONFIG_DMA_64BIT
|
||||
dw_write(dev_cfg->base, DW_SAR(channel), (uint32_t)(lli->sar & BIT_MASK(32)));
|
||||
dw_write(dev_cfg->base, DW_SAR_HI(channel), (uint32_t)(lli->sar >> 32));
|
||||
dw_write(dev_cfg->base, DW_DAR(channel), (uint32_t)(lli->dar & BIT_MASK(32)));
|
||||
dw_write(dev_cfg->base, DW_DAR_HI(channel), (uint32_t)(lli->dar >> 32));
|
||||
dw_write(dev_cfg->base, DW_SAR(channel), (uint32_t)(lli->sar & DW_ADDR_MASK_32));
|
||||
dw_write(dev_cfg->base, DW_SAR_HI(channel), (uint32_t)(lli->sar >> DW_ADDR_RIGHT_SHIFT));
|
||||
dw_write(dev_cfg->base, DW_DAR(channel), (uint32_t)(lli->dar & DW_ADDR_MASK_32));
|
||||
dw_write(dev_cfg->base, DW_DAR_HI(channel), (uint32_t)(lli->dar >> DW_ADDR_RIGHT_SHIFT));
|
||||
#else
|
||||
dw_write(dev_cfg->base, DW_SAR(channel), lli->sar);
|
||||
dw_write(dev_cfg->base, DW_DAR(channel), lli->dar);
|
||||
|
@ -548,7 +548,7 @@ int dw_dma_stop(const struct device *dev, uint32_t channel)
|
|||
struct dw_dma_chan_data *chan_data = &dev_data->chan[channel];
|
||||
int ret = 0;
|
||||
|
||||
if (channel >= DW_MAX_CHAN) {
|
||||
if (channel >= DW_CHAN_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -617,7 +617,7 @@ int dw_dma_resume(const struct device *dev, uint32_t channel)
|
|||
int ret = 0;
|
||||
|
||||
/* Validate channel index */
|
||||
if (channel >= DW_MAX_CHAN) {
|
||||
if (channel >= DW_CHAN_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ int dw_dma_suspend(const struct device *dev, uint32_t channel)
|
|||
int ret = 0;
|
||||
|
||||
/* Validate channel index */
|
||||
if (channel >= DW_MAX_CHAN) {
|
||||
if (channel >= DW_CHAN_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -704,7 +704,7 @@ int dw_dma_setup(const struct device *dev)
|
|||
|
||||
LOG_DBG("%s: dma %s", __func__, dev->name);
|
||||
|
||||
for (i = 0; i < DW_MAX_CHAN; i++) {
|
||||
for (i = 0; i < DW_CHAN_COUNT; i++) {
|
||||
dw_read(dev_cfg->base, DW_DMA_CHAN_EN);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,11 @@ extern "C" {
|
|||
(((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo))
|
||||
|
||||
#define DW_MAX_CHAN 8
|
||||
#define DW_CHAN_COUNT CONFIG_DMA_DW_CHANNEL_COUNT
|
||||
#define DW_CH_SIZE 0x58
|
||||
#define DW_CHAN_OFFSET(chan) (DW_CH_SIZE * chan)
|
||||
#define DW_ADDR_MASK_32 BIT_MASK(32)
|
||||
#define DW_ADDR_RIGHT_SHIFT 32
|
||||
|
||||
#define DW_SAR(chan) \
|
||||
(0x0000 + DW_CHAN_OFFSET(chan))
|
||||
|
@ -176,7 +179,7 @@ struct dw_chan_arbit_data {
|
|||
};
|
||||
|
||||
struct dw_drv_plat_data {
|
||||
struct dw_chan_arbit_data chan[DW_MAX_CHAN];
|
||||
struct dw_chan_arbit_data chan[DW_CHAN_COUNT];
|
||||
};
|
||||
|
||||
/* DMA descriptor used by HW */
|
||||
|
@ -187,6 +190,7 @@ struct dw_lli {
|
|||
#else
|
||||
uint32_t sar;
|
||||
uint32_t dar;
|
||||
#endif
|
||||
uint32_t llp;
|
||||
uint32_t ctrl_lo;
|
||||
uint32_t ctrl_hi;
|
||||
|
@ -242,10 +246,10 @@ static const uint32_t burst_elems[] = {1, 2, 4, 8};
|
|||
struct dw_dma_dev_data {
|
||||
struct dma_context dma_ctx;
|
||||
struct dw_drv_plat_data *channel_data;
|
||||
struct dw_dma_chan_data chan[DW_MAX_CHAN];
|
||||
struct dw_lli lli_pool[DW_MAX_CHAN][CONFIG_DMA_DW_LLI_POOL_SIZE] __aligned(64);
|
||||
struct dw_dma_chan_data chan[DW_CHAN_COUNT];
|
||||
struct dw_lli lli_pool[DW_CHAN_COUNT][CONFIG_DMA_DW_LLI_POOL_SIZE] __aligned(64);
|
||||
|
||||
ATOMIC_DEFINE(channels_atomic, DW_MAX_CHAN);
|
||||
ATOMIC_DEFINE(channels_atomic, DW_CHAN_COUNT);
|
||||
};
|
||||
|
||||
/* Device constant configuration parameters */
|
||||
|
|
100
drivers/dma/dma_intel_lpss.c
Normal file
100
drivers/dma/dma_intel_lpss.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT intel_lpss
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/drivers/dma.h>
|
||||
#include <zephyr/drivers/dma/dma_intel_lpss.h>
|
||||
#include "dma_dw_common.h"
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/irq.h>
|
||||
LOG_MODULE_REGISTER(dma_intel_lpss, CONFIG_DMA_LOG_LEVEL);
|
||||
|
||||
struct dma_intel_lpss_cfg {
|
||||
struct dw_dma_dev_cfg dw_cfg;
|
||||
const struct device *parent;
|
||||
};
|
||||
|
||||
static int dma_intel_lpss_init(const struct device *dev)
|
||||
{
|
||||
struct dma_intel_lpss_cfg *dev_cfg = (struct dma_intel_lpss_cfg *)dev->config;
|
||||
uint32_t base;
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(dev_cfg->parent)) {
|
||||
LOG_ERR("LPSS DMA parent not ready");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
base = DEVICE_MMIO_GET(dev_cfg->parent) + DMA_INTEL_LPSS_OFFSET;
|
||||
dev_cfg->dw_cfg.base = base;
|
||||
|
||||
ret = dw_dma_setup(dev);
|
||||
|
||||
if (ret != 0) {
|
||||
LOG_ERR("failed to initialize LPSS DMA %s", dev->name);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dma_intel_lpss_isr(const struct device *dev)
|
||||
{
|
||||
dw_dma_isr(dev);
|
||||
}
|
||||
|
||||
static const struct dma_driver_api dma_intel_lpss_driver_api = {
|
||||
.config = dw_dma_config,
|
||||
.start = dw_dma_start,
|
||||
.stop = dw_dma_stop,
|
||||
};
|
||||
|
||||
#define DMA_INTEL_LPSS_INIT(n) \
|
||||
\
|
||||
static struct dw_drv_plat_data dma_intel_lpss##n = { \
|
||||
.chan[0] = { \
|
||||
.class = 6, \
|
||||
.weight = 0, \
|
||||
}, \
|
||||
.chan[1] = { \
|
||||
.class = 6, \
|
||||
.weight = 0, \
|
||||
}, \
|
||||
}; \
|
||||
\
|
||||
\
|
||||
static struct dma_intel_lpss_cfg dma_intel_lpss##n##_config = { \
|
||||
.dw_cfg = { \
|
||||
.base = 0, \
|
||||
}, \
|
||||
.parent = DEVICE_DT_GET(DT_INST_PARENT(n)), \
|
||||
}; \
|
||||
\
|
||||
static struct dw_dma_dev_data dma_intel_lpss##n##_data = { \
|
||||
.channel_data = &dma_intel_lpss##n, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
&dma_intel_lpss_init, \
|
||||
NULL, \
|
||||
&dma_intel_lpss##n##_data, \
|
||||
&dma_intel_lpss##n##_config, POST_KERNEL, \
|
||||
DMA_INTEL_LPSS_INIT_PRIORITY, \
|
||||
&dma_intel_lpss_driver_api); \
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DMA_INTEL_LPSS_INIT)
|
15
dts/bindings/dma/intel,lpss.yaml
Normal file
15
dts/bindings/dma/intel,lpss.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: LPSS DMA Controller node
|
||||
|
||||
compatible: "intel,lpss"
|
||||
|
||||
include: dma-controller.yaml
|
||||
|
||||
properties:
|
||||
"#dma-cells":
|
||||
const: 1
|
||||
|
||||
dma-cells:
|
||||
- channel
|
20
include/zephyr/drivers/dma/dma_intel_lpss.h
Normal file
20
include/zephyr/drivers/dma/dma_intel_lpss.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_
|
||||
|
||||
#define DMA_INTEL_LPSS_INIT_PRIORITY 80
|
||||
#define DMA_INTEL_LPSS_OFFSET 0x800
|
||||
#define DMA_INTEL_LPSS_REMAP_LOW 0x240
|
||||
#define DMA_INTEL_LPSS_REMAP_HI 0x244
|
||||
#define DMA_INTEL_LPSS_TX_CHAN 0
|
||||
#define DMA_INTEL_LPSS_RX_CHAN 1
|
||||
#define DMA_INTEL_LPSS_ADDR_RIGHT_SHIFT 32
|
||||
|
||||
void dma_intel_lpss_isr(const struct device *dev);
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_INTEL_LPSS_H_ */
|
Loading…
Reference in a new issue