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:
Anisetti Avinash Krishna 2023-05-14 23:18:14 +05:30 committed by Anas Nashif
parent c828e8cd02
commit 5925a4670b
9 changed files with 178 additions and 14 deletions

View file

@ -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)

View file

@ -58,4 +58,5 @@ source "drivers/dma/Kconfig.xmc4xxx"
source "drivers/dma/Kconfig.rpi_pico"
source "drivers/dma/Kconfig.intel_lpss"
endif # DMA

View file

@ -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.

View 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

View file

@ -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);
}

View file

@ -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 */

View 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)

View 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

View 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_ */