Project

General

Profile

Spidev issues

Added by Fred Frantz about 8 years ago

The dev kit baseboard file has been modified to include a "spidev" device, and the kernel was compiled to include the SPI device driver for users. However, the expected /dev/spidev0.1 file is not generated. Can a pinmux conflict with other devices cause this problem? A possibly related problem is that ECC errors are preventing the kernel from booting from NAND, but it works from RAM.


Replies (32)

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

A pinmux conflict would likely cause the device not to work but it would not affect the creation of the spidev device file.

You need to make sure that SPIDEV is enabled in the kernel. It doesn't look like it is by default.

 $ grep -i spidev .config
# CONFIG_SPI_SPIDEV is not set

RE: Spidev issues - Added by Fred Frantz about 8 years ago

It looks like it is enabled to me.

 CONFIG_SPI=y
 # CONFIG_SPI_DEBUG is not set
 CONFIG_SPI_MASTER=y

 #
 # SPI Master Controller Drivers
 #
 # CONFIG_SPI_ALTERA is not set
 # CONFIG_SPI_BITBANG is not set
 # CONFIG_SPI_GPIO is not set
 # CONFIG_SPI_OC_TINY is not set
 CONFIG_SPI_OMAP24XX=y
 # CONFIG_SPI_PXA2XX_PCI is not set
 # CONFIG_SPI_XILINX is not set
 # CONFIG_SPI_DESIGNWARE is not set

 #
 # SPI Protocol Masters
 #
 CONFIG_SPI_SPIDEV=y
 # CONFIG_SPI_TLE62X0 is not set  

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Can you attach the bootlog for the device?

RE: Spidev issues - Added by Fred Frantz about 8 years ago

Hope this helps.

RE: Spidev issues - Added by Fred Frantz about 8 years ago

I added the boot log for the ECC errors also.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Hmm no noticeable errors. You can double check the kernel, on the booted device for the spidev support:

zcat /proc/config.gz | grep SPIDEV

The nand ECC errors may just be that the environment was never written or that it was originally written by the wrong u-boot which had the wrong ECC set.

You should be able to run saveenv to write the environment to the nand. And I suspect your ECC warnings will go away.

RE: Spidev issues - Added by Fred Frantz about 8 years ago

Thanks for the suggestions, but ZCAT on the target indicates that SPIDEV is enabled. Regarding the ECC errors, I reloaded an earlier version of the kernel and an environment variable file that was working without any problems, but the ECC errors still persist. I noticed in the boot log that nandecc is disabled. Could that be a problem?

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

Thanks for the suggestions, but ZCAT on the target indicates that SPIDEV is enabled.

Interesting. My troubleshooting steps when trying to diagnose a driver not loading is the following.
  • Check the boot log for any apparent errors.
    Didn't see any
  • Check the .config to make sure driver is built.
    Checked
  • Grep the kernel source code for other examples of driver being used and comparing with my setup. Starting in arch/arm/mach-omap2 and broadening search if needed.
    @grep -r 'spidev' arch/arm/mach-omap2/
  • Checking driver's probe function for any printk statements. If some exist search bootlog for them, otherwise add some and check bootlog. Also add printks to drivers _init function to be doubly sure driver is getting loaded into kernel.
  • Verify udev or mdev is running on filesystem. As it would be responsible for created /dev nodes

Regarding the ECC errors, I reloaded an earlier version of the kernel and an environment variable file that was working without any problems, but the ECC errors still persist.

Not sure what you mean. The ECC errors are coming from u-boot why would changing the kernel help? Are you saving the environment from linux?

I noticed in the boot log that nandecc is disabled. Could that be a problem?

Originally the nandecc command was used to set which ECC mode was needed for each nand size in u-boot. This feature was integrated into u-boot itself so it chooses the appropriate ECC during build time (an unfortunate limitation due to how the nand driver is setup). The nandecc command was left but modified to simply print "nandecc is disabled" and exit to ensure backwards compatibility with old environments.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Just checked and the 0x340000 address the ECC errors mention is the location of the kernel not the environment I initially assumed. How are you loading the kernel to boot the system if loading it from nand isn't working (tftp)? How are you writing the kernel into the nand?

