* [RFC] dmaengine: add fifo_size member
From: Vinod Koul @ 2019-05-02 6:04 UTC (permalink / raw)
To: Sameer Pujar; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
On 30-04-19, 17:00, Sameer Pujar wrote:
> During the DMA transfers from memory to I/O, it was observed that transfers
> were inconsistent and resulted in glitches for audio playback. It happened
> because fifo size on DMA did not match with slave channel configuration.
>
> currently 'dma_slave_config' structure does not have a field for fifo size.
> Hence the platform pcm driver cannot pass the fifo size as a slave_config.
> Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
> cannot be used to pass the size info. This patch introduces fifo_size field
> and the same can be populated on slave side. Users can set required size
> for slave peripheral (multiple channels can be independently running with
> different fifo sizes) and the corresponding sizes are programmed through
> dma_slave_config on DMA side.
FIFO size is a hardware property not sure why you would want an
interface to program that?
On mismatch, I guess you need to take care of src/dst_maxburst..
>
> Request for feedback/suggestions.
>
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> ---
> include/linux/dmaengine.h | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index d49ec5c..9ec198b 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
> * @slave_id: Slave requester id. Only valid for slave channels. The dma
> * slave peripheral will have unique id as dma requester which need to be
> * pass as slave config.
> + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
> + * fifo size and the same needs to be passed as slave config.
> *
> * This struct is passed in as configuration data to a DMA engine
> * in order to set up a certain channel for DMA transport at runtime.
> @@ -376,6 +378,7 @@ struct dma_slave_config {
> u32 dst_port_window_size;
> bool device_fc;
> unsigned int slave_id;
> + u32 fifo_size;
> };
>
> /**
> --
> 2.7.4
^ permalink raw reply
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Vinod Koul @ 2019-05-02 6:04 UTC (permalink / raw)
To: Sameer Pujar; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <1556623828-21577-1-git-send-email-spujar@nvidia.com>
On 30-04-19, 17:00, Sameer Pujar wrote:
> During the DMA transfers from memory to I/O, it was observed that transfers
> were inconsistent and resulted in glitches for audio playback. It happened
> because fifo size on DMA did not match with slave channel configuration.
>
> currently 'dma_slave_config' structure does not have a field for fifo size.
> Hence the platform pcm driver cannot pass the fifo size as a slave_config.
> Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
> cannot be used to pass the size info. This patch introduces fifo_size field
> and the same can be populated on slave side. Users can set required size
> for slave peripheral (multiple channels can be independently running with
> different fifo sizes) and the corresponding sizes are programmed through
> dma_slave_config on DMA side.
FIFO size is a hardware property not sure why you would want an
interface to program that?
On mismatch, I guess you need to take care of src/dst_maxburst..
>
> Request for feedback/suggestions.
>
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> ---
> include/linux/dmaengine.h | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index d49ec5c..9ec198b 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
> * @slave_id: Slave requester id. Only valid for slave channels. The dma
> * slave peripheral will have unique id as dma requester which need to be
> * pass as slave config.
> + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
> + * fifo size and the same needs to be passed as slave config.
> *
> * This struct is passed in as configuration data to a DMA engine
> * in order to set up a certain channel for DMA transport at runtime.
> @@ -376,6 +378,7 @@ struct dma_slave_config {
> u32 dst_port_window_size;
> bool device_fc;
> unsigned int slave_id;
> + u32 fifo_size;
> };
>
> /**
> --
> 2.7.4
--
~Vinod
^ permalink raw reply
* [v2,08/15] dt-bindings: spi: imx: add i.mx6ul to state errata fixed
From: Uwe Kleine-König @ 2019-05-02 6:59 UTC (permalink / raw)
To: Robin Gong, robh+dt@kernel.org
Cc: broonie@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de,
festevam@gmail.com, mark.rutland@arm.com, plyatov@gmail.com,
dan.j.williams@intel.com, catalin.marinas@arm.com,
will.deacon@arm.com, dl-linux-imx, linux-spi@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
devicetree@vger.kernel.org, kernel@pengutronix.de
On Fri, Apr 26, 2019 at 08:05:51AM +0000, Robin Gong wrote:
> ERR009165 fixed from i.mx6ul, add it to show the errata fixed.
>
> Signed-off-by: Robin Gong <yibin.gong@nxp.com>
> ---
> Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> index 2d32641..32c4263d 100644
> --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> @@ -10,6 +10,8 @@ Required properties:
> - "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
> - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
> - "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
> + - "fsl,imx6ul-ecspi" ERR009165 fixed on i.MX6UL and later Soc
> + (https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf)
I wouldn't mention this errata in the binding documentation. Just state
that fsl,imx6ul-ecspi is designed to be used on i.MX6UL. And that it
might also be used on later SoCs as a "fallback compatible" is a detail
that is so common that I would expect it not being worth mentioning. So
for me it would also be OK to drop "fsl,imx53-ecspi" from the list as
this is only used like:
compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
(But note that I have no authority here.)
Best regards
Uwe
^ permalink raw reply
* Re: [PATCH v2 08/15] dt-bindings: spi: imx: add i.mx6ul to state errata fixed
From: Uwe Kleine-König @ 2019-05-02 6:59 UTC (permalink / raw)
To: Robin Gong, robh+dt@kernel.org
Cc: broonie@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de,
festevam@gmail.com, mark.rutland@arm.com, plyatov@gmail.com,
dan.j.williams@intel.com, catalin.marinas@arm.com,
will.deacon@arm.com, dl-linux-imx, linux-spi@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
devicetree@vger.kernel.org, kernel@pengutronix.de
In-Reply-To: <1556265512-9130-9-git-send-email-yibin.gong@nxp.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="UTF-8", Size: 1633 bytes --]
On Fri, Apr 26, 2019 at 08:05:51AM +0000, Robin Gong wrote:
> ERR009165 fixed from i.mx6ul, add it to show the errata fixed.
>
> Signed-off-by: Robin Gong <yibin.gong@nxp.com>
> ---
> Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> index 2d32641..32c4263d 100644
> --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
> @@ -10,6 +10,8 @@ Required properties:
> - "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
> - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
> - "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
> + - "fsl,imx6ul-ecspi" ERR009165 fixed on i.MX6UL and later Soc
> + (https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf)
I wouldn't mention this errata in the binding documentation. Just state
that fsl,imx6ul-ecspi is designed to be used on i.MX6UL. And that it
might also be used on later SoCs as a "fallback compatible" is a detail
that is so common that I would expect it not being worth mentioning. So
for me it would also be OK to drop "fsl,imx53-ecspi" from the list as
this is only used like:
compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
(But note that I have no authority here.)
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v2] dmaengine: stm32-dma: fix residue calculation in stm32-dma
From: Arnaud Pouliquen @ 2019-05-02 9:28 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, arnaud.pouliquen, Pierre-Yves MORDRET, linux-stm32,
linux-kernel, dmaengine
In double buffer mode, during residue calculation, the DMA can
automatically switch to the next transfer. Indeed the CT bit that
gives position in the double buffer can has been updated by the
hardware, during calculation.
In this case the SxNDTR register value can not be trusted.
If a transition is detected we consider that the DMA has switched to
the beginning of next sg.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Signed-off-by: Pierre-Yves MORDRET <pierre-yves.mordret@st.com>
---
V1 to V2 update:
Change of the comments to provide better explanation of the race condition.
---
drivers/dma/stm32-dma.c | 90 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 77 insertions(+), 13 deletions(-)
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index ba239b529fa9..9fcaf882e38d 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -1042,33 +1042,97 @@ static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
return ndtr << width;
}
+/**
+ * stm32_dma_is_current_sg - check that expected sg_req is currently transferred
+ * @chan: dma channel
+ *
+ * This function called when IRQ are disable, checks that the hardware has not
+ * switched on the next transfer in double buffer mode. The test is done by
+ * comparing the next_sg memory address with the hardware related register
+ * (based on CT bit value).
+ *
+ * Returns true if expected current transfer is still running or double
+ * buffer mode is not activated.
+ */
+static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
+{
+ struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
+ struct stm32_dma_sg_req *sg_req;
+ u32 dma_scr, dma_smar, id;
+
+ id = chan->id;
+ dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
+
+ if (!(dma_scr & STM32_DMA_SCR_DBM))
+ return true;
+
+ sg_req = &chan->desc->sg_req[chan->next_sg];
+
+ if (dma_scr & STM32_DMA_SCR_CT) {
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
+ return (dma_smar == sg_req->chan_reg.dma_sm0ar);
+ }
+
+ dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
+
+ return (dma_smar == sg_req->chan_reg.dma_sm1ar);
+}
+
static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
struct stm32_dma_desc *desc,
u32 next_sg)
{
u32 modulo, burst_size;
- u32 residue = 0;
+ u32 residue;
+ u32 n_sg = next_sg;
+ struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
int i;
/*
- * In cyclic mode, for the last period, residue = remaining bytes from
- * NDTR
+ * Calculate the residue means compute the descriptors
+ * information:
+ * - the sg_req currently transferred
+ * - the Hardware remaining position in this sg (NDTR bits field).
+ *
+ * A race condition may occur if DMA is running in cyclic or double
+ * buffer mode, since the DMA register are automatically reloaded at end
+ * of period transfer. The hardware may have switched to the next
+ * transfer (CT bit updated) just before the position (SxNDTR reg) is
+ * read.
+ * In this case the SxNDTR reg could (or not) correspond to the new
+ * transfer position, and not the expected one.
+ * The strategy implemented in the stm32 driver is to:
+ * - read the SxNDTR register
+ * - crosscheck that hardware is still in current transfer.
+ * In case of switch, we can assume that the DMA is at the beginning of
+ * the next transfer. So we approximate the residue in consequence, by
+ * pointing on the beginning of next transfer.
+ *
+ * This race condition doesn't apply for none cyclic mode, as double
+ * buffer is not used. In such situation registers are updated by the
+ * software.
*/
- if (chan->desc->cyclic && next_sg == 0) {
- residue = stm32_dma_get_remaining_bytes(chan);
- goto end;
+
+ residue = stm32_dma_get_remaining_bytes(chan);
+
+ if (!stm32_dma_is_current_sg(chan)) {
+ n_sg++;
+ if (n_sg == chan->desc->num_sgs)
+ n_sg = 0;
+ residue = sg_req->len;
}
/*
- * For all other periods in cyclic mode, and in sg mode,
- * residue = remaining bytes from NDTR + remaining periods/sg to be
- * transferred
+ * In cyclic mode, for the last period, residue = remaining bytes
+ * from NDTR,
+ * else for all other periods in cyclic mode, and in sg mode,
+ * residue = remaining bytes from NDTR + remaining
+ * periods/sg to be transferred
*/
- for (i = next_sg; i < desc->num_sgs; i++)
- residue += desc->sg_req[i].len;
- residue += stm32_dma_get_remaining_bytes(chan);
+ if (!chan->desc->cyclic || n_sg != 0)
+ for (i = n_sg; i < desc->num_sgs; i++)
+ residue += desc->sg_req[i].len;
-end:
if (!chan->mem_burst)
return residue;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Sameer Pujar @ 2019-05-02 10:53 UTC (permalink / raw)
To: Vinod Koul; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <20190502060446.GI3845@vkoul-mobl.Dlink>
On 5/2/2019 11:34 AM, Vinod Koul wrote:
> On 30-04-19, 17:00, Sameer Pujar wrote:
>> During the DMA transfers from memory to I/O, it was observed that transfers
>> were inconsistent and resulted in glitches for audio playback. It happened
>> because fifo size on DMA did not match with slave channel configuration.
>>
>> currently 'dma_slave_config' structure does not have a field for fifo size.
>> Hence the platform pcm driver cannot pass the fifo size as a slave_config.
>> Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
>> cannot be used to pass the size info. This patch introduces fifo_size field
>> and the same can be populated on slave side. Users can set required size
>> for slave peripheral (multiple channels can be independently running with
>> different fifo sizes) and the corresponding sizes are programmed through
>> dma_slave_config on DMA side.
> FIFO size is a hardware property not sure why you would want an
> interface to program that?
>
> On mismatch, I guess you need to take care of src/dst_maxburst..
Yes, FIFO size is a HW property. But it is SW configurable(atleast in my
case) on
slave side and can be set to different sizes. The src/dst_maxburst is
programmed
for specific values, I think this depends on few factors related to
bandwidth
needs of client, DMA needs of the system etc.,
In such cases how does DMA know the actual FIFO depth of slave peripheral?
>> Request for feedback/suggestions.
>>
>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>> ---
>> include/linux/dmaengine.h | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
>> index d49ec5c..9ec198b 100644
>> --- a/include/linux/dmaengine.h
>> +++ b/include/linux/dmaengine.h
>> @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
>> * @slave_id: Slave requester id. Only valid for slave channels. The dma
>> * slave peripheral will have unique id as dma requester which need to be
>> * pass as slave config.
>> + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
>> + * fifo size and the same needs to be passed as slave config.
>> *
>> * This struct is passed in as configuration data to a DMA engine
>> * in order to set up a certain channel for DMA transport at runtime.
>> @@ -376,6 +378,7 @@ struct dma_slave_config {
>> u32 dst_port_window_size;
>> bool device_fc;
>> unsigned int slave_id;
>> + u32 fifo_size;
>> };
>>
>> /**
>> --
>> 2.7.4
^ permalink raw reply
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Vinod Koul @ 2019-05-02 12:25 UTC (permalink / raw)
To: Sameer Pujar; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <e852d576-9cc2-ed42-1a1a-d696112c88bf@nvidia.com>
On 02-05-19, 16:23, Sameer Pujar wrote:
>
> On 5/2/2019 11:34 AM, Vinod Koul wrote:
> > On 30-04-19, 17:00, Sameer Pujar wrote:
> > > During the DMA transfers from memory to I/O, it was observed that transfers
> > > were inconsistent and resulted in glitches for audio playback. It happened
> > > because fifo size on DMA did not match with slave channel configuration.
> > >
> > > currently 'dma_slave_config' structure does not have a field for fifo size.
> > > Hence the platform pcm driver cannot pass the fifo size as a slave_config.
> > > Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
> > > cannot be used to pass the size info. This patch introduces fifo_size field
> > > and the same can be populated on slave side. Users can set required size
> > > for slave peripheral (multiple channels can be independently running with
> > > different fifo sizes) and the corresponding sizes are programmed through
> > > dma_slave_config on DMA side.
> > FIFO size is a hardware property not sure why you would want an
> > interface to program that?
> >
> > On mismatch, I guess you need to take care of src/dst_maxburst..
> Yes, FIFO size is a HW property. But it is SW configurable(atleast in my
> case) on
> slave side and can be set to different sizes. The src/dst_maxburst is
Are you sure, have you talked to HW folks on that? IIUC you are
programming the data to be used in FIFO not the FIFO length!
> programmed
> for specific values, I think this depends on few factors related to
> bandwidth
> needs of client, DMA needs of the system etc.,
Precisely
> In such cases how does DMA know the actual FIFO depth of slave peripheral?
Why should DMA know? Its job is to push/pull data as configured by
peripheral driver. The peripheral driver knows and configures DMA
accordingly.
> > > Request for feedback/suggestions.
> > >
> > > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > > ---
> > > include/linux/dmaengine.h | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> > > index d49ec5c..9ec198b 100644
> > > --- a/include/linux/dmaengine.h
> > > +++ b/include/linux/dmaengine.h
> > > @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
> > > * @slave_id: Slave requester id. Only valid for slave channels. The dma
> > > * slave peripheral will have unique id as dma requester which need to be
> > > * pass as slave config.
> > > + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
> > > + * fifo size and the same needs to be passed as slave config.
> > > *
> > > * This struct is passed in as configuration data to a DMA engine
> > > * in order to set up a certain channel for DMA transport at runtime.
> > > @@ -376,6 +378,7 @@ struct dma_slave_config {
> > > u32 dst_port_window_size;
> > > bool device_fc;
> > > unsigned int slave_id;
> > > + u32 fifo_size;
> > > };
> > > /**
> > > --
> > > 2.7.4
--
~Vinod
^ permalink raw reply
* [PATCH 0/6] Add support for Tegra186/Tegra194 and generic fixes
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
Audio DMA(ADMA) interface is a gateway in the AHUB for facilitating DMA
transfers between memory and all of its clients. Currently the driver
supports Tegra210 based platforms. This series adds support for Tegra186
and Tegra194 based platforms and fixes few functional issues.
Patches in the series are classified into three categories,
1. Add support for Tegra186 and Tegra194
2. Add DMA pause/resume feature
3. Fixes common to differernt Tegra generations
Below change log describes the patches in detail.
Change log:
=====================================
v1
----
The series can be classified into 3 categories,
1. Add support for Tegra186 and Tegra194
[Patch 1/6] dmaengine: tegra210-adma: prepare for supporting newer
Tegra chips
* The support was there only for Tegra210
* This is a preparation for adding support for newer Tegra chips
* chip_data is enhanced to support differences between Tegra210 and
Tegra186/Tegra194
[Patch 2/6] Documentation: DT: Add compatibility binding for Tegra186
* New compatibility string is required for driver to work for
Tegra186 and Tegra194. Hence new compatibility is introduced.
* Tegra194 can use the same compatibility as Tegra186
[Patch 3/6] dmaengine: tegra210-adma: add support for Tegra186/
Tegra194
* Populates chip specific information for Tegra186
* There is a difference in the way ADMA CH_CONFIG registers are
encoded for Tegra210 and Tegra186. Added helper fucntions to
support different versions of burst size configuration
2. Add DMA pause/resume feature
[Patch 4/6] dmaengine: tegra210-adma: add pause/resume support
* Adds support for ADMA pause/resume, otherwise audio loss was seen
during continuous pause/resume of audio playback.
3. Fixes common to differernt Tegra generations
[Patch 5/6] dmaengine: tegra210-dma: free dma controller in remove()
* Fixes kernel panic observed during driver reload. DMA controller
needs to be freed when driver is unloaded
[Patch 6/6] dmaengine: tegra210-adma: restore channel status
* Fixes resume across system suspend. If the channel state is not
restored, the transfers won't resume from the state from where it
was left during suspend entry. In this case, audio playback did
not resume properly once system exited from low power state.
===============================
Sameer Pujar (6):
dmaengine: tegra210-adma: prepare for supporting newer Tegra chips
Documentation: DT: Add compatibility binding for Tegra186
dmaengine: tegra210-adma: add support for Tegra186/Tegra194
dmaengine: tegra210-adma: add pause/resume support
dmaengine: tegra210-dma: free dma controller in remove()
dmaengine: tegra210-adma: restore channel status
.../bindings/dma/nvidia,tegra210-adma.txt | 4 +-
drivers/dma/tegra210-adma.c | 232 +++++++++++++++++----
2 files changed, 193 insertions(+), 43 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH 2/6] Documentation: DT: Add compatibility binding for Tegra186
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
Tegra186 Audio DMA controller has new updates from Tegra210 version.
Thus add new compatibility binding string and the same can be used
by Tegra194 as well.
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt b/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt
index 2f35b04..245d306 100644
--- a/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt
+++ b/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt
@@ -4,7 +4,9 @@ The Tegra Audio DMA controller that is used for transferring data
between system memory and the Audio Processing Engine (APE).
Required properties:
-- compatible: Must be "nvidia,tegra210-adma".
+- compatible: Should contain one of the following:
+ - "nvidia,tegra210-adma": for Tegra210
+ - "nvidia,tegra186-adma": for Tegra186 and Tegra194
- reg: Should contain DMA registers location and length. This should be
a single entry that includes all of the per-channel registers in one
contiguous bank.
--
2.7.4
^ permalink raw reply related
* [PATCH 1/6] dmaengine: tegra210-adma: prepare for supporting newer Tegra chips
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
This is a preparatory patch to add support for Tegra186 and Tegra194 chips.
Following changes are necessary to make driver code generic.
* chip_data structure is enhanced to have chip specific details and
following are the additions to the structure
* Offset addresses for ADMA global and channel registers
* Offset values for Tx and Rx channel selection
* Maximum supported Tx and Rx channels
* Tx and Rx channel request mask
* ADMA channel register space size
* Make use of above chip_data to generalise the driver code
Support for Tegra186 and Tegra194 will be added in subsequent patches of
the series.
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
drivers/dma/tegra210-adma.c | 91 ++++++++++++++++++++++++++++-----------------
1 file changed, 57 insertions(+), 34 deletions(-)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 253d312..9aee015 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -36,10 +36,6 @@
#define ADMA_CH_INT_CLEAR 0x1c
#define ADMA_CH_CTRL 0x24
-#define ADMA_CH_CTRL_TX_REQ(val) (((val) & 0xf) << 28)
-#define ADMA_CH_CTRL_TX_REQ_MAX 10
-#define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24)
-#define ADMA_CH_CTRL_RX_REQ_MAX 10
#define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12)
#define ADMA_CH_CTRL_DIR_AHUB2MEM 2
#define ADMA_CH_CTRL_DIR_MEM2AHUB 4
@@ -57,8 +53,8 @@
#define ADMA_CH_FIFO_CTRL 0x2c
#define ADMA_CH_FIFO_CTRL_OVRFW_THRES(val) (((val) & 0xf) << 24)
#define ADMA_CH_FIFO_CTRL_STARV_THRES(val) (((val) & 0xf) << 16)
-#define ADMA_CH_FIFO_CTRL_TX_SIZE(val) (((val) & 0xf) << 8)
-#define ADMA_CH_FIFO_CTRL_RX_SIZE(val) ((val) & 0xf)
+#define ADMA_CH_FIFO_CTRL_TX_FIFO_SIZE_SHIFT 8
+#define ADMA_CH_FIFO_CTRL_RX_FIFO_SIZE_SHIFT 0
#define ADMA_CH_LOWER_SRC_ADDR 0x34
#define ADMA_CH_LOWER_TRG_ADDR 0x3c
@@ -68,25 +64,38 @@
#define ADMA_CH_XFER_STATUS 0x54
#define ADMA_CH_XFER_STATUS_COUNT_MASK 0xffff
-#define ADMA_GLOBAL_CMD 0xc00
-#define ADMA_GLOBAL_SOFT_RESET 0xc04
-#define ADMA_GLOBAL_INT_CLEAR 0xc20
-#define ADMA_GLOBAL_CTRL 0xc24
-
-#define ADMA_CH_REG_OFFSET(a) (a * 0x80)
+#define ADMA_GLOBAL_CMD 0x00
+#define ADMA_GLOBAL_SOFT_RESET 0x04
#define ADMA_CH_FIFO_CTRL_DEFAULT (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \
- ADMA_CH_FIFO_CTRL_STARV_THRES(1) | \
- ADMA_CH_FIFO_CTRL_TX_SIZE(3) | \
- ADMA_CH_FIFO_CTRL_RX_SIZE(3))
+ ADMA_CH_FIFO_CTRL_STARV_THRES(1))
+
+#define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift)
+
struct tegra_adma;
/*
* struct tegra_adma_chip_data - Tegra chip specific data
+ * @global_reg_offset: Register offset of DMA global register.
+ * @global_int_clear: Register offset of DMA global interrupt clear.
+ * @ch_req_tx_shift: Register offset for AHUB transmit channel select.
+ * @ch_req_rx_shift: Register offset for AHUB receive channel select.
+ * @ch_base_offset: Reister offset of DMA channel registers.
+ * @ch_req_mask: Mask for Tx or Rx channel select.
+ * @ch_req_max: Maximum number of Tx or Rx channels available.
+ * @ch_reg_size: Size of DMA channel register space.
* @nr_channels: Number of DMA channels available.
*/
struct tegra_adma_chip_data {
- int nr_channels;
+ unsigned int global_reg_offset;
+ unsigned int global_int_clear;
+ unsigned int ch_req_tx_shift;
+ unsigned int ch_req_rx_shift;
+ unsigned int ch_base_offset;
+ unsigned int ch_req_mask;
+ unsigned int ch_req_max;
+ unsigned int ch_reg_size;
+ unsigned int nr_channels;
};
/*
@@ -148,18 +157,20 @@ struct tegra_adma {
/* Used to store global command register state when suspending */
unsigned int global_cmd;
+ const struct tegra_adma_chip_data *cdata;
+
/* Last member of the structure */
struct tegra_adma_chan channels[0];
};
static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val)
{
- writel(val, tdma->base_addr + reg);
+ writel(val, tdma->base_addr + tdma->cdata->global_reg_offset + reg);
}
static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg)
{
- return readl(tdma->base_addr + reg);
+ return readl(tdma->base_addr + tdma->cdata->global_reg_offset + reg);
}
static inline void tdma_ch_write(struct tegra_adma_chan *tdc, u32 reg, u32 val)
@@ -209,14 +220,16 @@ static int tegra_adma_init(struct tegra_adma *tdma)
int ret;
/* Clear any interrupts */
- tdma_write(tdma, ADMA_GLOBAL_INT_CLEAR, 0x1);
+ tdma_write(tdma, tdma->cdata->global_int_clear, 0x1);
/* Assert soft reset */
tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
/* Wait for reset to clear */
ret = readx_poll_timeout(readl,
- tdma->base_addr + ADMA_GLOBAL_SOFT_RESET,
+ tdma->base_addr +
+ tdma->cdata->global_reg_offset +
+ ADMA_GLOBAL_SOFT_RESET,
status, status == 0, 20, 10000);
if (ret)
return ret;
@@ -236,13 +249,13 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc,
if (tdc->sreq_reserved)
return tdc->sreq_dir == direction ? 0 : -EINVAL;
+ if (sreq_index > tdma->cdata->ch_req_max) {
+ dev_err(tdma->dev, "invalid DMA request\n");
+ return -EINVAL;
+ }
+
switch (direction) {
case DMA_MEM_TO_DEV:
- if (sreq_index > ADMA_CH_CTRL_TX_REQ_MAX) {
- dev_err(tdma->dev, "invalid DMA request\n");
- return -EINVAL;
- }
-
if (test_and_set_bit(sreq_index, &tdma->tx_requests_reserved)) {
dev_err(tdma->dev, "DMA request reserved\n");
return -EINVAL;
@@ -250,11 +263,6 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc,
break;
case DMA_DEV_TO_MEM:
- if (sreq_index > ADMA_CH_CTRL_RX_REQ_MAX) {
- dev_err(tdma->dev, "invalid DMA request\n");
- return -EINVAL;
- }
-
if (test_and_set_bit(sreq_index, &tdma->rx_requests_reserved)) {
dev_err(tdma->dev, "DMA request reserved\n");
return -EINVAL;
@@ -487,6 +495,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
enum dma_transfer_direction direction)
{
struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
+ const struct tegra_adma_chip_data *cdata = tdc->tdma->cdata;
unsigned int burst_size, adma_dir;
if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
@@ -497,7 +506,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = fls(tdc->sconfig.dst_maxburst);
ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
- ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
+ ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
+ cdata->ch_req_mask,
+ cdata->ch_req_tx_shift);
ch_regs->src_addr = buf_addr;
break;
@@ -505,7 +516,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = fls(tdc->sconfig.src_maxburst);
ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
- ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
+ ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
+ cdata->ch_req_mask,
+ cdata->ch_req_rx_shift);
ch_regs->trg_addr = buf_addr;
break;
@@ -658,7 +671,15 @@ static int tegra_adma_runtime_resume(struct device *dev)
}
static const struct tegra_adma_chip_data tegra210_chip_data = {
- .nr_channels = 22,
+ .global_reg_offset = 0xc00,
+ .global_int_clear = 0x20,
+ .ch_req_tx_shift = 28,
+ .ch_req_rx_shift = 24,
+ .ch_base_offset = 0,
+ .ch_req_mask = 0xf,
+ .ch_req_max = 10,
+ .ch_reg_size = 0x80,
+ .nr_channels = 22,
};
static const struct of_device_id tegra_adma_of_match[] = {
@@ -687,6 +708,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
return -ENOMEM;
tdma->dev = &pdev->dev;
+ tdma->cdata = cdata;
tdma->nr_channels = cdata->nr_channels;
platform_set_drvdata(pdev, tdma);
@@ -715,7 +737,8 @@ static int tegra_adma_probe(struct platform_device *pdev)
for (i = 0; i < tdma->nr_channels; i++) {
struct tegra_adma_chan *tdc = &tdma->channels[i];
- tdc->chan_addr = tdma->base_addr + ADMA_CH_REG_OFFSET(i);
+ tdc->chan_addr = tdma->base_addr + cdata->ch_base_offset
+ + (cdata->ch_reg_size * i);
tdc->irq = of_irq_get(pdev->dev.of_node, i);
if (tdc->irq <= 0) {
--
2.7.4
^ permalink raw reply related
* [PATCH 3/6] dmaengine: tegra210-adma: add support for Tegra186/Tegra194
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
Add Tegra186 specific macro defines and chip_data structure for chip
specific information. New compatibility is added to select relevant
chip details. There is no major change for Tegra194 and hence it can
use the same chip data.
The bits in the BURST_SIZE field of the ADMA CH_CONFIG register are
encoded differently on Tegra186 and Tegra194 compared with Tegra210.
On Tegra210 the bits are encoded as follows ...
1 = WORD_1
2 = WORDS_2
3 = WORDS_4
4 = WORDS_8
5 = WORDS_16
Where as on Tegra186 and Tegra194 the bits are encoded as ...
0 = WORD_1
1 = WORDS_2
2 = WORDS_3
3 = WORDS_4
4 = WORDS_5
...
15 = WORDS_16
Add helper functions for generating the correct burst size.
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
drivers/dma/tegra210-adma.c | 45 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 9aee015..115ee10f 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -45,8 +45,8 @@
#define ADMA_CH_CONFIG 0x28
#define ADMA_CH_CONFIG_SRC_BUF(val) (((val) & 0x7) << 28)
#define ADMA_CH_CONFIG_TRG_BUF(val) (((val) & 0x7) << 24)
-#define ADMA_CH_CONFIG_BURST_SIZE(val) (((val) & 0x7) << 20)
-#define ADMA_CH_CONFIG_BURST_16 5
+#define ADMA_CH_CONFIG_BURST_SIZE_SHIFT 20
+#define ADMA_CH_CONFIG_MAX_BURST_SIZE 16
#define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0xf)
#define ADMA_CH_CONFIG_MAX_BUFS 8
@@ -87,6 +87,7 @@ struct tegra_adma;
* @nr_channels: Number of DMA channels available.
*/
struct tegra_adma_chip_data {
+ unsigned int (*adma_get_burst_config)(unsigned int burst_size);
unsigned int global_reg_offset;
unsigned int global_int_clear;
unsigned int ch_req_tx_shift;
@@ -489,6 +490,22 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc,
return ret;
}
+static unsigned int tegra210_adma_get_burst_config(unsigned int burst_size)
+{
+ if (!burst_size || burst_size > ADMA_CH_CONFIG_MAX_BURST_SIZE)
+ burst_size = ADMA_CH_CONFIG_MAX_BURST_SIZE;
+
+ return fls(burst_size) << ADMA_CH_CONFIG_BURST_SIZE_SHIFT;
+}
+
+static unsigned int tegra186_adma_get_burst_config(unsigned int burst_size)
+{
+ if (!burst_size || burst_size > ADMA_CH_CONFIG_MAX_BURST_SIZE)
+ burst_size = ADMA_CH_CONFIG_MAX_BURST_SIZE;
+
+ return (burst_size - 1) << ADMA_CH_CONFIG_BURST_SIZE_SHIFT;
+}
+
static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
struct tegra_adma_desc *desc,
dma_addr_t buf_addr,
@@ -504,7 +521,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
switch (direction) {
case DMA_MEM_TO_DEV:
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
- burst_size = fls(tdc->sconfig.dst_maxburst);
+ burst_size = tdc->sconfig.dst_maxburst;
ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask,
@@ -514,7 +531,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
case DMA_DEV_TO_MEM:
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
- burst_size = fls(tdc->sconfig.src_maxburst);
+ burst_size = tdc->sconfig.src_maxburst;
ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask,
@@ -527,13 +544,10 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
return -EINVAL;
}
- if (!burst_size || burst_size > ADMA_CH_CONFIG_BURST_16)
- burst_size = ADMA_CH_CONFIG_BURST_16;
-
ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir) |
ADMA_CH_CTRL_MODE_CONTINUOUS |
ADMA_CH_CTRL_FLOWCTRL_EN;
- ch_regs->config |= ADMA_CH_CONFIG_BURST_SIZE(burst_size);
+ ch_regs->config |= cdata->adma_get_burst_config(burst_size);
ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT;
ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
@@ -671,6 +685,7 @@ static int tegra_adma_runtime_resume(struct device *dev)
}
static const struct tegra_adma_chip_data tegra210_chip_data = {
+ .adma_get_burst_config = tegra210_adma_get_burst_config,
.global_reg_offset = 0xc00,
.global_int_clear = 0x20,
.ch_req_tx_shift = 28,
@@ -682,8 +697,22 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
.nr_channels = 22,
};
+static const struct tegra_adma_chip_data tegra186_chip_data = {
+ .adma_get_burst_config = tegra186_adma_get_burst_config,
+ .global_reg_offset = 0,
+ .global_int_clear = 0x402c,
+ .ch_req_tx_shift = 27,
+ .ch_req_rx_shift = 22,
+ .ch_base_offset = 0x10000,
+ .ch_req_mask = 0x1f,
+ .ch_req_max = 20,
+ .ch_reg_size = 0x100,
+ .nr_channels = 32,
+};
+
static const struct of_device_id tegra_adma_of_match[] = {
{ .compatible = "nvidia,tegra210-adma", .data = &tegra210_chip_data },
+ { .compatible = "nvidia,tegra186-adma", .data = &tegra186_chip_data },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_adma_of_match);
--
2.7.4
^ permalink raw reply related
* [PATCH 5/6] dmaengine: tegra210-dma: free dma controller in remove()
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
Following kernel panic is seen during DMA driver unload->load sequence
==========================================================================
Unable to handle kernel paging request at virtual address ffffff8001198880
Internal error: Oops: 86000007 [#1] PREEMPT SMP
CPU: 0 PID: 5907 Comm: HwBinder:4123_1 Tainted: G C 4.9.128-tegra-g065839f
Hardware name: galen (DT)
task: ffffffc3590d1a80 task.stack: ffffffc3d0678000
PC is at 0xffffff8001198880
LR is at of_dma_request_slave_channel+0xd8/0x1f8
pc : [<ffffff8001198880>] lr : [<ffffff8008746f30>] pstate: 60400045
sp : ffffffc3d067b710
x29: ffffffc3d067b710 x28: 000000000000002f
x27: ffffff800949e000 x26: ffffff800949e750
x25: ffffff800949e000 x24: ffffffbefe817d84
x23: ffffff8009f77cb0 x22: 0000000000000028
x21: ffffffc3ffda49c8 x20: 0000000000000029
x19: 0000000000000001 x18: ffffffffffffffff
x17: 0000000000000000 x16: ffffff80082b66a0
x15: ffffff8009e78250 x14: 000000000000000a
x13: 0000000000000038 x12: 0101010101010101
x11: 0000000000000030 x10: 0101010101010101
x9 : fffffffffffffffc x8 : 7f7f7f7f7f7f7f7f
x7 : 62ff726b6b64622c x6 : 0000000000008064
x5 : 6400000000000000 x4 : ffffffbefe817c44
x3 : ffffffc3ffda3e08 x2 : ffffff8001198880
x1 : ffffffc3d48323c0 x0 : ffffffc3d067b788
Process HwBinder:4123_1 (pid: 5907, stack limit = 0xffffffc3d0678028)
Call trace:
[<ffffff8001198880>] 0xffffff8001198880
[<ffffff80087459f8>] dma_request_chan+0x50/0x1f0
[<ffffff8008745bc0>] dma_request_slave_channel+0x28/0x40
[<ffffff8001552c44>] tegra_alt_pcm_open+0x114/0x170
[<ffffff8008d65fa4>] soc_pcm_open+0x10c/0x878
[<ffffff8008d18618>] snd_pcm_open_substream+0xc0/0x170
[<ffffff8008d1878c>] snd_pcm_open+0xc4/0x240
[<ffffff8008d189e0>] snd_pcm_playback_open+0x58/0x80
[<ffffff8008cfc6d4>] snd_open+0xb4/0x178
[<ffffff8008250628>] chrdev_open+0xb8/0x1d0
[<ffffff8008246fdc>] do_dentry_open+0x214/0x318
[<ffffff80082485d0>] vfs_open+0x58/0x88
[<ffffff800825bce0>] do_last+0x450/0xde0
[<ffffff800825c718>] path_openat+0xa8/0x368
[<ffffff800825dd84>] do_filp_open+0x8c/0x110
[<ffffff8008248a74>] do_sys_open+0x164/0x220
[<ffffff80082b66dc>] compat_SyS_openat+0x3c/0x50
[<ffffff8008083040>] el0_svc_naked+0x34/0x38
---[ end trace 67e6d544e65b5145 ]---
Kernel panic - not syncing: Fatal exception
==========================================================================
In device probe(), of_dma_controller_register() registers DMA controller.
But when driver is removed, this is not freed. During driver reload this
results in data abort and kernel panic. Add of_dma_controller_free() in
driver remove path to fix the issue.
Fixes: f46b195799b5 ("dmaengine: tegra-adma: Add support for Tegra210 ADMA")
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
drivers/dma/tegra210-adma.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index f26c458..953669d 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -888,6 +888,7 @@ static int tegra_adma_remove(struct platform_device *pdev)
struct tegra_adma *tdma = platform_get_drvdata(pdev);
int i;
+ of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&tdma->dma_dev);
for (i = 0; i < tdma->nr_channels; ++i)
--
2.7.4
^ permalink raw reply related
* [PATCH 4/6] dmaengine: tegra210-adma: add pause/resume support
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
During an audio playback session it is observed that, audio goes off after
few seconds of continuous pause and play. No audio is heard even when the
playback is resumed.
The reason for above is, currently ADMA driver does not handle DMA_PAUSE/
DMA_RESUME and relevant callbacks for dma_device are not implemented. This
patch implements device_pause and device_resume callbacks for the device.
During pause TRANSFER_PAUSE bit of dma channel control register is set and
the same is cleared during resume.
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
drivers/dma/tegra210-adma.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 115ee10f..f26c458 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -30,6 +30,7 @@
#define ADMA_CH_CMD 0x00
#define ADMA_CH_STATUS 0x0c
#define ADMA_CH_STATUS_XFER_EN BIT(0)
+#define ADMA_CH_STATUS_XFER_PAUSED BIT(1)
#define ADMA_CH_INT_STATUS 0x10
#define ADMA_CH_INT_STATUS_XFER_DONE BIT(0)
@@ -41,6 +42,7 @@
#define ADMA_CH_CTRL_DIR_MEM2AHUB 4
#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8)
#define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1)
+#define ADMA_CH_CTRL_XFER_PAUSE_SHIFT 0
#define ADMA_CH_CONFIG 0x28
#define ADMA_CH_CONFIG_SRC_BUF(val) (((val) & 0x7) << 28)
@@ -67,6 +69,8 @@
#define ADMA_GLOBAL_CMD 0x00
#define ADMA_GLOBAL_SOFT_RESET 0x04
+#define TEGRA_ADMA_BURST_COMPLETE_TIME 20
+
#define ADMA_CH_FIFO_CTRL_DEFAULT (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \
ADMA_CH_FIFO_CTRL_STARV_THRES(1))
@@ -437,6 +441,51 @@ static void tegra_adma_issue_pending(struct dma_chan *dc)
spin_unlock_irqrestore(&tdc->vc.lock, flags);
}
+static bool tegra_adma_is_paused(struct tegra_adma_chan *tdc)
+{
+ u32 csts;
+
+ csts = tdma_ch_read(tdc, ADMA_CH_STATUS);
+ csts &= ADMA_CH_STATUS_XFER_PAUSED;
+
+ return csts ? true : false;
+}
+
+static int tegra_adma_pause(struct dma_chan *dc)
+{
+ struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+ struct tegra_adma_desc *desc = tdc->desc;
+ struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
+ int dcnt = 10;
+
+ ch_regs->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL);
+ ch_regs->ctrl |= (1 << ADMA_CH_CTRL_XFER_PAUSE_SHIFT);
+ tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl);
+
+ while (dcnt-- && !tegra_adma_is_paused(tdc))
+ udelay(TEGRA_ADMA_BURST_COMPLETE_TIME);
+
+ if (dcnt < 0) {
+ dev_err(tdc2dev(tdc), "unable to pause DMA channel\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int tegra_adma_resume(struct dma_chan *dc)
+{
+ struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+ struct tegra_adma_desc *desc = tdc->desc;
+ struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
+
+ ch_regs->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL);
+ ch_regs->ctrl &= ~(1 << ADMA_CH_CTRL_XFER_PAUSE_SHIFT);
+ tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl);
+
+ return 0;
+}
+
static int tegra_adma_terminate_all(struct dma_chan *dc)
{
struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
@@ -798,6 +847,8 @@ static int tegra_adma_probe(struct platform_device *pdev)
tdma->dma_dev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+ tdma->dma_dev.device_pause = tegra_adma_pause;
+ tdma->dma_dev.device_resume = tegra_adma_resume;
ret = dma_async_device_register(&tdma->dma_dev);
if (ret < 0) {
--
2.7.4
^ permalink raw reply related
* [PATCH 6/6] dmaengine: tegra210-adma: restore channel status
From: Sameer Pujar @ 2019-05-02 12:55 UTC (permalink / raw)
To: vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, jonathanh, ldewangan, dmaengine, devicetree,
linux-tegra, linux-kernel, Sameer Pujar
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
Status of ADMA channel registers is not saved and restored during system
suspend. During active playback if system enters suspend, this results in
wrong state of channel registers during system resume and playback fails
to resume properly. Fix this by saving following channel registers in
runtime suspend and restore during runtime resume.
* ADMA_CH_LOWER_SRC_ADDR
* ADMA_CH_LOWER_TRG_ADDR
* ADMA_CH_FIFO_CTRL
* ADMA_CH_CONFIG
* ADMA_CH_CTRL
* ADMA_CH_CMD
* ADMA_CH_TC
Runtime PM calls will be inovked during system resume path if a playback
or capture needs to be resumed. Hence above changes work fine for system
suspend case.
Fixes: f46b195799b5 ("dmaengine: tegra-adma: Add support for Tegra210 ADMA")
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
drivers/dma/tegra210-adma.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 953669d..21f6be1 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -112,6 +112,7 @@ struct tegra_adma_chan_regs {
unsigned int src_addr;
unsigned int trg_addr;
unsigned int fifo_ctrl;
+ unsigned int cmd;
unsigned int tc;
};
@@ -141,6 +142,7 @@ struct tegra_adma_chan {
enum dma_transfer_direction sreq_dir;
unsigned int sreq_index;
bool sreq_reserved;
+ struct tegra_adma_chan_regs ch_regs;
/* Transfer count and position info */
unsigned int tx_buf_count;
@@ -711,8 +713,30 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
static int tegra_adma_runtime_suspend(struct device *dev)
{
struct tegra_adma *tdma = dev_get_drvdata(dev);
+ struct tegra_adma_chan_regs *ch_reg;
+ struct tegra_adma_chan *tdc;
+ int i;
tdma->global_cmd = tdma_read(tdma, ADMA_GLOBAL_CMD);
+ if (!tdma->global_cmd)
+ goto clk_disable;
+
+ for (i = 0; i < tdma->nr_channels; i++) {
+ tdc = &tdma->channels[i];
+ ch_reg = &tdc->ch_regs;
+ ch_reg->cmd = tdma_ch_read(tdc, ADMA_CH_CMD);
+ /* skip if channel is not active */
+ if (!ch_reg->cmd)
+ continue;
+ ch_reg->tc = tdma_ch_read(tdc, ADMA_CH_TC);
+ ch_reg->src_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_SRC_ADDR);
+ ch_reg->trg_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_TRG_ADDR);
+ ch_reg->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL);
+ ch_reg->fifo_ctrl = tdma_ch_read(tdc, ADMA_CH_FIFO_CTRL);
+ ch_reg->config = tdma_ch_read(tdc, ADMA_CH_CONFIG);
+ }
+
+clk_disable:
clk_disable_unprepare(tdma->ahub_clk);
return 0;
@@ -721,7 +745,9 @@ static int tegra_adma_runtime_suspend(struct device *dev)
static int tegra_adma_runtime_resume(struct device *dev)
{
struct tegra_adma *tdma = dev_get_drvdata(dev);
- int ret;
+ struct tegra_adma_chan_regs *ch_reg;
+ struct tegra_adma_chan *tdc;
+ int ret, i;
ret = clk_prepare_enable(tdma->ahub_clk);
if (ret) {
@@ -730,6 +756,24 @@ static int tegra_adma_runtime_resume(struct device *dev)
}
tdma_write(tdma, ADMA_GLOBAL_CMD, tdma->global_cmd);
+ if (!tdma->global_cmd)
+ return 0;
+
+ for (i = 0; i < tdma->nr_channels; i++) {
+ tdc = &tdma->channels[i];
+ ch_reg = &tdc->ch_regs;
+ /* skip if channel was not active earlier */
+ if (!ch_reg->cmd)
+ continue;
+ tdma_ch_write(tdc, ADMA_CH_TC, ch_reg->tc);
+ tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_reg->src_addr);
+ tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_reg->trg_addr);
+ tdma_ch_write(tdc, ADMA_CH_CTRL, ch_reg->ctrl);
+ tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_reg->fifo_ctrl);
+ tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_reg->config);
+ tdma_ch_write(tdc, ADMA_CH_CMD, ch_reg->cmd);
+ }
+
return 0;
}
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Sameer Pujar @ 2019-05-02 13:29 UTC (permalink / raw)
To: Vinod Koul; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <20190502122506.GP3845@vkoul-mobl.Dlink>
On 5/2/2019 5:55 PM, Vinod Koul wrote:
> On 02-05-19, 16:23, Sameer Pujar wrote:
>> On 5/2/2019 11:34 AM, Vinod Koul wrote:
>>> On 30-04-19, 17:00, Sameer Pujar wrote:
>>>> During the DMA transfers from memory to I/O, it was observed that transfers
>>>> were inconsistent and resulted in glitches for audio playback. It happened
>>>> because fifo size on DMA did not match with slave channel configuration.
>>>>
>>>> currently 'dma_slave_config' structure does not have a field for fifo size.
>>>> Hence the platform pcm driver cannot pass the fifo size as a slave_config.
>>>> Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
>>>> cannot be used to pass the size info. This patch introduces fifo_size field
>>>> and the same can be populated on slave side. Users can set required size
>>>> for slave peripheral (multiple channels can be independently running with
>>>> different fifo sizes) and the corresponding sizes are programmed through
>>>> dma_slave_config on DMA side.
>>> FIFO size is a hardware property not sure why you would want an
>>> interface to program that?
>>>
>>> On mismatch, I guess you need to take care of src/dst_maxburst..
>> Yes, FIFO size is a HW property. But it is SW configurable(atleast in my
>> case) on
>> slave side and can be set to different sizes. The src/dst_maxburst is
> Are you sure, have you talked to HW folks on that? IIUC you are
> programming the data to be used in FIFO not the FIFO length!
Yes, I mentioned about FIFO length.
1. MAX FIFO size is fixed in HW. But there is a way to limit the usage
per channel
in multiples of 64 bytes.
2. Having a separate member would give independent control over MAX
BURST SIZE and
FIFO SIZE.
>
>> programmed
>> for specific values, I think this depends on few factors related to
>> bandwidth
>> needs of client, DMA needs of the system etc.,
> Precisely
>
>> In such cases how does DMA know the actual FIFO depth of slave peripheral?
> Why should DMA know? Its job is to push/pull data as configured by
> peripheral driver. The peripheral driver knows and configures DMA
> accordingly.
I am not sure if there is any HW logic that mandates DMA to know the size
of configured FIFO depth on slave side. I will speak to HW folks and
would update here.
>
>>>> Request for feedback/suggestions.
>>>>
>>>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>>>> ---
>>>> include/linux/dmaengine.h | 3 +++
>>>> 1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
>>>> index d49ec5c..9ec198b 100644
>>>> --- a/include/linux/dmaengine.h
>>>> +++ b/include/linux/dmaengine.h
>>>> @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
>>>> * @slave_id: Slave requester id. Only valid for slave channels. The dma
>>>> * slave peripheral will have unique id as dma requester which need to be
>>>> * pass as slave config.
>>>> + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
>>>> + * fifo size and the same needs to be passed as slave config.
>>>> *
>>>> * This struct is passed in as configuration data to a DMA engine
>>>> * in order to set up a certain channel for DMA transport at runtime.
>>>> @@ -376,6 +378,7 @@ struct dma_slave_config {
>>>> u32 dst_port_window_size;
>>>> bool device_fc;
>>>> unsigned int slave_id;
>>>> + u32 fifo_size;
>>>> };
>>>> /**
>>>> --
>>>> 2.7.4
^ permalink raw reply
* Re: [PATCH 0/6] Add support for Tegra186/Tegra194 and generic fixes
From: Jon Hunter @ 2019-05-02 13:36 UTC (permalink / raw)
To: Sameer Pujar, vkoul, dan.j.williams, robh+dt, mark.rutland
Cc: thierry.reding, ldewangan, dmaengine, devicetree, linux-tegra,
linux-kernel
In-Reply-To: <1556801717-31507-1-git-send-email-spujar@nvidia.com>
On 02/05/2019 13:55, Sameer Pujar wrote:
> Audio DMA(ADMA) interface is a gateway in the AHUB for facilitating DMA
> transfers between memory and all of its clients. Currently the driver
> supports Tegra210 based platforms. This series adds support for Tegra186
> and Tegra194 based platforms and fixes few functional issues.
>
> Patches in the series are classified into three categories,
> 1. Add support for Tegra186 and Tegra194
> 2. Add DMA pause/resume feature
> 3. Fixes common to differernt Tegra generations
>
> Below change log describes the patches in detail.
>
> Change log:
> =====================================
> v1
> ----
> The series can be classified into 3 categories,
> 1. Add support for Tegra186 and Tegra194
> [Patch 1/6] dmaengine: tegra210-adma: prepare for supporting newer
> Tegra chips
> * The support was there only for Tegra210
> * This is a preparation for adding support for newer Tegra chips
> * chip_data is enhanced to support differences between Tegra210 and
> Tegra186/Tegra194
> [Patch 2/6] Documentation: DT: Add compatibility binding for Tegra186
> * New compatibility string is required for driver to work for
> Tegra186 and Tegra194. Hence new compatibility is introduced.
> * Tegra194 can use the same compatibility as Tegra186
> [Patch 3/6] dmaengine: tegra210-adma: add support for Tegra186/
> Tegra194
> * Populates chip specific information for Tegra186
> * There is a difference in the way ADMA CH_CONFIG registers are
> encoded for Tegra210 and Tegra186. Added helper fucntions to
> support different versions of burst size configuration
>
> 2. Add DMA pause/resume feature
> [Patch 4/6] dmaengine: tegra210-adma: add pause/resume support
> * Adds support for ADMA pause/resume, otherwise audio loss was seen
> during continuous pause/resume of audio playback.
>
> 3. Fixes common to differernt Tegra generations
> [Patch 5/6] dmaengine: tegra210-dma: free dma controller in remove()
> * Fixes kernel panic observed during driver reload. DMA controller
> needs to be freed when driver is unloaded
> [Patch 6/6] dmaengine: tegra210-adma: restore channel status
> * Fixes resume across system suspend. If the channel state is not
> restored, the transfers won't resume from the state from where it
> was left during suspend entry. In this case, audio playback did
> not resume properly once system exited from low power state.
>
> ===============================
> Sameer Pujar (6):
> dmaengine: tegra210-adma: prepare for supporting newer Tegra chips
> Documentation: DT: Add compatibility binding for Tegra186
> dmaengine: tegra210-adma: add support for Tegra186/Tegra194
> dmaengine: tegra210-adma: add pause/resume support
> dmaengine: tegra210-dma: free dma controller in remove()
> dmaengine: tegra210-adma: restore channel status
>
> .../bindings/dma/nvidia,tegra210-adma.txt | 4 +-
> drivers/dma/tegra210-adma.c | 232 +++++++++++++++++----
> 2 files changed, 193 insertions(+), 43 deletions(-)
>
Thanks!
For the series ...
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCH] dmaengine: at_xdmac: remove a stray bottom half unlock
From: Dan Carpenter @ 2019-05-03 13:15 UTC (permalink / raw)
To: Ludovic Desroches, Barry Song
Cc: Vinod Koul, Dan Williams, dmaengine, kernel-janitors
We switched this code from spin_lock_bh() to vanilla spin_lock() but
there was one stray spin_unlock_bh() that was overlooked. This
patch converts it to spin_unlock() as well.
Fixes: d8570d018f69 ("dmaengine: at_xdmac: move spin_lock_bh to spin_lock in tasklet")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
drivers/dma/at_xdmac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 06cbe54e4c30..e4ae2ee46d3f 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1655,7 +1655,7 @@ static void at_xdmac_tasklet(unsigned long data)
dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc);
if (!desc->active_xfer) {
dev_err(chan2dev(&atchan->chan), "Xfer not active: exiting");
- spin_unlock_bh(&atchan->lock);
+ spin_unlock(&atchan->lock);
return;
}
--
2.18.0
^ permalink raw reply related
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Peter Ujfalusi @ 2019-05-03 19:10 UTC (permalink / raw)
To: Sameer Pujar, Vinod Koul
Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <3368d1e1-0d7f-f602-5b96-a978fcf4d91b@nvidia.com>
On 5/2/19 4:29 PM, Sameer Pujar wrote:
>
> On 5/2/2019 5:55 PM, Vinod Koul wrote:
>> On 02-05-19, 16:23, Sameer Pujar wrote:
>>> On 5/2/2019 11:34 AM, Vinod Koul wrote:
>>>> On 30-04-19, 17:00, Sameer Pujar wrote:
>>>>> During the DMA transfers from memory to I/O, it was observed that
>>>>> transfers
>>>>> were inconsistent and resulted in glitches for audio playback. It
>>>>> happened
>>>>> because fifo size on DMA did not match with slave channel
>>>>> configuration.
>>>>>
>>>>> currently 'dma_slave_config' structure does not have a field for
>>>>> fifo size.
>>>>> Hence the platform pcm driver cannot pass the fifo size as a
>>>>> slave_config.
>>>>> Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size
>>>>> field which
>>>>> cannot be used to pass the size info. This patch introduces
>>>>> fifo_size field
>>>>> and the same can be populated on slave side. Users can set required
>>>>> size
>>>>> for slave peripheral (multiple channels can be independently
>>>>> running with
>>>>> different fifo sizes) and the corresponding sizes are programmed
>>>>> through
>>>>> dma_slave_config on DMA side.
>>>> FIFO size is a hardware property not sure why you would want an
>>>> interface to program that?
>>>>
>>>> On mismatch, I guess you need to take care of src/dst_maxburst..
>>> Yes, FIFO size is a HW property. But it is SW configurable(atleast in my
>>> case) on
>>> slave side and can be set to different sizes. The src/dst_maxburst is
>> Are you sure, have you talked to HW folks on that? IIUC you are
>> programming the data to be used in FIFO not the FIFO length!
> Yes, I mentioned about FIFO length.
>
> 1. MAX FIFO size is fixed in HW. But there is a way to limit the usage
> per channel
> in multiples of 64 bytes.
> 2. Having a separate member would give independent control over MAX
> BURST SIZE and
> FIFO SIZE.
Why would the DMA care about the FIFO size of a peripheral?
All it should be concerned that how many bytes it should transfer per
DMA request from the peripheral.
It is the task of the peripheral driver to choose the maxburst to match
with the peripheral's configuration and the peripheral configuration
should not allow maxburst to overflow (or underflow) the peripheral FIFO.
>>
>>> programmed
>>> for specific values, I think this depends on few factors related to
>>> bandwidth
>>> needs of client, DMA needs of the system etc.,
>> Precisely
>>
>>> In such cases how does DMA know the actual FIFO depth of slave
>>> peripheral?
>> Why should DMA know? Its job is to push/pull data as configured by
>> peripheral driver. The peripheral driver knows and configures DMA
>> accordingly.
> I am not sure if there is any HW logic that mandates DMA to know the size
> of configured FIFO depth on slave side. I will speak to HW folks and
> would update here.
>>
>>>>> Request for feedback/suggestions.
>>>>>
>>>>> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
>>>>> ---
>>>>> include/linux/dmaengine.h | 3 +++
>>>>> 1 file changed, 3 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
>>>>> index d49ec5c..9ec198b 100644
>>>>> --- a/include/linux/dmaengine.h
>>>>> +++ b/include/linux/dmaengine.h
>>>>> @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
>>>>> * @slave_id: Slave requester id. Only valid for slave channels.
>>>>> The dma
>>>>> * slave peripheral will have unique id as dma requester which
>>>>> need to be
>>>>> * pass as slave config.
>>>>> + * @fifo_size: Fifo size value. The dma slave peripheral can
>>>>> configure required
>>>>> + * fifo size and the same needs to be passed as slave config.
>>>>> *
>>>>> * This struct is passed in as configuration data to a DMA engine
>>>>> * in order to set up a certain channel for DMA transport at
>>>>> runtime.
>>>>> @@ -376,6 +378,7 @@ struct dma_slave_config {
>>>>> u32 dst_port_window_size;
>>>>> bool device_fc;
>>>>> unsigned int slave_id;
>>>>> + u32 fifo_size;
>>>>> };
>>>>> /**
>>>>> --
>>>>> 2.7.4
- Peter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* [PATCH 1/2] dmaengine: fsl-edma: Fix typo in Vybrid name
From: Krzysztof Kozlowski @ 2019-05-04 9:52 UTC (permalink / raw)
To: Vinod Koul, Dan Williams, Minas Harutyunyan, Greg Kroah-Hartman,
dmaengine, linux-kernel, linux-usb
Cc: Krzysztof Kozlowski
Fix typo in comment for Vybrid SoC family.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/dma/fsl-edma-common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index b435d8e1e3a1..c53f76eeb4d3 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -136,7 +136,7 @@ struct fsl_edma_desc {
};
enum edma_version {
- v1, /* 32ch, Vybdir, mpc57x, etc */
+ v1, /* 32ch, Vybrid, mpc57x, etc */
v2, /* 64ch Coldfire */
};
--
2.17.1
^ permalink raw reply related
* [PATCH] usb: dwc2: gadget: Replace phyif with phy_utmi_width
From: Krzysztof Kozlowski @ 2019-05-04 9:52 UTC (permalink / raw)
To: Vinod Koul, Dan Williams, Minas Harutyunyan, Greg Kroah-Hartman,
dmaengine, linux-kernel, linux-usb
Cc: Jules Maselbas, Felipe Balbi
In-Reply-To: <20190504095225.23883-1-krzk@kernel.org>
From: Jules Maselbas <jmaselbas@kalray.eu>
The phy utmi width information is already set in hsotg params,
phyif is only used in few places and I don't see any reason to
not use hsotg's params.
Moreover the utmi width was being forced to 16 bits by platform
initialization which doesn't take in account HW configuration.
Acked-by: Minas Harutyunyan <hminas@synopsys.com>
Signed-off-by: Jules Maselbas <jmaselbas@kalray.eu>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
---
drivers/usb/dwc2/core.h | 2 --
drivers/usb/dwc2/gadget.c | 20 ++++++++++++++------
drivers/usb/dwc2/platform.c | 5 +----
3 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 764c78ebee28..8e3edf10d76d 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -871,7 +871,6 @@ struct dwc2_hregs_backup {
* removed once all SoCs support usb transceiver.
* @supplies: Definition of USB power supplies
* @vbus_supply: Regulator supplying vbus.
- * @phyif: PHY interface width
* @lock: Spinlock that protects all the driver data structures
* @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
@@ -1056,7 +1055,6 @@ struct dwc2_hsotg {
struct dwc2_hsotg_plat *plat;
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
struct regulator *vbus_supply;
- u32 phyif;
spinlock_t lock;
void *priv;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 9b737c4e8f50..614f8c34d759 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3314,20 +3314,28 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
/* keep other bits untouched (so e.g. forced modes are not lost) */
usbcfg = dwc2_readl(hsotg, GUSBCFG);
+ /* remove the HNP/SRP */
usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
- GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
+ GUSBCFG_HNPCAP);
+ usbcfg |= GUSBCFG_TOUTCAL(7);
if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
(hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
hsotg->params.speed == DWC2_SPEED_PARAM_LOW)) {
/* FS/LS Dedicated Transceiver Interface */
usbcfg |= GUSBCFG_PHYSEL;
- } else {
- /* set the PLL on, remove the HNP/SRP and set the PHY */
- val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
- usbcfg |= hsotg->phyif | GUSBCFG_TOUTCAL(7) |
- (val << GUSBCFG_USBTRDTIM_SHIFT);
+ } else if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_UTMI) {
+ if (hsotg->params.phy_utmi_width == 16)
+ usbcfg |= GUSBCFG_PHYIF16;
+
+ /* Set turnaround time */
+ usbcfg &= ~GUSBCFG_USBTRDTIM_MASK;
+ if (hsotg->params.phy_utmi_width == 16)
+ usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT;
+ else
+ usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT;
}
+
dwc2_writel(hsotg, usbcfg, GUSBCFG);
dwc2_hsotg_init_fifo(hsotg);
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index c01fa8ffc0c8..d10a7f8daec3 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -230,9 +230,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
reset_control_deassert(hsotg->reset_ecc);
- /* Set default UTMI width */
- hsotg->phyif = GUSBCFG_PHYIF16;
-
/*
* Attempt to find a generic PHY, then look for an old style
* USB PHY and then fall back to pdata
@@ -280,7 +277,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
* width is 8-bit and set the phyif appropriately.
*/
if (phy_get_bus_width(hsotg->phy) == 8)
- hsotg->phyif = GUSBCFG_PHYIF8;
+ hsotg->params.phy_utmi_width = 8;
}
/* Clock */
--
2.17.1
^ permalink raw reply related
* [PATCH 2/2] dmaengine: fsl-edma: Adjust indentation
From: Krzysztof Kozlowski @ 2019-05-04 9:52 UTC (permalink / raw)
To: Vinod Koul, Dan Williams, Minas Harutyunyan, Greg Kroah-Hartman,
dmaengine, linux-kernel, linux-usb
Cc: Krzysztof Kozlowski
In-Reply-To: <20190504095225.23883-1-krzk@kernel.org>
Fix indentation and remove unneeded space after 'return' keyword. This
fixes checkpatch warning:
WARNING: Statements should start on a tabstop
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/dma/fsl-edma.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 75e8a7ba3a22..d641ef85a634 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -144,21 +144,21 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
fsl_edma_irq_handler, 0, "eDMA", fsl_edma);
if (ret) {
dev_err(&pdev->dev, "Can't register eDMA IRQ.\n");
- return ret;
+ return ret;
}
} else {
ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
fsl_edma_tx_handler, 0, "eDMA tx", fsl_edma);
if (ret) {
dev_err(&pdev->dev, "Can't register eDMA tx IRQ.\n");
- return ret;
+ return ret;
}
ret = devm_request_irq(&pdev->dev, fsl_edma->errirq,
fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
if (ret) {
dev_err(&pdev->dev, "Can't register eDMA err IRQ.\n");
- return ret;
+ return ret;
}
}
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v2] dmaengine: stm32-dma: fix residue calculation in stm32-dma
From: Vinod Koul @ 2019-05-04 10:18 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Dan Williams, Pierre-Yves MORDRET, linux-stm32, linux-kernel,
dmaengine
In-Reply-To: <1556789322-7232-1-git-send-email-arnaud.pouliquen@st.com>
On 02-05-19, 11:28, Arnaud Pouliquen wrote:
> In double buffer mode, during residue calculation, the DMA can
> automatically switch to the next transfer. Indeed the CT bit that
> gives position in the double buffer can has been updated by the
> hardware, during calculation.
> In this case the SxNDTR register value can not be trusted.
> If a transition is detected we consider that the DMA has switched to
> the beginning of next sg.
Applied, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH 1/2] dmaengine: fsl-edma: Fix typo in Vybrid name
From: Vinod Koul @ 2019-05-04 10:21 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Dan Williams, Minas Harutyunyan, Greg Kroah-Hartman, dmaengine,
linux-kernel, linux-usb
In-Reply-To: <20190504095225.23883-1-krzk@kernel.org>
On 04-05-19, 11:52, Krzysztof Kozlowski wrote:
> Fix typo in comment for Vybrid SoC family.
Applied both in the series and ignore the (3rd?) usb patch! thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH] [RFC] dmaengine: add fifo_size member
From: Vinod Koul @ 2019-05-04 10:23 UTC (permalink / raw)
To: Sameer Pujar; +Cc: dan.j.williams, tiwai, jonathanh, dmaengine, linux-kernel
In-Reply-To: <3368d1e1-0d7f-f602-5b96-a978fcf4d91b@nvidia.com>
On 02-05-19, 18:59, Sameer Pujar wrote:
>
> On 5/2/2019 5:55 PM, Vinod Koul wrote:
> > On 02-05-19, 16:23, Sameer Pujar wrote:
> > > On 5/2/2019 11:34 AM, Vinod Koul wrote:
> > > > On 30-04-19, 17:00, Sameer Pujar wrote:
> > > > > During the DMA transfers from memory to I/O, it was observed that transfers
> > > > > were inconsistent and resulted in glitches for audio playback. It happened
> > > > > because fifo size on DMA did not match with slave channel configuration.
> > > > >
> > > > > currently 'dma_slave_config' structure does not have a field for fifo size.
> > > > > Hence the platform pcm driver cannot pass the fifo size as a slave_config.
> > > > > Note that 'snd_dmaengine_dai_dma_data' structure has fifo_size field which
> > > > > cannot be used to pass the size info. This patch introduces fifo_size field
> > > > > and the same can be populated on slave side. Users can set required size
> > > > > for slave peripheral (multiple channels can be independently running with
> > > > > different fifo sizes) and the corresponding sizes are programmed through
> > > > > dma_slave_config on DMA side.
> > > > FIFO size is a hardware property not sure why you would want an
> > > > interface to program that?
> > > >
> > > > On mismatch, I guess you need to take care of src/dst_maxburst..
> > > Yes, FIFO size is a HW property. But it is SW configurable(atleast in my
> > > case) on
> > > slave side and can be set to different sizes. The src/dst_maxburst is
> > Are you sure, have you talked to HW folks on that? IIUC you are
> > programming the data to be used in FIFO not the FIFO length!
> Yes, I mentioned about FIFO length.
>
> 1. MAX FIFO size is fixed in HW. But there is a way to limit the usage per
> channel
> in multiples of 64 bytes.
> 2. Having a separate member would give independent control over MAX BURST
> SIZE and
> FIFO SIZE.
> >
> > > programmed
> > > for specific values, I think this depends on few factors related to
> > > bandwidth
> > > needs of client, DMA needs of the system etc.,
> > Precisely
> >
> > > In such cases how does DMA know the actual FIFO depth of slave peripheral?
> > Why should DMA know? Its job is to push/pull data as configured by
> > peripheral driver. The peripheral driver knows and configures DMA
> > accordingly.
> I am not sure if there is any HW logic that mandates DMA to know the size
> of configured FIFO depth on slave side. I will speak to HW folks and
> would update here.
I still do not comprehend why dma would care about slave side
configuration. In the absence of patch which uses this I am not sure
what you are trying to do...
> > > > > Request for feedback/suggestions.
> > > > >
> > > > > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > > > > ---
> > > > > include/linux/dmaengine.h | 3 +++
> > > > > 1 file changed, 3 insertions(+)
> > > > >
> > > > > diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> > > > > index d49ec5c..9ec198b 100644
> > > > > --- a/include/linux/dmaengine.h
> > > > > +++ b/include/linux/dmaengine.h
> > > > > @@ -351,6 +351,8 @@ enum dma_slave_buswidth {
> > > > > * @slave_id: Slave requester id. Only valid for slave channels. The dma
> > > > > * slave peripheral will have unique id as dma requester which need to be
> > > > > * pass as slave config.
> > > > > + * @fifo_size: Fifo size value. The dma slave peripheral can configure required
> > > > > + * fifo size and the same needs to be passed as slave config.
> > > > > *
> > > > > * This struct is passed in as configuration data to a DMA engine
> > > > > * in order to set up a certain channel for DMA transport at runtime.
> > > > > @@ -376,6 +378,7 @@ struct dma_slave_config {
> > > > > u32 dst_port_window_size;
> > > > > bool device_fc;
> > > > > unsigned int slave_id;
> > > > > + u32 fifo_size;
> > > > > };
> > > > > /**
> > > > > --
> > > > > 2.7.4
--
~Vinod
^ permalink raw reply
* Re: [PATCH] dmaengine: at_xdmac: remove a stray bottom half unlock
From: Vinod Koul @ 2019-05-04 10:41 UTC (permalink / raw)
To: Dan Carpenter
Cc: Ludovic Desroches, Barry Song, Dan Williams, dmaengine,
kernel-janitors
In-Reply-To: <20190503131507.GA1236@mwanda>
On 03-05-19, 16:15, Dan Carpenter wrote:
> We switched this code from spin_lock_bh() to vanilla spin_lock() but
> there was one stray spin_unlock_bh() that was overlooked. This
> patch converts it to spin_unlock() as well.
Applied, thanks
--
~Vinod
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox