Hi All,
We are using iMX8M Mini based custom board. We have loaded Linux (using uBoot + Yocto) whose Kernel version is 4.14.98-2.2.0.
We are have written SPI driver for ecSPI3. We would like to use SPI in Mode 3 (i.e., CPOL = CPOH = 1).
Following are the parameters we are using
void init_eeprom_spi(void)
{
strcpy(eeprom_spiconfig.spi_device, SPI_EEPROM_DEVICE);
eeprom_spiconfig.spi_bits = 8;
eeprom_spiconfig.spi_mode = 0x03;//SPI_EEPROM_MODE;
eeprom_spiconfig.spi_speed = 4000000;//SPI_SPEED_6MHZ; /*5 MHz */
eeprom_spiconfig.spi_tx_buffer = (char *)spi_eeprom_txbuffer;
eeprom_spiconfig.spi_rx_buffer = (char *)spi_eeprom_rxbuffer;
eeprom_spiconfig.spi_buffsz = SPI_BUFFER_MAX_SIZE;
eeprom_spiconfig.spi_fd = -1;
}
And here is the code were we are writing the data to SPI driver
int spi_transfer(struct spi_eeprom_conf *conf, char *txBuff, char *rxBuff, int size, int endian)
{
int ret;
void *txptr, *rxptr;
txptr = (void *)txBuff;
rxptr = (void *)rxBuff;
/* Check endianess and swap if necessary*/
if (endian == SPI_BIG_ENDIAN)
for (int i = 0; i < (size/M_FOUR); i ++)
SwapEndian((uint32_t *)txptr + i);
/* Was not getting proper clock polarity, hence adding CPOL, CPOH init here */
/* Set read mode */
if ((ret = ioctl(conf->spi_fd, SPI_IOC_RD_MODE, &conf->spi_mode)) < M_ZERO) {
printdbg(("\n spi_open: set read mode failed"));
close(conf->spi_fd);
return M_INVALID;
}
printdbg(("\n spi_open: set read mode successfull"));
/* Set write mode */
if ((ret = ioctl(conf->spi_fd, SPI_IOC_WR_MODE, &conf->spi_mode)) < M_ZERO) {
printdbg(("\n spi_open: set write mode failed"));
close(conf->spi_fd);
return M_INVALID;
}
printdbg(("\n spi_open: set wrie mode successfull"));
/* Initialize transfer structure for SPI linux API */
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)(char *)txBuff,
.rx_buf = (unsigned long)(char *)rxBuff,
.len = size,
.delay_usecs = conf->spi_delay,
.speed_hz = conf->spi_speed,
.bits_per_word = conf->spi_bits,
};
/* Initiate SPI transfer */
if ((ret = ioctl(conf->spi_fd, SPI_IOC_MESSAGE(1), &tr)) < M_ZERO) {
printdbg(("\n spi_transfer: transfer failed"));
return M_INVALID;
}
/* Check endianess and swap bytes if necessary */
if (endian == SPI_BIG_ENDIAN)
for (int i = 0; i < (size/M_FOUR); i ++)
SwapEndian((uint32_t *)rxptr + i);
printdbg(("\n spi_transfer: transfer success [Size = %d bytes]", ret));
/* Return no of bytes trasnferred */
return ret;
}
In-spite of all the trials, I am not able to change the mode of SPI. It is stuck with "CLOCK being Low in Idle". Interestingly, I can manipulate clock frequency without any problem. I am able to get the data out from MOSI also.
Can some one guide me how to change SPI mode? Do you see any problem in code?
Regards,
Aravind
已解决! 转到解答。
one can try to debug it to find reason why polarity change is not happening,
read SCLK_PHA field register ECSPIx_CONFIGREG, use
AN4553 Using Open Source Debugging Tools for Linux on i.MX Processors
https://www.nxp.com/docs/en/application-note/AN4553.pdf
or memtool
https://source.codeaurora.org/external/imx/imx-test/tree/test/memtool?h=lf-5.10.y_2.0.0
Best regards
igor
HI Igor,
Thank you for your reply. I did go through the SPI device driver code. However, I felt it is beyond my capability.
I am actually looking something which modifiable in user space not at kernel/driver level.
Thank you,
Aravind
one can try to debug it to find reason why polarity change is not happening,
read SCLK_PHA field register ECSPIx_CONFIGREG, use
AN4553 Using Open Source Debugging Tools for Linux on i.MX Processors
https://www.nxp.com/docs/en/application-note/AN4553.pdf
or memtool
https://source.codeaurora.org/external/imx/imx-test/tree/test/memtool?h=lf-5.10.y_2.0.0
Best regards
igor
Hi Aravind
for clock polarity one can look at "MX51_ECSPI_CONFIG_SCLKPOL" in function mx51_ecspi_prepare_message() spi driver spi-imx.c
https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/spi/spi-imx.c?h=lf-5.10.y
Best regards
igor