Hello,
Trying to enable two chip selects for SPI1 with GPIO6_19 and GPIO6_20. The SPI node on device tree looks like this (fsl-imx8qm-apalis.dts)
/* Apalis SPI1 */
&lpspi0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpspi0 >;
num-cs = <2>;
fsl,espi-num-chipselects = <2>;
cs-gpios =<&gpio6 19 GPIO_ACTIVE_LOW>,
<&gpio6 20 GPIO_ACTIVE_LOW>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
clock-frequency= <40000000>;
spidev0: spi@0 {
compatible = "toradex,evalspi";
reg = <0>;
spi-max-frequency = <20000000>;
};
spidev1: spi@1 {
compatible = "toradex,evalspi";
reg = <1>;
spi-max-frequency = <20000000>;
};
};
muxing:
/* Apalis SPI1 */
pinctrl_lpspi0: lpspi0grp {
fsl,pins = <
SC_P_SPI0_SCK_DMA_SPI0_SCK 0x0600004c
SC_P_SPI0_SDO_DMA_SPI0_SDO 0x0600004c
SC_P_SPI0_SDI_DMA_SPI0_SDI 0x0600004c
SC_P_ENET1_RGMII_RXD1_LSIO_GPIO6_IO19 0x0600004c
SC_P_ENET1_RGMII_RXD2_LSIO_GPIO6_IO20 0x0600004c
>;
};
Linux dev:
root@apalis-imx8:~# ls /dev |grep spidev
spidev0.0
spidev0.1
spidev1.0
SPI C code:
#define SPI_CLK_SPEED 20 * 1000000 //10Mhz
#define SPI_BITS 8
#define SPI_DELAY 0
static const char *device = "/dev/spidev0.0";
static const char *device01 = "/dev/spidev0.1";
struct spi_ioc_transfer tr;
struct spi_ioc_transfer tr01;
int fd_spi,fd_spi01;
uint8_t default_tx[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x0D,
};
uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
void transfer(int fd,struct spi_ioc_transfer* tr, uint8_t const *tx, uint8_t const *rx, size_t len)
{
int ret;
tr->tx_buf = (unsigned long)tx;
tr->rx_buf = (unsigned long)rx;
tr->len = len;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr);
if (ret < 1)
{
pabort("can't send spi message");
exit(1);
}
}
int SPI_init( const char *dev,struct spi_ioc_transfer *tr,uint32_t mode,uint8_t bits,uint32_t speed,uint16_t delay)
{
int spiFD,ret;
tr->delay_usecs = delay;
tr->speed_hz = speed;
tr->bits_per_word = bits;
if (mode & SPI_TX_QUAD)
tr->tx_nbits = 4;
else if (mode & SPI_TX_DUAL)
tr->tx_nbits = 2;
if (mode & SPI_RX_QUAD)
tr->rx_nbits = 4;
else if (mode & SPI_RX_DUAL)
tr->rx_nbits = 2;
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
tr->rx_buf = 0;
else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
tr->tx_buf = 0;
}
spiFD = open(dev, O_RDWR);
if (spiFD < 0)
pabort("can't open device");
// spi mode
ret = ioctl(spiFD, SPI_IOC_WR_MODE32, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(spiFD, SPI_IOC_RD_MODE32, &mode);
if (ret == -1)
pabort("can't get spi mode");
//bits per word
ret = ioctl(spiFD, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(spiFD, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
// max speed hz
ret = ioctl(spiFD, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(spiFD, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
printf("spi mode: 0x%x\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
return (spiFD);
}
int main()
{
fd_spi = SPI_init(device,&tr,SPI_MODE,SPI_BITS,SPI_CLK_SPEED,SPI_DELAY);
fd_spi01 = SPI_init(device01,&tr01,SPI_MODE,SPI_BITS,SPI_CLK_SPEED,SPI_DELAY);
while(1)
{
//transfer value:
usleep(2000);
transfer(fd_spi,&tr, default_tx, default_rx, 5); // (was &rx instead of str) 1 byte
usleep(2000);
transfer(fd_spi01,&tr01, default_tx, default_rx, 5);
}
}
The result on oscilloscope: only one of the chip selects is working with a big delay (dmesg.log is in attachements)dmesg.log. (In addition the native chip select goes low with every byte sent.)
Oscilloscope images:
[upload|1t5z4IdE4MLycrgtfUDWfd+Elt0=]
zoom in:
[upload|GXBbDw0sl8tl2csq40mE6g7Gzu0=]
linux version: Linux apalis-imx8 4.14.117
is there something I should change in the device tree?.
Best regards,
Majd