Chip select 1 stuck low on SPI1

Background

I’m trying to get two MCP2515 SPI-CAN devices working on SPI1 through the J21 header. I have one device on each of the two available chip selects. The J24 jumper is set to 3.3v. My MCP2515 devices are on these breakout boards: http://microcontrollershop.com/product_info.php?products_id=4719&osCsid=phbigj7bgcfmkgps6qerlam8a0. I’ve used the references listed below to get to my current point.

Some shorthand:

CS = Chip select
M0 = MCP2515 connected to SPI1 CS0 (J21 header pin 24)
M1 = MCP2515 connected to SPI1 CS1 (J21 header pin 26)

Problem Description

As long as M1 is disabled, M0 behaves correctly. The MCP251x driver successfully probes M0, and the SocketCAN driver is able to create a “can0” device that is reported by ifconfig -a. The MCP251x driver’s probe of M1 fails in this case, and dmesg reports “mcp251x spi0.1: MCP251x didn’t enter in conf mode after reset”, but M0 behaves properly. I disable M1 by disconnecting its CS wire from the J21 header, and connecting it to a 3.3v rail, so its CS is never asserted.

However, if I reconnect the M1’s CS wire to J21 pin 26, both devices fail probe and no CAN network interfaces are created. A logic analyzer shows that CS1 is never deasserted. It is low as soon as SCLK begins running, and remains asserted for as long as I capture it. This causes bus contention on MOSI and MISO.

Configuration

My device tree is derived from the default tree at /boot/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb on a flashed Jetson device. These are my additions:

Under gpio@6000d000:

gpio_default: default {                                                                     

    /*                                                                                    
     * Set pins to input for RX interrupts from SPI-CAN controllers                       
     * Controller 0: Pin 38 (PE6)                                                         
     * Controller 1: Pin 219 (PBB3)                                                       
     */                                                                                   
    gpio-input = <38 219>;
                                                                                    
    /* Assigns default function of GPIOs to SPI conroller */                              
    gpio-to-sfio = <16 17 18 19 20>;                                                      
};

I’ve opted to not add any SPI devices under spi@7000d400, because I don’t need to use spidev.

Additions to arch/arm64/mach-tegra/board-t210ref.c:

#define SPI0_INT_GPIO TEGRA_GPIO_PE6
#define SPI1_INT_GPIO TEGRA_GPIO_PBB3

static struct mcp251x_platform_data mcp251x_info = {
  .oscillator_frequency = 16 * 1000 * 1000, /* Oscillator on MCP2515 board is 16MHz */
  /* none of these three fields are necessary for our configuration */
  .board_specific_setup = NULL,
  .power_enable         = NULL,
  .transceiver_enable   = NULL,
};

struct spi_board_info mcp251x_spi_board[] = {

  /* SPI-CAN device 0 */
  {
    .modalias = "mcp2515",            /* chip controller to use (MCP2510 also works) */
    .platform_data = &mcp251x_info,
    .max_speed_hz  = 2 * 1000 * 1000, /* max speed of the chip in use */
    .chip_select   = 0,               /* which CS on the SPI bus is used */
    .bus_num = 0,                     /* Tegra SPI1 maps to our SPIO bus #0 */
    .mode = SPI_MODE_0,
  },

  /* SPI-CAN device 1 */
  {
    .modalias = "mcp2515",            /* chip controller to use (MCP2510 also works) */
    .platform_data = &mcp251x_info,
    .max_speed_hz  = 2 * 1000 * 1000, /* max speed of the chip in use */
    .chip_select   = 1,               /* which CS on the SPI bus is used */
    .bus_num = 0,                     /* Tegra SPI1 maps to our SPIO bus #0 */
    .mode = SPI_MODE_0,
  },
};

static int __init mcp251x_init(void)
{

  int status;

  mcp251x_spi_board[0].irq = gpio_to_irq(SPI0_INT_GPIO);
  mcp251x_spi_board[1].irq = gpio_to_irq(SPI1_INT_GPIO);

  status = spi_register_board_info(mcp251x_spi_board, ARRAY_SIZE(mcp251x_spi_board));
  printk(KERN_DEBUG "mcp251x_init: spi_register_board_info retval: %d", status);

  return 0;
}

/* snip */

static void __init tegra_t210ref_late_init(void)
{
  /* snip */

  #ifdef CONFIG_CAN_MCP251X
    mcp251x_init();
  #endif
}

The Question
How can I fix CS1 so that it behaves properly and resolves the SPI1 bus contention?

References

https://devtalk.nvidia.com/default/topic/998947/jetson-tx1/guide-to-enabling-mcp251x-on-the-tx1-spi-/
https://devtalk.nvidia.com/default/topic/915614/jetson-tx1/did-anybody-get-spi-interface-working-on-tx1-/
https://devtalk.nvidia.com/default/topic/974743/jetson-tx1/configuring-a-can-bus-with-mcp2515-over-spi-in-tx1/1
https://turlucode.com/nvidia-jetson-tk1-spi-to-can-interface-mcp251x-mcp25625/
http://elinux.org/Jetson/TX1_SPI

Attachments

  1. spi1_cs_connected_logiccap.png: Shows failure of CS1 to ever deassert
  2. spi1_cs_high_logiccap.png: Shows that when CS1 is tied high, M0 is successfully probed begins communication

spi1_cs_connected_logiccap.png
spi1_cs_high_logiccap.png

Hi
We are go through your issue to see what could the problem be caused.

Thank you for your attention. This is a significant issue for my company and is impacting our product development.

Please let me know if any other information would be helpful.

Hi Slawson

  1. Could you check the pinmux of the spi1_cs1 "sudo cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins | grep -i spi1_cs

  2. Have you ever try connect M1 to CS0 ?

Thank you for your reply ShaneCCC.

  1. Output of “sudo cat /sys/kernel/debug/pinctrl/700008d4.pinmux/pinmux-pins | grep -i spi1_cs”:

    pin 19 (SPI1_CS0_PC3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
    pin 20 (SPI1_CS1_PC4): (MUX UNCLAIMED) (GPIO UNCLAIMED)

  2. Yes, I have connected M1 to CS0. It is probed correctly when I do so, assuming I have also tied M0’s CS high and left CS1 unconnected.

Hi Lawson
I export the spidev0.0 and spidev0.1 and use the spidev_test to send data probe the CS1 I can see the CS1 is working as expect. Below is my test command. Could you verify it.
Also please dump the pin to make sure those pin are’t set as GPIO pin. The bit 0 -4 should be 0 in bank C .

cat /sys/kernel/debug/tegra_gpio

./spidev_test -D /dev/spidev0.1 -s1000000 -g8 -b8 -p0 -n1 -zzz -t

Hi SLawson,

Have you tried the suggestion we provided?
Can it resolve your issue or still a problem on your case?
Please share the the result, then we can help to move it forward.

Thanks

I encountered the same problem on Jetson Nano Dev Kit. I wish that the problem have been fixed after almost 3 years.

BTW, some SPI slave devices cannot function correctly if CS does not return to HIGH, and it looks like a rising CS edge is needed to terminate a read/write transaction correctly. Also one of the SPI slave sensors I used requires initially CS goes from low to high once to switch from I2C mode to SPI mode.