Interface SPI to CAN controller MCP2515

Hello,

I’m trying to interface CAN chip MCP2515 with Nano. I’m using L4T 32.2.1.
There are two SPI buses out from Nano that are connected to two MCP2515 on our carrier.
I’ve interfaced MCP2515 with TX1, TX2 for our other carriers in the past.
But I’m not able to make progress for Nano. I’ve the following device tree

#include “tegra210-porg-p3448-common.dtsi”
#include “porg-platforms/tegra210-porg-pinmux-p3448-0000-a02.dtsi”
#include “porg-platforms/tegra210-porg-gpio-p3448-0000-a02.dtsi”

/ {
model = “NVIDIA Jetson Nano Developer Kit”;
compatible = “nvidia,jetson-nano”, “nvidia,tegra210”;
nvidia,dtsfilename = FILE;

sdhci@700b0600 { /* SDMMC4 for EMMC */
	status = "okay";
};

sdhci@700b0000 { /* SDMMC1 for SD card */
	status = "okay";
};

spi@70410000 { /* QSPI */
	status = "disabled";
};

can_clock: can_clock{
    compatible = "fixed-clock";
    #clock-cells = <0>;
    clock-frequency = <20000000>;
    clock-accuracy = <100>;
};


spi@7000d400 {
	status = "okay";
	can@0 {
        status = "okay";
        compatible = "microchip,mcp2515";
        reg = <0>;	/* spi chip select 0 */
        clocks = <&can_clock>;
        interrupt-parent = <&gpio>;
            /* the first cell defines the
                index of the interrupt within the controller, while the second cell is used
                to specify any of the following flags:
                - bits[3:0] trigger type and level flags
                1 = low-to-high edge triggered
                2 = high-to-low edge triggered
                4 = active high level-sensitive
                8 = active low level-sensitive
            */
		interrupts = <TEGRA_GPIO(P, 6) 0x01>; 
		vdd-supply = <&battery_reg>;
		xceiver-supply = <&battery_reg>;
		spi-max-frequency=<24000000>;
		
	};
};

spi@7000d600 {
	status = "okay";
	can@0 {
        status = "okay";
        compatible = "microchip,mcp2515";
        reg = <0>;	/* spi chip select 0 */
        clocks = <&can_clock>;
        interrupt-parent = <&gpio>;
            /* the first cell defines the
                index of the interrupt within the controller, while the second cell is used
                to specify any of the following flags:
                - bits[3:0] trigger type and level flags
                1 = low-to-high edge triggered
                2 = high-to-low edge triggered
                4 = active high level-sensitive
                8 = active low level-sensitive
            */
		interrupts = <TEGRA_GPIO(P, 2) 0x01>; 
		vdd-supply = <&battery_reg>;
		xceiver-supply = <&battery_reg>;
		spi-max-frequency=<24000000>;
		
	};
};

gpio@6000d000 {
		/* gpio-name for 40-pin header, gpio-name given as COL(10) x ROW(20) */
		gpio-line-names = "",   "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "SPI1_MOSI",    "SPI1_MISO",    "SPI1_SCK",     "SPI1_CS0",     "SPI0_MOSI",    "SPI0_MISO",    "SPI0_SCK",     "SPI0_CS0",
		"SPI0_CS1",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "GPIO13",      "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"UART1_RTS",    "UART1_CTS",    "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "I2S0_FS",    "I2S0_DIN",    "I2S0_DOUT",   "I2S0_SCLK",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "GPIO01",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "GPIO07",   "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "GPIO12",       "",     "",     "",     "",     "",
		"GPIO11",      "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "GPIO09",     "",     "",     "",
		"",     "",     "",     "",     "",     "",     "",     "",     "",     "",
		"",     "",     "SPI1_CS1",     "",     "",     "",     "",     "",     "",     "";
};

};

I see the following in the dmesg due to SPI transaction fail during driver probe.

[ 1.073870] mcp251x spi0.0: Cannot initialize MCP2515. Wrong wiring?
[ 1.080343] mcp251x spi0.0: Probe failed, err=19
[ 1.095922] mcp251x spi1.0: Cannot initialize MCP2515. Wrong wiring?
[ 1.102326] mcp251x spi1.0: Probe failed, err=19

I’ve a scope connected to SPI clock and data to see the transaction and I see no activity.
So, the bus is not prepared properly in device tree for SPI transaction.

Any help is appreciated.

Thanks,
Hakim

You can reference to below link to update the bootloader to make sure the PIN is correct.

Hi,

Pins you are using for SPI is GPIO configured, Please make them to have SPI functionality then try the setup.
Btw, can you please share steps you have used to communicate MCP with TX1/TX2?

Thanks,
Shubhi

The devkit pin configuration in Tx1/TX2 was configured as SPI for uboot and in even kernel DT, I didn’t have to do anything for them. It was natural expectation to be like this for Nano as well.

Have a confirm the GPIO by below command

sudo cat /sys/kernel/debug/tegra_gpio

Thanks, I got both MCP2515 working, only change I had to make is to adjust the SPI frequency to match with MCP2515.

Hi hj-ca,

I am debugging the same setup (MCP with Jetson) but unfortunately am not able to communicate. Can you please share your SW changes you have done and what all frequencies you have set? What extra things you have to do.

Thanks,
Shubhi

You’ll need to hook-up a scope to see whether all signals are working, SPI clock should be spi-max-frequency=<10000000> as per datasheet of mcp2515; then you’ll need to ensure CS signal to bracket data line, then the interrupt line needs to be checked. For all of these, correct GPIO for CS, interrupt etc. will need to be enabled both in u-boot and kernel dtb. This is what I’ve done.

can_clock: can_clock{
compatible = “fixed-clock”;
#clock-cells = <0>;
clock-frequency = <20000000>;
clock-accuracy = <100>;
};
spi@7000d400 { /* SPI 1 to 40 pin header /
status = “okay”;
num-cs = <1>;
cs-gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
can@0 {
status = “okay”;
compatible = “microchip,mcp2515”;
reg = <0>; /
spi chip select 0 /
clocks = <&can_clock>;
interrupt-parent = <&gpio>;
/
the first cell defines the
index of the interrupt within the controller, while the second cell is used
to specify any of the following flags:
- bits[3:0] trigger type and level flags
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
*/
interrupts = <TEGRA_GPIO(H, 6) 0x01>;
vdd-supply = <&battery_reg>;
xceiver-supply = <&battery_reg>;
spi-max-frequency=<10000000>;
controller-data {
nvidia,cs-setup-clk-count = <0x1e>;
nvidia,cs-hold-clk-count = <0x1e>;
nvidia,rx-clk-tap-delay = <0x1f>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
};

Hi hj-ca,
Did you make some change to mcp251x.ko driver file. Is interrupt pin pre defined on <&gpio 19 GPIO_ACTIVE_LOW>. Mine other question is about clock frequency. Mine mcp2515 is clone one and it has 8MHZ oscillator. Therefore I adjust the clock frequency 16M and spi-max-frequency =8M. Do you have any comment for that.