diff options
Diffstat (limited to 'drivers/dma/stm32-mdma.c')
| -rw-r--r-- | drivers/dma/stm32-mdma.c | 53 | 
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);  	} | 
