SPI based CANFD driver & overlay (MCP2517/MCP2518)

Recommended Posts

Following a successful deployment of an MCP2515 SPI to CAN device with the great help of https://forum.armbian.com/topic/3588-can-bus-support-orange-pi-zero/ I’ve been looking into using an SPI to CANFD device with the orangePi R1 (H2+ based). (CANFD allows greater bitrate than the “regular” CAN)
I am looking into using the driver made for the mcp2517fd/mcp2518fd, which has been submitted but not yet linux mainlined: https://github.com/msperl/linux-rpi/tree/upstream-v5.0-rc3-mcp25xxfd-v6.11/drivers/net/can/spi/mcp25xxfd


This driver seems to be functional with the raspberry pi, and an example of PCB and associated overlay can be seen here: https://github.com/Seeed-Studio/pi-hats/tree/master/CAN-HAT


I’ve been able to compile the drivers successfully (on kernel 4.19.72) and insmod/modprobe them. I also managed to compile the overlays into a dtbo (with dtc v1.4.7 and using -@ argument), but uBoot seems to find some errors in it:


Applying kernel provided DT overlay sun8i-h3-spi1-mcp25xxfd.dtbo
failed on fdt_overlay_apply(): FDT_ERR_BADOVERLAY
Error applying DT overlays, restoring original DT
29943 bytes read in 4 ms (7.1 MiB/s)

Any ideas as to how I could look into debugging this? libfdt (https://github.com/qemu/dtc/blob/master/libfdt/fdt_overlay.c) shows 14 different ways that the dtbo file can fail loading and have FDT_ERR_BADOVERLAY thrown :(


This is my dts:


//#include <dt-bindings/interrupt-controller/irq.h>

/ {
    compatible = "allwinner,sun8i-h3";

    fragment@0 {
        target-path = "/aliases";
        __overlay__ {
            spi1 = "/soc/spi@01c69000";

    /* the interrupt pin of the can-controller */
    fragment@1 {
        target = <&pio>;
        __overlay__ {
            can0_pin_irq: can0_pin_irq {
                allwinner,pins = "PA2";
                allwinner,function = "irq";
                allwinner,drive = <0x0>;
                allwinner,pull = <0x1>;
                linux,phandle = <0x1>;
                phandle = <0x1>;

    /* the clock/oscillator of the can-controller */
    fragment@2 {
        target-path = "/clocks";
        __overlay__ {
            /* external 20M oscillator of mcp2517fd on SPI0.0 */
            mcp2517fd_osc: mcp2517fd_osc {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <0x400000>;
                linux,phandle = <0x2>;
                phandle = <0x2>;

    /* the spi config of the can-controller itself binding everything together */
    fragment@3 {
        //target = <0xffffffff>;
        target = <&spi1>;
        can_overlay:__overlay__ {
            status = "okay";
            /* needed to avoid dtc warning */
            #address-cells = <1>;
            #size-cells = <0>;
            mcp2517fd: mcp2517fd@0 {
                reg = <0>;
                compatible = "microchip,mcp2517fd";
                pinctrl-names = "default";
                pinctrl-0 = <&can0_pin_irq>;
                spi-max-frequency = <10000000>;
                interrupt-parent = <&pio>;
                interrupts = <0 2 8>; /* PA2 / IRQ_TYPE_LEVEL_LOW */
                clocks = <&mcp2517fd_osc>;


Edited by HW_guy
broken link
Link to post
Share on other sites
Armbian is a community driven open source project. Do you like to contribute your code?

Got it to work! :)



[    7.288654] CAN device driver interface
[    7.309697] mcp25xxfd_can: loading out-of-tree module taints kernel.
[   11.562405] mcp25xxfd spi1.0 can0: bitrate error 0.1%


candump and cansend produce expected results against another CAN device on the network. Great!

2 main issues were:

  1. target-path = "/"; (instead of target-path = "/clocks"; )

    1. This solves uBoot FDT_ERR_BADOVERLAY error

  2. clock-frequency = <40000000>; (instead of clock-frequency = <0x400000>; )

    1. This is the clock frequency of the Crystal oscillator on your board. If you get this wrong, you will still see traffic in the CAN bus, it will just be at the wrong bitrate.

Also worth mentioning, if you are testing it against a non FD adapter (e.g. CANable), you should temporarily disabled the FD from the mcp2517/mcp2518 by using "fd off" when setting the interface:

$ip link set can0 up type can bitrate 250000 fd off

There is no need to set the dbitrate if you use fd off. More info about this here: https://www.kernel.org/doc/Documentation/networking/can.txt

Link to post
Share on other sites

I have a similar poblem and I hope you can maybe help me out.

I also wan't to work with a SPI to CANFD device on the Raspberry Pi. The board I'm working is also using the MCP2517FD/MCP2518FD for CAN communication, which is how I stumbled on your thread. Can you maybe walk me through how the compilation of the driver works, since that is where I'm stuck. I haven't been able to get any other drivers I have found for the MCP2517FD to work, which is why I'm hoping this one will.

Thanks in advance 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.