2010/10/22 Alan Cox <a...@lxorguk.ukuu.org.uk>:

> From: Mathieu SOULARD <mathieux.soul...@intel.com>
> (...)
> +/**
> + * intel_mid_ssp_spi_dma_init() - Initialize DMA
> + * @drv_context:       Pointer to the private driver context
> + *
> + * This function is called at driver setup phase to allocate DMA
> + * ressources.
> + */
> +static void intel_mid_ssp_spi_dma_init(struct ssp_driver_context 
> *drv_context)
> +{
> +       struct intel_mid_dma_slave *rxs, *txs;
> +       struct dma_slave_config *ds;

Hey, I really like this :-)

But where are you actually using this config?

It looks like you're in some transition phase to the
generic API.

> +       dma_cap_mask_t mask;
> +       struct device *dev = &drv_context->pdev->dev;
> +       unsigned int device_id;
> +
> +       /* Configure RX channel parameters */
> +       rxs = &drv_context->dmas_rx;
> +       ds = &rxs->dma_slave;
> +
> +       ds->direction = DMA_FROM_DEVICE;
> +       rxs->hs_mode = LNW_DMA_HW_HS;
> +       rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
> +       ds->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +       ds->src_addr_width = drv_context->n_bytes;
> +
> +       /* Use a DMA burst according to the FIFO thresholds */
> +       if (drv_context->rx_fifo_threshold == 8) {
> +               ds->src_maxburst = 8;
> +               ds->dst_maxburst = 8;
> +       } else if (drv_context->rx_fifo_threshold == 4) {
> +               ds->src_maxburst = 4;
> +               ds->dst_maxburst = 4;
> +       } else {
> +               ds->src_maxburst = 1;
> +               ds->dst_maxburst = 1;
> +       }
> +
> +       /* Configure TX channel parameters */
> +       txs = &drv_context->dmas_tx;
> +       ds = &txs->dma_slave;
> +
> +       ds->direction = DMA_TO_DEVICE;
> +       txs->hs_mode = LNW_DMA_HW_HS;
> +       txs->cfg_mode = LNW_DMA_MEM_TO_PER;

What I cannot wrap my head around is why your DMA
controller cannot figure these things out from the data
passed in to the

> +       ds->src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +       ds->dst_addr_width = drv_context->n_bytes;

You also want to se
ds->src_addr and ds->dst_addr instead of passing that
through an artificial memcpy() call.

> +       /* Use a DMA burst according to the FIFO thresholds */
> +       if (drv_context->rx_fifo_threshold == 8) {
> +               ds->src_maxburst = 8;
> +               ds->dst_maxburst = 8;
> +       } else if (drv_context->rx_fifo_threshold == 4) {
> +               ds->src_maxburst = 4;
> +               ds->dst_maxburst = 4;
> +       } else {
> +               ds->src_maxburst = 1;
> +               ds->dst_maxburst = 1;
> +       }
> +
> +       /* Nothing more to do if already initialized */

There isn't?

You need to call
rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
                                       (unsigned long) ds);

To use that config you've set.

> +       if (drv_context->dma_initialized)
> +               return;
> +
> +       /* Use DMAC1 */
> +       if (drv_context->quirks & QUIRKS_PLATFORM_MRST)
> +               device_id = PCI_MRST_DMAC1_ID;
> +       else
> +               device_id = PCI_MDFL_DMAC1_ID;
> +
> +       drv_context->dmac1 = pci_get_device(PCI_VENDOR_ID_INTEL,
> +                                                       device_id, NULL);
> +
> +       if (!drv_context->dmac1) {
> +               dev_err(dev, "Can't find DMAC1");
> +               return;
> +       }
> +
> +       if (drv_context->quirks & QUIRKS_SRAM_ADDITIONAL_CPY) {
> +               drv_context->virt_addr_sram_rx = 
> ioremap_nocache(SRAM_BASE_ADDR,
> +                               2 * MAX_SPI_TRANSFER_SIZE);
> +               if (drv_context->virt_addr_sram_rx)
> +                       drv_context->virt_addr_sram_tx =
> +                               drv_context->virt_addr_sram_rx +
> +                               MAX_SPI_TRANSFER_SIZE;
> +               else
> +                       dev_err(dev, "Virt_addr_sram_rx is null\n");
> +       }
> +
> +       /* 1. Allocate rx channel */
> +       dma_cap_zero(mask);
> +       dma_cap_set(DMA_MEMCPY, mask);
> +       dma_cap_set(DMA_SLAVE, mask);

You only want to request DMA_SLAVE really.

