SPI Clock Polarity not changing

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SPI Clock Polarity not changing

Jump to solution
1,194 Views
aravindchakrava
Contributor II

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

Labels (2)
0 Kudos
1 Solution
1,165 Views
igorpadykov
NXP Employee
NXP Employee

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

 

View solution in original post

4 Replies
1,174 Views
aravindchakrava
Contributor II

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

0 Kudos
1,166 Views
igorpadykov
NXP Employee
NXP Employee

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

 

1,143 Views
aravindchakrava
Contributor II

Hi Igor, 

This is nice way of debugging within Linux. I will check. 

Thank you very much.

 

Regards, 

Aravind

0 Kudos
1,189 Views
igorpadykov
NXP Employee
NXP Employee

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

0 Kudos