* [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips
@ 2024-10-31 12:35 Csókás, Bence
2024-10-31 12:35 ` [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk Csókás, Bence
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Csókás, Bence @ 2024-10-31 12:35 UTC (permalink / raw)
To: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel
Cc: Mesih Kilinc, Csókás, Bence, Vinod Koul, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland
From: Mesih Kilinc <mesihkilinc@gmail.com>
Allwinner suniv F1C100s has similar DMA engine to sun4i. Several
registers has different addresses. Total dma channels, endpoint counts
and max burst counts are also different.
In order to support F1C100s add a quirk structure to hold IC specific
data.
Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
[ csokas.bence: Resolve conflict in `sun4i_dma_prep_dma_cyclic()`, fix whitespace ]
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
---
Notes:
Changes in v2:
* Whitespace
drivers/dma/sun4i-dma.c | 138 ++++++++++++++++++++++++++++++----------
1 file changed, 106 insertions(+), 32 deletions(-)
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 2e7f9b07fdd2..d472f57a39ea 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_dma.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -31,6 +32,8 @@
#define SUN4I_DMA_CFG_SRC_ADDR_MODE(mode) ((mode) << 5)
#define SUN4I_DMA_CFG_SRC_DRQ_TYPE(type) (type)
+#define SUN4I_MAX_BURST 8
+
/** Normal DMA register values **/
/* Normal DMA source/destination data request type values */
@@ -132,6 +135,32 @@
#define SUN4I_DDMA_MAX_SEG_SIZE SZ_16M
#define SUN4I_DMA_MAX_SEG_SIZE SUN4I_NDMA_MAX_SEG_SIZE
+/*
+ * Hardware channels / ports representation
+ *
+ * The hardware is used in several SoCs, with differing numbers
+ * of channels and endpoints. This structure ties those numbers
+ * to a certain compatible string.
+ */
+struct sun4i_dma_config {
+ u32 ndma_nr_max_channels;
+ u32 ndma_nr_max_vchans;
+
+ u32 ddma_nr_max_channels;
+ u32 ddma_nr_max_vchans;
+
+ u32 dma_nr_max_channels;
+
+ void (*set_dst_data_width)(u32 *p_cfg, s8 data_width);
+ void (*set_src_data_width)(u32 *p_cfg, s8 data_width);
+ int (*convert_burst)(u32 maxburst);
+
+ u8 ndma_drq_sdram;
+ u8 ddma_drq_sdram;
+
+ u8 max_burst;
+};
+
struct sun4i_dma_pchan {
/* Register base of channel */
void __iomem *base;
@@ -170,7 +199,7 @@ struct sun4i_dma_contract {
};
struct sun4i_dma_dev {
- DECLARE_BITMAP(pchans_used, SUN4I_DMA_NR_MAX_CHANNELS);
+ unsigned long *pchans_used;
struct dma_device slave;
struct sun4i_dma_pchan *pchans;
struct sun4i_dma_vchan *vchans;
@@ -178,6 +207,7 @@ struct sun4i_dma_dev {
struct clk *clk;
int irq;
spinlock_t lock;
+ const struct sun4i_dma_config *cfg;
};
static struct sun4i_dma_dev *to_sun4i_dma_dev(struct dma_device *dev)
@@ -200,7 +230,17 @@ static struct device *chan2dev(struct dma_chan *chan)
return &chan->dev->device;
}
-static int convert_burst(u32 maxburst)
+static void set_dst_data_width_a10(u32 *p_cfg, s8 data_width)
+{
+ *p_cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(data_width);
+}
+
+static void set_src_data_width_a10(u32 *p_cfg, s8 data_width)
+{
+ *p_cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(data_width);
+}
+
+static int convert_burst_a10(u32 maxburst)
{
if (maxburst > 8)
return -EINVAL;
@@ -233,15 +273,15 @@ static struct sun4i_dma_pchan *find_and_use_pchan(struct sun4i_dma_dev *priv,
int i, max;
/*
- * pchans 0-SUN4I_NDMA_NR_MAX_CHANNELS are normal, and
- * SUN4I_NDMA_NR_MAX_CHANNELS+ are dedicated ones
+ * pchans 0-priv->cfg->ndma_nr_max_channels are normal, and
+ * priv->cfg->ndma_nr_max_channels+ are dedicated ones
*/
if (vchan->is_dedicated) {
- i = SUN4I_NDMA_NR_MAX_CHANNELS;
- max = SUN4I_DMA_NR_MAX_CHANNELS;
+ i = priv->cfg->ndma_nr_max_channels;
+ max = priv->cfg->dma_nr_max_channels;
} else {
i = 0;
- max = SUN4I_NDMA_NR_MAX_CHANNELS;
+ max = priv->cfg->ndma_nr_max_channels;
}
spin_lock_irqsave(&priv->lock, flags);
@@ -444,6 +484,7 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
size_t len, struct dma_slave_config *sconfig,
enum dma_transfer_direction direction)
{
+ struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
struct sun4i_dma_promise *promise;
int ret;
@@ -467,13 +508,13 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
sconfig->src_addr_width, sconfig->dst_addr_width);
/* Source burst */
- ret = convert_burst(sconfig->src_maxburst);
+ ret = priv->cfg->convert_burst(sconfig->src_maxburst);
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
/* Destination burst */
- ret = convert_burst(sconfig->dst_maxburst);
+ ret = priv->cfg->convert_burst(sconfig->dst_maxburst);
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
@@ -482,13 +523,13 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
ret = convert_buswidth(sconfig->src_addr_width);
if (ret < 0)
goto fail;
- promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
+ priv->cfg->set_src_data_width(&promise->cfg, ret);
/* Destination bus width */
ret = convert_buswidth(sconfig->dst_addr_width);
if (ret < 0)
goto fail;
- promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
+ priv->cfg->set_dst_data_width(&promise->cfg, ret);
return promise;
@@ -510,6 +551,7 @@ static struct sun4i_dma_promise *
generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
size_t len, struct dma_slave_config *sconfig)
{
+ struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
struct sun4i_dma_promise *promise;
int ret;
@@ -524,13 +566,13 @@ generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
SUN4I_DDMA_CFG_BYTE_COUNT_MODE_REMAIN;
/* Source burst */
- ret = convert_burst(sconfig->src_maxburst);
+ ret = priv->cfg->convert_burst(sconfig->src_maxburst);
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
/* Destination burst */
- ret = convert_burst(sconfig->dst_maxburst);
+ ret = priv->cfg->convert_burst(sconfig->dst_maxburst);
if (ret < 0)
goto fail;
promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
@@ -539,13 +581,13 @@ generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
ret = convert_buswidth(sconfig->src_addr_width);
if (ret < 0)
goto fail;
- promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
+ priv->cfg->set_src_data_width(&promise->cfg, ret);
/* Destination bus width */
ret = convert_buswidth(sconfig->dst_addr_width);
if (ret < 0)
goto fail;
- promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
+ priv->cfg->set_dst_data_width(&promise->cfg, ret);
return promise;
@@ -622,6 +664,7 @@ static struct dma_async_tx_descriptor *
sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
dma_addr_t src, size_t len, unsigned long flags)
{
+ struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
struct dma_slave_config *sconfig = &vchan->cfg;
struct sun4i_dma_promise *promise;
@@ -638,8 +681,8 @@ sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
*/
sconfig->src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
sconfig->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- sconfig->src_maxburst = 8;
- sconfig->dst_maxburst = 8;
+ sconfig->src_maxburst = priv->cfg->max_burst;
+ sconfig->dst_maxburst = priv->cfg->max_burst;
if (vchan->is_dedicated)
promise = generate_ddma_promise(chan, src, dest, len, sconfig);
@@ -654,11 +697,13 @@ sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
/* Configure memcpy mode */
if (vchan->is_dedicated) {
- promise->cfg |= SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_DDMA_DRQ_TYPE_SDRAM) |
- SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_DDMA_DRQ_TYPE_SDRAM);
+ promise->cfg |=
+ SUN4I_DMA_CFG_SRC_DRQ_TYPE(priv->cfg->ddma_drq_sdram) |
+ SUN4I_DMA_CFG_DST_DRQ_TYPE(priv->cfg->ddma_drq_sdram);
} else {
- promise->cfg |= SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM) |
- SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM);
+ promise->cfg |=
+ SUN4I_DMA_CFG_SRC_DRQ_TYPE(priv->cfg->ndma_drq_sdram) |
+ SUN4I_DMA_CFG_DST_DRQ_TYPE(priv->cfg->ndma_drq_sdram);
}
/* Fill the contract with our only promise */
@@ -673,6 +718,7 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
size_t period_len, enum dma_transfer_direction dir,
unsigned long flags)
{
+ struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
struct dma_slave_config *sconfig = &vchan->cfg;
struct sun4i_dma_promise *promise;
@@ -696,11 +742,11 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
if (vchan->is_dedicated) {
io_mode = SUN4I_DDMA_ADDR_MODE_IO;
linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
- ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
+ ram_type = priv->cfg->ddma_drq_sdram;
} else {
io_mode = SUN4I_NDMA_ADDR_MODE_IO;
linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
- ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
+ ram_type = priv->cfg->ndma_drq_sdram;
}
if (dir == DMA_MEM_TO_DEV) {
@@ -793,6 +839,7 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
{
+ struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
struct dma_slave_config *sconfig = &vchan->cfg;
struct sun4i_dma_promise *promise;
@@ -818,11 +865,11 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (vchan->is_dedicated) {
io_mode = SUN4I_DDMA_ADDR_MODE_IO;
linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
- ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
+ ram_type = priv->cfg->ddma_drq_sdram;
} else {
io_mode = SUN4I_NDMA_ADDR_MODE_IO;
linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
- ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
+ ram_type = priv->cfg->ndma_drq_sdram;
}
if (dir == DMA_MEM_TO_DEV)
@@ -1150,6 +1197,10 @@ static int sun4i_dma_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->cfg = of_device_get_match_data(&pdev->dev);
+ if (!priv->cfg)
+ return -ENODEV;
+
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
@@ -1197,23 +1248,26 @@ static int sun4i_dma_probe(struct platform_device *pdev)
priv->slave.dev = &pdev->dev;
- priv->pchans = devm_kcalloc(&pdev->dev, SUN4I_DMA_NR_MAX_CHANNELS,
+ priv->pchans = devm_kcalloc(&pdev->dev, priv->cfg->dma_nr_max_channels,
sizeof(struct sun4i_dma_pchan), GFP_KERNEL);
priv->vchans = devm_kcalloc(&pdev->dev, SUN4I_DMA_NR_MAX_VCHANS,
sizeof(struct sun4i_dma_vchan), GFP_KERNEL);
- if (!priv->vchans || !priv->pchans)
+ priv->pchans_used = devm_kcalloc(&pdev->dev,
+ BITS_TO_LONGS(priv->cfg->dma_nr_max_channels),
+ sizeof(unsigned long), GFP_KERNEL);
+ if (!priv->vchans || !priv->pchans || !priv->pchans_used)
return -ENOMEM;
/*
- * [0..SUN4I_NDMA_NR_MAX_CHANNELS) are normal pchans, and
- * [SUN4I_NDMA_NR_MAX_CHANNELS..SUN4I_DMA_NR_MAX_CHANNELS) are
+ * [0..priv->cfg->ndma_nr_max_channels) are normal pchans, and
+ * [priv->cfg->ndma_nr_max_channels..priv->cfg->dma_nr_max_channels) are
* dedicated ones
*/
- for (i = 0; i < SUN4I_NDMA_NR_MAX_CHANNELS; i++)
+ for (i = 0; i < priv->cfg->ndma_nr_max_channels; i++)
priv->pchans[i].base = priv->base +
SUN4I_NDMA_CHANNEL_REG_BASE(i);
- for (j = 0; i < SUN4I_DMA_NR_MAX_CHANNELS; i++, j++) {
+ for (j = 0; i < priv->cfg->dma_nr_max_channels; i++, j++) {
priv->pchans[i].base = priv->base +
SUN4I_DDMA_CHANNEL_REG_BASE(j);
priv->pchans[i].is_dedicated = 1;
@@ -1284,8 +1338,28 @@ static void sun4i_dma_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
}
+static struct sun4i_dma_config sun4i_a10_dma_cfg = {
+ .ndma_nr_max_channels = SUN4I_NDMA_NR_MAX_CHANNELS,
+ .ndma_nr_max_vchans = SUN4I_NDMA_NR_MAX_VCHANS,
+
+ .ddma_nr_max_channels = SUN4I_DDMA_NR_MAX_CHANNELS,
+ .ddma_nr_max_vchans = SUN4I_DDMA_NR_MAX_VCHANS,
+
+ .dma_nr_max_channels = SUN4I_NDMA_NR_MAX_CHANNELS +
+ SUN4I_DDMA_NR_MAX_CHANNELS,
+
+ .set_dst_data_width = set_dst_data_width_a10,
+ .set_src_data_width = set_src_data_width_a10,
+ .convert_burst = convert_burst_a10,
+
+ .ndma_drq_sdram = SUN4I_NDMA_DRQ_TYPE_SDRAM,
+ .ddma_drq_sdram = SUN4I_DDMA_DRQ_TYPE_SDRAM,
+
+ .max_burst = SUN4I_MAX_BURST,
+};
+
static const struct of_device_id sun4i_dma_match[] = {
- { .compatible = "allwinner,sun4i-a10-dma" },
+ { .compatible = "allwinner,sun4i-a10-dma", .data = &sun4i_a10_dma_cfg },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, sun4i_dma_match);
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk
2024-10-31 12:35 [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Csókás, Bence
@ 2024-10-31 12:35 ` Csókás, Bence
2024-10-31 15:47 ` Krzysztof Kozlowski
2024-10-31 12:35 ` [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA Csókás, Bence
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Csókás, Bence @ 2024-10-31 12:35 UTC (permalink / raw)
To: dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel
Cc: Mesih Kilinc, Chen-Yu Tsai, Krzysztof Kozlowski,
Csókás, Bence, Vinod Koul, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel
From: Mesih Kilinc <mesihkilinc@gmail.com>
Allwinner suniv F1C100s has a reset bit for DMA in CCU. Sun4i do not
has this bit but in order to support suniv we need to add it. So add
support for reset bit.
Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
[ csokas.bence: Rebased and addressed comments ]
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
---
Notes:
Changes in v2:
* Call reset_control_deassert() unconditionally, as it supports optional resets
* Use dev_err_probe()
* Whitespace
Changes in v3:
* More dev_err_probe() fixes
Changes in v3:
* Use return value of dev_err_probe()
drivers/dma/sun4i-dma.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index d472f57a39ea..4626cc8ad114 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -15,6 +15,7 @@
#include <linux/of_dma.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -159,6 +160,7 @@ struct sun4i_dma_config {
u8 ddma_drq_sdram;
u8 max_burst;
+ bool has_reset;
};
struct sun4i_dma_pchan {
@@ -208,6 +210,7 @@ struct sun4i_dma_dev {
int irq;
spinlock_t lock;
const struct sun4i_dma_config *cfg;
+ struct reset_control *rst;
};
static struct sun4i_dma_dev *to_sun4i_dma_dev(struct dma_device *dev)
@@ -1215,6 +1218,15 @@ static int sun4i_dma_probe(struct platform_device *pdev)
return PTR_ERR(priv->clk);
}
+ if (priv->cfg->has_reset) {
+ priv->rst = devm_reset_control_get_exclusive(&pdev->dev,
+ NULL);
+ if (IS_ERR(priv->rst)) {
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst),
+ "Failed to get reset control\n");
+ }
+ }
+
platform_set_drvdata(pdev, priv);
spin_lock_init(&priv->lock);
@@ -1287,6 +1299,14 @@ static int sun4i_dma_probe(struct platform_device *pdev)
return ret;
}
+ /* Deassert the reset control */
+ ret = reset_control_deassert(priv->rst);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret,
+ "Failed to deassert the reset control\n");
+ goto err_clk_disable;
+ }
+
/*
* Make sure the IRQs are all disabled and accounted for. The bootloader
* likes to leave these dirty
@@ -1356,6 +1376,7 @@ static struct sun4i_dma_config sun4i_a10_dma_cfg = {
.ddma_drq_sdram = SUN4I_DDMA_DRQ_TYPE_SDRAM,
.max_burst = SUN4I_MAX_BURST,
+ .has_reset = false,
};
static const struct of_device_id sun4i_dma_match[] = {
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk
2024-10-31 12:35 ` [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk Csókás, Bence
@ 2024-10-31 15:47 ` Krzysztof Kozlowski
0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-31 15:47 UTC (permalink / raw)
To: Csókás, Bence, dmaengine, linux-arm-kernel, linux-sunxi,
linux-kernel
Cc: Mesih Kilinc, Chen-Yu Tsai, Vinod Koul, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Philipp Zabel
On 31/10/2024 13:35, Csókás, Bence wrote:
> From: Mesih Kilinc <mesihkilinc@gmail.com>
>
> Allwinner suniv F1C100s has a reset bit for DMA in CCU. Sun4i do not
> has this bit but in order to support suniv we need to add it. So add
> support for reset bit.
>
> Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
> [ csokas.bence: Rebased and addressed comments ]
> Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
> ---
>
> Notes:
> Changes in v2:
> * Call reset_control_deassert() unconditionally, as it supports optional resets
> * Use dev_err_probe()
> * Whitespace
> Changes in v3:
> * More dev_err_probe() fixes
> Changes in v3:
> * Use return value of dev_err_probe()
>
> drivers/dma/sun4i-dma.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
> index d472f57a39ea..4626cc8ad114 100644
> --- a/drivers/dma/sun4i-dma.c
> +++ b/drivers/dma/sun4i-dma.c
> @@ -15,6 +15,7 @@
> #include <linux/of_dma.h>
> #include <linux/of_device.h>
> #include <linux/platform_device.h>
> +#include <linux/reset.h>
> #include <linux/slab.h>
> #include <linux/spinlock.h>
>
> @@ -159,6 +160,7 @@ struct sun4i_dma_config {
> u8 ddma_drq_sdram;
>
> u8 max_burst;
> + bool has_reset;
> };
>
> struct sun4i_dma_pchan {
> @@ -208,6 +210,7 @@ struct sun4i_dma_dev {
> int irq;
> spinlock_t lock;
> const struct sun4i_dma_config *cfg;
> + struct reset_control *rst;
> };
>
> static struct sun4i_dma_dev *to_sun4i_dma_dev(struct dma_device *dev)
> @@ -1215,6 +1218,15 @@ static int sun4i_dma_probe(struct platform_device *pdev)
> return PTR_ERR(priv->clk);
> }
>
> + if (priv->cfg->has_reset) {
> + priv->rst = devm_reset_control_get_exclusive(&pdev->dev,
> + NULL);
Unnecessary wrapping.
> + if (IS_ERR(priv->rst)) {
Drop {}.
> + return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst),
> + "Failed to get reset control\n");
And this should be aligned with opening (. Run checkpatch --strict.
> + }
> + }
> +
> platform_set_drvdata(pdev, priv);
> spin_lock_init(&priv->lock);
>
> @@ -1287,6 +1299,14 @@ static int sun4i_dma_probe(struct platform_device *pdev)
> return ret;
> }
>
> + /* Deassert the reset control */
> + ret = reset_control_deassert(priv->rst);
> + if (ret) {
> + dev_err_probe(&pdev->dev, ret,
> + "Failed to deassert the reset control\n");
Missing alignment.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA
2024-10-31 12:35 [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Csókás, Bence
2024-10-31 12:35 ` [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk Csókás, Bence
@ 2024-10-31 12:35 ` Csókás, Bence
2024-10-31 18:17 ` Rob Herring
2024-10-31 12:35 ` [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s Csókás, Bence
2024-10-31 18:15 ` [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Amit Singh Tomar
3 siblings, 1 reply; 10+ messages in thread
From: Csókás, Bence @ 2024-10-31 12:35 UTC (permalink / raw)
To: Chen-Yu Tsai, Maxime Ripard, dmaengine, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel
Cc: Csókás, Bence, Conor Dooley, Vinod Koul, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland
Add compatible string for Allwinner suniv F1C100s DMA.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/linux-kernel/20241024-recycler-borrowing-5d4296fd4a56@spud/
[ csokas.bence: Reimplemented Mesih Kilinc's binding in YAML ]
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
---
.../devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
index 02d5bd035409..9b5180c0a7c4 100644
--- a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
@@ -22,7 +22,9 @@ properties:
number.
compatible:
- const: allwinner,sun4i-a10-dma
+ enum:
+ - allwinner,sun4i-a10-dma
+ - allwinner,suniv-f1c100s-dma
reg:
maxItems: 1
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA
2024-10-31 12:35 ` [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA Csókás, Bence
@ 2024-10-31 18:17 ` Rob Herring
2024-11-02 8:57 ` Csókás Bence
0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2024-10-31 18:17 UTC (permalink / raw)
To: Csókás, Bence
Cc: Chen-Yu Tsai, Maxime Ripard, dmaengine, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, Conor Dooley,
Vinod Koul, Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec,
Samuel Holland
On Thu, Oct 31, 2024 at 01:35:29PM +0100, Csókás, Bence wrote:
> Add compatible string for Allwinner suniv F1C100s DMA.
>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Link: https://lore.kernel.org/linux-kernel/20241024-recycler-borrowing-5d4296fd4a56@spud/
You don't need a link to Conor's ack.
> [ csokas.bence: Reimplemented Mesih Kilinc's binding in YAML ]
> Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
> ---
> .../devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
> index 02d5bd035409..9b5180c0a7c4 100644
> --- a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
> +++ b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
> @@ -22,7 +22,9 @@ properties:
> number.
>
> compatible:
> - const: allwinner,sun4i-a10-dma
> + enum:
> + - allwinner,sun4i-a10-dma
> + - allwinner,suniv-f1c100s-dma
>
> reg:
> maxItems: 1
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA
2024-10-31 18:17 ` Rob Herring
@ 2024-11-02 8:57 ` Csókás Bence
0 siblings, 0 replies; 10+ messages in thread
From: Csókás Bence @ 2024-11-02 8:57 UTC (permalink / raw)
To: Rob Herring
Cc: Chen-Yu Tsai, Maxime Ripard, dmaengine, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, Conor Dooley,
Vinod Koul, Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec,
Samuel Holland
On 2024. 10. 31. 19:17, Rob Herring wrote:
> On Thu, Oct 31, 2024 at 01:35:29PM +0100, Csókás, Bence wrote:
>> Add compatible string for Allwinner suniv F1C100s DMA.
>>
>> Acked-by: Conor Dooley <conor.dooley@microchip.com>
>> Link: https://lore.kernel.org/linux-kernel/20241024-recycler-borrowing-5d4296fd4a56@spud/
>
> You don't need a link to Conor's ack.
I don't? I thought whenever I collect a tag I should provide the link as
well...
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s
2024-10-31 12:35 [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Csókás, Bence
2024-10-31 12:35 ` [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk Csókás, Bence
2024-10-31 12:35 ` [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA Csókás, Bence
@ 2024-10-31 12:35 ` Csókás, Bence
2024-10-31 19:05 ` Amit Singh Tomar
2024-10-31 18:15 ` [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Amit Singh Tomar
3 siblings, 1 reply; 10+ messages in thread
From: Csókás, Bence @ 2024-10-31 12:35 UTC (permalink / raw)
To: dmaengine, linux-kernel, linux-arm-kernel, linux-sunxi
Cc: Mesih Kilinc, Csókás, Bence, Vinod Koul, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland
From: Mesih Kilinc <mesihkilinc@gmail.com>
DMA of Allwinner suniv F1C100s is similar to sun4i. It has 4 NDMA, 4
DDMA channels and endpoints are different. Also F1C100s has reset bit
for DMA in CCU. Add support for it.
Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
[ csokas.bence: Rebased on current master ]
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
---
drivers/dma/Kconfig | 4 +--
drivers/dma/sun4i-dma.c | 60 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d9ec1e69e428..fc25bfc356f3 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -162,8 +162,8 @@ config DMA_SA11X0
config DMA_SUN4I
tristate "Allwinner A10 DMA SoCs support"
- depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
- default (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
+ depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNIV
+ default (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNIV)
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 4626cc8ad114..c0a4e40134dc 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -33,7 +33,11 @@
#define SUN4I_DMA_CFG_SRC_ADDR_MODE(mode) ((mode) << 5)
#define SUN4I_DMA_CFG_SRC_DRQ_TYPE(type) (type)
+#define SUNIV_DMA_CFG_DST_DATA_WIDTH(width) ((width) << 24)
+#define SUNIV_DMA_CFG_SRC_DATA_WIDTH(width) ((width) << 8)
+
#define SUN4I_MAX_BURST 8
+#define SUNIV_MAX_BURST 4
/** Normal DMA register values **/
@@ -41,6 +45,9 @@
#define SUN4I_NDMA_DRQ_TYPE_SDRAM 0x16
#define SUN4I_NDMA_DRQ_TYPE_LIMIT (0x1F + 1)
+#define SUNIV_NDMA_DRQ_TYPE_SDRAM 0x11
+#define SUNIV_NDMA_DRQ_TYPE_LIMIT (0x17 + 1)
+
/** Normal DMA register layout **/
/* Dedicated DMA source/destination address mode values */
@@ -54,6 +61,9 @@
#define SUN4I_NDMA_CFG_BYTE_COUNT_MODE_REMAIN BIT(15)
#define SUN4I_NDMA_CFG_SRC_NON_SECURE BIT(6)
+#define SUNIV_NDMA_CFG_CONT_MODE BIT(29)
+#define SUNIV_NDMA_CFG_WAIT_STATE(n) ((n) << 26)
+
/** Dedicated DMA register values **/
/* Dedicated DMA source/destination address mode values */
@@ -66,6 +76,9 @@
#define SUN4I_DDMA_DRQ_TYPE_SDRAM 0x1
#define SUN4I_DDMA_DRQ_TYPE_LIMIT (0x1F + 1)
+#define SUNIV_DDMA_DRQ_TYPE_SDRAM 0x1
+#define SUNIV_DDMA_DRQ_TYPE_LIMIT (0x9 + 1)
+
/** Dedicated DMA register layout **/
/* Dedicated DMA configuration register layout */
@@ -119,6 +132,11 @@
#define SUN4I_DMA_NR_MAX_VCHANS \
(SUN4I_NDMA_NR_MAX_VCHANS + SUN4I_DDMA_NR_MAX_VCHANS)
+#define SUNIV_NDMA_NR_MAX_CHANNELS 4
+#define SUNIV_DDMA_NR_MAX_CHANNELS 4
+#define SUNIV_NDMA_NR_MAX_VCHANS (24 * 2 - 1)
+#define SUNIV_DDMA_NR_MAX_VCHANS 10
+
/* This set of SUN4I_DDMA timing parameters were found experimentally while
* working with the SPI driver and seem to make it behave correctly */
#define SUN4I_DDMA_MAGIC_SPI_PARAMETERS \
@@ -243,6 +261,16 @@ static void set_src_data_width_a10(u32 *p_cfg, s8 data_width)
*p_cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(data_width);
}
+static void set_dst_data_width_f1c100s(u32 *p_cfg, s8 data_width)
+{
+ *p_cfg |= SUNIV_DMA_CFG_DST_DATA_WIDTH(data_width);
+}
+
+static void set_src_data_width_f1c100s(u32 *p_cfg, s8 data_width)
+{
+ *p_cfg |= SUNIV_DMA_CFG_SRC_DATA_WIDTH(data_width);
+}
+
static int convert_burst_a10(u32 maxburst)
{
if (maxburst > 8)
@@ -252,6 +280,15 @@ static int convert_burst_a10(u32 maxburst)
return (maxburst >> 2);
}
+static int convert_burst_f1c100s(u32 maxburst)
+{
+ if (maxburst > 4)
+ return -EINVAL;
+
+ /* 1 -> 0, 4 -> 1 */
+ return (maxburst >> 2);
+}
+
static int convert_buswidth(enum dma_slave_buswidth addr_width)
{
if (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES)
@@ -1379,8 +1416,31 @@ static struct sun4i_dma_config sun4i_a10_dma_cfg = {
.has_reset = false,
};
+static struct sun4i_dma_config suniv_f1c100s_dma_cfg = {
+ .ndma_nr_max_channels = SUNIV_NDMA_NR_MAX_CHANNELS,
+ .ndma_nr_max_vchans = SUNIV_NDMA_NR_MAX_VCHANS,
+
+ .ddma_nr_max_channels = SUNIV_DDMA_NR_MAX_CHANNELS,
+ .ddma_nr_max_vchans = SUNIV_DDMA_NR_MAX_VCHANS,
+
+ .dma_nr_max_channels = SUNIV_NDMA_NR_MAX_CHANNELS +
+ SUNIV_DDMA_NR_MAX_CHANNELS,
+
+ .set_dst_data_width = set_dst_data_width_f1c100s,
+ .set_src_data_width = set_src_data_width_f1c100s,
+ .convert_burst = convert_burst_f1c100s,
+
+ .ndma_drq_sdram = SUNIV_NDMA_DRQ_TYPE_SDRAM,
+ .ddma_drq_sdram = SUNIV_DDMA_DRQ_TYPE_SDRAM,
+
+ .max_burst = SUNIV_MAX_BURST,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_dma_match[] = {
{ .compatible = "allwinner,sun4i-a10-dma", .data = &sun4i_a10_dma_cfg },
+ { .compatible = "allwinner,suniv-f1c100s-dma",
+ .data = &suniv_f1c100s_dma_cfg },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, sun4i_dma_match);
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s
2024-10-31 12:35 ` [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s Csókás, Bence
@ 2024-10-31 19:05 ` Amit Singh Tomar
2024-11-02 9:06 ` Csókás Bence
0 siblings, 1 reply; 10+ messages in thread
From: Amit Singh Tomar @ 2024-10-31 19:05 UTC (permalink / raw)
To: Csókás, Bence, dmaengine, linux-kernel,
linux-arm-kernel, linux-sunxi
Cc: Mesih Kilinc, Vinod Koul, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland
Hi,
>
> From: Mesih Kilinc <mesihkilinc@gmail.com>
>
> DMA of Allwinner suniv F1C100s is similar to sun4i. It has 4 NDMA, 4
> DDMA channels and endpoints are different. Also F1C100s has reset bit
> for DMA in CCU. Add support for it.
>
> Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
> [ csokas.bence: Rebased on current master ]
> Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
> ---
> drivers/dma/Kconfig | 4 +--
> drivers/dma/sun4i-dma.c | 60 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 62 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index d9ec1e69e428..fc25bfc356f3 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -162,8 +162,8 @@ config DMA_SA11X0
>
> config DMA_SUN4I
> tristate "Allwinner A10 DMA SoCs support"
> - depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
> - default (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
> + depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNIV
> + default (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNIV)
> select DMA_ENGINE
> select DMA_VIRTUAL_CHANNELS
> help
> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
> index 4626cc8ad114..c0a4e40134dc 100644
> --- a/drivers/dma/sun4i-dma.c
> +++ b/drivers/dma/sun4i-dma.c
> @@ -33,7 +33,11 @@
> #define SUN4I_DMA_CFG_SRC_ADDR_MODE(mode) ((mode) << 5)
> #define SUN4I_DMA_CFG_SRC_DRQ_TYPE(type) (type)
>
> +#define SUNIV_DMA_CFG_DST_DATA_WIDTH(width) ((width) << 24)
> +#define SUNIV_DMA_CFG_SRC_DATA_WIDTH(width) ((width) << 8)
nit: Are the extra parentheses around width truly necessary? They seem
to be used throughout the file.
> +
> #define SUN4I_MAX_BURST 8
> +#define SUNIV_MAX_BURST 4
>
> /** Normal DMA register values **/
>
> @@ -41,6 +45,9 @@
> #define SUN4I_NDMA_DRQ_TYPE_SDRAM 0x16
> #define SUN4I_NDMA_DRQ_TYPE_LIMIT (0x1F + 1)
>
> +#define SUNIV_NDMA_DRQ_TYPE_SDRAM 0x11
> +#define SUNIV_NDMA_DRQ_TYPE_LIMIT (0x17 + 1)
> +
> /** Normal DMA register layout **/
>
> /* Dedicated DMA source/destination address mode values */
> @@ -54,6 +61,9 @@
> #define SUN4I_NDMA_CFG_BYTE_COUNT_MODE_REMAIN BIT(15)
> #define SUN4I_NDMA_CFG_SRC_NON_SECURE BIT(6)
>
> +#define SUNIV_NDMA_CFG_CONT_MODE BIT(29)
> +#define SUNIV_NDMA_CFG_WAIT_STATE(n) ((n) << 26)
> +
> /** Dedicated DMA register values **/
>
> /* Dedicated DMA source/destination address mode values */
> @@ -66,6 +76,9 @@
> #define SUN4I_DDMA_DRQ_TYPE_SDRAM 0x1
> #define SUN4I_DDMA_DRQ_TYPE_LIMIT (0x1F + 1)
>
> +#define SUNIV_DDMA_DRQ_TYPE_SDRAM 0x1
> +#define SUNIV_DDMA_DRQ_TYPE_LIMIT (0x9 + 1)
> +
> /** Dedicated DMA register layout **/
>
> /* Dedicated DMA configuration register layout */
> @@ -119,6 +132,11 @@
> #define SUN4I_DMA_NR_MAX_VCHANS \
> (SUN4I_NDMA_NR_MAX_VCHANS + SUN4I_DDMA_NR_MAX_VCHANS)
>
> +#define SUNIV_NDMA_NR_MAX_CHANNELS 4
> +#define SUNIV_DDMA_NR_MAX_CHANNELS 4
> +#define SUNIV_NDMA_NR_MAX_VCHANS (24 * 2 - 1)
> +#define SUNIV_DDMA_NR_MAX_VCHANS 10
> +
> /* This set of SUN4I_DDMA timing parameters were found experimentally while
> * working with the SPI driver and seem to make it behave correctly */
> #define SUN4I_DDMA_MAGIC_SPI_PARAMETERS \
> @@ -243,6 +261,16 @@ static void set_src_data_width_a10(u32 *p_cfg, s8 data_width)
> *p_cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(data_width);
> }
>
> +static void set_dst_data_width_f1c100s(u32 *p_cfg, s8 data_width)
> +{
> + *p_cfg |= SUNIV_DMA_CFG_DST_DATA_WIDTH(data_width);
> +}
> +
> +static void set_src_data_width_f1c100s(u32 *p_cfg, s8 data_width)
> +{
> + *p_cfg |= SUNIV_DMA_CFG_SRC_DATA_WIDTH(data_width);
> +}
> +
> static int convert_burst_a10(u32 maxburst)
> {
> if (maxburst > 8)
> @@ -252,6 +280,15 @@ static int convert_burst_a10(u32 maxburst)
> return (maxburst >> 2);
> }
>
> +static int convert_burst_f1c100s(u32 maxburst)
> +{
> + if (maxburst > 4)
> + return -EINVAL;
> +
> + /* 1 -> 0, 4 -> 1 */
> + return (maxburst >> 2);
> +}
> +
> static int convert_buswidth(enum dma_slave_buswidth addr_width)
> {
> if (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES)
> @@ -1379,8 +1416,31 @@ static struct sun4i_dma_config sun4i_a10_dma_cfg = {
> .has_reset = false,
> };
>
> +static struct sun4i_dma_config suniv_f1c100s_dma_cfg = {
> + .ndma_nr_max_channels = SUNIV_NDMA_NR_MAX_CHANNELS,
> + .ndma_nr_max_vchans = SUNIV_NDMA_NR_MAX_VCHANS,
> +
> + .ddma_nr_max_channels = SUNIV_DDMA_NR_MAX_CHANNELS,
> + .ddma_nr_max_vchans = SUNIV_DDMA_NR_MAX_VCHANS,
> +
> + .dma_nr_max_channels = SUNIV_NDMA_NR_MAX_CHANNELS +
> + SUNIV_DDMA_NR_MAX_CHANNELS,
> +
> + .set_dst_data_width = set_dst_data_width_f1c100s,
> + .set_src_data_width = set_src_data_width_f1c100s,
> + .convert_burst = convert_burst_f1c100s,
> +
> + .ndma_drq_sdram = SUNIV_NDMA_DRQ_TYPE_SDRAM,
> + .ddma_drq_sdram = SUNIV_DDMA_DRQ_TYPE_SDRAM,
> +
> + .max_burst = SUNIV_MAX_BURST,
> + .has_reset = true,
> +};
> +
> static const struct of_device_id sun4i_dma_match[] = {
> { .compatible = "allwinner,sun4i-a10-dma", .data = &sun4i_a10_dma_cfg },
> + { .compatible = "allwinner,suniv-f1c100s-dma",
> + .data = &suniv_f1c100s_dma_cfg },
> { /* sentinel */ },
> };
> MODULE_DEVICE_TABLE(of, sun4i_dma_match);
> --
> 2.34.1
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s
2024-10-31 19:05 ` Amit Singh Tomar
@ 2024-11-02 9:06 ` Csókás Bence
0 siblings, 0 replies; 10+ messages in thread
From: Csókás Bence @ 2024-11-02 9:06 UTC (permalink / raw)
To: Amit Singh Tomar, dmaengine, linux-kernel, linux-arm-kernel,
linux-sunxi
Cc: Mesih Kilinc, Vinod Koul, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland
On 2024. 10. 31. 20:05, Amit Singh Tomar wrote:
>> #define SUN4I_DMA_CFG_SRC_ADDR_MODE(mode) ((mode) << 5)
>> #define SUN4I_DMA_CFG_SRC_DRQ_TYPE(type) (type)
>> +#define SUNIV_DMA_CFG_DST_DATA_WIDTH(width) ((width) << 24)
>> +#define SUNIV_DMA_CFG_SRC_DATA_WIDTH(width) ((width) << 8)
>
> nit: Are the extra parentheses around width truly necessary? They seem
> to be used throughout the file.
It's macro safety. So for instance if someone writes
~SUNIV_DMA_CFG_DST_DATA_WIDTH(1 + 2), which would expand to ~1 + 2 << 24
it doesn't get mis-interpreted as (~1) + (2 << 24) for instance. So
yeah, I sure hope that _all code_ that has macros with parameters did
not forget to wrap everything in parentheses, and not just "throughout
[this] file".
Bence
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips
2024-10-31 12:35 [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Csókás, Bence
` (2 preceding siblings ...)
2024-10-31 12:35 ` [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s Csókás, Bence
@ 2024-10-31 18:15 ` Amit Singh Tomar
3 siblings, 0 replies; 10+ messages in thread
From: Amit Singh Tomar @ 2024-10-31 18:15 UTC (permalink / raw)
To: Csókás, Bence, dmaengine, linux-arm-kernel, linux-sunxi,
linux-kernel
Cc: Mesih Kilinc, Vinod Koul, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland
Hi,
>
> Notes:
> Changes in v2:
> * Whitespace
>
> drivers/dma/sun4i-dma.c | 138 ++++++++++++++++++++++++++++++----------
> 1 file changed, 106 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
> index 2e7f9b07fdd2..d472f57a39ea 100644
> --- a/drivers/dma/sun4i-dma.c
> +++ b/drivers/dma/sun4i-dma.c
> @@ -13,6 +13,7 @@
> #include <linux/interrupt.h>
> #include <linux/module.h>
> #include <linux/of_dma.h>
> +#include <linux/of_device.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/spinlock.h>
> @@ -31,6 +32,8 @@
> #define SUN4I_DMA_CFG_SRC_ADDR_MODE(mode) ((mode) << 5)
> #define SUN4I_DMA_CFG_SRC_DRQ_TYPE(type) (type)
>
> +#define SUN4I_MAX_BURST 8
> +
> /** Normal DMA register values **/
>
> /* Normal DMA source/destination data request type values */
> @@ -132,6 +135,32 @@
> #define SUN4I_DDMA_MAX_SEG_SIZE SZ_16M
> #define SUN4I_DMA_MAX_SEG_SIZE SUN4I_NDMA_MAX_SEG_SIZE
>
> +/*
> + * Hardware channels / ports representation
> + *
> + * The hardware is used in several SoCs, with differing numbers
> + * of channels and endpoints. This structure ties those numbers
> + * to a certain compatible string.
> + */
> +struct sun4i_dma_config {
> + u32 ndma_nr_max_channels;
> + u32 ndma_nr_max_vchans;
> +
> + u32 ddma_nr_max_channels;
> + u32 ddma_nr_max_vchans;
> +
> + u32 dma_nr_max_channels;
> +
> + void (*set_dst_data_width)(u32 *p_cfg, s8 data_width);
> + void (*set_src_data_width)(u32 *p_cfg, s8 data_width);
> + int (*convert_burst)(u32 maxburst);
> +
> + u8 ndma_drq_sdram;
> + u8 ddma_drq_sdram;
> +
> + u8 max_burst;
> +};
> +
> struct sun4i_dma_pchan {
> /* Register base of channel */
> void __iomem *base;
> @@ -170,7 +199,7 @@ struct sun4i_dma_contract {
> };
>
> struct sun4i_dma_dev {
> - DECLARE_BITMAP(pchans_used, SUN4I_DMA_NR_MAX_CHANNELS);
Is this macro "SUN4I_DMA_NR_MAX_CHANNELS" referenced elsewhere? If it’s
not in use, can we clean it up?
> + unsigned long *pchans_used;
> struct dma_device slave;
> struct sun4i_dma_pchan *pchans;
> struct sun4i_dma_vchan *vchans;
> @@ -178,6 +207,7 @@ struct sun4i_dma_dev {
> struct clk *clk;
> int irq;
> spinlock_t lock;
> + const struct sun4i_dma_config *cfg;
> };
>
> static struct sun4i_dma_dev *to_sun4i_dma_dev(struct dma_device *dev)
> @@ -200,7 +230,17 @@ static struct device *chan2dev(struct dma_chan *chan)
> return &chan->dev->device;
> }
>
> -static int convert_burst(u32 maxburst)
> +static void set_dst_data_width_a10(u32 *p_cfg, s8 data_width)
> +{
> + *p_cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(data_width);
> +}
> +
> +static void set_src_data_width_a10(u32 *p_cfg, s8 data_width)
> +{
> + *p_cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(data_width);
> +}
> +
> +static int convert_burst_a10(u32 maxburst)
> {
> if (maxburst > 8)
> return -EINVAL;
> @@ -233,15 +273,15 @@ static struct sun4i_dma_pchan *find_and_use_pchan(struct sun4i_dma_dev *priv,
> int i, max;
>
> /*
> - * pchans 0-SUN4I_NDMA_NR_MAX_CHANNELS are normal, and
> - * SUN4I_NDMA_NR_MAX_CHANNELS+ are dedicated ones
> + * pchans 0-priv->cfg->ndma_nr_max_channels are normal, and
> + * priv->cfg->ndma_nr_max_channels+ are dedicated ones
> */
> if (vchan->is_dedicated) {
> - i = SUN4I_NDMA_NR_MAX_CHANNELS;
> - max = SUN4I_DMA_NR_MAX_CHANNELS;
> + i = priv->cfg->ndma_nr_max_channels;
> + max = priv->cfg->dma_nr_max_channels;
> } else {
> i = 0;
> - max = SUN4I_NDMA_NR_MAX_CHANNELS;
> + max = priv->cfg->ndma_nr_max_channels;
> }
>
> spin_lock_irqsave(&priv->lock, flags);
> @@ -444,6 +484,7 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> size_t len, struct dma_slave_config *sconfig,
> enum dma_transfer_direction direction)
> {
> + struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
> struct sun4i_dma_promise *promise;
> int ret;
>
> @@ -467,13 +508,13 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> sconfig->src_addr_width, sconfig->dst_addr_width);
>
> /* Source burst */
> - ret = convert_burst(sconfig->src_maxburst);
> + ret = priv->cfg->convert_burst(sconfig->src_maxburst);
> if (ret < 0)
> goto fail;
> promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
>
> /* Destination burst */
> - ret = convert_burst(sconfig->dst_maxburst);
> + ret = priv->cfg->convert_burst(sconfig->dst_maxburst);
> if (ret < 0)
> goto fail;
> promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
> @@ -482,13 +523,13 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> ret = convert_buswidth(sconfig->src_addr_width);
> if (ret < 0)
> goto fail;
> - promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
> + priv->cfg->set_src_data_width(&promise->cfg, ret);
>
> /* Destination bus width */
> ret = convert_buswidth(sconfig->dst_addr_width);
> if (ret < 0)
> goto fail;
> - promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
> + priv->cfg->set_dst_data_width(&promise->cfg, ret);
>
> return promise;
>
> @@ -510,6 +551,7 @@ static struct sun4i_dma_promise *
> generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> size_t len, struct dma_slave_config *sconfig)
> {
> + struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
> struct sun4i_dma_promise *promise;
> int ret;
>
> @@ -524,13 +566,13 @@ generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> SUN4I_DDMA_CFG_BYTE_COUNT_MODE_REMAIN;
>
> /* Source burst */
> - ret = convert_burst(sconfig->src_maxburst);
> + ret = priv->cfg->convert_burst(sconfig->src_maxburst);
> if (ret < 0)
> goto fail;
> promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
>
> /* Destination burst */
> - ret = convert_burst(sconfig->dst_maxburst);
> + ret = priv->cfg->convert_burst(sconfig->dst_maxburst);
> if (ret < 0)
> goto fail;
> promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
> @@ -539,13 +581,13 @@ generate_ddma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest,
> ret = convert_buswidth(sconfig->src_addr_width);
> if (ret < 0)
> goto fail;
> - promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
> + priv->cfg->set_src_data_width(&promise->cfg, ret);
>
> /* Destination bus width */
> ret = convert_buswidth(sconfig->dst_addr_width);
> if (ret < 0)
> goto fail;
> - promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
> + priv->cfg->set_dst_data_width(&promise->cfg, ret);
>
> return promise;
>
> @@ -622,6 +664,7 @@ static struct dma_async_tx_descriptor *
> sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
> dma_addr_t src, size_t len, unsigned long flags)
> {
> + struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
> struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
> struct dma_slave_config *sconfig = &vchan->cfg;
> struct sun4i_dma_promise *promise;
> @@ -638,8 +681,8 @@ sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
> */
> sconfig->src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> sconfig->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> - sconfig->src_maxburst = 8;
> - sconfig->dst_maxburst = 8;
> + sconfig->src_maxburst = priv->cfg->max_burst;
> + sconfig->dst_maxburst = priv->cfg->max_burst;
>
> if (vchan->is_dedicated)
> promise = generate_ddma_promise(chan, src, dest, len, sconfig);
> @@ -654,11 +697,13 @@ sun4i_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
>
> /* Configure memcpy mode */
> if (vchan->is_dedicated) {
> - promise->cfg |= SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_DDMA_DRQ_TYPE_SDRAM) |
> - SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_DDMA_DRQ_TYPE_SDRAM);
> + promise->cfg |=
> + SUN4I_DMA_CFG_SRC_DRQ_TYPE(priv->cfg->ddma_drq_sdram) |
> + SUN4I_DMA_CFG_DST_DRQ_TYPE(priv->cfg->ddma_drq_sdram);
> } else {
> - promise->cfg |= SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM) |
> - SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM);
> + promise->cfg |=
> + SUN4I_DMA_CFG_SRC_DRQ_TYPE(priv->cfg->ndma_drq_sdram) |
> + SUN4I_DMA_CFG_DST_DRQ_TYPE(priv->cfg->ndma_drq_sdram);
> }
>
> /* Fill the contract with our only promise */
> @@ -673,6 +718,7 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
> size_t period_len, enum dma_transfer_direction dir,
> unsigned long flags)
> {
> + struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
> struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
> struct dma_slave_config *sconfig = &vchan->cfg;
> struct sun4i_dma_promise *promise;
> @@ -696,11 +742,11 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len,
> if (vchan->is_dedicated) {
> io_mode = SUN4I_DDMA_ADDR_MODE_IO;
> linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
> - ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
> + ram_type = priv->cfg->ddma_drq_sdram;
> } else {
> io_mode = SUN4I_NDMA_ADDR_MODE_IO;
> linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
> - ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
> + ram_type = priv->cfg->ndma_drq_sdram;
> }
>
> if (dir == DMA_MEM_TO_DEV) {
> @@ -793,6 +839,7 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
> unsigned int sg_len, enum dma_transfer_direction dir,
> unsigned long flags, void *context)
> {
> + struct sun4i_dma_dev *priv = to_sun4i_dma_dev(chan->device);
> struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(chan);
> struct dma_slave_config *sconfig = &vchan->cfg;
> struct sun4i_dma_promise *promise;
> @@ -818,11 +865,11 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
> if (vchan->is_dedicated) {
> io_mode = SUN4I_DDMA_ADDR_MODE_IO;
> linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
> - ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
> + ram_type = priv->cfg->ddma_drq_sdram;
> } else {
> io_mode = SUN4I_NDMA_ADDR_MODE_IO;
> linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
> - ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
> + ram_type = priv->cfg->ndma_drq_sdram;
> }
>
> if (dir == DMA_MEM_TO_DEV)
> @@ -1150,6 +1197,10 @@ static int sun4i_dma_probe(struct platform_device *pdev)
> if (!priv)
> return -ENOMEM;
>
> + priv->cfg = of_device_get_match_data(&pdev->dev);
> + if (!priv->cfg)
> + return -ENODEV;
> +
> priv->base = devm_platform_ioremap_resource(pdev, 0);
> if (IS_ERR(priv->base))
> return PTR_ERR(priv->base);
> @@ -1197,23 +1248,26 @@ static int sun4i_dma_probe(struct platform_device *pdev)
>
> priv->slave.dev = &pdev->dev;
>
> - priv->pchans = devm_kcalloc(&pdev->dev, SUN4I_DMA_NR_MAX_CHANNELS,
> + priv->pchans = devm_kcalloc(&pdev->dev, priv->cfg->dma_nr_max_channels,
> sizeof(struct sun4i_dma_pchan), GFP_KERNEL);
> priv->vchans = devm_kcalloc(&pdev->dev, SUN4I_DMA_NR_MAX_VCHANS,
> sizeof(struct sun4i_dma_vchan), GFP_KERNEL);
> - if (!priv->vchans || !priv->pchans)
> + priv->pchans_used = devm_kcalloc(&pdev->dev,
> + BITS_TO_LONGS(priv->cfg->dma_nr_max_channels),
> + sizeof(unsigned long), GFP_KERNEL);
> + if (!priv->vchans || !priv->pchans || !priv->pchans_used)
> return -ENOMEM;
>
> /*
> - * [0..SUN4I_NDMA_NR_MAX_CHANNELS) are normal pchans, and
> - * [SUN4I_NDMA_NR_MAX_CHANNELS..SUN4I_DMA_NR_MAX_CHANNELS) are
> + * [0..priv->cfg->ndma_nr_max_channels) are normal pchans, and
> + * [priv->cfg->ndma_nr_max_channels..priv->cfg->dma_nr_max_channels) are
> * dedicated ones
> */
> - for (i = 0; i < SUN4I_NDMA_NR_MAX_CHANNELS; i++)
> + for (i = 0; i < priv->cfg->ndma_nr_max_channels; i++)
> priv->pchans[i].base = priv->base +
> SUN4I_NDMA_CHANNEL_REG_BASE(i);
>
> - for (j = 0; i < SUN4I_DMA_NR_MAX_CHANNELS; i++, j++) {
> + for (j = 0; i < priv->cfg->dma_nr_max_channels; i++, j++) {
> priv->pchans[i].base = priv->base +
> SUN4I_DDMA_CHANNEL_REG_BASE(j);
> priv->pchans[i].is_dedicated = 1;
> @@ -1284,8 +1338,28 @@ static void sun4i_dma_remove(struct platform_device *pdev)
> clk_disable_unprepare(priv->clk);
> }
>
> +static struct sun4i_dma_config sun4i_a10_dma_cfg = {
> + .ndma_nr_max_channels = SUN4I_NDMA_NR_MAX_CHANNELS,
> + .ndma_nr_max_vchans = SUN4I_NDMA_NR_MAX_VCHANS,
> +
> + .ddma_nr_max_channels = SUN4I_DDMA_NR_MAX_CHANNELS,
> + .ddma_nr_max_vchans = SUN4I_DDMA_NR_MAX_VCHANS,
> +
> + .dma_nr_max_channels = SUN4I_NDMA_NR_MAX_CHANNELS +
> + SUN4I_DDMA_NR_MAX_CHANNELS,
> +
Or else use "SUN4I_DMA_NR_MAX_CHANNELS" here.
> + .set_dst_data_width = set_dst_data_width_a10,
> + .set_src_data_width = set_src_data_width_a10,
> + .convert_burst = convert_burst_a10,
> +
> + .ndma_drq_sdram = SUN4I_NDMA_DRQ_TYPE_SDRAM,
> + .ddma_drq_sdram = SUN4I_DDMA_DRQ_TYPE_SDRAM,
> +
> + .max_burst = SUN4I_MAX_BURST,
> +};
> +
> static const struct of_device_id sun4i_dma_match[] = {
> - { .compatible = "allwinner,sun4i-a10-dma" },
> + { .compatible = "allwinner,sun4i-a10-dma", .data = &sun4i_a10_dma_cfg },
> { /* sentinel */ },
> };
> MODULE_DEVICE_TABLE(of, sun4i_dma_match);
> --
> 2.34.1
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-11-02 9:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-31 12:35 [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Csókás, Bence
2024-10-31 12:35 ` [PATCH v4 02/10] dma-engine: sun4i: Add has_reset option to quirk Csókás, Bence
2024-10-31 15:47 ` Krzysztof Kozlowski
2024-10-31 12:35 ` [PATCH v4 03/10] dt-bindings: dmaengine: Add Allwinner suniv F1C100s DMA Csókás, Bence
2024-10-31 18:17 ` Rob Herring
2024-11-02 8:57 ` Csókás Bence
2024-10-31 12:35 ` [PATCH v4 04/10] dma-engine: sun4i: Add support for Allwinner suniv F1C100s Csókás, Bence
2024-10-31 19:05 ` Amit Singh Tomar
2024-11-02 9:06 ` Csókás Bence
2024-10-31 18:15 ` [PATCH v4 01/10] dma-engine: sun4i: Add a quirk to support different chips Amit Singh Tomar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox