This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux SPI driver and DMA

Other Parts Discussed in Thread: OMAP-L138, DA8XX

Hi there.

Our company is currently prototyping a solution using the Digital Spectrum DM355 EVM,
running Montavista Linux 5.0 (kernel 2.6.18). In order to implement our application,
we'll need an SPI communication channel capable of high speed data transfers. For that,
the SPI driver included in the kernel must be capable of DMA transfers. In the Montavista
kernel sources, there's an SPI driver which apparently has support for DMA transfers enabled,
but only when the system processor is not a DM355:

<mv_kernel_src_2.6.18>/drivers/spi/davinci_spi_master.c, line 974 says:
   
    /* DM355 does not have DMA capabilities */
    if(cpu_is_davinci_dm355())
        use_dma = 0;

We are not certain about what that comment line means. Does the DM355 SPI not support DMA transfers,
in spite of its datasheets and manuals stating clearly that it does? Or does the DM355 have unpublished errata?
A third interpretation could be that this specific driver doesn't use the DMA on the DM355, but
it could be done.


So, our question is: is the lack of DMA support in the SPI driver only a question of driver capabilities?
If that's the case, we can investigate the possibilty of developing a DMA aware SPI driver for
this processor. If the problem is that some kind of hardware issue forbids the use of the DMA controller
for SPI transfers on the DM355, then we could start looking for alternatives for this processor.


Thanks,


Moyses Borges
moyses@esystech.com.br
Esystech Embedded Systems

  • Hi,

     

    According to the datasheet of SPI for DM35x processors, the hardware supports DMA, so it's only a driver limitation on current implementation. Last time I checked the SPI driver on DM355 (I was interfacing to a touch screen chip) it wasn't an outstanding driver and we have to tweak it a bit to make it work right (AFAIK it didn't support SPI1). Adding DMA shouldn't be really difficult. If you get in trouble you can contact us for some support services.

     

    Regards,

     

    Diego Dompe

    RidgeRun Engineering

  • I agree with Diego, based on the documentation I see no reason that the SPI should not be capible of DMA servicing at the hardware level (this SPI port has the same erratas as some other Davinci devices), so this is most likely just how the driver was written.

  • Hmm, I see; thank you both, Diego and Bernie. That is more or less what we were expecting while working with the 2.6.10-mvl kernel, the one that came with the evaluation board. The SPI driver didn't even mention DMA, so we were beginning to work on a DMA driver on there. But then, after we downloaded the updated kernel (2.6.18) and saw that the SPI driver was extended to support DMA but explicitly excluded the DM355, we were a little confused. I guess that the wording in the commentary (“DM355 does not have DMA capabilities”) is misleading in that it doesn't make clear whether by 'DM355' the programmer was referring to the SPI driver or to the processor itself.
    Anyway, based on what the datasheets say and on your replies, I guess it's safe to assume that the support for DMA was left out of the SPI driver for the DM355 not because of some technical barrier on this processor but because of some other external issue.

    Well then, guess it's time for some fun in kernel space now... ;)

    -moyses

  • hello,

    I want to use "davinci_spi_master.c", so that i can transfer data in the user space through DMA-SPI driver.

    As per some clarifaction i got to know that DM355 support SPI_DMA.

    Could you suggest me how to intreact with this driver from user space.

     As i can not see any "file_operation" structure for this.

    Most importantly how to talk to this driver, i am not used to this at all.

    Could you give some examples on this.

    Regards,

    Ram

  • Ram,

    Did you find the information you were looking for? I am looking for the same info, how to access the spi from user space.

    Tank you,

    David

  • Hi David & Ram,

     

    I am facing the same problem and I do not know hot to acces spi from user space. I  load the driver spidev.ko and no /dev handler is createad. Am using the right driver (spidev.ko)? I am puzzled.

     

    Thanks

    jesus

  • Hi,

    You should use the Documentation/spi/spidev_test.c file to test the SPI user mode interface. No need of using spidev.c in drivers/spi folder. Refer to http://e2e.ti.com/support/embedded/f/354/p/74188/297335.aspx#297335 for some hints. This link talks about enabling spidev interface on OMAP-L138.

    Regards, Sudhakar

  • Hi Sudhakar

    I use a DM365 eval board, a Linux arago version 2.6.32 and dvsdk 3.10 00 19. I can not use spidev_test.c to test the SPI as you suggested because I have no /dev/spiX.X file to interface with. I have checked the link you suggested (and many others) and I also read the the documentation on Documentation/spi to figure out how to configure the kernel properly to generate my load the spidev driver and allow Linux to create the /dev file.

    I have compiled the spi drivers as part of the kernel.

    Here are the menuconfig options

    --- SPI support                                                  │ │  
      │ │    [*]  Debug support for SPI drivers                              │ │  
      │ │          *** SPI Master Controller Drivers ***                      │ │  
      │ │    <*>   SPI controller driver for DaVinci/DA8xx SoC's              │ │  
      │ │    -*-   Utilities for Bitbanging SPI masters                       │ │  
      │ │    <*>   GPIO-based bitbanging SPI Master                           │ │  
      │ │          *** SPI Protocol Masters ***                               │ │  
      │ │    <*>   User mode SPI device driver support                        │ │  
      │ │    <*>   Infineon TLE62X0 (for power switching)                     │ │  
      │ │                                                  

     

    The modifications I have made are:

     

    board-dm365-evm.c :


    static struct spi_board_info dm365_evm_spi_info[] __initconst = {
        [0] = {
            .modalias    = "at25",
            .platform_data    = &at25640,
            .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
            .bus_num    = 0,
            .chip_select    = 0,
            .mode        = SPI_MODE_0,
        },


    // Added by Jesus Lopez
        [1] = {
            .modalias = "spidev",
            .max_speed_hz = 30000000,       /* max sample rate at 3V */
            .bus_num = 1,
            .chip_select = 0,
            .mode = SPI_MODE_0,
        },
    /// end

    };

    which as far as I understand are the only ones needed.

     And this is what I have got on the startup

    Jumping to entry point at 0x81080000.
    
     LSP 2.10 BETA RELEASE 
     VERSION: 2.10.008.02 
    
    U-Boot 1.3.4 (Mar  2 2009 - 11:50:39)
    
    I2C:   ready
    DRAM:  128 MB
    NAND:  NAND device: Manufacturer ID: 0x2c, Chip ID: 0xd3 (Micron NAND 1GiB 3,3V 8-bit)
    Bad block table found at page 524096, version 0x01
    Bad block table found at page 524032, version 0x01
    NAND device: Manufacturer ID: 0x2c, Chip ID: 0xd3 (Micron NAND 1GiB 3,3V 8-bit)
    Bad block table found at page 524224, version 0x01
    Bad block table found at page 524160, version 0x01
    2048 MiB
    In:    serial
    Out:   serial
    Err:   serial
    Ethernet PHY: GENERIC @ 0x00
    Hit any key to stop autoboot:  4 ### 3 ### 2 ### 1 ### 0 
    BOOTP broadcast 1
    DHCP client bound to address 10.10.0.55
    TFTP from server 10.10.0.143; our IP address is 10.10.0.55
    Filename 'uImage'.
    Load address: 0x80700000
    Loading: *##################################################################
    	 #################################################################
    	 ################
    done
    Bytes transferred = 2141612 (20adac hex)
    ## Booting kernel from Legacy Image at 80700000 ...
       Image Name:   Linux-2.6.32-rc2-davinci1
       Image Type:   ARM Linux Kernel Image (uncompressed)
       Data Size:    2141548 Bytes =  2 MB
       Load Address: 80008000
       Entry Point:  80008000
       Verifying Checksum ... OK
       Loading Kernel Image ... OK
    OK
    
    Starting kernel ...
    
    Uncompressing Linux............................................................................................................................................ done, booting the kernel.
    Linux v4.3.3 (Sourcery G++ Lite 2009qopez@ubuntu-virtual) (gcc version get UART2 clock
    EVM: HD imager video input
    init:97: failed to io-0> at 0
    DMk
    EVM: HD imager video input
    bio: create slab <bio-0> at 0
    DM365 IPIPE initialized in Continuous mode
    SCSI subsystem initialized
    usbcore: registered new interface driver usbfs
    usbcore: registered new interface driver hub
    usbcore: registered new device driver usb
    pca9543a_probe
    vpss vpss: dm365_vpss vpss probed
    vpss vpss: dm365_vpss vpss probe success
    dm365_afew_hw_init
    ch0 default output "COMPOSITE", mode "NTSC"
    VPBE Encoder Initialized
    cfg80211: Using static regulatory domain info
    cfg80211: Regulatory domain: US
    	(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
    	(2402000 KHz - 2472000 KHz @ 40000 KHz), (600 mBi, 2700 mBm)
    	(5170000 KHz - 5190000 KHz @ 40000 KHz), (600 mBi, 2300 mBm)
    	(5190000 KHz - 5210000 KHz @ 40000 KHz), (600 mBi, 2300 mBm)
    	(521000 KHz - 5330000 KHzz @ 40000 KHz), (600 mBi, 2300 mBm)
    	(5230000 KHz - 5330000 KHz @ 40000 KHz), (600 mBi, 2300 mBm)
    	(5735000 KHz - 5835000 KHz @ 40000 KHz), (600 mBi, 3000 mBm)
    cfg80211: Calling CRDA for country: US
    LogicPD encoder initialized
    Switching to clocksource timer0_1
    musb_hdrc: version 6.0, cppi-dma, host, debug=0
    musb_hdrc: USB Host mod MUSBtroller at fec64000 using DMA, IRQ 12
    musb_hdrc musb_hdrc: MUSB HDRC host driver
    musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
    usb usb1: configu1-0:on #1 chosen from 1 choice
    hub 1-0:1.0: USB hub found
    hub 1-0:1.0: 1 port detected
    NET: Registered protocol family 2
    IP route cache hash table entries: 1024 (order:: 2, 096 bytes)
    TCP established hash table entries: 2048 (order: 2, 16384 bytes)
    TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
    TCP: Hash tables configured (established 2048 bind 2048)
    TCP reno registered
    NET: Registered protocred tmily 1
    RPC: Registered udp transport module.
    RPC: Registered tcp transport module.
    RPC: Registered tcp NFSv4.1 backchannel transpo
    msgmule.
    JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
    msgmni has been set to 109
    alg: No test for stdrng (krng)
    io scheduler noop registered
    io scheduler anticipatory registered (default)
    davincifb davincifb.0: dm_osd0_fb: Initial window configuration is invalid.
    Console: switching to colour frame buffer device 90x36
    davincif4050KBncifb.0: dm_osd0_fb: 720x576x16@0,0 with framebuffer size 4050KB
    davincifb davincifb.0: dm_vid0_fb: 0x0x16@0,0 with framebuffer size 1020KB
    davincifb davincifb.0: dm_osd1_fb: 720x480x4@0,0 with framebuffer size 675KB
    davincifb davincifb.0: dm_vid1_fb: 0x0x16@0,0 with framebuffer size 1020KB
    DM365 IPIPEIF probed
    imp serializer initial
    Ser
    davinci_previewer initialized
    davinci_resizer initialized
    Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
    serial8250.0: ttyS0 at MMIO 0x1c20000 (irq = 40) is a 16550A
    console [ttyS0] enabled
    brd: module loaded
    at24 1-0050: 32768 byte 24c256 EEPROM (writable)
    Read MAC addr from EEPROM: 00:0e:99:02:cd:fc
    NAND device: Manufacturer ID: 0x2c, Chip ID: 0xd3 (Micron NAND 1GiB 3,3V 8-bit)
    2 NAND chips detected
    Creating 5000 : "bootloadern "davinci_nand.0":
    0x000000000000-0x000000f00000 : "bootloader"
    0x000000f00000-0x000001000000 : "params"
    0x000001000000-0x000001400000 : "kernel"
    0x000001400000-0x000021400000 : "filesystem1"
    0x000021400000-0x000080000000 : "filesystem2"
    davinci_nand davinci_nand.0: controller rev. 2.3
    spi_davinci spi_davinci.0: DaVinci SPI driver in EDMA mode
    Using RX channel = 17 , TX channel = 16 and event queue = 3
    spi_davinci spi_davinci.0: Controller at 0xfec66000 
    console [netcon0] enabled
    netconsole: network logging started
    Initializing USB Mass Storage driver...
    usbcore: registered new interface driver usb-storage
    USB Mass Storage support registered.
    usbcore: registered new interface driver usbtest
    mice: PS/2 mouse device common for all mice
    input: DM365 EVM Controls as /devices/platform/i2c_davinci.1/i2c-1/1-0025/input/input0
    i2c /dev entries driver
    Linux video capture interface: v2.00
    ths7303 1-002c: chip found @ 0x58 (DaVinci I2C adapter)
    vpfe_init
    vpfe-capture: vpss clock vpss_master enabled
    vpfe-capture vpfe-capture: v4l2 device registered
    vpfe-capture vpfe-capture: video device registered
    EVM: switch to tvp5146 SD video input
    tvp514x 1-005d: tvp514x 1-005d decoder driver registered !!
    vpfe-capture vpfe-capture: v4l2 sub device tvp5146 registered
    EVM: switch to tvp7002 HD video input
    tvp7002 1-005c: tvp7002 1-005c decoder driver registered !!
    vpfe-capture vpfe-capture: v4l2 sub device tvp7002 registered
    EVM: switch to tvp7002 HD video input
    ths7353 1-002e: chip found @ 0x5c (DaVinci I2C adapter)
    ths7353 1-002e: No platform data!!
    vpfe-capture vpfe-capture: v4l2 sub device ths7353 registered
    vpfe_register_ccdc_device: DM365 ISIF
    DM365 ISIF is registered with vpfe.
    af major#: 252, minor# 0
    AF Driver initialized
    aew major#: 251, minor# 0
    AEW Driver initialized
    Trying to register davinci display video device.
    layer=c217e600,layer->video_dev=c217e770
    ,layeg to register davinci display video device.
    layer=c217e200,layer->video_dev=c217e370
    davinci_init:DaVinci V4L2 Display Driver V1.0 loaded
    watchdog watchdog: heartbeat 60 sec
    davinci_mmc davinci_mmc.0: Using DMA, 4-bit mode
    usbcore: registered new interface driver usbhid
    usbhid: v2.6:USB HID core driver
    Advanced Linux Sound Architecture Driver Version 1.0.21.
    No device for DAI tlv320aic3x
    No device for DAI davinci-i2s
    asoc: tlv320aic3x <-> davinci-i2s mapping ok
    ALSA device list:
      #0: DaVinci EVM (tlv320aic3x)
    TCP cubic registered
    NET: Registered protocol family 17
    lib80211: common routines for IEEE802.11 drivers
    Clocks: disable unused mmcsd1
    Clocks: disable unused spi1
    Clocks: disable unused spi2
    Clocks: disable unused spi3
    Clocks: disable unused spi4
    Clocks: disable unused pwm0
    Clocks: disable unused pwm1
    Clocks: disable unused pwm2
    Clocks: disable unused pwm3
    Clocks: disable unused timer1
    Clocks: disable ud voi timer3
    Clocks: disable unused emac
    Clocks: disable unused voice_codec
    Clocks: disable unused rto
    Clocks: disable unused mjcp
    emac-mii: probed
    eth0: attached PHY driver [Generic PHY] (mii_bus:phy_addr=1:01, id=221613)
    Sending DHCP requests .
    PHY: 1:01 - Link is Up - 100/Full
    ., OK
    IP-Config: Got DHCP answer from 0.0.0.0, my address is 10.10.0.55
    IP-Config: Complete:
         device=eth0, addr=10.10.0.55, mask=255.255.255.0, gw=10.10.0.1,
         host=10.10.0.55, domain=arquimea.com, nis-domain=(none),
         bootserver=0.0.0.0, rootserver=10.10.0.143, rootpath=
    Looking up port of RPC 100003/2 on 10.10.0.143
    Looking up port of RPC 100005/1 on 10.10.0.143
    VFS: Mounted root (nfs filesystem) on device 0:14.
    Freeing init memory: 144K
    
    Warning: unable to open an initial console.
    udev: s0) failed: Bad address
    
    
    1036]: inotify_add_watch(3, (null), 10) failed: Bad address
    
    
    modprobe: ep: No such file or directorydules/2.6.32-rc2-davinci1/modules.ddirectory
    
    
    /2.6.32-rc2-davinci1/modules.dep: No such file or directory
    
    
    /2.6.32-rc2-davinci1/modules.dep: No such file or directory
    
    
    modprobe: FA: No such file or directory
    les/2.6.32-rc2-davinci1/modules.dep: No such file or directory
    
    
    
     _____                    _____           _         _   
    |  _  |___ ___ ___ ___   |  _  |___ ___  |_|___ ___| |_ 
    |     |  _| .'| . | . |  |   __|  _| . | | | -_|  _|  _|
    |__|__|_| |__,|_  |___|  |__|  |_| |___|_| |___|___|_|  
                  |___|                    |___|            
    
    Arago Project http://arago-project.org dm365-evm ttyS0
    
    Arago 2009.11 dm365-evm ttyS0
    
    dm365-evm login: root

    root@dm365-evm: ~# ls /dev/*spi*

    ls: /dev/*spi*: No such file or directory




    So no /dev handler is generated. The driver is loaded because I get on the startup:

    spi_davinci spi_davinci.0: DaVinci SPI driver in EDMA mode

    My question is: What I am doing wrong? Why I do not get the /dev handler?
    I should not use mknod as the minor number in spidev is dynamic (I already tried and it does not work).
    I have already spent several weeks trying to sort out this issue. I have also tried with Montavista 5.0 and dvsdk 2.0 with similar results.

    Any help would be appreciated. Thanks in advance



     

     

  • Hi,

    Jesus Lopez said:

    static struct spi_board_info dm365_evm_spi_info[] __initconst = {
        [0] = {
            .modalias    = "at25",
            .platform_data    = &at25640,
            .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
            .bus_num    = 0,
            .chip_select    = 0,
            .mode        = SPI_MODE_0,
        },


    // Added by Jesus Lopez
        [1] = {
            .modalias = "spidev",
            .max_speed_hz = 30000000,       /* max sample rate at 3V */
            .bus_num = 1,
            .chip_select = 0,
            .mode = SPI_MODE_0,
        },
    /// end

    };

    From the above configuration, it seems that you are trying to access a SPI device present on the 2nd instance of SPI. In that case you have to make sure that the muxing for accessing the 2nd SPI interface is setup correctly.

    If you are trying to access the SPI device on the same instance as the first one, then you need to modify the 'chip_select' member in the structure to '1' and 'bus_num' should be ZERO. I tried this change on my DM365 EVM with 2.6.32 kernel and I was able see the /dev/spi interface. Apart from modifying 'chip_select' member in the structure I disabled the SPI DMA mode my initializing use_dma to ZERO in arch/arm/mach-davinci/dm365.c file.

    You can also make sure whether SPI device interface is working properly by doing the following modification:

    static struct spi_board_info dm365_evm_spi_info[] __initconst = {

    [0] = {

    // .modalias = "at25",

    .modalias = "spidev",

    // .platform_data = &at25640,

    .max_speed_hz = 20 * 1000 * 1000, /* at 3v3 */

    .bus_num = 0,

    .chip_select = 0,

    .mode = SPI_MODE_0,

    },

    };

    With this above modification, the existing SPI eeprom will be accessible as a SPI device.

    Regards, Sudhakar

  • Hi Sudhakar,

     

    I have been able to replicate what you explained and I get the /dev/spidev0.1 handler, but I am facing to issues now:

     

    1- I can not use DMA, I need it because I need to perform high speed transfers through DMA. What should I do to be able to use DMA with SPI?

    1- I need to use SPI1 or any free SPI instead of SPI0 (connected to the EEPROM), so tried to modify   arch/arm/mach-davinci/dm365.c file, adding the following:

     

    // Added by Jesus Lopez

    static u64 dm365_spi1_dma_mask = DMA_BIT_MASK(32);

    static struct davinci_spi_platform_data dm365_spi1_pdata = {
        .version     = SPI_VERSION_1,
        .num_chipselect = 2,
        .clk_internal    = 1,
        .cs_hold    = 1,
        .intr_level    = 0,
        .poll_mode    = 1,    /* 0 -> interrupt mode 1-> polling mode */
        .use_dma    = 0,    /* when 1, value in poll_mode is ignored */
        .c2tdelay    = 0,
        .t2cdelay    = 0,
    };

    static struct resource dm365_spi1_resources[] = {
        {


            .start = 0x01c66800, // THIS IS THE BEGGINING ADDRESS OF SPI1

            .end   = 0x01c66fff,   // THIS IS THE END OF SPI1                           
            .flags = IORESOURCE_MEM,
        },
        {
            .start = IRQ_DM365_SPIINT0_0,
            .flags = IORESOURCE_IRQ,
        },
        {
            .start = 17,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_RX_CHAN,
        },
        {
            .start = 16,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_TX_CHAN,
        },
        {
            .start = EVENTQ_3,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_EVENT_Q,
        },
    };

    static struct platform_device dm365_spi1_device = {
        .name = "spi_davinci",
        .id = 1,                                                                                                   // SHOULD I USE id=1 HERE?
        .dev = {
            .dma_mask = &dm365_spi1_dma_mask,
            .coherent_dma_mask = DMA_BIT_MASK(32),
            .platform_data = &dm365_spi1_pdata,
        },
        .num_resources = ARRAY_SIZE(dm365_spi1_resources),
        .resource = dm365_spi1_resources,
    };

    void __init dm365_init_spi1(unsigned chipselect_mask,
            struct spi_board_info *info, unsigned len)
    {
        davinci_cfg_reg(DM365_SPI1_SCLK);
        davinci_cfg_reg(DM365_SPI1_SDI);
        davinci_cfg_reg(DM365_SPI1_SDO);

        /* not all slaves will be wired up */
        if (chipselect_mask & BIT(0))
            davinci_cfg_reg(DM365_SPI1_SDENA0);
        if (chipselect_mask & BIT(1))
            davinci_cfg_reg(DM365_SPI1_SDENA1);

        spi_register_board_info(info, len);

        platform_device_register(&dm365_spi1_device);
    }

    // END

    I also added in board-dm365-evm.c the following (in red):

    static struct spi_board_info dm365_evm_spi_info[] __initconst = {
        [0] = {
            .modalias    = "at25",
    //.modalias = "spidev",
            .platform_data    = &at25640,
            .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
            .bus_num    = 0,
            .chip_select    = 0,
            .mode        = SPI_MODE_0,
        },

    // Added by Jesus Lopez
        [1] = {

    // THIS ONE GENERATES /DEV/SPIDEV0.1 CORRECTLY
            .modalias = "spidev",
            .max_speed_hz = 30000000,       /* max sample rate at 3V */
            .bus_num = 0,
            .chip_select = 1,
            .mode = SPI_MODE_0,
        },

    // THIS ONE DOES NOT GENERATE /DEV/SPIDEV1.0
        [2] = {
            .modalias = "spidev",
            .max_speed_hz = 30000000,       /* max sample rate at 3V */
            .bus_num = 1,
            .chip_select = 0,
            .mode = SPI_MODE_0,
        },

    // end
    };

     

    After adding this and recompiling the kernel I do not get any /dev/spidev1.0 handler. Any hints?

     

    Thanks in advance

     

    Jesus Lopez

  • Hi,

    Jesus Lopez said:
    I can not use DMA, I need it because I need to perform high speed transfers through DMA. What should I do to be able to use DMA with SPI?

    You can use the latest SPI driver available for 2.6.37 at http://arago-project.org/git/projects/?p=linux-davinci.git;a=shortlog;h=refs/heads/03.21.00.03. This kernel has an updated SPI driver which works fine in Polled, Interrupt and DMA modes.

    Jesus Lopez said:
    I need to use SPI1 or any free SPI instead of SPI0 (connected to the EEPROM),

    I'll get back to you on this.

    Regards, Sudhakar

  • Hi Jesus Lopez,

    By making below changes, I was able to get /dev/spidev0.0 & /dev/spidev1.0

    1. Duplicating the SPI instance inside the dm365_evm_spi_info doesn't work. Make 2 separate
       structures and define the instance separately.

        static struct spi_board_info dm365_evm_spi_info[] __initconst = {
            {
                //.modalias    = "at25",
                .modalias    = "spidev",
                //.platform_data    = &at25640,
                .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
                .bus_num    = 0,
                .chip_select    = 0,
                .mode        = SPI_MODE_0,
            },
        };

        static struct spi_board_info dm365_evm_spi1_info[] __initconst = {
            {
                //.modalias    = "at25",
                .modalias    = "spidev",
                //.platform_data    = &at25640,
                .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
                .bus_num    = 1,
                .chip_select    = 0,
                .mode        = SPI_MODE_0,
            },
        };  

    in dm365_evm_init(), initialize the above structures separately

        dm365_init_spi0(BIT(0), dm365_evm_spi_info,
                ARRAY_SIZE(dm365_evm_spi_info));
        dm365_init_spi1(BIT(0), dm365_evm_spi1_info,
                ARRAY_SIZE(dm365_evm_spi1_info));
               
               
    SPI module compares master->bus_num which is dm365_spi0_device.id with chip->bus_num which is dm365_evm_spi1_info.bus_num.
    If they match, it registers the device.

    Thanks & regards
    Gururaja

  • Hi Gururaja

     

    I managed to make it work, /dev/spidev1.0 is generated as you said but i had to add also:

     

    dm365.c


    static u64 dm365_spi1_dma_mask = DMA_BIT_MASK(32);

    static struct davinci_spi_platform_data dm365_spi1_pdata = {
        .version     = SPI_VERSION_1,
        .num_chipselect = 2,
        .clk_internal    = 1,
        .cs_hold    = 1,
        .intr_level    = 0,
        .poll_mode    = 1,    /* 0 -> interrupt mode 1-> polling mode */
        .use_dma    = 1,    /* when 1, value in poll_mode is ignored */
        .c2tdelay    = 0,
        .t2cdelay    = 0,
    };

    static struct resource dm365_spi1_resources[] = {
        {
            .start = 0x01c66800,
            .end   = 0x01c66fff,
            .flags = IORESOURCE_MEM,
        },
        {
            .start = IRQ_DM365_SPIINT3_0, //IMPORTANT: DIFFERENT INTERRUPT NUMBER IN SPI0 AND SPI1
            .flags = IORESOURCE_IRQ,
        },
        {
            .start = 17,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_RX_CHAN,
        },
        {
            .start = 16,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_TX_CHAN,
        },
        {
            .start = EVENTQ_3,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_EVENT_Q,
        },
    };

    static struct platform_device dm365_spi1_device = {
        .name = "spi_davinci",
        .id = 1,
        .dev = {
            .dma_mask = &dm365_spi1_dma_mask,
            .coherent_dma_mask = DMA_BIT_MASK(32),
            .platform_data = &dm365_spi1_pdata,
        },
        .num_resources = ARRAY_SIZE(dm365_spi1_resources),
        .resource = dm365_spi1_resources,
    };

    void __init dm365_init_spi1(unsigned chipselect_mask,
            struct spi_board_info *info, unsigned len)
    {
        davinci_cfg_reg(DM365_SPI1_SCLK);
        davinci_cfg_reg(DM365_SPI1_SDI);
        davinci_cfg_reg(DM365_SPI1_SDO);

        /* not all slaves will be wired up */
        if (chipselect_mask & BIT(0))
            davinci_cfg_reg(DM365_SPI1_SDENA0);
        if (chipselect_mask & BIT(1))
            davinci_cfg_reg(DM365_SPI1_SDENA1);

        spi_register_board_info(info, len);

        platform_device_register(&dm365_spi1_device);
    }

     

    and also in

     

    dm365.h

    void dm365_init_spi1(unsigned chipselect_mask,
            struct spi_board_info *info, unsigned len);

     

    It is important to use different IRQ numbers between SPI0 and SPI1, if not does not registers properly.

    In relation to the use of DMA, I still have to test it. I download the spidev.c from 2.6.37 kernel and I am using it in 2.6.32 kernel, as Sudhakar suggested.

    I will keep this post updated with my progress fo future references.

    Thanks,

    Jesus

     

     

     

     

  • Hi,

    Thats good.

    Also

    1. update DMA Rx/Tx Channel numbers

        {
            .start = 15,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_RX_CHAN,
        },
        {
            .start = 14,
            .flags = IORESOURCE_DMA | IORESOURCE_DMA_TX_CHAN,
        },

     

    2. Update MUX Configurations

     

    Reagrds

    Gururaja

  • Hi Gururaja,

    In the end I've decided to use SPI4 through the J10 Imager Interface connector. I compiled spidev_test to test SPI4 but as you suggested I have to update the mux configurations to allow SPI4 to be connected to J10. I am not sure how to do it, I have been trying to configure the mux with no success, any suggesstion on how to do it?

    Also I have tried to use spidev_test in loopback mode to see if SPI4 works (it should work even if the muxing is not right) and it gets blocked, any idea why? 

    Thanks in advance

     

    Jesus Lopez

  • Hi,

    Note that Interrupts and EDAM events are not supported on SPI4.

     

    Thanks and regards

    Gururaja

  • Hi Gururaja,

     

    If I use SPI1, the SPI seem to work (using spidev_test) as long as I do not use DMA. When I set to 1 the "use_dma" variable (see text in red below), the system hangs when using spidev_test. I am using the DMA channels you suggested 14 for TX and 15 for RX. I have not updated the muxes becuase I think it is not neccesary. On the other hand I do not see any SPI signal on the Pin 27,29 of the J18 connector which should be the SPI1 signals even in poll mode (when spidev_test seem to work). Any ideas?

     

    in board-dm365-evm:

     

    static struct davinci_spi_platform_data dm365_spi1_pdata = {

    .version = SPI_VERSION_1,

    .num_chipselect = 2,

    .clk_internal = 1,

    .cs_hold = 1,

    .intr_level = 0,

    .poll_mode = 1, /* 0 -> interrupt mode 1-> polling mode */

    .use_dma = 1, /* when 1, value in poll_mode is ignored */ //IF I SET THIS TO 1 SPIDEV_TEST GET HANGED

    .c2tdelay = 0,

    .t2cdelay = 0,

    };

     

    static struct resource dm365_spi1_resources[] = {

    {

    // SPI1

    .start = 0x01c66800,

    .end   = 0x01c66fff,

    .flags = IORESOURCE_MEM,

    },

    {

    .start = IRQ_DM365_SPIINT3_0,

    .flags = IORESOURCE_IRQ,

    },

    {

    .start = 15,

    .flags = IORESOURCE_DMA | IORESOURCE_DMA_RX_CHAN,

    },

    {

    .start = 14,

    .flags = IORESOURCE_DMA | IORESOURCE_DMA_TX_CHAN,

    },

    {

    .start = EVENTQ_3,

    .flags = IORESOURCE_DMA | IORESOURCE_DMA_EVENT_Q,

    },

    };

     

    static struct platform_device dm365_spi1_device = {

    .name = "spi_davinci",

    .id = 1,

    .dev = {

    .dma_mask = &dm365_spi1_dma_mask,

    .coherent_dma_mask = DMA_BIT_MASK(32),

    .platform_data = &dm365_spi1_pdata,

    },

    .num_resources = ARRAY_SIZE(dm365_spi1_resources),

    .resource = dm365_spi1_resources,

    };

     

    void __init dm365_init_spi1(unsigned chipselect_mask,

    struct spi_board_info *info, unsigned len)

    {

    davinci_cfg_reg(DM365_SPI1_SCLK);

    davinci_cfg_reg(DM365_SPI1_SDI);

    davinci_cfg_reg(DM365_SPI1_SDO);

     

    /* not all slaves will be wired up */

    if (chipselect_mask & BIT(0))

    davinci_cfg_reg(DM365_SPI1_SDENA0);

    if (chipselect_mask & BIT(1))

    davinci_cfg_reg(DM365_SPI1_SDENA1);

     

    spi_register_board_info(info, len);

     

    platform_device_register(&dm365_spi1_device);

    }

     /

  • Hi Gurujaja,

     

    I am still trying to make the SPI to work in DMA mode. As suggested in this post I installed the new spidev driver under development  in for kernel v37 version, which theiretically works in DMA mode, as appears in this link:

    http://arago-project.org/git/projects/?p=linux-davinci.git;a=tree;hb=09aeb001ce6463a5e9cac3425fe229a156f19ee3 

    I downloaded ../git/drivers/spi/spidev.c, drivers/spi/davinci_spi.c and include/inux/spi/spi.h, inserted into my v32 kernel, modified board-dm365-evm. and dm365.c, compiled it and test it using spidev_test. The spi device gets registered as /dev/spidev1.0. The result is that the the systems gets blocked when I try to access it as with the old driver in DMA mode. any ideas?

     

    Here are my modifications for the new driver:

    board-dm365-evm.c

    static struct spi_board_info dm365_evm_spi1_info[] __initconst = {
        {
            .modalias    = "spidev",
            .max_speed_hz    = 20 * 1000 * 1000,    /* at 3v3 */
            .bus_num    = 1,
            .chip_select    = 0,
            .mode        = SPI_MODE_0,
        },
    };

    .....

        dm365_init_spi1(BIT(0), dm365_evm_spi1_info,
                ARRAY_SIZE(dm365_evm_spi1_info));

     

    in dm365.c

    static u64 dm365_spi1_dma_mask = DMA_BIT_MASK(32);

    static struct davinci_spi_platform_data dm365_spi1_pdata = {
        .version     = SPI_VERSION_1,
        .num_chipselect = 2,
    };

    static struct resource dm365_spi1_resources[] = {
        {
            .start = 0x01c66800,
            .end   = 0x01c66fff,
            .flags = IORESOURCE_MEM,
        },
        {
            .start = IRQ_DM365_SPIINT3_0,
            .flags = IORESOURCE_IRQ,
        },
        {
            .start = 15,
            .flags = IORESOURCE_DMA,
        },
        {
            .start = 14,
            .flags = IORESOURCE_DMA,
        },
        {
            .start = EVENTQ_3,
            .flags = IORESOURCE_DMA,
        },
    };

    static struct platform_device dm365_spi1_device = {
        .name = "spi_davinci",
        .id = 1,
        .dev = {
            .dma_mask = &dm365_spi1_dma_mask,
            .coherent_dma_mask = DMA_BIT_MASK(32),
            .platform_data = &dm365_spi1_pdata,
        },
        .num_resources = ARRAY_SIZE(dm365_spi1_resources),
        .resource = dm365_spi1_resources,
    };

    void __init dm365_init_spi1(unsigned chipselect_mask,
            struct spi_board_info *info, unsigned len)
    {
        davinci_cfg_reg(DM365_SPI1_SCLK);
        davinci_cfg_reg(DM365_SPI1_SDI);
        davinci_cfg_reg(DM365_SPI1_SDO);

        /* not all slaves will be wired up */
        if (chipselect_mask & BIT(0))
            davinci_cfg_reg(DM365_SPI1_SDENA0);
        if (chipselect_mask & BIT(1))
            davinci_cfg_reg(DM365_SPI1_SDENA1);

        spi_register_board_info(info, len);

        platform_device_register(&dm365_spi1_device);
    }

    Thanks,

     

    Jesus

  • Hi,

    I managed the spidev to work in DMA mode. For those who need the info is on the post:

     

    http://e2e.ti.com/support/embedded/f/354/p/69019/342473.aspx#342473

     

    Thanks for your help,

    Jesus

  • Hi gururaja,

     

    I was trying to configure SPI for DM368 leopard board and found issues in PINMUXING after changing the same in dm365.c file.

    Kindly can you let me know what should be the PINUMUX valur for SPI and where should we change this.

    we are finding that once we change in the file mentioned then the kernel is not booting up.

    Thanks & regards

    Ravi chandran