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.

SPIDEV2.0 problem: how to control the CS pin

I'm using ti-sdk-am335x-evm-05.05.00.00 and an AM335x EVM. Linux 3.2.0-psp04.06.00.08

The SPI is working fine, when I generate the uImage and boot the kernel on my board I can see the spidev2.0 device file in the /dev folder. The communication is also working and I'm able to execute an application that writes to and reads from the bus.

My problem is that I need to control the CS line. The communication model I intend to do issues more then one command to the slave device and waits for it's response. In this scenario, if the CS goes from "enable" to "disable" it would be considered as a communication error by the slave and nothing would work. I'm not trying to make it enable the device all the time either, it should disable the line after the command is done.

Right now, when my application (user space) issues a write call to the spidev driver, CS goes from 1 to 0 before the SCLK starts and returns to 1 after the number of bytes I send is written. The same thing happens when I issue a read call.

My first thought was to change the file drivers/spi/spidev.c so that I could add a command to the ioctl call in order to control the CS pin as I see fit. This would work if I knew what to change in the other functions and files...

Anyone knows a simpler way to do this or what I should change to make it work?

Thanks a lot!

Davi

  • Davi,

    From my understanding of the spidev/spi interface, I think there is a way to do this without modification of the drivers.  In include/linux/spi/spidev.h there is the following definition:

    struct spi_ioc_transfer {
    	__u64		tx_buf;
    	__u64		rx_buf;
    
    	__u32		len;
    	__u32		speed_hz;
    
    	__u16		delay_usecs;
    	__u8		bits_per_word;
    	__u8		cs_change;
    	__u32		pad;

    This can be sent through an ioctl using code similar to this:

    int ret;
    struct spi_ioc_transfer tr = {
      .tx_buf = (unsigned long)tx,
      .rx_buf = (unsigned long)rx,
      .len = len,
      .delay_usecs = 1,
      .speed_hz = 10000,
      .bits_per_word = 8,
      .cs_change = 0,
    };
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);

    where tx and rx are the transmit and receive buffers.  If you want to do half duplex transfers, simply point one of the buffers to NULL.  For your application, I believe you would want to set .cs_change to zero.  There is much to be read about this in the kernel source, as it is well documented.  You may also want to look at include/linux/spi/spi.h, where you will find spi_message defined, which would allow you to send multiple transfers.

    Bear in mind that this is simply my understanding of this from digging around trying to get my code to work.  I have not substantially tested this, but the documentation seems to point to this being the right course.

    Hope it helps,

    Jeff