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.

SPI data transfer error, transfer stops after one byte sent

Other Parts Discussed in Thread: AM1705, OMAP-L137

Hi all,

I am trying to hunt down what I think is a bug in setting SPI bus devices from a kernel module. The kernel is from PSP SDK 03.22.00.06, the processor is am1705.The board is custom.

When I run spidev_test against spidev1.0 I get this SPI data transfer error after the first byte of 2 is sent out. This error statement is found in spi-davinci.c, davinci_spi_bufs and I have seen that the rcount and wcound are not zero indicating the transfer didn't complete. I have tried SPI_MODEs 0 to 3 but the result is always the same.1050.csi_module_config.h4527.csi_module_config.c

An analyzer shows me that this data is also not what was supposed to be sent. I have no trouble reading and writing to the SPI flash on bus 0.

This output is from the kernel module running the configuration to setup the SPI buses.

Configuring for CSI module SPM. . .
GPIO setup complete
spi_davinci spi_davinci.0: DMA: supported
spi_davinci spi_davinci.0: DMA: RX channel: 14, TX channel: 15, event queue: 0
spi_davinci spi_davinci.0: Controller at 0xfec41000
SPI master on bus 0 registered. . .
m25p80 spi0.0: found s25fl016k, expected m25p80
m25p80 spi0.0: s25fl016k (2048 Kbytes)
created spidev0.0
created spidev0.1
spi_davinci spi_davinci.1: DMA: supported
spi_davinci spi_davinci.1: DMA: RX channel: 18, TX channel: 19, event queue: 0
spi_davinci spi_davinci.1: Controller at 0xfee12000
SPI master on bus 1 registered. . .
created spidev1.0
CSI Module config complete for CSI_MODULE_SPM

