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.

DM368 SPI slave read

I am currently developing an application on the DM368 that needs to make use of an SPI port in slave mode. I’ve gotten everything to work with an SPI port configured as a master, but I’m not having much luck with slave mode. Specifically, I’m unable to perform a non-blocking read when in slave mode. Any attempt to read from an SPI port while it is in slave mode causes the application performing the read to lock up. I do not have anything connected to the SPI port at the moment, so there isn’t any actual data to read, but I would expect a non-blocking read to return an error rather than hang. Any suggestions or input would be greatly appreciated. I’ve included below the relevant bits from the kernel as well as the test application I’m using.

My development board is an LI-TB02,  I’m running a Yocto based BSP with the 2.6.32.17 kernel, and my SPI driver is spidev.

dm365.c:

static u64 dm365_spi0_dma_mask = DMA_BIT_MASK(32);
static struct davinci_spi_platform_data dm365_spi0_pdata = {
        .version       = SPI_VERSION_1,
        .num_chipselect = 1,
        .intr_line             = 1,
        .cshold_bug            = false,
}; 
static struct resource dm365_spi0_resources[] = {
        {
               .start = 0x01c66000,
               .end   = 0x01c667ff,
               .flags = IORESOURCE_MEM,
        },
        {
               .start = IRQ_DM365_SPIINT0_0,
               .flags = IORESOURCE_IRQ,
        },
        {
               .start = 17,
               .flags = IORESOURCE_DMA,
        },
        {
               .start = 16,
               .flags = IORESOURCE_DMA,
        },
        {
               .start = EVENTQ_3,
               .flags = IORESOURCE_DMA,
        },
};

static
struct platform_device dm365_spi0_device = {
        .name = "spi_davinci",
        .id = 0,
        .dev = {
               .dma_mask = &dm365_spi0_dma_mask,
               .coherent_dma_mask = DMA_BIT_MASK(32),
               .platform_data = &dm365_spi0_pdata,
        },
        .num_resources = ARRAY_SIZE(dm365_spi0_resources),
        .resource = dm365_spi0_resources,
};

void
__init dm365_init_spi0(unsigned chipselect_mask, struct spi_board_info *info, unsigned len)
{
        davinci_cfg_reg(DM365_SPI0_SCLK);
        davinci_cfg_reg(DM365_SPI0_SDI);
        davinci_cfg_reg(DM365_SPI0_SDO);
        /* not all slaves will be wired up */
        if (chipselect_mask & BIT(0))
               davinci_cfg_reg(DM365_SPI0_SDENA0);
        if (chipselect_mask & BIT(1))
               davinci_cfg_reg(DM365_SPI0_SDENA1);
        spi_register_board_info(info, len);
        platform_device_register(&dm365_spi0_device);
}

board-dm368.c:

static struct davinci_spi_config dev_spi0_cfg = {
        .wdelay                = 0,
        .parity_enable = false,
        .io_type               = SPI_IO_TYPE_POLL,//io type does not make a difference
        .timer_disable = true,
};

static
struct spi_board_info dm368_spi0_info[] __initconst = {
        {
               .modalias      = "spidev",
               .platform_data = NULL,
               .controller_data = &dev_spi0_cfg,
               .max_speed_hz  = 50 * 1000 * 1000,    /* at 3v3 */
               .bus_num       = 0,
               .chip_select   = 0,
               .mode          = SPI_MODE_0,
        },
};

davinci_spi.c:

static int davinci_spi_probe(struct platform_device *pdev)
{
        ...

        //configure SPI port as slave
        clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
        clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);

        OR

        //configure SPI port as master
        set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
        set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);

        ...

}
 

test application: (reads 0’s in master mode, but hangs when configured as a slave)

#include <stdio.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <linux/spi/spidev.h>

int main()

