This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/OMAP-L138: SPI Configuration not reflecting changes to parity and shift direction

Part Number: OMAP-L138

Tool/software: Linux

Hello,

I am using the OMAP-L138 LCDK with embedded Linux.  Thus far, I have succeeded in GPIO and UART implementation in the user space, but I am having some trouble with the implementation of SPI.  I have successfully implemented SPI communication that successfully reads and writes when SOMI and SIMO are shorted together; however, when I attempt to change the configuration (MSB first, No Parity, etc) no changes seem to be reflected in the output waveform.

It appears that the default is Odd Parity, LSB First.  When I attempt to send "0xA0A0", I see 0b000001011 repeated twice on the output.  Given the same transmit buffer, the output does not change regardless of configuration.

In Linux, the following files exist:

/sys/class/spi_master/spi1 exists
/sys/class/spidev/spidev1.0 /sys/class/spidev/spidev1.1 exist
/sys/class/spi_master/spi1/

and 

cat /sys/class/spi_master/spi1/device/modalias

reads platform:spi_davinci

I take this to mean that the system is set up with spi_davinci as the controller driver and that spidev is the protocol driver.  Is this the correct implementation/understanding?

I have made the following changes to files:

board-omapl138-lcdk.c edits:

//davinci_spi_config :
static struct davinci_spi_config da850evm_spi_cfg = {
	.wdelay		= 2,
	.io_type	= SPI_IO_TYPE_POLL,
	.c2tdelay	= 8,
	.t2cdelay	= 8,
	.parity_enable = 0,
	.odd_parity = 0,
};

//spi_board_info
static struct spi_board_info da850evm_spi_info[] = {
	{
		.modalias		= "spi_davinci",
		.controller_data	= &da850evm_spi_cfg,
		.mode			= SPI_MODE_0 ,
		.max_speed_hz		= 8000000,
		.bus_num		= 1,
		.chip_select		= 0,
	},
	{
		.modalias		= "spi_davinci",
		.controller_data	= &da850evm_spi_cfg,
		.mode			= SPI_MODE_0 ,
		.max_speed_hz		= 8000000,
		.bus_num		= 1,
		.chip_select		= 1,
	},
};

//spi_init
static void omapl138_lcdk_spi_init(void)
{
	int ret;

	ret = davinci_cfg_reg_list(da850_spi1_pins);
	if (ret)
		pr_warn("omapl138_lcdk_init: spi1 mux setup failed: %d\n",
				ret);
	ret = da8xx_register_spi(1, da850evm_spi_info,
				 ARRAY_SIZE(da850evm_spi_info));
	if (ret)
		pr_warning("omapl138_lcdk_init: spi 1 registration failed: %d\n",
				ret);
}

devices-da8xx changes:

//SPI Resources:
static struct resource da8xx_spi0_resources[] = {
 [0] = {
   .start	= DA8XX_SPI0_BASE,
   .end	= DA8XX_SPI0_BASE + SZ_4K - 1,
   .flags	= IORESOURCE_MEM,
 },
 [1] = {
   .start	= IRQ_DA8XX_SPINT0,
   .end	= IRQ_DA8XX_SPINT0,
   .flags	= IORESOURCE_IRQ,
 },
 [2] = {
   .start	= DA8XX_DMA_SPI0_RX,
   .end	= DA8XX_DMA_SPI0_RX,
   .flags	= IORESOURCE_DMA,
 },
 [3] = {
   .start	= DA8XX_DMA_SPI0_TX,
   .end	= DA8XX_DMA_SPI0_TX,
   .flags	= IORESOURCE_DMA,
 },
};

static struct resource da8xx_spi1_resources[] = {
 [0] = {
   .start	= DA850_SPI1_BASE,
   .end	= DA850_SPI1_BASE + SZ_4K - 1,
   .flags	= IORESOURCE_MEM,
 },
 [1] = {
   .start	= IRQ_DA8XX_SPINT1,
   .end	= IRQ_DA8XX_SPINT1,
   .flags	= IORESOURCE_IRQ,
 },
 [2] = {
   .start	= DA8XX_DMA_SPI1_RX,
   .end	= DA8XX_DMA_SPI1_RX,
   .flags	= IORESOURCE_DMA,
 },
 [3] = {
   .start	= DA8XX_DMA_SPI1_TX,
   .end	= DA8XX_DMA_SPI1_TX,
   .flags	= IORESOURCE_DMA,
 },
};


//platform data:
struct davinci_spi_platform_data da8xx_spi_pdata[] = {
	[0] = {
		.version	= SPI_VERSION_2,
		.intr_line	= 1,
		.dma_event_q	= EVENTQ_0,
	},
	[1] = {
		.version	= SPI_VERSION_2,
		.intr_line	= 1,
		.dma_event_q	= EVENTQ_0,
	},
};

//platform device:
static struct platform_device da8xx_spi_device[] = {
	[0] = {
		.name		= "spi_davinci",
		.id		= 0,
		.num_resources	= ARRAY_SIZE(da8xx_spi0_resources),
		.resource	= da8xx_spi0_resources,
		.dev		= {
			.platform_data = &da8xx_spi_pdata[0],
		},
	},
	[1] = {
		.name		= "spi_davinci", ///// Used to match driver
		.id		= 1,
		.num_resources	= ARRAY_SIZE(da8xx_spi1_resources),
		.resource	= da8xx_spi1_resources,
		.dev		= {
			.platform_data = &da8xx_spi_pdata[1],
		},
	},
};

Also, in my userspace code, ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb); shows that lsb is set to zero, indicating to me that the driver thinks the controller is configured for MSB first.  Since the waveform seems to indicate otherwise, I connected the debugger (XDS100v2) and dumped the registers after starting the userspace code. I found the following (Under SPI1ARM):

SPICGR0 = 0X00000001
SPICGR1 = 0X00000103 
SPIFMT_1 = 0X3FF7EA08

PARENA = 1 (Enabled)
SHIFTDIR = 1(LSB First)

If I attempt to manually set these registers the way I want (No Parity, MSB First), the values are reset when I stop the processor next.  This seems to indicate to me that the code running on the processor is setting the values to the incorrect values.

I have also tried eliminating anywhere in spi_davinci.c that LSB_FIRST is set with no effect on the waveform.

Is there something I have overlooked?  It seems like configuration of the peripheral should be a simple operation, but it has proven to be more difficult that I expected.  Please let me know if there is any more information I can provide to help in solving this issue.

JLimbocker