From: Sascha Hauer on
Hi,

I am currently looking into implementing the Freescale i.MX SDMA engine
into the dmaengine API. The SDMA engine can handle sg transfers from/to
devices. During implementation some questions came up.

On the i.MX we already have a DMA engine which can do slave dma
transfers, the IPU (drivers/dma/ipu/), which is exclusively used for
image operations. My problem is that I found no way for the clients
to select which DMA engine to use as both have the same capabilities
(DMA_SLAVE).

For the SDMA engine the clients have to pass some platform specific data
to the SDMA engine (dma request line, word width and the like). The
current mechanism is to pass this data through the dma_chan->private
field, which seems more like tunneling instead of passing the data as we
lose type safety. Are there any ideas to improve this?

Sascha



--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Dan Williams on
On Thu, Aug 12, 2010 at 8:00 AM, Sascha Hauer <s.hauer(a)pengutronix.de> wrote:
> Hi,
>
> I am currently looking into implementing the Freescale i.MX SDMA engine
> into the dmaengine API. The SDMA engine can handle sg transfers from/to
> devices. During implementation some questions came up.
>
> On the i.MX we already have a DMA engine which can do slave dma
> transfers, the IPU (drivers/dma/ipu/), which is exclusively used for
> image operations. My problem is that I found no way for the clients
> to select which DMA engine to use as both have the same capabilities
> (DMA_SLAVE).

Yes, if you need finer grained matching of channels, beyond simple
capability matching, this is the intended purpose of the
'dma_filter_fn' and 'filter_param' arguments to dma_request_channel.
Dmaengine will pass all available channels that match the base
capability to the filter function for further, usually architecture
specific, discrimination.

> For the SDMA engine the clients have to pass some platform specific data
> to the SDMA engine (dma request line, word width and the like). The
> current mechanism is to pass this data through the dma_chan->private
> field, which seems more like tunneling instead of passing the data as we
> lose type safety. Are there any ideas to improve this?

Hopefully dma_chan->private can eventually be phased out in favor of
Linus' dma_slave_config scheme [1].

--
Dan

[1]: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=c156d0a5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Sascha Hauer on
On Thu, Aug 12, 2010 at 12:14:20PM -0700, Dan Williams wrote:
> On Thu, Aug 12, 2010 at 8:00 AM, Sascha Hauer <s.hauer(a)pengutronix.de> wrote:
> > Hi,
> >
> > I am currently looking into implementing the Freescale i.MX SDMA engine
> > into the dmaengine API. The SDMA engine can handle sg transfers from/to
> > devices. During implementation some questions came up.
> >
> > On the i.MX we already have a DMA engine which can do slave dma
> > transfers, the IPU (drivers/dma/ipu/), which is exclusively used for
> > image operations. My problem is that I found no way for the clients
> > to select which DMA engine to use as both have the same capabilities
> > (DMA_SLAVE).
>
> Yes, if you need finer grained matching of channels, beyond simple
> capability matching, this is the intended purpose of the
> 'dma_filter_fn' and 'filter_param' arguments to dma_request_channel.
> Dmaengine will pass all available channels that match the base
> capability to the filter function for further, usually architecture
> specific, discrimination.

Ok, so I could do a strcmp(dev_name(chan->device->dev), "imx-sdma") in
the filter function.

>
> > For the SDMA engine the clients have to pass some platform specific data
> > to the SDMA engine (dma request line, word width and the like). The
> > current mechanism is to pass this data through the dma_chan->private
> > field, which seems more like tunneling instead of passing the data as we
> > lose type safety. Are there any ideas to improve this?
>
> Hopefully dma_chan->private can eventually be phased out in favor of
> Linus' dma_slave_config scheme [1].

This looks promising. Two things are missing here for the SDMA engine.
First is the DMA request line which is probably needed for other dma
engines aswell, so this could be added to dma_slave_config. The other
one is really specific to the SDMA engine, it's the following enum. The
SDMA engine is a programmable controller in the i.MX and each peripheral
has its own copy function in this controller. This enum is used to
determine their start addresses.

