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 
<http://lxr.free-electrons.com/source/arch/arm/boot/dts/am33xx.dtsi#L510>) 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) 
<http://lxr.free-electrons.com/source/drivers/spi/spi-omap2-mcspi.c#L962>* is 
defined and called by *omap2_mcspi_setup( struct spi_device *spi) 
<http://lxr.free-electrons.com/source/drivers/spi/spi-omap2-mcspi.c#L1006>. 
*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) 
<http://lxr.free-electrons.com/source/drivers/spi/spi-omap2-mcspi.c#L1353>.*

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) 
<http://lxr.free-electrons.com/source/drivers/spi/spi.c#L2057>*) 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.


-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to