RE: Spidev issues - Added by Fred Frantz about 8 years ago

The kernel and environment were reloaded just to get to a known point where everything was working previously. The kernel is being loaded via tftp.

U-Boot# tftp 0x82000000 $serverip:uImage
U-Boot# nand write.i 0x82000000 0x340000 $filesize

No errors are reported during the write. The kernel is started manually with bootm if the ECC errors occur.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

U-Boot# tftp 0x82000000 $serverip:uImage
U-Boot# nand write.i 0x82000000 0x340000 $filesize
No errors are reported during the write. The kernel is started manually with bootm if the ECC errors occur.

By writing the nand like this without erasing, you will corrupt the image stored including the ECC. Nand flash must be erased before writing to it.

Note in the following guide I erase the whole chip before writing each section. https://support.criticallink.com/redmine/projects/armc8-platforms/wiki/UBIFS_Nand_Boot#Flashing-Nand-from-U-boot-2

For your case you just need to erase the kernel section.
nand erase 0x340000 0x500000

hex(5MB * 1024KB/MB * 1024B/KB) = 0x500000 Bytes

Note: During kernel development when you are changing the kernel often, it is unnecessary to write the kernel into the nand each time. You can simply load the kernel into ram using your tftp command and then run bootm. This can be automated by updating the bootcmd variable to run your commands on each boot.

For example:

setenv oldbootcmd $bootcmd
setenv bootcmd 'tftp 0x82000000 $serverip:uImage; bootm'
saveenv

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Jonathan Cormier wrote:

For your case you just need to erase the kernel section.
nand erase 0x340000 0x500000

hex(5MB * 1024KB/MB * 1024B/KB) = 0x500000 Bytes

Do double check my math on this, if wrong it could erase part of your filesystem image.

RE: Spidev issues - Added by Fred Frantz about 8 years ago

After erasing the NAND, the ECC errors are resolved. Thanks, that was a self inflicted problem due to misinterpretation of our documentation.

Can the McSPI conflict with SPIDEV if both are trying to access the same port? Disabling McSPI in the kernel does not seem to be an option since it results in a kernel panic after the UBIFS can't be installed. What is using McSPI on the SOM?

RE: Spidev issues - Added by Michael Williamson about 8 years ago

SPIDEV sits on top of McSPI. It's an abstraction layer on top of the specific SPI driver. That may be the problem.

You may need to configure (either via a platform file or via device tree) a SPIDEV device that is attached to a specific chip select of your SPI device.

John C: the 335x uses device tree, right? Can you post your device tree file?

-Mike

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Michael Williamson wrote:

SPIDEV sits on top of McSPI. It's an abstraction layer on top of the specific SPI driver. That may be the problem.

What Mike said. The McSPI driver is necessary for the spidev driver to work.

You may need to configure (either via a platform file or via device tree) a SPIDEV device that is attached to a specific chip select of your SPI device.

He has already attached his baseboard file. It looks like he has done this correctly. Though I didn't try to build and run it myself.

John C: the 335x uses device tree, right? Can you post your device tree file?

No the 3.14 kernel isn't released yet. He is using the 3.2 kernel.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

After erasing the NAND, the ECC errors are resolved. Thanks, that was a self inflicted problem due to misinterpretation of our documentation.

Glad that helped.

What is using McSPI on the SOM?

The SOM is using the spi1 bus to talk to the NOR module. You are using the spi0 bus so there should be no conflict. However when I was looking into this I noticed that your bus_num is set incorrectly for the spidev. The bus number is unfortunately one based in the kernel code but zero based in the hardware schematic. So your bus_num needs to be set to 1 in order to use spi0.
https://support.criticallink.com/redmine/attachments/9985/baseboard-mityarm335x-frantec-aec.c#L432

Also I believe you still need the .controller_data set for it to work.

RE: Spidev issues - Added by Fred Frantz about 8 years ago