typedef enum {
IMX_DMATYPE_SSI, /* MCU domain SSI */
IMX_DMATYPE_SSI_SP, /* Shared SSI */
IMX_DMATYPE_MMC, /* MMC */
IMX_DMATYPE_SDHC, /* SDHC */
IMX_DMATYPE_UART, /* MCU domain UART */
IMX_DMATYPE_UART_SP, /* Shared UART */
IMX_DMATYPE_FIRI, /* FIRI */
IMX_DMATYPE_CSPI, /* MCU domain CSPI */
IMX_DMATYPE_CSPI_SP, /* Shared CSPI */
IMX_DMATYPE_SIM, /* SIM */
IMX_DMATYPE_ATA, /* ATA */
IMX_DMATYPE_CCM, /* CCM */
IMX_DMATYPE_EXT, /* External peripheral */
IMX_DMATYPE_MSHC, /* Memory Stick Host Controller */
IMX_DMATYPE_MSHC_SP, /* Shared Memory Stick Host Controller */
IMX_DMATYPE_DSP, /* DSP */
IMX_DMATYPE_MEMORY, /* Memory */
IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */
IMX_DMATYPE_SPDIF, /* SPDIF */
IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */
IMX_DMATYPE_ASRC, /* ASRC */
IMX_DMATYPE_ESAI, /* ESAI */
} sdma_peripheral_type;

Sascha

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Linus Walleij on
2010/8/12 Sascha Hauer <s.hauer(a)pengutronix.de>:
> [Dan]
>> Hopefully dma_chan->private can eventually be phased out in favor of
>> Linus' dma_slave_config scheme [1].
>
> This looks promising. Two things are missing here for the SDMA engine.
> First is the DMA request line which is probably needed for other dma
> engines aswell, so this could be added to dma_slave_config.

Do you really need to configure this at runtime?
The idea is to pass in stuff that is changed dynamically wheras
things that are fixed are passed in from platform data.

In the PL180 there was multiplexing functions for the lines even
(so one line was shared between different devices) in that case
I implemented platform-specific callbacks in the platform data
to request the lines.

> The other
> one is really specific to the SDMA engine, it's the following enum. The
> SDMA engine is a programmable controller in the i.MX and each peripheral
> has its own copy function in this controller. This enum is used to
> determine their start addresses.

Can't you pass in the actual address in src_address for RX and
dst_address for TX?

The idea here is that the driver know the physical address where
the bitpipe is supposed to end up, and the DMAengine does not.
If it was always the same address we could pass that also through
platform data but experience shows that some devices use different
addresses for different kinds of configurations, that's why it's there.

Maybe I'm just not getting it...

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Sascha Hauer on
On Fri, Aug 13, 2010 at 12:32:08AM +0200, Linus Walleij wrote:
> 2010/8/12 Sascha Hauer <s.hauer(a)pengutronix.de>:
> > [Dan]
> >> Hopefully dma_chan->private can eventually be phased out in favor of
> >> Linus' dma_slave_config scheme [1].
> >
> > This looks promising. Two things are missing here for the SDMA engine.
> > First is the DMA request line which is probably needed for other dma
> > engines aswell, so this could be added to dma_slave_config.
>
> Do you really need to configure this at runtime?
> The idea is to pass in stuff that is changed dynamically wheras
> things that are fixed are passed in from platform data.

It's not changed dynamically, but the information which dma request a
client has to use is in its resources. So the client does a
platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); to get the
request line to use. Somehow this information must get to the SDMA
engine. By platform data do you mean the private pointer in dma_chan?

>
> In the PL180 there was multiplexing functions for the lines even
> (so one line was shared between different devices) in that case
> I implemented platform-specific callbacks in the platform data
> to request the lines.

Do you have a pointer to the code?

>
> > The other
> > one is really specific to the SDMA engine, it's the following enum. The
> > SDMA engine is a programmable controller in the i.MX and each peripheral
> > has its own copy function in this controller. This enum is used to
> > determine their start addresses.
>
> Can't you pass in the actual address in src_address for RX and
> dst_address for TX?

I'm not talking about addresses in the physical address space of the
i.MX here. I'm talking about addresses in the program address space of
the SDMA controller. Let me explain this a little more in detail. The
SDMA engine has a little microcontroller in it which gets a 6k or
something firmware image. The firmware consists of several functions
(which are running in the controller). The SDMA driver now translates
the information 'sdhc controller receive' into an offset in the firmware
image.

The actual FIFO address of the peripheral is of course passed in
src_address/dst_address.

>
> The idea here is that the driver know the physical address where
> the bitpipe is supposed to end up, and the DMAengine does not.
> If it was always the same address we could pass that also through
> platform data but experience shows that some devices use different
> addresses for different kinds of configurations, that's why it's there.
>
> Maybe I'm just not getting it...

I hope my explanation above helps. The following function is the snippet
in the SDMA driver which does this translation work:

static void sdma_get_pc(struct sdma_channel *sdma,
sdma_peripheral_type peripheral_type)
{
int res = 0;
int per_2_emi = 0, emi_2_per = 0;
int per_2_int = 0, int_2_per = 0;
int per_2_per = 0, emi_2_emi = 0;

sdma->pc_from_device = 0;
sdma->pc_to_device = 0;

switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
emi_2_emi = sdma_script_addrs->ap_2_ap_addr;
break;
case IMX_DMATYPE_DSP:
emi_2_per = sdma_script_addrs->bp_2_ap_addr;
per_2_emi = sdma_script_addrs->ap_2_bp_addr;
break;
case IMX_DMATYPE_FIRI:
per_2_int = sdma_script_addrs->firi_2_per_addr;
per_2_emi = sdma_script_addrs->firi_2_mcu_addr;
int_2_per = sdma_script_addrs->per_2_firi_addr;
emi_2_per = sdma_script_addrs->mcu_2_firi_addr;
break;
case IMX_DMATYPE_UART:
per_2_int = sdma_script_addrs->uart_2_per_addr;
per_2_emi = sdma_script_addrs->uart_2_mcu_addr;
int_2_per = sdma_script_addrs->per_2_app_addr;
emi_2_per = sdma_script_addrs->mcu_2_app_addr;
break;
case IMX_DMATYPE_UART_SP:
per_2_int = sdma_script_addrs->uartsh_2_per_addr;
per_2_emi = sdma_script_addrs->uartsh_2_mcu_addr;
int_2_per = sdma_script_addrs->per_2_shp_addr;
emi_2_per = sdma_script_addrs->mcu_2_shp_addr;
break;
case IMX_DMATYPE_ATA:
per_2_emi = sdma_script_addrs->ata_2_mcu_addr;
emi_2_per = sdma_script_addrs->mcu_2_ata_addr;
break;
case IMX_DMATYPE_CSPI:
case IMX_DMATYPE_EXT:
case IMX_DMATYPE_SSI:
per_2_int = sdma_script_addrs->app_2_per_addr;
per_2_emi = sdma_script_addrs->app_2_mcu_addr;
int_2_per = sdma_script_addrs->per_2_app_addr;
emi_2_per = sdma_script_addrs->mcu_2_app_addr;
break;
case IMX_DMATYPE_SSI_SP:
case IMX_DMATYPE_MMC:
case IMX_DMATYPE_SDHC:
case IMX_DMATYPE_CSPI_SP:
case IMX_DMATYPE_ESAI:
case IMX_DMATYPE_MSHC_SP:
per_2_int = sdma_script_addrs->shp_2_per_addr;
per_2_emi = sdma_script_addrs->shp_2_mcu_addr;
int_2_per = sdma_script_addrs->per_2_shp_addr;
emi_2_per = sdma_script_addrs->mcu_2_shp_addr;
break;
case IMX_DMATYPE_ASRC:
per_2_emi = sdma_script_addrs->asrc_2_mcu_addr;
emi_2_per = sdma_script_addrs->asrc_2_mcu_addr;
per_2_per = sdma_script_addrs->per_2_per_addr;
break;
case IMX_DMATYPE_MSHC:
per_2_emi = sdma_script_addrs->mshc_2_mcu_addr;
emi_2_per = sdma_script_addrs->mcu_2_mshc_addr;
break;
case IMX_DMATYPE_CCM:
per_2_emi = sdma_script_addrs->dptc_dvfs_addr;
break;
case IMX_DMATYPE_FIFO_MEMORY:
res = sdma_script_addrs->ap_2_ap_fixed_addr;
break;
case IMX_DMATYPE_SPDIF:
per_2_emi = sdma_script_addrs->spdif_2_mcu_addr;
emi_2_per = sdma_script_addrs->mcu_2_spdif_addr;
break;
case IMX_DMATYPE_IPU_MEMORY:
emi_2_per = sdma_script_addrs->ext_mem_2_ipu_addr;
break;
default:
break;
}

sdma->pc_from_device = per_2_emi;
sdma->pc_to_device = emi_2_per;
}

Regards,
Sascha

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/