How to initialize DMA channels of SPI master

457 views
Skip to first unread message

ilikepepsi

unread,
Mar 18, 2016, 9:53:13 AM3/18/16
to BeagleBoard
Hi,

I'm developing a kernel module that is supposed to communicate with a TI ADS1274 ADC via SPI. So far I have a working kernel module that doesn't use DMA for the SPI communication. Therefore the CPU get's a hell of a load and I need to fix that. The way to do it presumably is using DMA but that's where the struggle starts. At first I delved into the SPI interface structures struct spi_device and struct spi_master. From the device tree (am33xx.dtsi) I know that the SPI controller has 2 DMA channels assigned for each CS, namely 'tx0', 'rx0', 'tx1' and 'rx1'.

I thought these can be used through the struct dma_chan pointers in struct spi_master but the pointers are null (I tried to print out their values within my probing function). The respective dmesg output is.

[  +0.000010] DEBUG /root/Code/kmod/selton.c:970: ads_spi_probe: spi m rx:   (null)
[  +0.000008] DEBUG /root/Code/kmod/selton.c:971: ads_spi_probe: spi m tx:   (null)

As a next step I tried to figure out how these pointers could get initialized and found that in the TI driver omap2_mcspi.c a function omap2_mcspi_request_dma( struct spi_device *spi) is defined and called by omap2_mcspi_setup( struct spi_device *spi). The latter is assigned to the setup function of the struct spi_master allocated in the drivers probe function omap2_mcspi_probe( struct platform_device *pdev).

So I thought everything left to do is calling the SPI masters setup function (what seems to be done in spi_setup( struct spi_device *spi)) to make the DMA channels accessible but they still remain as null pointers. Here is my probe function.


static int
ads_spi_probe
(struct spi_device *spi)
{
    ads_data_t  
*ads; //--> driver data struct
   
int         err = 0;
   
   
/* Is there a matching device in the device tree? */
   
if (!of_match_device(ads1274_dt_ids, &spi->dev)) {
        err
= -ENODEV;
       
goto error;
   
}
    debug
("Probed compat. devices: %s", //--> .compatible = "ti,ads1274",
            ads1274_dt_ids
[0].compatible);

   
/* Then allocate the driver data */
    ads
= (ads_data_t *)kzalloc(sizeof(ads_data_t), GFP_KERNEL);
   
if (IS_ERR(ads)) {
        err
= PTR_ERR(ads);
        debug
("Could not allocate driver data: ERR %d", err);
       
goto error;
   
}
    debug
("Initialized SPI data structure at %p", ads);

    init_waitqueue_head
(&ads->wait_read);
    spin_lock_init
(&ads->spi_lock);
   
    INIT_LIST_HEAD
(&device_list);
    mutex_lock
(&device_list_lock);
   
   
/* Request and configure GPIO trigger */
    err
= ads_gpio_init(&ads->gpio, p9, true, true);
   
if (err < 0) {
        pr_err
("%s: Could not initialze GPIO %d", MODNAME, p9);
       
goto free_driver_data;
   
}
    debug
("GPIO pin %d mapped to irq %d",
            ads
->gpio.pin, ads->gpio.irq_number);

   
/* Request 1 minor device number from the kernel */
   
if (alloc_chrdev_region(&ads->devt, 0, 1, MODNAME) < 0) {
        err
= -EIO;
       
goto free_workqueue;
   
}
    debug
("Requested major/minor %d : %d", MAJOR(ads->devt), MINOR(ads->devt));
   
   
/* SPI setup */
    ads
->spi = spi;
    spi_set_drvdata
(spi, ads);
    spi_setup
(ads->spi); //--> should init dma channels
   
    debug
("spi: %p", ads->spi);
    debug
("spi m: %p", ads->spi->master);
    debug
("spi m rx: %p", ads->spi->master->dma_rx); //--> NULL
    debug
("spi m tx: %p", ads->spi->master->dma_tx); //--> NULL

   
/* Create character device */
    ads
->cdev = cdev_alloc();

   
if (ads->cdev == NULL)
       
goto free_chrdev_region;
       
    debug
("Cdev initialized");
   
    ads
->cdev->owner = THIS_MODULE;
    ads
->cdev->ops = &fops;

   
if (cdev_add(ads->cdev, ads->devt, 1))
       
goto free_cdev;

    device_create
(ads_class, &ads->spi->dev, ads->devt, ads->spi,
           
"ads1274-spi%d.%d", ads->spi->master->bus_num, ads->spi->chip_select);
   
    list_add_tail
(&(ads->device_entry), &device_list);
    mutex_unlock
(&device_list_lock);

    pr_info
("%s: Added SPI device %s-spi%d.%d", MODNAME, spi->modalias,
        spi
->master->bus_num, spi->chip_select);
   
   
/* Should be 0 */
   
return err;    

free_cdev
:
    kobject_put
(&(ads->cdev->kobj));
free_chrdev_region
:
    unregister_chrdev_region
(ads->devt, 1);
free_workqueue
:
//    ads_workqueue_free(&ads);
//free_gpio:
    ads_gpio_free
(&(ads->gpio));
free_driver_data
:
    kfree
(ads);
    debug
("There was an error while probing devices");

error
:
   
return err;
}

So can anybody tell me how to initialize the DMA channels in spi_master or how to use SPI with DMA generally. 

Thx in advance.


John Syne

unread,
Mar 18, 2016, 3:13:41 PM3/18/16
to beagl...@googlegroups.com
Look at how this is done in drivers/mmc/host/mmc_spi.c

Regards,
John




--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages