summaryrefslogtreecommitdiff
path: root/drivers/dma/stm32-mdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/stm32-mdma.c')
-rw-r--r--drivers/dma/stm32-mdma.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
index 6f57ff0e7b37..caf0cce8f528 100644
--- a/drivers/dma/stm32-mdma.c
+++ b/drivers/dma/stm32-mdma.c
@@ -34,7 +34,6 @@
#include "virt-dma.h"
#define STM32_MDMA_GISR0 0x0000 /* MDMA Int Status Reg 1 */
-#define STM32_MDMA_GISR1 0x0004 /* MDMA Int Status Reg 2 */
/* MDMA Channel x interrupt/status register */
#define STM32_MDMA_CISR(x) (0x40 + 0x40 * (x)) /* x = 0..62 */
@@ -73,6 +72,7 @@
#define STM32_MDMA_CCR_WEX BIT(14)
#define STM32_MDMA_CCR_HEX BIT(13)
#define STM32_MDMA_CCR_BEX BIT(12)
+#define STM32_MDMA_CCR_SM BIT(8)
#define STM32_MDMA_CCR_PL_MASK GENMASK(7, 6)
#define STM32_MDMA_CCR_PL(n) FIELD_PREP(STM32_MDMA_CCR_PL_MASK, (n))
#define STM32_MDMA_CCR_TCIE BIT(5)
@@ -168,7 +168,7 @@
#define STM32_MDMA_MAX_BUF_LEN 128
#define STM32_MDMA_MAX_BLOCK_LEN 65536
-#define STM32_MDMA_MAX_CHANNELS 63
+#define STM32_MDMA_MAX_CHANNELS 32
#define STM32_MDMA_MAX_REQUESTS 256
#define STM32_MDMA_MAX_BURST 128
#define STM32_MDMA_VERY_HIGH_PRIORITY 0x3
@@ -248,6 +248,7 @@ struct stm32_mdma_device {
u32 nr_channels;
u32 nr_requests;
u32 nr_ahb_addr_masks;
+ u32 chan_reserved;
struct stm32_mdma_chan chan[STM32_MDMA_MAX_CHANNELS];
u32 ahb_addr_masks[];
};
@@ -1317,26 +1318,16 @@ static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan)
static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
{
struct stm32_mdma_device *dmadev = devid;
- struct stm32_mdma_chan *chan = devid;
+ struct stm32_mdma_chan *chan;
u32 reg, id, ccr, ien, status;
/* Find out which channel generates the interrupt */
status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0);
- if (status) {
- id = __ffs(status);
- } else {
- status = readl_relaxed(dmadev->base + STM32_MDMA_GISR1);
- if (!status) {
- dev_dbg(mdma2dev(dmadev), "spurious it\n");
- return IRQ_NONE;
- }
- id = __ffs(status);
- /*
- * As GISR0 provides status for channel id from 0 to 31,
- * so GISR1 provides status for channel id from 32 to 62
- */
- id += 32;
+ if (!status) {
+ dev_dbg(mdma2dev(dmadev), "spurious it\n");
+ return IRQ_NONE;
}
+ id = __ffs(status);
chan = &dmadev->chan[id];
if (!chan) {
@@ -1354,9 +1345,12 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
if (!(status & ien)) {
spin_unlock(&chan->vchan.lock);
- dev_warn(chan2dev(chan),
- "spurious it (status=0x%04x, ien=0x%04x)\n",
- status, ien);
+ if (chan->busy)
+ dev_warn(chan2dev(chan),
+ "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien);
+ else
+ dev_dbg(chan2dev(chan),
+ "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien);
return IRQ_NONE;
}
@@ -1456,10 +1450,23 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c)
chan->desc_pool = NULL;
}
+static bool stm32_mdma_filter_fn(struct dma_chan *c, void *fn_param)
+{
+ struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
+ struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
+
+ /* Check if chan is marked Secure */
+ if (dmadev->chan_reserved & BIT(chan->id))
+ return false;
+
+ return true;
+}
+
static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
struct stm32_mdma_device *dmadev = ofdma->of_dma_data;
+ dma_cap_mask_t mask = dmadev->ddev.cap_mask;
struct stm32_mdma_chan *chan;
struct dma_chan *c;
struct stm32_mdma_chan_config config;
@@ -1485,7 +1492,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
return NULL;
}
- c = dma_get_any_slave_channel(&dmadev->ddev);
+ c = __dma_request_channel(&mask, stm32_mdma_filter_fn, &config, ofdma->of_node);
if (!c) {
dev_err(mdma2dev(dmadev), "No more channels available\n");
return NULL;
@@ -1615,6 +1622,10 @@ static int stm32_mdma_probe(struct platform_device *pdev)
for (i = 0; i < dmadev->nr_channels; i++) {
chan = &dmadev->chan[i];
chan->id = i;
+
+ if (stm32_mdma_read(dmadev, STM32_MDMA_CCR(i)) & STM32_MDMA_CCR_SM)
+ dmadev->chan_reserved |= BIT(i);
+
chan->vchan.desc_free = stm32_mdma_desc_free;
vchan_init(&chan->vchan, dd);
}