kernel/0011-drivers-dw-axi-dmac-DMA-driver-changes-for-EIC7700.patch
2025-02-02 00:10:15 -05:00

638 lines
19 KiB
Diff

From 1971e8465456a4775d89de75f54cd646a319adb3 Mon Sep 17 00:00:00 2001
From: Xiang Xu <xuxiang@eswincomputing.com>
Date: Tue, 30 Jul 2024 04:54:27 +0000
Subject: [PATCH 011/128] drivers: dw-axi-dmac: DMA driver changes for EIC7700
- Removed cfgr clock as aon dma has separate cfg clk register bit
while dma0 havn't. Since dma cfg clk is default on we do not
need to control it
- Add arst and prst reset control
- Power on tbu and configure sid from hw init
Signed-off-by: Xiang Xu <xuxiang@eswincomputing.com>
Signed-off-by: Darshan Prajapati <darshan.prajapati@einfochips.com>
Signed-off-by: Pinkesh Vaghela <pinkesh.vaghela@einfochips.com>
---
.../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 292 +++++++++++++++++-
drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 28 +-
2 files changed, 312 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index 72fb40de58b3..c0c8763ca453 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -32,6 +32,13 @@
#include "dw-axi-dmac.h"
#include "../dmaengine.h"
#include "../virt-dma.h"
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#include <linux/iommu.h>
+#include <linux/mfd/syscon.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/eic7700-sid-cfg.h>
+#endif
/*
* The set of bus widths supported by the DMA controller. DW AXI DMAC supports
@@ -51,6 +58,15 @@
#define AXI_DMA_FLAG_HAS_RESETS BIT(1)
#define AXI_DMA_FLAG_USE_CFG2 BIT(2)
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#define AWSMMUSID GENMASK(31, 24) // The sid of write operation
+#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation
+#define ARSMMUSID GENMASK(15, 8) // The sid of read operation
+#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation
+
+static int eswin_dma_sid_cfg(struct device *dev);
+#endif
+
static inline void
axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val)
{
@@ -98,14 +114,26 @@ static inline void axi_chan_config_write(struct axi_dma_chan *chan,
config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS |
config->src_per << CH_CFG_H_SRC_PER_POS |
config->dst_per << CH_CFG_H_DST_PER_POS |
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ config->prior << CH_CFG_H_PRIORITY_POS |
+ 0xF <<CH_CFG_H_SRC_OSR_LMT_POS |
+ 0xF <<CH_CFG_H_DST_OSR_LMT_POS;
+#else
config->prior << CH_CFG_H_PRIORITY_POS;
+#endif
} else {
cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS |
config->dst_per << CH_CFG2_L_DST_PER_POS;
cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS |
config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS |
config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS |
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ config->prior << CH_CFG2_H_PRIORITY_POS |
+ 0xF <<CH_CFG2_H_SRC_OSR_LMT_POS |
+ 0xF <<CH_CFG2_H_DST_OSR_LMT_POS;
+#else
config->prior << CH_CFG2_H_PRIORITY_POS;
+#endif
}
axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo);
axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi);
@@ -228,6 +256,20 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip)
ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
if (ret)
dev_warn(chip->dev, "Unable to set coherent mask\n");
+
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp"))
+ {
+ eswin_dma_sid_cfg(chip->dev);
+ }
+ else
+ {
+ eic7700_aon_sid_cfg(chip->dev);
+ }
+
+ /* TBU power up */
+ eic7700_tbu_power(chip->dev, true);
+#endif
}
static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
@@ -333,7 +375,12 @@ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
completed_length = completed_blocks * len;
bytes = length - completed_length;
}
-
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ else
+ {
+ bytes = vd_to_axi_desc(vdesc)->length;
+ }
+#endif
spin_unlock_irqrestore(&chan->vc.lock, flags);
dma_set_residue(txstate, bytes);
@@ -455,6 +502,9 @@ static void dma_chan_issue_pending(struct dma_chan *dchan)
unsigned long flags;
spin_lock_irqsave(&chan->vc.lock, flags);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ chan->trigger = true;
+#endif
if (vchan_issue_pending(&chan->vc))
axi_chan_start_first_queued(chan);
spin_unlock_irqrestore(&chan->vc.lock, flags);
@@ -575,25 +625,60 @@ static void write_desc_dar(struct axi_dma_hw_desc *desc, dma_addr_t adr)
desc->lli->dar = cpu_to_le64(adr);
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+static void set_desc_src_master(struct axi_dma_hw_desc *desc, struct axi_dma_chan *chan)
+#else
static void set_desc_src_master(struct axi_dma_hw_desc *desc)
+#endif
{
u32 val;
/* Select AXI0 for source master */
val = le32_to_cpu(desc->lli->ctl_lo);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ if (chan->chip->dw->hdata->nr_masters > 1)
+ {
+ if(DMA_DEV_TO_MEM == chan->direction || DMA_DEV_TO_DEV == chan->direction) {
+ val |= CH_CTL_L_SRC_MAST;
+ }
+ else
+ {
+ val &= ~CH_CTL_L_SRC_MAST;
+ }
+ }
+ else
+ val &= ~CH_CTL_L_SRC_MAST;
+#else
val &= ~CH_CTL_L_SRC_MAST;
+#endif
desc->lli->ctl_lo = cpu_to_le32(val);
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc,
+ struct axi_dma_chan *chan)
+#else
static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc,
struct axi_dma_desc *desc)
+#endif
{
u32 val;
/* Select AXI1 for source master if available */
val = le32_to_cpu(hw_desc->lli->ctl_lo);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ if (chan->chip->dw->hdata->nr_masters > 1)
+ {
+ if(DMA_MEM_TO_DEV == chan->direction || DMA_DEV_TO_DEV == chan->direction) {
+ val |= CH_CTL_L_DST_MAST;
+ }
+ else
+ val &= ~CH_CTL_L_DST_MAST;
+ }
+#else
if (desc->chan->chip->dw->hdata->nr_masters > 1)
val |= CH_CTL_L_DST_MAST;
+#endif
else
val &= ~CH_CTL_L_DST_MAST;
@@ -612,6 +697,10 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
size_t block_ts;
u32 ctllo, ctlhi;
u32 burst_len;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ u32 src_maxburst;
+ u32 dst_maxburst;
+#endif
axi_block_ts = chan->chip->dw->hdata->block_size[chan->id];
@@ -624,6 +713,11 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
return -EINVAL;
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ src_maxburst = chan->chip->dw->hdata->max_msize;
+ dst_maxburst = chan->chip->dw->hdata->max_msize;
+#endif
+
switch (chan->direction) {
case DMA_MEM_TO_DEV:
reg_width = __ffs(chan->config.dst_addr_width);
@@ -632,6 +726,9 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
mem_width << CH_CTL_L_SRC_WIDTH_POS |
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS |
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ dst_maxburst = chan->config.dst_maxburst;
+#endif
block_ts = len >> mem_width;
break;
case DMA_DEV_TO_MEM:
@@ -641,6 +738,9 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
mem_width << CH_CTL_L_DST_WIDTH_POS |
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ src_maxburst = chan->config.src_maxburst;
+#endif
block_ts = len >> reg_width;
break;
default:
@@ -674,12 +774,27 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
}
hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
-
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ if(is_power_of_2(dst_maxburst) && is_power_of_2(src_maxburst))
+ {
+ dst_maxburst = order_base_2(dst_maxburst)? order_base_2(dst_maxburst) - 1 : 0;
+ src_maxburst = order_base_2(src_maxburst)? order_base_2(src_maxburst) - 1 : 0;
+ }else
+ dev_err(chan->chip->dev, "dst_burst or src_burst error!\n");
+ ctllo |= dst_maxburst << CH_CTL_L_DST_MSIZE_POS |
+ src_maxburst << CH_CTL_L_SRC_MSIZE_POS;
+#else
ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
+#endif
hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ set_desc_src_master(hw_desc, chan);
+ set_desc_dest_master(hw_desc, chan);
+#else
set_desc_src_master(hw_desc);
+#endif
hw_desc->len = len;
return 0;
@@ -880,6 +995,9 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
struct axi_dma_hw_desc *hw_desc = NULL;
struct axi_dma_desc *desc = NULL;
u32 xfer_width, reg, num;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ u32 max_burst_len;
+#endif
u64 llp = 0;
u8 lms = 0; /* Select AXI0 master for LLI fetching */
@@ -887,6 +1005,12 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
axi_chan_name(chan), &src_adr, &dst_adr, len, flags);
max_block_ts = chan->chip->dw->hdata->block_size[chan->id];
+
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ max_burst_len = chan->chip->dw->hdata->max_msize;
+ max_burst_len = order_base_2(max_burst_len)? order_base_2(max_burst_len) - 1 : 0;
+#endif
+
xfer_width = axi_chan_get_xfer_width(chan, src_adr, dst_adr, len);
num = DIV_ROUND_UP(len, max_block_ts << xfer_width);
desc = axi_desc_alloc(num);
@@ -937,17 +1061,26 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
}
hw_desc->lli->ctl_hi = cpu_to_le32(reg);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ reg = (max_burst_len << CH_CTL_L_DST_MSIZE_POS |
+ max_burst_len << CH_CTL_L_SRC_MSIZE_POS |
+#else
reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
+#endif
xfer_width << CH_CTL_L_DST_WIDTH_POS |
xfer_width << CH_CTL_L_SRC_WIDTH_POS |
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS);
hw_desc->lli->ctl_lo = cpu_to_le32(reg);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ set_desc_src_master(hw_desc, chan);
+ set_desc_dest_master(hw_desc, chan);
+#else
set_desc_src_master(hw_desc);
set_desc_dest_master(hw_desc, desc);
-
+#endif
hw_desc->len = xfer_len;
desc->length += hw_desc->len;
/* update the length and addresses for the next loop cycle */
@@ -1157,7 +1290,9 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
spin_lock_irqsave(&chan->vc.lock, flags);
vchan_get_all_descriptors(&chan->vc, &head);
-
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ chan->trigger = false;
+#endif
chan->cyclic = false;
spin_unlock_irqrestore(&chan->vc.lock, flags);
@@ -1246,8 +1381,9 @@ static int axi_dma_suspend(struct axi_dma_chip *chip)
axi_dma_disable(chip);
clk_disable_unprepare(chip->core_clk);
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
clk_disable_unprepare(chip->cfgr_clk);
-
+#endif
return 0;
}
@@ -1255,9 +1391,11 @@ static int axi_dma_resume(struct axi_dma_chip *chip)
{
int ret;
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
ret = clk_prepare_enable(chip->cfgr_clk);
if (ret < 0)
return ret;
+#endif
ret = clk_prepare_enable(chip->core_clk);
if (ret < 0)
@@ -1283,6 +1421,43 @@ static int __maybe_unused axi_dma_runtime_resume(struct device *dev)
return axi_dma_resume(chip);
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+int eic7700_dma_sel_cfg(struct axi_dma_chan *chan, u32 val)
+{
+ struct axi_dma_chip *chip = chan->chip;
+ struct device *dev = chan->chip->dev;
+ int ret = 0;
+ struct regmap *regmap;
+ int dma_sel_reg;
+ u32 dma_sel = 0;
+
+ regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg");
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "No eswin,syscfg phandle specified\n");
+ return -1;
+ }
+
+ ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", 2,
+ &dma_sel_reg);
+ if (ret) {
+ dev_err(dev, "can't get sid cfg reg offset in sys_con(errno:%d)\n", ret);
+ return ret;
+ }
+ regmap_read(regmap, dma_sel_reg, &dma_sel);
+
+ if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp")) {
+ if (val < 32)
+ dma_sel &= ~(1 << val);
+ }
+ else {
+ if (val < 32)
+ dma_sel |= (1 << val);
+ }
+ regmap_write(regmap, dma_sel_reg, dma_sel);
+ return 0;
+}
+#endif
+
static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
@@ -1296,6 +1471,10 @@ static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec,
chan = dchan_to_axi_dma_chan(dchan);
chan->hw_handshake_num = dma_spec->args[0];
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ if (dma_spec->args_count > 1)
+ eic7700_dma_sel_cfg(chan, dma_spec->args[1]);
+#endif
return dchan;
}
@@ -1366,6 +1545,20 @@ static int parse_device_properties(struct axi_dma_chip *chip)
chip->dw->hdata->axi_rw_burst_len = tmp;
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ /* max-size is optional property */
+ ret = device_property_read_u32(dev, "snps,max-msize", &tmp);
+ if (!ret) {
+ if (tmp > 1024)
+ return -EINVAL;
+ if (tmp < 1)
+ return -EINVAL;
+
+ chip->dw->hdata->max_msize = tmp;
+ }else
+ chip->dw->hdata->max_msize = 4;
+#endif
+
return 0;
}
@@ -1426,10 +1619,31 @@ static int dw_probe(struct platform_device *pdev)
if (IS_ERR(chip->core_clk))
return PTR_ERR(chip->core_clk);
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ chip->arst = devm_reset_control_get_optional(&pdev->dev, "arst");
+ if (IS_ERR_OR_NULL(chip->arst)) {
+ dev_err(chip->dev, "Failed to get axi reset handle\n");
+ return -EFAULT;
+ }
+ reset_control_deassert(chip->arst);
+
+ chip->prst = devm_reset_control_get_optional(&pdev->dev, "prst");
+ if (IS_ERR_OR_NULL(chip->prst)) {
+ dev_err(chip->dev, "Failed to get ahb reset handle\n");
+ return -EFAULT;
+ }
+ reset_control_deassert(chip->prst);
+#endif
+
+ /*
+ For EIC7700 SoC, aon dma has separate cfg clk register bit while dma0 havn't.
+ Since dma cfg clk is default on, so we don't control it
+ */
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
chip->cfgr_clk = devm_clk_get(chip->dev, "cfgr-clk");
if (IS_ERR(chip->cfgr_clk))
return PTR_ERR(chip->cfgr_clk);
-
+#endif
ret = parse_device_properties(chip);
if (ret)
return ret;
@@ -1463,7 +1677,12 @@ static int dw_probe(struct platform_device *pdev)
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
/* DMA capabilities */
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ dw->dma.chancnt = hdata->nr_channels;
+ dw->dma.max_burst = hdata->max_msize;
+#else
dw->dma.max_burst = hdata->axi_rw_burst_len;
+#endif
dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
dw->dma.directions = BIT(DMA_MEM_TO_MEM);
@@ -1533,6 +1752,53 @@ static int dw_probe(struct platform_device *pdev)
return ret;
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+static int eswin_dma_sid_cfg(struct device *dev)
+{
+ int ret;
+ struct regmap *regmap;
+ int hsp_mmu_dma_reg;
+ u32 rdwr_sid_ssid;
+ u32 sid;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+ /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/
+ if (fwspec == NULL) {
+ dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n");
+ return 0;
+ }
+ sid = fwspec->ids[0];
+
+ regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr");
+ if (IS_ERR(regmap)) {
+ dev_dbg(dev, "No hsp_sp_csr phandle specified\n");
+ return 0;
+ }
+
+ ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1,
+ &hsp_mmu_dma_reg);
+ if (ret) {
+ dev_err(dev, "can't get dma sid cfg reg offset (%d)\n", ret);
+ return ret;
+ }
+
+ /* make the reading sid the same as writing sid, ssid is fixed to zero */
+ rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid);
+ rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid);
+ rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0);
+ rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0);
+ regmap_write(regmap, hsp_mmu_dma_reg, rdwr_sid_ssid);
+
+ ret = eic7700_dynm_sid_enable(dev_to_node(dev));
+ if (ret < 0)
+ dev_err(dev, "failed to config dma streamID(%d)!\n", sid);
+ else
+ dev_dbg(dev, "success to config dma streamID(%d)!\n", sid);
+
+ return ret;
+}
+#endif
+
static int dw_remove(struct platform_device *pdev)
{
struct axi_dma_chip *chip = platform_get_drvdata(pdev);
@@ -1541,7 +1807,9 @@ static int dw_remove(struct platform_device *pdev)
u32 i;
/* Enable clk before accessing to registers */
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
clk_prepare_enable(chip->cfgr_clk);
+#endif
clk_prepare_enable(chip->core_clk);
axi_dma_irq_disable(chip);
for (i = 0; i < dw->hdata->nr_channels; i++) {
@@ -1559,10 +1827,20 @@ static int dw_remove(struct platform_device *pdev)
list_for_each_entry_safe(chan, _chan, &dw->dma.channels,
vc.chan.device_node) {
+#ifndef CONFIG_SOC_SIFIVE_EIC7700
list_del(&chan->vc.chan.device_node);
+#endif
tasklet_kill(&chan->vc.task);
}
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ /* TBU power down before reset */
+ eic7700_tbu_power(chip->dev, false);
+
+ reset_control_assert(chip->arst);
+ reset_control_assert(chip->prst);
+#endif
+
return 0;
}
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index 8521530a34ec..96f8ea7731de 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -15,7 +15,9 @@
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
-
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#include <linux/reset.h>
+#endif
#include "../virt-dma.h"
#define DMAC_MAX_CHANNELS 16
@@ -30,6 +32,9 @@ struct dw_axi_dma_hcfg {
u32 priority[DMAC_MAX_CHANNELS];
/* maximum supported axi burst length */
u32 axi_rw_burst_len;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ u32 max_msize;
+#endif
/* Register map for DMAX_NUM_CHANNELS <= 8 */
bool reg_map_8_channels;
bool restrict_axi_burst_len;
@@ -52,6 +57,9 @@ struct axi_dma_chan {
bool cyclic;
/* these other elements are all protected by vc.lock */
bool is_paused;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ bool trigger;
+#endif
};
struct dw_axi_dma {
@@ -71,6 +79,10 @@ struct axi_dma_chip {
struct clk *core_clk;
struct clk *cfgr_clk;
struct dw_axi_dma *dw;
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+ struct reset_control *arst;
+ struct reset_control *prst;
+#endif
};
/* LLI == Linked List Item */
@@ -203,7 +215,11 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define UNUSED_CHANNEL 0x3F /* Set unused DMA channel to 0x3F */
#define DMA_APB_HS_SEL_BIT_SIZE 0x08 /* HW handshake bits per channel */
#define DMA_APB_HS_SEL_MASK 0xFF /* HW handshake select masks */
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#define MAX_BLOCK_SIZE 0x80000 /* 1024 blocks * 512 bytes data width */
+#else
#define MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 4 bytes data width */
+#endif
#define DMA_REG_MAP_CH_REF 0x08 /* Channel count to choose register map */
/* DMAC_CFG */
@@ -283,6 +299,10 @@ enum {
#define CH_CTL_L_SRC_MAST BIT(0)
/* CH_CFG_H */
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#define CH_CFG_H_DST_OSR_LMT_POS 27
+#define CH_CFG_H_SRC_OSR_LMT_POS 23
+#endif
#define CH_CFG_H_PRIORITY_POS 17
#define CH_CFG_H_DST_PER_POS 12
#define CH_CFG_H_SRC_PER_POS 7
@@ -322,7 +342,13 @@ enum {
#define CH_CFG2_H_TT_FC_POS 0
#define CH_CFG2_H_HS_SEL_SRC_POS 3
#define CH_CFG2_H_HS_SEL_DST_POS 4
+#ifdef CONFIG_SOC_SIFIVE_EIC7700
+#define CH_CFG2_H_PRIORITY_POS 15
+#define CH_CFG2_H_SRC_OSR_LMT_POS 23
+#define CH_CFG2_H_DST_OSR_LMT_POS 27
+#else
#define CH_CFG2_H_PRIORITY_POS 20
+#endif
/**
* DW AXI DMA channel interrupts
--
2.47.0