Thanks for the correction. Setting the .bus_num = 1 solved the module issue, and the .controller_data information is required for the spi0_d0 line to be used as MOSI.

The data is now being clocked out correctly, and the device is responding with the correct data on the spi0_d1 line. However, the ioctl() call is always reporting a 0 data value for all bytes received without indicating any errors. The pin mux for the spi0 port is the same as the dev kit file. The data is making it to the SOM, but I expect there is another configuration parameter that needs to be set for the spi0_d1 line to be used as the MISO.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

Thanks for the correction. Setting the .bus_num = 1 solved the module issue, and the .controller_data information is required for the spi0_d0 line to be used as MOSI.

The data is now being clocked out correctly, and the device is responding with the correct data on the spi0_d1 line. However, the ioctl() call is always reporting a 0 data value for all bytes received without indicating any errors. The pin mux for the spi0 port is the same as the dev kit file. The data is making it to the SOM, but I expect there is another configuration parameter that needs to be set for the spi0_d1 line to be used as the MISO.

It should be correct. If data is coming out of the MOSI pin then the other pin will be MISO (as long as pinmux is correct). You might want to play with the spi MODE. SPI_MODE3 seems to be what a lot of devices i've used need. I'm pretty sure this can be changed via ioctl. See -H and -O in Documentation/spi/spidev_test.c

Additional info:
http://dlnware.com/theory/SPI-Transfer-Modes

RE: Spidev issues - Added by Michael Williamson about 8 years ago

I think there is also a control for the McSPI that can swap the din / dout pins between "d0" and "d1". We had trouble with this in the past.

-Mike

RE: Spidev issues - Added by Fred Frantz about 8 years ago

Mike, are you referring to the .d0_is_mosi parameter in the ompa2_mcspi_device_config structure? That is set to 1, but all of the SPI_MODE's give a similar result. All the data bytes returned are the same value, which is not what is being transmitted on the spi0_d1 signal. Is there another parameter that also needs to be set? The dev kit has the TLV320AIC26 audio codec configured on the SPI0 port using spidev, but the code I located for the device seems to use the direct spi functions to access the device. Am I not looking at the correct file mitydsp/projects/linux-mityarm-335x/sound/soc/codecs/tlv320aic26.c?

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

Mike, are you referring to the .d0_is_mosi parameter in the ompa2_mcspi_device_config structure?

Yes. You should have it correct if you are seeing the data output coming on the correct pin.

That is set to 1, but all of the SPI_MODE's give a similar result. All the data bytes returned are the same value, which is not what is being transmitted on the spi0_d1 signal. Is there another parameter that also needs to be set?

Not that I can think of.

The dev kit has the TLV320AIC26 audio codec configured on the SPI0 port using spidev, but the code I located for the device seems to use the direct spi functions to access the device. Am I not looking at the correct file mitydsp/projects/linux-mityarm-335x/sound/soc/codecs/tlv320aic26.c?

The tlv320 is not configured using spidev, the driver is specified in the .modalias field see below. The driver file you pointed out has direct spi control of that device.

          .modalias   = "tlv320aic26-codec",
          .controller_data = &spi0_ctlr_data,
          .irq        = -1,
          .max_speed_hz   = 2000000,
          .bus_num    = 1,
          .chip_select    = 1,
          .mode       = SPI_MODE_1,

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

The data is now being clocked out correctly, and the device is responding with the correct data on the spi0_d1 line.

Does this mean you have a spi analyser attached to the bus?

RE: Spidev issues - Added by Fred Frantz about 8 years ago

Yes, I am looking at all the SPI0 signals on a scope, and they are correct. The transmitted data is configuring the devices correctly, and the received data from the device on d1 is correct, but it is not returned from ioctl(). I have varied all the parameters through ioctl calls and verified the signals are adjusted correctly.

RE: Spidev issues - Added by Jonathan Cormier about 8 years ago

Fred Frantz wrote:

Yes, I am looking at all the SPI0 signals on a scope, and they are correct. The transmitted data is configuring the devices correctly, and the received data from the device on d1 is correct, but it is not returned from ioctl(). I have varied all the parameters through ioctl calls and verified the signals are adjusted correctly.

If you have the scope captures, you should be able to determine which spi mode you need using the following link.
http://dlnware.com/theory/SPI-Transfer-Modes

Perhaps there is something going wrong with the ioctl calls. Would you be able to post that code? Did you base it off the spidev_test.c?

RE: Spidev issues - Added by Fred Frantz about 8 years ago

This is based on spidev_test.c and other examples. There are two devices on the bus that have to be configured to read address input pins before they can be configured. That is working fine since the correct device is responding to the read command. I know the devices operate in spi mode 0 or 3, and that has been verified on the scope. Parameter changes have been disabled since it is using the default values in the baseboard file.

    int fd;
    struct spi_ioc_transfer xfer[2];
    int len, status;
    unsigned char rxbuf[32];
    unsigned char txbuf[32];
    uint8_t parm = SPI_MODE_0;
    char *devname = "/dev/spidev1.1";

    fd = open(devname, O_RDWR|O_SYNC);

    memset(xfer, 0, sizeof xfer);
    memset(txbuf, 0, sizeof txbuf);
    memset(rxbuf, 0, sizeof rxbuf);

    xfer[0].tx_buf = (unsigned long) txbuf;
//    xfer[0].rx_buf = (unsigned long) rxbuf;
//    xfer[0].bits_per_word = 8;
//    xfer[0].cs_change = 0;
//    xfer[0].speed_hz = 1000000;
//    xfer[0].delay_usecs = 0;

//    xfer[1].tx_buf = (unsigned long) txbuf;
    xfer[1].rx_buf = (unsigned long) rxbuf;
//    xfer[1].bits_per_word = 8;
//    xfer[1].cs_change = 0;
//    xfer[1].speed_hz = 1000000;
//    xfer[1].delay_usecs = 0;

    // U4 - LCD Address = 0x40,BankA = inputs, BankB = Outputs
    // U26 - I/O Address = 0x42, BankA 6:0 = outputs 7 = input, BankB = Inputs

    txbuf[0] = 0x40;
    txbuf[1] = 0x0A;
    txbuf[2] = 0x08;
    xfer[0].len = 3;
    status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);

    txbuf[0] = 0x40;
    txbuf[1] = 0x00;
    txbuf[2] = 0xFF;
    txbuf[3] = 0x00;
    xfer[0].len = 4;
    status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);

    txbuf[0] = 0x42;
    txbuf[1] = 0x00;
    txbuf[2] = 0x80;
    txbuf[3] = 0xFF;
    xfer[0].len = 4;
    status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);

//    status = ioctl(fd,SPI_IOC_WR_MODE,&parm);
//    printf("%d",status);

    while(1)
    {
        if(--tick == 0)
        {
        tick = 100000000;

            txbuf[0] = 0x42 | 0x01;
            txbuf[1] = 0x00;             // READ CONFIGURATION
            txbuf[2] = 3;                    // INIT BUFFERS TO DETECT CHANGES
            txbuf[3] = 3;
            rxbuf[0] = 3;
            rxbuf[1] = 3;
            rxbuf[2] = 3;
            rxbuf[3] = 3;
            xfer[0].len = 2;
            xfer[1].len = 2;
            status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
            printf("%d %d (%02X %02X %02X %02X) %02X %02X %02X %02X\n",fd,status,txbuf[0],txbuf[1],txbuf[2],txbuf[3],rxbuf[0],rxbuf[1],rxbuf[2],rxbuf[3]);
              }
         }

The expected values are
5 4 (43 00 03 03) 80 FF 03 03
the actual values are
5 4 (43 00 03 03) 00 00 03 03

The 80 FF values are being clocked out on the d1 line in the 3rd and 4th bytes as expected.

I also tried a single message with len=4 and the xfer0.rx_buf = rxbuf, but the results were the same.

(1-25/32) Go to top
Add picture from clipboard (Maximum size: 1 GB)