{

    int bits_per_word = 8;

    int max_speed_hz = 10000000;

    int mode = SPI_MODE_0;

    char* device = "/dev/spidev0.0";

    int read_fd = open(device, O_RDWR | O_NONBLOCK);   

    if (read_fd < 0) {

               printf("Could not open read device %s\n",device);

        return -1;

    }   

        /*spi mode*/  

    if (ioctl(read_fd, SPI_IOC_WR_MODE, &mode) < 0) {

        printf("Could not set spi mode on device %s\n", device);

        close(read_fd);

        return -1;

    }       

    if (ioctl(read_fd, SPI_IOC_RD_MODE, &mode) < 0) {

        printf("Could not get spi mode on device %s\n", device);

        close(read_fd);

        return -1;

    }       

        /*bits per word*/   

    if (ioctl(read_fd, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word) < 0) {

        printf("Could not set bits per word on device %s\n", device);

        close(read_fd);

    }       

    if (ioctl(read_fd, SPI_IOC_RD_BITS_PER_WORD, &bits_per_word) < 0) {

        printf("Could not get bits per word on device %s\n", device);

        close(read_fd);

        return -1;

    }   

    /*bus speed*/ 

    if (ioctl(read_fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed_hz) < 0) {

        printf("Could not set bus speed device %s\n", device);

        close(read_fd);

        return -1;

    } 

    if (ioctl(read_fd, SPI_IOC_RD_MAX_SPEED_HZ, &max_speed_hz) < 0) {

        printf("Could not get bus speed device %s\n", device);

        close(read_fd);

        return -1;

    }   

    char buf[8];   

    printf("Calling read on %s\n",device);

    if(read(read_fd,buf,sizeof(buf)) < 0) {

               printf("No data to read\n");  

        }

        else {

               printf("Read: %s\n",buf);

        }

   return 0;

}

Test application stack trace: (read call never returns)

158 open("/dev/spidev0.0", O_RDWR|O_NONBLOCK)=3
158   ioctl(3, 0x40016b01, 0xbeeb3c9c)  = 0
158   ioctl(3, 0x80016b01, 0xbeeb3c9c)  = 0
158   ioctl(3, 0x40016b03, 0xbeeb3ca4)  = 0
158   ioctl(3, 0x80016b03, 0xbeeb3ca4)  = 0
158   ioctl(3, 0x40046b04, 0xbeeb3ca0)  = 0
158   ioctl(3, 0x80046b04, 0xbeeb3ca0)  = 0
158   fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
158   mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4017a000
158   write(1, "Calling read on /dev/spidev0.0\n", 31) = 31
158   read(3,

/proc/sysrq-trigger output: ("spidev_read" calls "spidev_sync" which calls "wait_for_completion" and never returns)
[  221.110000] Backtrace:
[  221.110000] [<c026bb68>] (schedule+0x0/0x408) from [<c026c64c>] (schedule_timeout+0x20/0x1cc)
[  221.110000] [<c026c62c>] (schedule_timeout+0x0/0x1cc) from [<c026c13c>] (wait_for_common+0x170/0x1c0)
[  221.110000]  r8:00000002 r7:c16ec010 r6:c16edea4 r5:c16ec000 r4:7fffffff
[  221.110000] [<c026bfcc>] (wait_for_common+0x0/0x1c0) from [<c026c1a4>] (wait_for_completion+0x18/0x1c)
[  221.110000]  r9:c16ec000 r8:beeb3c94 r7:c16edea4 r6:c16edef4 r5:c16ec020
[  221.110000] r4:00000000
[  221.110000] [<c026c18c>] (wait_for_completion+0x0/0x1c) from [<c0184dc4>] (spidev_sync+0x104/0x158)
[  221.110000] [<c0184cc0>] (spidev_sync+0x0/0x158) from [<c01856c8>] (spidev_read+0xa0/0x144)
[  221.110000]  r7:c10a8a50 r6:beeb3c94 r5:c10a8a40 r4:c16edef4
[  221.110000] [<c0185628>] (spidev_read+0x0/0x144) from [<c0091b04>] (vfs_read+0xb8/0x158)
[  221.110000]  r7:00000000 r6:c16edf78 r5:c141f280 r4:beeb3c94
[  221.110000] [<c0091a4c>] (vfs_read+0x0/0x158) from [<c0091ef8>] (sys_read+0x44/0x70)
[  221.110000]  r8:beeb3c94 r7:00000000 r6:00000000 r5:00000008 r4:c141f280
[  221.110000] [<c0091eb4>] (sys_read+0x0/0x70) from [<c0025f20>] (__sys_trace_return+0x0/0x20)
[  221.110000]  r8:c0025f44 r7:00000003 r6:000085f8 r5:00000000 r4:0000897c