> +
> +       drv_context->rxchan = dma_request_channel(mask, chan_filter,
> +               drv_context);
> +       if (!drv_context->rxchan)
> +               goto err_exit;
> +
> +       drv_context->rxchan->private = rxs;
> +
> +       /* 2. Allocate tx channel */
> +       dma_cap_set(DMA_SLAVE, mask);
> +       dma_cap_set(DMA_MEMCPY, mask);
> +
> +       drv_context->txchan = dma_request_channel(mask, chan_filter,
> +               drv_context);
> +
> +       if (!drv_context->txchan)
> +               goto free_rxchan;
> +       else
> +               drv_context->txchan->private = txs;

rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
                                       (unsigned long) ds);
txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
                                       (unsigned long) ds);

> +       /* set the dma done bit to 1 */
> +       drv_context->txdma_done = 1;
> +       drv_context->rxdma_done = 1;
> +
> +       drv_context->tx_param.drv_context  = drv_context;
> +       drv_context->tx_param.direction = TX_DIRECTION;
> +       drv_context->rx_param.drv_context  = drv_context;
> +       drv_context->rx_param.direction = RX_DIRECTION;
> +
> +       drv_context->dma_initialized = 1;
> +
> +       return;
> +
> +free_rxchan:
> +       dma_release_channel(drv_context->rxchan);
> +err_exit:
> +       dev_err(dev, "Error : DMA Channel Not available\n");
> +
> +       if (drv_context->quirks & QUIRKS_SRAM_ADDITIONAL_CPY)
> +               iounmap(drv_context->virt_addr_sram_rx);
> +
> +       pci_dev_put(drv_context->dmac1);
> +       return;
> +}
> +
> (...)
> +/**
> + * dma_transfer() - Initiate a DMA transfer
> + * @drv_context:       Pointer to the private driver context
> + */
> +static void dma_transfer(struct ssp_driver_context *drv_context)
> +{
> +       dma_addr_t ssdr_addr;
> +       struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
> +       struct dma_chan *txchan, *rxchan;
> +       enum dma_ctrl_flags flag;
> +       struct device *dev = &drv_context->pdev->dev;
> +
> +       /* get Data Read/Write address */
> +       ssdr_addr = (dma_addr_t)(drv_context->paddr + 0x10);
> +
> +       if (drv_context->tx_dma)
> +               drv_context->txdma_done = 0;
> +
> +       if (drv_context->rx_dma)
> +               drv_context->rxdma_done = 0;
> +
> +       /* 2. prepare the RX dma transfer */
> +       txchan = drv_context->txchan;
> +       rxchan = drv_context->rxchan;
> +
> +       flag = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
> +
> +       if (likely(drv_context->quirks & QUIRKS_DMA_USE_NO_TRAIL)) {
> +               /* Since the DMA is configured to do 32bits access */
> +               /* to/from the DDR, the DMA transfer size must be  */
> +               /* a multiple of 4 bytes                           */
> +               drv_context->len_dma_rx = drv_context->len & ~(4 - 1);
> +               drv_context->len_dma_tx = drv_context->len_dma_rx;
> +
> +               /* In Rx direction, TRAIL Bytes are handled by memcpy */
> +               if (drv_context->rx_dma &&
> +                       (drv_context->len_dma_rx >
> +                       drv_context->rx_fifo_threshold * 
> drv_context->n_bytes))
> +                       drv_context->len_dma_rx =
> +                                       TRUNCATE(drv_context->len_dma_rx,
> +                                       drv_context->rx_fifo_threshold *
> +                                       drv_context->n_bytes);
> +               else if (!drv_context->rx_dma)
> +                       dev_err(dev, "ERROR : rx_dma is null\r\n");
> +       } else {
> +               /* TRAIL Bytes are handled by DMA */
> +               if (drv_context->rx_dma) {
> +                       drv_context->len_dma_rx = drv_context->len;
> +                       drv_context->len_dma_tx = drv_context->len;
> +               } else {
> +                       dev_err(dev, "ERROR : drv_context->rx_dma is 
> null!\n");
> +               }
> +       }
> +
> +       rxdesc = rxchan->device->device_prep_dma_memcpy
> +               (rxchan,                                /* DMA Channel */
> +               drv_context->rx_dma,                    /* DAR */

/* DAR */ ?

Isn't that just a buffer?

> +               ssdr_addr,                              /* SAR */

This is not really a memcpy() targetr address because it's fixed,
right?

> +               drv_context->len_dma_rx,                /* Data Length */
> +               flag);                                  /* Flag */

If your slave config command is working then replace this
with ->device_prep_slave_sg() and drop these address
encoding through memcpy calls.

> +       /* 3. prepare the TX dma transfer */
> +       if (drv_context->tx_dma) {
> +               txdesc = txchan->device->device_prep_dma_memcpy
> +               (txchan,                                /* DMA Channel */
> +               ssdr_addr,                              /* DAR */
> +               drv_context->tx_dma,                    /* SAR */
> +               drv_context->len_dma_tx,                /* Data Length */
> +               flag);                                  /* Flag */

Dito.

Yours,
Linus Walleij

------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

Reply via email to