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.

66AK2E05: KEYSTONE II <-> mcp2515 SPI TO CAN BUS controller <-> GPIO / INTERRUPT <-> NOT WORKING

Part Number: 66AK2E05

Hello,

we try to use the mcp2515 (CAN BUS to SPI) chip with no success.

It is connected on the spi1 bus of our ARM processor (KEYSTONE II - 66AK2E05), the interrupt PIN of the chip is connected on the GPIO-5 pin of the CPU too.


We are developing our Software (OS + Apps) using the:

TI ΚΕΥΣΤΟΝΕ ΙΙ - SDK

v06.03.00.106

Linux kernel src:

linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85

I order to enable the specific CAN driver, the following lines has been added to the linux kernel configuration

CONFIG_CAN=y
CONFIG_CAN_MCP251X=m

Also, the following lines has been added ( according to <kernel documentation > )  to our custom board device tree, which is based on keystone-k2e-evm.dts file.

&spi1 {

....

can0: mcp2515@0 {

compatible = "microchip,mcp2515";
reg = <0>;
spi-max-frequency = <1000000>;
clocks = <&canclk>;

interrupt-parent = <&gpio0>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;

}

....

}

&soc0 {

...

canclk: canclk {


compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <8000000>;
clock-output-names = "can-clk";

};

...

}

When building the DTB we get the warning below:

Warning (interrupts_property): /soc@0/gpio@260bf00: Missing interrupt-controller or interrupt-map property
Warning (interrupts_property): /soc@0/gpio@260bf00: Missing #interrupt-cells in interrupt-parent

After booting the system, the `dmesg` command shows 

root@ccm:~# dmesg | grep mcp
[ 11.995130] mcp251x spi1.0 can0: MCP2515 successfully initialized.

Then, we setup our CAN controller with:

ip link set can0 type can bitrate 250000
ip link set up can0

At this point we have to situations:

1) If we do not patch the linux kernel mcp2515 driver

Then, the mcp2515 driver tries to acquire IRQ, but it gets a `0` assigned and it fails.

PS: We also tried adding interrupt-controller and #interrupt-cells properties in gpio0 in DTB but it did not help.

2) If we do patch the linux kernel mcp2515 driver

If we hard code the IRQ assignment (which is not obviously a solution) by adding

mcp251x.c, line ~943, function `static int mcp251x_open(struct net_device *net)` :

int oldIrq = spi->irq;

spi->irq=gpio_to_irq(5);

printk("mcp251x spi->irq: set from %i to %i (IRQ on GPIO-5 PIN)\n",oldIrq,spi->irq);

in the mcp251x.c src file, then the device is showing up as can0 and the `ifconfig can0` command shows:

can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B

Also the `dmesg` command shows 

root@ccm:~# dmesg | grep mcp
[ 11.995130] mcp251x spi1.0 can0: MCP2515 successfully initialized.

...

[ 1758.176391] mcp251x spi->irq: set from 0 to 41 (IRQ on GPIO-5 PIN)

...

Then, from a windows PC, we use a USB to CAN controller in order to send / receive CAN data .

The wire CAN connection between the 2 controllers is checked and it is correct!

By sending data from windows PC to our Linux KEYSTONE II board, the windows CAN controller reports no transmission errors and by running `candump can0` command at the linux side we should see something like:

<< can0 001 [8] 11 22 33 44 55 66 77 88 >>

but we get nothing.

No data are received by the Linux KEYSTONE II board.

Also if we try to send data from the Linux KEYSTONE II board with the `cansend can0 001#1122334455667788` command,

then on the windows PC, using the CAN to USB controller software we see that no data are received too...

In any of the mentioned steps (Loading linux kernel, loading the CAN driver, attempt of sending/receiving data) the linux kernel does not produce any IRQ....

The `cat /proc/interrupts` command shows that at IRQ 41 (hard coded GPIO-5 <-> IRQ in CAN driver  the counter value is always `0`


CPU0 CPU1 CPU2 CPU3
17: 0 0 0 0 GICv2 29 Level arch_timer
18: 619776 613791 609211 618116 GICv2 30 Level arch_timer
21: 0 0 0 0 GICv2 142 Edge timer-keystone
22: 0 0 0 0 GICv2 52 Edge arm-pmu
23: 0 0 0 0 GICv2 53 Edge arm-pmu
24: 0 0 0 0 GICv2 54 Edge arm-pmu
25: 0 0 0 0 GICv2 55 Edge arm-pmu
26: 1 0 0 0 GICv2 36 Edge 26202a0.keystone_irq
27: 9038 0 0 0 GICv2 309 Edge ttyS0
28: 241675 0 0 0 GICv2 312 Edge
29: 8 0 0 0 GICv2 315 Edge 2530000.i2c
30: 0 0 0 0 GICv2 318 Edge 2530400.i2c
31: 0 0 0 0 GICv2 321 Edge 2530800.i2c
32: 110 0 0 0 GICv2 324 Edge 21000400.spi
33: 39 0 0 0 GICv2 328 Edge 21000600.spi
34: 2 0 0 0 GICv2 332 Edge 21000800.spi
35: 0 0 0 0 GICv2 184 Edge 2680000.usb, xhci-hcd:usb1
41: 0 0 0 0 GPIO-AINTC 157 Edge mcp251x
68: 0 0 0 0 GICv2 70 Edge ks-pcie-error-irq
70: 0 0 0 0 GICv2 446 Edge 25000000.usb, xhci-hcd:usb3
71: 0 0 0 0 GICv2 417 Edge ks-pcie-error-irq
80: 0 0 0 0 PCI-MSI 0 Edge PCIe PME, aerdrv
89: 0 0 0 0 PCI-MSI 134217728 Edge PCIe PME, aerdrv
98: 0 0 0 0 GICv2 80 Level hwqueue-528
99: 7882 0 0 0 GICv2 81 Level hwqueue-529
100: 5221 0 0 0 GICv2 82 Level hwqueue-530
101: 0 0 0 0 GICv2 83 Level hwqueue-531
102: 0 0 0 0 GICv2 84 Level hwqueue-532
103: 7859 0 0 0 GICv2 85 Level hwqueue-533
104: 6739 0 0 0 GICv2 86 Level hwqueue-534
105: 0 0 0 0 GICv2 87 Level hwqueue-535
130: 1 0 0 0 keystone-irq 0 Edge 10800000.dsp
131: 0 0 0 0 keystone-irq 8 Edge dsp0
IPI0: 0 0 0 0 CPU wakeup interrupts
IPI1: 0 0 0 0 Timer broadcast interrupts
IPI2: 252323 228722 241768 263646 Rescheduling interrupts
IPI3: 3 7 10 8 Function call interrupts
IPI4: 0 0 0 0 CPU stop interrupts
IPI5: 3 0 1 481 IRQ work interrupts
IPI6: 0 0 0 0 completion interrupts
Err: 0

Debugging info:

With help of an oscilloscope, we observer:

While loading the linux kernel and after loading the mcp251x driver, the GPIO-5 pin value is HIGH (1)

and we also see on the SPI BUS that `some` data are exchanged between the linux kernel and the chip.

After setting up the chip with the following commands,

ip link set can0 type can bitrate 250000
ip link set up can0

we see that the GPIO-5 pin value is changing to LOW (0)

From that point the CAN communication between the windows PC and the Linux board with the mcp251x chip is not responding (no transmission/reception of any data)...

It seems that the Keystone/davinci GPIO driver is not working properly.

Any suggestions/ideas on how we can solve this problem would be appreciated.

Regards,

Ioannis.

 

  • Dear TI Team,

    Do we have any feedback or advice on how to proceed?

    Thank you,

    Daniel

  • Hi Loannis,

    Please refer the device tree bindings in Processor-sdk-linux for K2E under "Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt"


    * Microchip MCP251X stand-alone CAN controller device tree bindings
    
    Required properties:
     - compatible: Should be one of the following:
       - "microchip,mcp2510" for MCP2510.
       - "microchip,mcp2515" for MCP2515.
     - reg: SPI chip select.
     - clocks: The clock feeding the CAN controller.
     - interrupt-parent: The parent interrupt controller.
     - interrupts: Should contain IRQ line for the CAN controller.
    
    Optional properties:
     - vdd-supply: Regulator that powers the CAN controller.
     - xceiver-supply: Regulator that powers the CAN transceiver.
    
    Example:
    	can0: can@1 {
    		compatible = "microchip,mcp2515";
    		reg = <1>;
    		clocks = <&clk24m>;
    		interrupt-parent = <&gpio4>;
    		interrupts = <13 0x2>;
    		vdd-supply = <&reg5v0>;
    		xceiver-supply = <&reg5v0>;
    	};

    For gpio-5,

    	can0: can@1 {
    		compatible = "microchip,mcp2515";
    		reg = <1>;
    		clocks = <&clk24m>;
    		interrupt-parent = <&gpio5>;  // gpio 5
    		interrupts = <13 0x2>;        //13 is CAN interrupt number and 2 is for high-to-low edge triggered
    		vdd-supply = <&reg5v0>;
    		xceiver-supply = <&reg5v0>;
    	};

    Also, please refer to below links for, "Interrupt" and "Interrupt-parent".

    https://elinux.org/Device_Tree_Mysteries#Interrupt_Mapping

    http://billauer.co.il/blog/2012/08/irq-zynq-dts-cortex-a9/

    Thanks,

    Rajarajan U

  • Hi  Rajarajan,

    first of all, thank you for the support.

    As we mention before, the mcp2515 entry in our device tree is:

    can0: mcp2515@0 {

    compatible = "microchip,mcp2515";
    reg = <0>;
    spi-max-frequency = <1000000>;
    clocks = <&canclk>;

    interrupt-parent = <&gpio0>;
    interrupts = <5 IRQ_TYPE_EDGE_FALLING>;

    }

    and the clock definition:

    &soc0 {

    ...

    canclk: canclk {
    compatible = "fixed-clock";
    #clock-cells = <0>;
    clock-frequency = <8000000>;
    clock-output-names = "can-clk";

    };

    ...

    }

    where the `&gpio0` in `interrupt-parent` attribute reference to the entry with the same name (gpio0) in TI device tree, keystone.dtsi.

    (in linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85/arch/arm/boot/dts/keystone.dtsi)

    gpio0: gpio@260bf00 {
    compatible = "ti,keystone-gpio";
    reg = <0x0260bf00 0x100>;
    gpio-controller;
    #gpio-cells = <2>;

    /* HW Interrupts mapped to GPIO pins */
    interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 121 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 122 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 123 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 124 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 128 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 132 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 133 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 134 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 135 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 136 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 137 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 138 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 139 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 145 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 146 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 147 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>,
    <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;

    clocks = <&clkgpio>;
    clock-names = "gpio";
    ti,ngpio = <32>;
    ti,davinci-gpio-unbanked = <32>;

    };

    Also the `5` in `interrupts = <5 IRQ_TYPE_EDGE_FALLING>` declaration refers to GPIO 5 which is the GPIO PIN where we have connected the interrupt of the mcp2515 CAN to SPI chip.

    According to the Keystone II CPU datasheet, the GPIO 5 is described as  BOOTMODE04,  (W30 ball of the SoC) with description:

    "User defined Boot Mode pin. Secondary function for GPIO05"

    The `IRQ_TYPE_EDGE_FALLING` is declared in `linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85//include/dt-bindings/interrupt-controller/irq.h`

    * #define IRQ_TYPE_NONE 0
    * #define IRQ_TYPE_EDGE_RISING 1
    * #define IRQ_TYPE_EDGE_FALLING 2
    * #define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
    * #define IRQ_TYPE_LEVEL_HIGH 4
    * #define IRQ_TYPE_LEVEL_LOW 8

    Is our declaration ok? Is something that we are missing?

    Regards,

    Ioannis.

  • Hi Loannis,

    Please refer following document GPIO configured as Interrupt,

    https://www.ti.com/lit/ug/sprugv1/sprugv1.pdf?ts=1634791867994

    Make sure register settings are as specifed.

    Thanks,

    Rajarajan U