When using an SPI device with multiple chip selects (say /dev/spidev1.0 to /dev/spidev1.3), I’m unable to receive data from the devices spidev1.1 to spidev1.3. The read data is always 0xff even though the MISO line carries the correct information. When talking to spidev1.0 this problem does not occur. I suspect there is a problem with the spi-driver, since when changing the cs-gpios in the device tree, it’s always spidev1.0 that works, and spidev1.1 to spidev1.3 cause problems.
I’m on an apalis imx6. My image is built with OpenEmbedded/Yocto and based upon Apalis-iMX6_LXDE-Image_2.8b4.129-20181005. For the kernel package linux-toradex, I use a customized defconfig, device tree, and the patch MLK-15305-2: dma: imx-sdma: force to load context in sdma_config.
I’d appreciate any help in resolving this issue.
Relevant device tree bindings:
/* Apalis SPI1 */
&iomuxc {
pinctrl_ekt_mot_spi: mot_spi {
fsl,pins = <
MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1 // MOT_MISO
MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1 // MOT_MOSI
MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1 // MOT_SCK
MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x000b1 // MOT_nCS
MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x000b1 // MOT1_nCS
MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000b1 // MOT2_nCS
MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x000b1 // MOT3_nCS
>;
};
};
&ecspi2 {
status = "okay";
fsl,spi-num-chipselects = <4>; // obsolete
num-cs = <4>;
cs-gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>,
<&gpio2 4 GPIO_ACTIVE_HIGH>,
<&gpio2 5 GPIO_ACTIVE_HIGH>,
<&gpio2 6 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&pinctrl_ekt_mot_spi>;
ekt_spi_tmc429: spi_tmc429@0 {
compatible = "toradex,evalspi";
reg = <0>;
spi-max-frequency = <18000000>;
};
ekt_spi_tmc26x1: spi_tmc26x@1 {
compatible = "toradex,evalspi";
reg = <1>;
spi-max-frequency = <18000000>;
};
ekt_spi_tmc26x2: spi_tmc26x@2 {
compatible = "toradex,evalspi";
reg = <2>;
spi-max-frequency = <18000000>;
};
ekt_spi_tmc26x3: spi_tmc26x@3 {
compatible = "toradex,evalspi";
reg = <3>;
spi-max-frequency = <18000000>;
};
};
The following minimal code sample will always print “Read: -1” even though the logic analyzer shows the proper response on the MISO line. If /dev/spidev1.0 is used instead, the read value corresponds with the data on the MISO line.
#include <linux/spi/spidev.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int result;
int mode = SPI_CPOL | SPI_CPHA;
uint32_t tx = 0x60000000 | 0x12000000 | 0x01000000;
uint32_t rx = 0;
struct spi_ioc_transfer xfr = {
.tx_buf = (unsigned long)&tx,
.rx_buf = (unsigned long)&rx,
.len = 4,
.bits_per_word = 8,
.speed_hz = 1000000};
int fd = open("/dev/spidev1.2", O_RDWR);
result = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
if (result != 0)
return result;
result = ioctl(fd, SPI_IOC_MESSAGE(1), &xfr);
printf("Read %d\n", rx);
close(fd);
}