I am attaching my kernel module code and would appreciate any feedback regarding this issue. Two more things to note here. Uboot sspi can communicate with no problem at all so it seems to be the kernel driver configuration. The second thing to note is that I have another custom board with a few more, and different, spi devices. This same kernel module configures that board as well and I have not seen this problem at all on this other board.

  • Hi Dan,

    Why don't you try with the davinci SPI driver from TI SDK ?

    Is there intention to use your own module driver ?

  • Hi Titus,

    I don't understand why you ask that so I guess I was not clear as to what I'm trying to do. :-)

    I am using the davinci spi driver. All I have done is move the gpio and SPI configuration from the board file to a kernel module that stays in the file system. This way the same uboot, kernel, and ubl can be used on our two boards. Also, upgrades to our software is basically just a file system upgrade. Although these are custom boards they are based on the da830evm, which is also the configuration we use for building software. The kernel boots up, mounts the file system, reads a data structure in SPI flash to determine which gpio and SPI configuration to run.

    What I was seeing yesterday on the analyzer is that no matter what mode I set in spi_board_info structure, the clock appeared to always be in SPI_MODE_2 with CPOL set. Now that I have the analyzer I will try to capture some more evidence of what is and isn't happening. I will try to get some pictures.

    The issue with the one board where the spi transfer just stops seems to be isolated to that board. I mean that I can run the same configuration on the other board and the transfer seems to go fine. I have double checked pin mux and both boards show the same settings.

    Just to add another wrinkle. The sspi command in uboot does successfully access the device on the board where the kernel driver seems to hang. So at least I know the basic connections are correct in hardware.

  • Hi Dan,

    Thanks for the detailed explanation and understood your configuration.

    What is the difference between working and non-working boards in sw and hw case ?

  • Titus,

    I believe this is a bug in my kernel module, or the kernel just doesn't like to do this device configuration outside of the board file.

    Fortunately, our integration test setup has boards still running the old code that sets up SPI in the board file. That code performs properly with respect to SPI clock phase and polarity.

    So, while one board may hang on these spi transactions, the other board is not really working properly either when running my kernel module.

    I will keep this thread open for a while in case I find the bug and will post here if I find anything that makes this work from a kernel module.

    thanks,

    Dan

  • I have moved back to initializing spi devices from the board file. However, the results are the same. At least I can rule out my kernel module.

    We have also lifted the resistors on SPI bus 1 clock, chip select and data lines. I still see the spi transfer hang after the first byte and the driver report "spi_davinci spi_davinci.1: SPI data transfer error" and "can't send spi message: Input/output error". I believe the first error is from davinci_spi_bufs in spi-davinci, line ~735 where the rcount and wcount are checked for not zero values.

    What I am seeing on the analyzer isn't making complete sense to me. The spidev is setup as follows:

    .modalias  = "spidev"

    .mode = SPI_MODE_0

    .max_speed_hz = 500000

    .bus_num = 1

    .chip_select = 0

    However, I see clock ALWAYS start from high when the chip select is asserted, no matter what mode is specified. In other words I never see clock polarity change. I do see phase change with different mode settings. I will re-capture analyzer output on the board where all SPI is working but I believe what I see is the same regarding clock and chip select. Several of those devices are using gpio pins as chip selects, maybe that helps things to work, or those devices are not as strict in adherence to spi (?). Again, I will try to get some pictures from the analyzer.

  • Hi Dan,

    Could you please share your board file and devices-da8xx.c.

  • HI Titus,

    Sure, uploading them here. You will see some #defines for which board is being setup. The CSI_REMOTE_OM is the board that SPI seems happy on. The CSI_REMOTE_SPM is the unhappy board.

    5430.board-da830-evm.c

    5270.devices-da8xx.c

    thanks,

    Dan

  • Hi Dan,

    /* CSI, define OM gpio chip selects. These arrays identify to
    the spi bus controller what pins are used for gpio cs to spi
    devices on the bus. The am17xx has 8 banks of 16 gpio pins. The
    pin designations below are calculated as follows:
     (bank # * 16) + pin. For example, the second gpio on spi 0 is
    gpio pin GP5[10]. So, (5 * 16) + 10 = 90 */
    #ifdef CSI_REMOTE_OM

    GPIO5[10 is not GPIO90 and acutal GPIO number is GPIO91.

    GPIO5[10] = 16*5 + 11 = 91

    Please check out the OMAPL137 TRM, p.g no : 870.

    Please make sure that you are doing GPIO configurations correctly.

  • Yes, I remember being confused by that. I agree with what you say and what the TRM says. However, when I change the them to what they are calculated as the board complains.

    WARNING: at drivers/gpio/gpiolib.c:101 gpio_ensure_requested+0x54/0x110()
    autorequest GPIO-73
    Modules linked in:
    Backtrace:
    [<c000c098>] (dump_backtrace+0x0/0x110) from [<c02b7800>] (dump_stack+0x18/0x1c)
     r6:c035e501 r5:00000065 r4:c1829e00 r3:c0447720
    [<c02b77e8>] (dump_stack+0x0/0x1c) from [<c0016a98>] (warn_slowpath_common+0x54/0x6c)
    [<c0016a44>] (warn_slowpath_common+0x0/0x6c) from [<c0016b54>] (warn_slowpath_fmt+0x38/0x40)
     r8:80000013 r7:00000000 r6:00000049 r5:c047497c r4:c047402c
    r3:00000009
    [<c0016b1c>] (warn_slowpath_fmt+0x0/0x40) from [<c01933c8>] (gpio_ensure_requested+0x54/0x110)
     r3:00000049 r2:c035e518
    [<c0193374>] (gpio_ensure_requested+0x0/0x110) from [<c0193628>] (gpio_direction_output+0x84/0x180)
     r8:80000013 r7:c047497c r6:00000009 r5:c047402c r4:c1a552f8
    r3:00000020
    [<c01935a4>] (gpio_direction_output+0x0/0x180) from [<c02b5e14>] (davinci_spi_probe+0x314/0x488)
    [<c02b5b00>] (davinci_spi_probe+0x0/0x488) from [<c01c7e5c>] (platform_drv_probe+0x1c/0x20)
    [<c01c7e40>] (platform_drv_probe+0x0/0x20) from [<c01c6aec>] (driver_probe_device+0xb8/0x170)
    [<c01c6a34>] (driver_probe_device+0x0/0x170) from [<c01c6c0c>] (__driver_attach+0x68/0x8c)
     r7:00000000 r6:c045cc64 r5:c044629c r4:c0446268
    [<c01c6ba4>] (__driver_attach+0x0/0x8c) from [<c01c54e8>] (bus_for_each_dev+0x58/0x88)
     r6:c01c6ba4 r5:c1829ef8 r4:c045cc64 r3:00000000
    [<c01c5490>] (bus_for_each_dev+0x0/0x88) from [<c01c67a8>] (driver_attach+0x20/0x28)
     r7:00000000 r6:c04587b0 r5:c1b1e0c0 r4:c045cc64
    [<c01c6788>] (driver_attach+0x0/0x28) from [<c01c63d4>] (bus_add_driver+0xb4/0x234)
    [<c01c6320>] (bus_add_driver+0x0/0x234) from [<c01c7160>] (driver_register+0xa8/0x134)
    [<c01c70b8>] (driver_register+0x0/0x134) from [<c01c8158>] (platform_driver_register+0x4c/0x60)
    [<c01c810c>] (platform_driver_register+0x0/0x60) from [<c03a7380>] (davinci_spi_driver_init+0x14/0x1c)
    [<c03a736c>] (davinci_spi_driver_init+0x0/0x1c) from [<c00087cc>] (do_one_initcall+0x98/0x170)

  • I will try that again after I go through all of the gpio setup. If that is also wrong it would cause the kernel to complain.

  • Linux uses zero-based numbering of GPIOs. The TRM uses one-based. There is macro defined for converting bank and pin to gpio number than is defined in /include/linux/platform_data/gpio-davinci.h:

    #define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio))

    Note that the GPIO controller use banks of 16 but linux uses a virtual "chip" with 32 GPIOs per chip. This is reflected in the sysfs gpio.

  • Norman,

    Thanks for clearing that up. In the back of my mind I was thinking that if the number was off then how are things working at all on the one board. :-)

    Dan

  • Hi Dan,

    WARNING: at drivers/gpio/gpiolib.c:101 gpio_ensure_requested+0x54/0x110()
    autorequest GPIO-73
    Modules linked in:
    Backtrace:
    [<c000c098>] (dump_backtrace+0x0/0x110) from [<c02b7800>] (dump_stack+0x18/0x1c)
     r6:c035e501 r5:00000065 r4:c1829e00 r3:c0447720
    [<c02b77e8>] (dump_stack+0x0/0x1c) from [<c0016a98>] (warn_slowpath_common+0x54/0x6c)
    [<c0016a44>] (warn_slowpath_common+0x0/0x6c) from [<c0016b54>] (warn_slowpath_fmt+0x38/0x40)
     r8:80000013 r7:00000000 r6:00000049 r5:c047497c r4:c047402c
    r3:00000009

    This seems to be not a panic or problem.

    This is due to that you are accessing the GPIO with out requesting it.

    You have to do( before going to access) "gpio_request(GPIO_NO, device name)" then try to access the GPIO.

    The board file seems to be you are doing "gpio_request" and please make sure that you are doing before accessing the GPIO.

    /* CSI, define OM gpio chip selects. These arrays identify to
    the spi bus controller what pins are used for gpio cs to spi
    devices on the bus. The am17xx has 8 banks of 16 gpio pins. The
    pin designations below are calculated as follows:
     (bank # * 16) + pin. For example, the second gpio on spi 0 is
    gpio pin GP5[10]. So, (5 * 16) + 10 = 90 */
    #ifdef CSI_REMOTE_OM
    u8 csi_spi0_chip_selects[] = {SPI_INTERN_CS,72,72};
    u8 csi_spi1_chip_selects[] = {SPI_INTERN_CS,69,70};
    #elif defined(CSI_REMOTE_SPM)
    u8 csi_spi0_chip_selects[] = {SPI_INTERN_CS,90};
    u8 csi_spi1_chip_selects[] = {SPI_INTERN_CS};
    #endif

    Are you trying to access the GPIO4_8 (GPIO no 73) ?

    If yes, then now I can assume that you are accessing the GPIO correctly.

    Please attach your complete bootup log.

  • Hi Titus,

    Yes, GP4[8] is the chip select. The error you referenced was from trying the ones-based numbering. Also, the OM is the board that does work well. The SPM is the non-functioning board. Here is the usual boot output from an SPM using the kernel module SPI initialization after the file system is mounted.

    Booting with TI UBL
    Device OPP (456MHz, 1.3V)
    booting U-Boot image A . . .

    U-Boot 2012.04.01 (Jul 24 2014 - 15:02:37)

    I2C:   ready
    DRAM:  32 MiB
    WARNING: Caches not enabled
    NAND:  512 MiB
    Bad block table found at page 262080, version 0x01
    Bad block table found at page 262016, version 0x01
    In:    serial
    Out:   serial
    Err:   serial
    Net:   SF: Detected W25Q16 with page size 4 KiB, total 2 MiB
    DaVinci-EMAC
    Hit any key to stop autoboot:  0

    Loading from nand0, offset 0xc0000
       Image Name:   Linux-3.3.0
       Image Type:   ARM Linux Kernel Image (uncompressed)
       Data Size:    2500320 Bytes = 2.4 MiB
       Load Address: c0008000
       Entry Point:  c0008000
    ## Booting kernel from Legacy Image at c0700000 ...
       Image Name:   Linux-3.3.0
       Image Type:   ARM Linux Kernel Image (uncompressed)
       Data Size:    2500320 Bytes = 2.4 MiB
       Load Address: c0008000
       Entry Point:  c0008000
       Verifying Checksum ... OK
       Loading Kernel Image ... OK
    OK

    Starting kernel ...

    Booting Linux on physical CPU 0
    Linux version 3.3.0 (dedmondson@Hertz) (gcc version 4.6.2 (OSELAS.Toolchain-2011.11.1 linaro-4.6-2011.11) ) #1 PREEMPT Thu Jul 24 15:02:35 EDT 2014
    CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
    CPU: VIVT data cache, VIVT instruction cache
    Machine: DaVinci DA830/OMAP-L137/AM17x EVM
    Memory policy: ECC disabled, Data cache writethrough
    DaVinci da830/omap-l137 rev2.0 variant 0x9
    Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8128
    Kernel command line: mem=32M console=ttyS1,115200n8 root=/dev/nfs rw ip=192.168.10.30 nfsroot=192.168.10.218:/home/dedmondson/fs_work/debfs
    PID hash table entries: 128 (order: -3, 512 bytes)
    Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
    Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
    Memory: 32MB = 32MB total
    Memory: 27844k/27844k available, 4924k reserved, 0K highmem
    Virtual kernel memory layout:
        vector  : 0xffff0000 - 0xffff1000   (   4 kB)
        fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
        vmalloc : 0xc2800000 - 0xff000000   ( 968 MB)
        lowmem  : 0xc0000000 - 0xc2000000   (  32 MB)
        modules : 0xbf000000 - 0xc0000000   (  16 MB)
          .text : 0xc0008000 - 0xc0393000   (3628 kB)
          .init : 0xc0393000 - 0xc043d000   ( 680 kB)
          .data : 0xc043e000 - 0xc0461ec0   ( 144 kB)
           .bss : 0xc0461ee4 - 0xc047cf8c   ( 109 kB)
    SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
    NR_IRQS:245
    Console: colour dummy device 80x30
    Calibrating delay loop... 227.32 BogoMIPS (lpj=1136640)
    pid_max: default: 32768 minimum: 301
    Mount-cache hash table entries: 512
    CPU: Testing write buffer coherency: ok
    Setting up static identity map for 0xc02bc820 - 0xc02bc878
    devtmpfs: initialized
    gpiochip_add: registered GPIOs 0 to 31 on device: DaVinci
    gpiochip_add: registered GPIOs 32 to 63 on device: DaVinci
    gpiochip_add: registered GPIOs 64 to 95 on device: DaVinci
    gpiochip_add: registered GPIOs 96 to 127 on device: DaVinci
    DaVinci: 128 gpio irqs
    NET: Registered protocol family 16
    bio: create slab <bio-0> at 0
    SCSI subsystem initialized
    Switching to clocksource timer0_0
    NET: Registered protocol family 2
    IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
    TCP established hash table entries: 1024 (order: 1, 8192 bytes)
    TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
    TCP: Hash tables configured (established 1024 bind 1024)
    TCP reno registered
    UDP hash table entries: 256 (order: 0, 4096 bytes)
    UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
    NET: Registered protocol family 1
    RPC: Registered named UNIX socket transport module.
    RPC: Registered udp transport module.
    RPC: Registered tcp transport module.
    RPC: Registered tcp NFSv4.1 backchannel transport module.
    JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
    msgmni has been set to 54
    io scheduler noop registered (default)
    Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
    serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a AR7
    serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a AR7
    console [ttyS1] enabled
    serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a AR7
    brd: module loaded
    at24 1-0050: 32768 byte 24c256 EEPROM, writable, 64 bytes/write
    ONFI flash detected
    ONFI param page 0 valid
    NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron MT29F4G08ABADAWP)
    Bad block table not found for chip 0
    Bad block table not found for chip 0
    Scanning device for bad blocks
    Bad block table written to 0x00001ffe0000, version 0x01
    Bad block table written to 0x00001ffc0000, version 0x01
    Creating 7 MTD partitions on "davinci_nand.1":
    0x000000000000-0x000000020000 : "bootloader"
    0x000000020000-0x000000040000 : "AISUBL"
    0x000000040000-0x0000000a0000 : "U-Boot"
    0x0000000a0000-0x0000000c0000 : "U-BootEnv"
    0x0000000c0000-0x0000006c0000 : "kernelA"
    0x0000006c0000-0x000000cc0000 : "kernelB"
    0x000000cc0000-0x000020000000 : "filesystem1"
    davinci_nand davinci_nand.1: controller rev. 2.5
    Fixed MDIO Bus: probed
    davinci_mdio davinci_mdio.0: davinci mdio revision 1.5
    davinci_mdio davinci_mdio.0: detected phy mask ffffff7f
    davinci_mdio.0: probed
    davinci_mdio davinci_mdio.0: phy[7]: device davinci_mdio-0:07, driver unknown
    omap_rtc omap_rtc: rtc core: registered omap_rtc as rtc0
    omap_rtc: RTC power up reset detected
    i2c /dev entries driver
    watchdog watchdog: heartbeat 60 sec
    TCP cubic registered
    NET: Registered protocol family 17
    console [netcon0] enabled
    netconsole: network logging started
    davinci_emac davinci_emac.1: using random MAC addr: d2:1b:f3:77:92:ff
    omap_rtc omap_rtc: setting system clock to 2000-01-01 00:00:00 UTC (946684800)
    net eth0: no phy, defaulting to 100/full
    IP-Config: Guessing netmask 255.255.255.0
    IP-Config: Complete:
         device=eth0, addr=192.168.10.30, mask=255.255.255.0, gw=255.255.255.255,
         host=192.168.10.30, domain=, nis-domain=(none),
         bootserver=255.255.255.255, rootserver=192.168.10.218, rootpath=
    Warning: unable to open an initial console.
    Freeing init memory: 680K
    >> Testing connection to NFS Server: 192.168.10.218 ...
    >> Connection test PASSED ...
    >> Mounting rootfs from NFS 192.168.10.218:/home/dedmondson/fs_work/debfs ...
    >> Remounting 192.168.10.218:/home/dedmondson/fs_work/debfs READ-WRITABLE...
    >> Booting Linux...
    INIT: version 2.88 booting
    [info] Using makefile-style concurrent boot in runlevel S.
    [....] Starting the hotplug events dispatcher: udevdsystemd-udevd[537]: starting version 204
    . ok
    [ ok ] Synthesizing the initial hotplug events...done.
    [ ok ] Waiting for /dev to be fully populated...done.
    Starting fake hwclock: loading system time.
    Thu Jul 10 06:17:01 UTC 2014
    [ ok ] Activating swap...done.
    [ ok ] Activating lvm and md swap...done.
    [....] Checking file systems...fsck from util-linux 2.20.1
    done.
    [ ok ] Cleaning up temporary files... /tmp.
    [ ok ] Mounting local filesystems...done.
    [ ok ] Activating swapfile swap...done.
    [ ok ] Cleaning up temporary files....
    [ ok ] Setting kernel variables ...done.
    [ ok ] Configuring network interfaces...done.
    [ ok ] Starting rpcbind daemon....
    [ ok ] Cleaning up temporary files....
    INIT: Entering runlevel: 2
    [info] Using makefile-style concurrent boot in runlevel 2.
    Configuring for CSI module SPM. . .
    GPIO setup complete
    spi_davinci spi_davinci.0: DMA: supported
    spi_davinci spi_davinci.0: DMA: RX channel: 14, TX channel: 15, event queue: 0
    spi_davinci spi_davinci.0: Controller at 0xfec41000
    SPI master on bus 0 registered. . .
    m25p80 spi0.0: found s25fl016k, expected m25p80
    m25p80 spi0.0: s25fl016k (2048 Kbytes)
    created spidev0.0
    created spidev0.1
    spi_davinci spi_davinci.1: DMA: supported
    spi_davinci spi_davinci.1: DMA: RX channel: 18, TX channel: 19, event queue: 0
    spi_davinci spi_davinci.1: Controller at 0xfee12000
    SPI master on bus 0 registered. . .
    created spidev1.0
    CSI Module config complete for CSI_MODULE_SPM
    [info] Already running: rcpbind.
    [ ok ] Starting enhanced syslogd: rsyslogd.
    Starting DAS NTPDATE init...
    [ ok ] Starting periodic command scheduler: cron.
    [ ok ] Starting OpenBSD Secure Shell server: sshd.

    Debian GNU/Linux jessie/sid module ttyS1

    module login:

  • Here is an update which tells me the issue of the transfer hang is only on bus 1. That's encouraging.

    root@module:~# spidev_test -D /dev/spidev0.1
    spi mode: 0
    bits per word: 8
    max speed: 100000 Hz (100 KHz)

    FF FF
    root@module:~# spidev_test -D /dev/spidev1.0
    spi mode: 0spi_davinci spi_davinci.1: SPI data transfer error

    bits per word: 8
    max speed: 100000 Hz (100 KHz)
    can't send spi message: Input/output error
    Aborted
    root@module:~#

  • Hi Dan,

    Already I have configured SPI for loopback test without using CS.

    Thanks for clearing that up. In the back of my mind I was thinking that if the number was off then how are things working at all on the one board. :-)

    May be that is the reason, you able to working, but I'm not sure.

    Monday I will try to configure the OMAPL137 EVM board and will come back to you on this.

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/t/332434.aspx

    Did you connect the SPI slave devices ?

  • The "SPI data transfer error" is odd. SPI Masters usually do not care if there the slave is even there. It will just clock data out and in regardless of the existence of the slave. The exception is the ENA mode but I don't that is used here. From what I can tell, the error message is a result of the DMA failinh and counts don't decrement. No idea what the DMA would fail. A quick summary of the working and not-working settings:

    //CSI_REMOTE_OM - Works
    [0]= {
     .modalias     = "spidev",   /* OM-DL2_ATTEN, SPM-CPLD */
     .mode         = SPI_MODE_3 | SPI_NO_CS,
     .max_speed_hz = 2000000,
     .bus_num      = 1,
     .chip_select  = 0,
    },
    u8 csi_spi1_chip_selects[] = {SPI_INTERN_CS,69,70};
    
    //CSI_REMOTE_SPM - Doesn't work
    [0]= {
     .modalias     = "spidev",   /* SPM-CPLD */
     .mode         = SPI_MODE_0,
     .max_speed_hz = 500000,
     .bus_num      = 1,
     .chip_select  = 0, 
    },
    u8 csi_spi1_chip_selects[] = {SPI_INTERN_CS};

    I am guessing that the working case talks to OM-DL2_ATTEN and the non-working case talks to the SPM-CPLD. Each use a different mode. The SPM will drive the CS0 line. Not sure you can say SPM should work because OM works. Maybe try OM SPI1.0 settings on the SPM. The slave won't be happy but the master side might process error free. That would indicate some weirdness in the driver or HW that cause the DMA to end early.

  • Hi Norman,

    The mode in the first structure should be SPI_MODE_0 | SPI_NO_CS. I think I posted after trying that mode to see how it looks. Also, I have run the non-erroring setup from OM on SPM, and the erroring setup from SPM on OM. The error reported stays with the SPM hardware.

    This is the spidev_test running on the OM. I have modified the test to only send 08 00. What we can't see here is the actual gpio chip select attached to the slave device. However, I can see the clock start at the correct polarity of 0.

    This is the same spidev_test running on the SPM. This slave device does use the CS1.0 chip select. Notice the clock polarity. No matter what phase and polarity I tell spidev_test to use, this is always the waveform and we never see the second byte come out. Waaay down the trace we do see the chip select de-assert.

    This is u-boot on the SPM. This is how I would expect a spi transfer to look in mode 0.

  • Question: How can I ensure that no DMA of any kind is used by the kernel spi driver?  I currently have no davinci_spi_config structure for any spidevs. What is the default io_type?

  • I set up a davinci_spi_config structure to register with the controller data of this spidev when it is created.

    The structure has only the following:

    .parity_enable  = 0,

    .io_type              = SPI_IO_TYPE_POLL,

    Here is the output from spidev_test. The error indicated in SPIFLG register is a PARITY error, even though I am not enabling parity.

    root@module:~# spidev_test -D /dev/spidev1.0
    spi mode: 0

    spi_davinci spi_davinci.1: spi io not DMA

    bits per word: 8

    spi_davinci spi_davinci.1: spi io events poll

    max speed: 100000 Hz (100 KHz)
    spi_davinci spi_davinci.1:
    spi io events poll errors: 00000004
    can't send spi message: Input/output error
    Aborted
    root@module:~#

  • Not much to add. Since the problem follows the board, maybe there is something with the SPI1 signals. Are the SPI1 signals shared with anything else? Intentionally or unintentionally?

  • Hi Norman and Titus,

    I really appreciate the attention you guys have given to this issue.

    Yes, this got to the point where things just didn't make sense. However, I am happy to say I've found the problem. Running the SPI transaction from spidev_test at any rate below 1MHz will cause this bug to rear up.

    Here is the last bit if instrumentation that led to finding out what is happening. I arrived here after finding that the SPIFLG register had bit 2, PARERRFLG, set after a transaction failed. We do not want to use parity, and specifically turning parity off did not keep that check from occuring. This code snippet is from davinci_spi_setup_transfer in spi-davinci.c. The dev_info calls are my additions for debug. The highlighted code is the part in question. In theory, if davinci_spi_get_prescale returns a negative value, the function will return without going further. That is NOT what is happening.

        /* Set up SPIFMTn register, unique to this chipselect. */
    dev_info(sdev, "setup xfer:calling prescale with %08x hz\n", hz);
        prescale = davinci_spi_get_prescale(dspi, hz);
        if (prescale < 0)
            return prescale;

        spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
    dev_info(sdev, "setup xfer:prescale %08x spifmt %08x\n", prescale, spifmt);
        if (spi->mode & SPI_LSB_FIRST)
            spifmt |= SPIFMT_SHIFTDIR_MASK;

        if (spi->mode & SPI_CPOL)
            spifmt |= SPIFMT_POLARITY_MASK;

        if (!(spi->mode & SPI_CPHA))
            spifmt |= SPIFMT_PHASE_MASK;

    Here is console output at various speed settings. Watch what happens to spifmt. Also note that 0xffffffea is -22 decimal, which is the error return value -EINVAL returned from the prescale function.

    root@module:~# spidev_test -D /dev/spidev1.0
    spi mode: 0spi_davinci spi_davinci.1: setup xfer:calling prescale with 000186a0 hz

    bits per word: 8
    max speed: 100000 Hz (100 KHz)
    spi_davinci spi_davinci.1: get prescale: max hz 000186a0  ret 000008e8
    spi_davinci spi_davinci.1: setup xfer:prescale ffffffea spifmt ffffea08
    spi_davinci spi_davinci.1:
    spi io events poll errors: 00000004
    can't send spi message: Input/output error
    Aborted

    Now a test at 1MHz. The 00 DE is the correct value coming from the cpld.

    root@module:~# spidev_test -s 1000000 -D /dev/spidev1.0
    spi mode: 0spi_davinci spi_davinci.1: setup xfer:calling prescale with 000f4240 hz

    bits per word: 8
    max speed: 1000000 Hz (1000 spi_davinci spi_davinci.1: get prescale: max hz 000f4240  ret 000000e4
    KHz)
    spi_davinci spi_davinci.1: setup xfer:prescale 000000e3 spifmt 0000e308

    00 DE
    root@module:~#

    Here is the inline function with my instrumentation in bold.

    /**
     * davinci_spi_get_prescale - Calculates the correct prescale value
     * @maxspeed_hz: the maximum rate the SPI clock can run at
     *
     * This function calculates the prescale value that generates a clock rate
     * less than or equal to the specified maximum.
     *
     * Returns: calculated prescale - 1 for easy programming into SPI registers
     * or negative error number if valid prescalar cannot be updated.
     */
    static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
                                u32 max_speed_hz)
    {
        int ret;
    struct device *sdev = dspi->bitbang.master->dev.parent;

        ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
    dev_info(sdev, "get prescale: max hz %08x  ret %08x\n", max_speed_hz, (int)ret);
        if (ret < 3 || ret > 256)
            return -EINVAL;

        return ret - 1;
    }

    I have some more explaining to do as to why this did not happen on the OM board, even though I see this same behavior with my instrumented spi-davinci running on that board. Beside the fact that the slave devices are different between boards, the OM on spi bus 1 does not use any internal spi chip selects. All gpio chip selects. I am guessing this will prevent the spi controller from doing a parity check even though the same over-writing of SPIFMT is happening. Also, since the cpld code on the SPM was new, the engineer developing that code asked that we run at a slower rate on the SPM. That is another reason why this followed hardware.

    At this point I am looking through objdumps of the driver to see if this is an optimization issue or just the way this code gets compiled.

  • Wow. I think you found your bug. The problem is that prescale is an unsigned variable. The comparision "if (prescale < 0)" is meaningless and the compiler usually reports something like "comparision is always false". I think the kernel writers have cranked the warnings down because there are a lot of tests of true or false throughout the kernel code. Note that spi-davinci.c at kernel.org fixes this comparision by declaring prescale as signed int.

    No idea why the same negative prescale error would work on the OM but not on the SPM. The parity should results in an extra parity bit in the data stream regardless of internal or GPIO chip select. The negative prescale would have resulted in SPI_MODE_3 being used all the time. I would think the extra data bit or fixed mode would be noticed.

  • Norman,

    You are correct! It is easy to google up spi-davicni.c and see that prescale is declare int. But in the PSP version it is declared u32. I believe I was looking at the google version on line last night and forgetting to check what this code is actually doing.

    thanks again for looking at this.

    From google land:

     static int davinci_spi_setup_transfer(struct spi_device *spi,
    276                 struct spi_transfer *t)
    277 {
    278 
    279         struct davinci_spi *dspi;
    280         struct davinci_spi_config *spicfg;
    281         u8 bits_per_word = 0;
    282         u32 hz = 0, spifmt = 0;
    283         int prescale;
  • For reference, the version of PSP we're using is DaVinci-PSP-SDK-03.22.00.06.

    Dan

  • Hi Dan,

    I'm glad that you able to fix your problem.

    Thanks for your update.

    Hi Norman,

    Thanks for your support.