SPI not working in iMX6

Hi, I’m unable to communicate with an SPI display connected to the iMX6 with the spidev driver.

I’ve already changed the DTS as stated in your SPI (linux) documentation and the spidev3.0 is correctly shown in /dev/. I’m testing with a C program which works perfectly with an VF61 and T30 (with its respective spidevX.Y changes).

Descriptor is correctly opened, and nor the write nor the read returns any error with the ioctl operation, but nothing is read. This is my init operation:

    if (Driver->Board == COLIBRI){
        fd = open("/dev/spidev1.0", O_RDWR);
    }

    else if (Driver->Board == TEGRA){
        fd = open("/dev/spidev0.0", O_RDWR);
    }
    
    else if (Driver->Board == IMX6){
        fd = open("/dev/spidev3.0", O_RDWR);
    }

    if (fd <= 0){
        fprintf(stderr,"can't open spi device: %s\n", strerror(errno));
        return -1;
    }

    mode = SPI_MODE_0 | SPI_LSB_FIRST;

    if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0){
        fprintf(stderr,"SPI rd_mode");
        return -1;
    }

    if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0){
       fprintf(stderr,"SPI wr_mode");
       return -1;
    }

    if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &mode) < 0){
       fprintf(stderr,"SPI rd_lsb_fist");
       return -1;
    }

    if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &mode) < 0){
       fprintf(stderr,"SPI rw_lsb_fist");
       return -1;
    }

    Driver->Transfer[channel][0].delay_usecs = 0, //delay in us
    Driver->Transfer[channel][0].speed_hz = 20000000, //speed
    Driver->Transfer[channel][0].bits_per_word = 8, // bites per word 8
    Driver->Transfer[channel][1].delay_usecs = 0;
    Driver->Transfer[channel][1].speed_hz = 20000000;
    Driver->Transfer[channel][1].bits_per_word = 8;

    Driver->Descriptor[channel] = fd;

Driver struct is as follow:

#define MAX_SPI_BUF         4096UL
#define MAX_SPI_CONNECTIONS 2

typedef unsigned char UCHAR;
typedef unsigned char BOOL;
typedef signed char SCHAR;
typedef char CHAR;

typedef unsigned short int UWORD;
typedef signed short int SWORD;
typedef short int WORD;

typedef unsigned int UDWORD;
typedef signed int SDWORD;
typedef int DWORD;
struct SPIDriver {
UWORD                       Board;
DWORD                       Descriptor      [MAX_SPI_CONNECTIONS];
BOOL                        Opened          [MAX_SPI_CONNECTIONS];
CHAR                        Tx              [MAX_SPI_BUF];
CHAR                        Rx              [MAX_SPI_BUF];
SWORD                       ChannelsUsed;
struct spi_ioc_transfer     Transfer        [MAX_SPI_CONNECTIONS][2]; //0 = Tx, 1 = Rx
UWORD                       Debug;
 } ISpiDriver;

Attached I leave the logic analyzer output for both VF61 and iMX6 respectively. I’m noticing that the CS is not really working the same in both SoC so that could be the issue but it’s beyond what I currently know.
[upload|Whl5pMeJ1LCsNOJDD/EBqdE8ZK4=]
[upload|nZK6imBAoXVhPxg5rjrWV2nv0Ug=]

As additional info, I haven’t made any other changes to the iMX6 DTS but just activating UART4 and 5, in case some GPIO changes are required…

Thanks, Álvaro.

Hi ,

Apart from the inputs which toradex team will share based on your query , please find some inputs in case they help you.

I am sharing few pointers by which you can have SPI on SPI_0 for bare minimum data transfer . Cant share driver code as its an official record .
( Plese note that this is no way an driver code, it is just an SCRATCH code to help you
have some data on spi bus )

But with link text & below mentioned structure binding in spi driver you can just call spi_read in your probe , it works

A) Basic driver binding structure

const struct of_device_id slaveic_of_match_table[] = {
    { .compatible = "adi,adccc7606-8",},
    { .compatible = "adi,adcdata7606-8",},
    {}
};
MODULE_DEVICE_TABLE(of,slaveic_of_match_table);

static struct spi_driver slaveic_driver = {
    .driver = {
        .name     = "custom-spi-driver", /* cat /sys/bus/spi/drivers/ */
        .owner     = THIS_MODULE,
        .of_match_table = of_match_ptr(slaveic_of_match_table),
        .pm        = NULL,
    },
    .probe         = slaveic_spi_probe,
    .remove     = slaveic_spi_remove,
    .id_table     = slaveic_id_table,
};

B) In init register the spi driver which will call the probe function
In probe you can call spi_read .

Hi, thanks for your message! If I’m correct, in that DTS you are making use of the CAN driver? The problem is that using the spidev driver is preferred since these functions will be part of some SPI libraries for VF61, T30 and now iMX6.

For now I’m comparing the DTS between the VF61 and the iMX6 expecting some parameter setted or something like that, but I haven’t found anything yet…

Hi ,

Not the can interface , please have a look at .dtsi file as the spidev is commented out

/* Apalis SPI1 */
&ecspi1 {
	status = "okay";
/*
	spidev0: spidev@1 {
		compatible = "toradex,evalspi";
		reg = <0>;
		spi-max-frequency = <18000000>;

	};
*/

	/* It can be adcc7606@123456789abcdef */
	adcc7606-8@0 {
		compatible = "adi,adcdata7606-8";
		reg = <0>;
		spi-max-frequency = <18000000>;
		default_os = <0>;
                default_range = <10000>;     
		
		/* PINMUX to get the GPIO02 */
		pinctrl-names = "default";                                       
                pinctrl-0 = <&pinctrl_adcc7606>;

               gpio_pin_number = <&gpio1 2 0>;                                  

                gpio_convst = <9>;     
                gpio_reset = <10>;     
                gpio_range = <0>;     
                gpio_os0 = <1>;     
                gpio_os1 = <2>;     
		adc-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
                gpio_os2 = <3>;     
                gpio_frstdata = "-1";     
                gpio_stby = "GPIO_PF12";
	};

};
  1. In second step you can create an standard character module with call to spi_register_driver using first comment as an input

  2. In probe function you will get an pointer to struct spi_device which you can use to transfer the data say spi_write( spi_device_instance_received , buffer, size)

At the end, the problem was not related to the SPI module but to the display itself and a PD (power down) GPIO which was not correctly set which rendered the display unable to initialize. After correctly setting all the GPIOs, the SPI started working… Sorry for the trouble.

Thanks for the update.