diff mbox series

[v4,4/5] dma: imx-sdma: add a test for imx8mq multi sdma devices

Message ID 20190125025528.15645-5-angus@akkea.ca (mailing list archive)
State Changes Requested
Headers show
Series [v4,1/5] dmaengine: imx-sdma: add clock ratio 1:1 check | expand

Commit Message

Angus Ainslie Jan. 25, 2019, 2:55 a.m. UTC
On i.mx8mq, there are two sdma instances, and the common dma framework
will get a channel dynamically from any available sdma instance whether
it's the first sdma device or the second sdma device. Some IPs like
SAI only work with sdma2 not sdma1. To make sure the sdma channel is from
the correct sdma device, use the phandle to match.

Signed-off-by: Angus Ainslie (Purism) <angus@akkea.ca>
---
 drivers/dma/imx-sdma.c                | 8 ++++++++
 include/linux/platform_data/dma-imx.h | 1 +
 2 files changed, 9 insertions(+)

Comments

Lucas Stach Jan. 25, 2019, 9:34 a.m. UTC | #1
Am Donnerstag, den 24.01.2019, 19:55 -0700 schrieb Angus Ainslie (Purism):
> On i.mx8mq, there are two sdma instances, and the common dma framework
> will get a channel dynamically from any available sdma instance whether
> it's the first sdma device or the second sdma device. Some IPs like
> SAI only work with sdma2 not sdma1. To make sure the sdma channel is from
> the correct sdma device, use the phandle to match.
> 
> > Signed-off-by: Angus Ainslie (Purism) <angus@akkea.ca>
> ---
>  drivers/dma/imx-sdma.c                | 8 ++++++++
>  include/linux/platform_data/dma-imx.h | 1 +
>  2 files changed, 9 insertions(+)
> 
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index ec6fb48f387a..88e112a4aabf 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -1927,11 +1927,17 @@ static int sdma_init(struct sdma_engine *sdma)
>  static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
>  {
> >  	struct sdma_channel *sdmac = to_sdma_chan(chan);
> > +	struct sdma_engine *sdma = sdmac->sdma;
> >  	struct imx_dma_data *data = fn_param;
>  
> >  	if (!imx_dma_is_general_purpose(chan))
> >  		return false;
>  
> > +	/* return false if it's not the right device */
> +	if ((sdmac->sdma->drvdata == &sdma_imx8mq)

Why do this check only on i.MX8M? This is completely generic and can
and should be done for every SDMA engine with a OF node.

Also why use the phandle to match this instead of the of_node pointer
directly?

Regards,
Lucas

> +		&& (sdma->dev->of_node->phandle != data->phandle))
> > +		return false;
> +
> >  	sdmac->data = *data;
> >  	chan->private = &sdmac->data;
>  
> @@ -1942,6 +1948,7 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
> >  				   struct of_dma *ofdma)
>  {
> >  	struct sdma_engine *sdma = ofdma->of_dma_data;
> > +	struct device_node *np = ofdma->of_node;
> >  	dma_cap_mask_t mask = sdma->dma_device.cap_mask;
> >  	struct imx_dma_data data;
>  
> @@ -1959,6 +1966,7 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
> >  	 * be set to sdmac->event_id1.
> >  	 */
> >  	data.dma_request2 = 0;
> > +	data.phandle = np->phandle;
>  
> >  	return dma_request_channel(mask, sdma_filter_fn, &data);
>  }
> diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
> index 7d964e787299..eeb5b73ae542 100644
> --- a/include/linux/platform_data/dma-imx.h
> +++ b/include/linux/platform_data/dma-imx.h
> @@ -55,6 +55,7 @@ struct imx_dma_data {
> >  	int dma_request2; /* secondary DMA request line */
> >  	enum sdma_peripheral_type peripheral_type;
> >  	int priority;
> > +	int phandle;
>  };
>  
>  static inline int imx_dma_is_ipu(struct dma_chan *chan)
diff mbox series

Patch

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index ec6fb48f387a..88e112a4aabf 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1927,11 +1927,17 @@  static int sdma_init(struct sdma_engine *sdma)
 static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
+	struct sdma_engine *sdma = sdmac->sdma;
 	struct imx_dma_data *data = fn_param;
 
 	if (!imx_dma_is_general_purpose(chan))
 		return false;
 
+	/* return false if it's not the right device */
+	if ((sdmac->sdma->drvdata == &sdma_imx8mq)
+		&& (sdma->dev->of_node->phandle != data->phandle))
+		return false;
+
 	sdmac->data = *data;
 	chan->private = &sdmac->data;
 
@@ -1942,6 +1948,7 @@  static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
 				   struct of_dma *ofdma)
 {
 	struct sdma_engine *sdma = ofdma->of_dma_data;
+	struct device_node *np = ofdma->of_node;
 	dma_cap_mask_t mask = sdma->dma_device.cap_mask;
 	struct imx_dma_data data;
 
@@ -1959,6 +1966,7 @@  static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
 	 * be set to sdmac->event_id1.
 	 */
 	data.dma_request2 = 0;
+	data.phandle = np->phandle;
 
 	return dma_request_channel(mask, sdma_filter_fn, &data);
 }
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index 7d964e787299..eeb5b73ae542 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -55,6 +55,7 @@  struct imx_dma_data {
 	int dma_request2; /* secondary DMA request line */
 	enum sdma_peripheral_type peripheral_type;
 	int priority;
+	int phandle;
 };
 
 static inline int imx_dma_is_ipu(struct dma_chan *chan)