CAN device-tree configuration on iMX6ULL

Hello,

I’d like to control a motor through a CAN bus.

Configuration:

Colibri iMX6ULL 512MB Wi-Fi / Bluetooth (IT) 
Viola Plus Carrier Board | V1.2B Plus 
LinuxImageV2.8

I’m using pin 17 and 18 on the X9 connector of the Viola. According to the Colibri datasheet it respectively maps to pin 55 and 63 of its X1 connector.

I have seen in the documentation (can-linux) how to patch a dts file, there is no details for the iMX6ULL though (iMX6 documentation only).

This is the patch I’m using:

diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
index 75ba991..65561d4 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
@@ -102,12 +102,23 @@
 		status = "okay";
 	};
 
-	spidev0: spidev@0 {
-		compatible = "toradex,evalspi";
-		reg = <0>;
-		spi-max-frequency = <23000000>;
-		status = "disabled";
-	};
+	#if 0
+		spidev0: spidev@0 {
+			compatible = "toradex,evalspi";
+			reg = <0>;
+			spi-max-frequency = <23000000>;
+			status = "disabled";
+		};
+	#else
+	  can0: can@1 {
+			compatible = "microchip,mcp2515";
+			reg = <0>;
+			clocks = <&clk16m>;
+			interrupt-parent = <&gpio3>;
+			interrupts = <27 0x2>;
+			spi-max-frequency = <10000000>;
+	   };
+	#endif
 };
 
 &i2c1 {
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
index 36a9dc1..b228d6f 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
@@ -22,9 +22,13 @@
 	};
 };
 
+&flexcan1 {
+  status = "okay";
+};
+
 &iomuxc {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2 &pinctrl_hog_3
+	pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_3
 		&pinctrl_hog_4 &pinctrl_hog_5>;
 
 };

I use &flexcan1 and not &can1 because it would not pass bitbake otherwise. Another helpful documentation page was can-colibri.

I have installed canutils and iproute2.

I did:

root@colibri-imx6ull:~# ip link set can0 up type can bitrate 500000 berr-reporting on

The result of:

root@colibri-imx6ull:~# zcat /proc/config.gz | grep CONFIG_CAN_MCP251X
CONFIG_CAN_MCP251X=m

Which looks fine if I look at:

root@colibri-imx6ull:~# lsmod
Module                  Size  Used by
rfcomm                 34153  2
bnep                   11114  2
usb_f_rndis            15638  2
u_ether                12497  1 usb_f_rndis
mwifiex_sdio           27085  0
mwifiex               269330  1 mwifiex_sdio
btmrvl_sdio            16033  0
btmrvl                 12942  1 btmrvl_sdio
bluetooth             332396  29 btmrvl_sdio,bnep,rfcomm,btmrvl
cfg80211              241241  1 mwifiex
compat                 21291  7 mwifiex,btmrvl_sdio,bluetooth,bnep,rfcomm,mwifiex_sdio,cfg80211
flexcan                 9440  0
mcp251x                10164  0
can_dev                12333  2 flexcan,mcp251x
libcomposite           44338  10 usb_f_rndis
configfs               30885  3 usb_f_rndis,libcomposite

Also:

root@colibri-imx6ull:~# ip -details link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can <BERR-REPORTING> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 
	  bitrate 500000 sample-point 0.866 
	  tq 133 prop-seg 6 phase-seg1 6 phase-seg2 2 sjw 1
	  flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
	  clock 30000000numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 

When it becomes interesting:

root@colibri-imx6ull:~# dmesg | fgrep -i mcp
[   18.465207] mcp251x spi0.0: Cannot initialize MCP2515. Wrong wiring?
[   18.552767] mcp251x spi0.0: Probe failed, err=19

Also:

root@colibri-imx6ull:~# dmesg | fgrep -i can
[    0.173796] i2c i2c-0: can't use DMA, using PIO instead.
[    0.175562] i2c i2c-1: can't use DMA, using PIO instead.
[    1.330437] spi_master spi0: spi_device register error /soc/aips-bus@02000000/spba-bus@02000000/ecspi@02008000/can@1
[    1.348337] spi_master spi0: Failed to create SPI device for /soc/aips-bus@02000000/spba-bus@02000000/ecspi@02008000/can@1
[    4.438634] ubi0: scanning is finished
[   18.324426] CAN device driver interface
[   18.394998] 2090000.can supply xceiver not found, using dummy regulator
[   18.465207] mcp251x spi0.0: Cannot initialize MCP2515. Wrong wiring?
[   18.503948] flexcan 2090000.can: device registered (reg_base=a0bf0000, irq=23)
[ 5434.225234] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready

To test I try to send:

root@colibri-imx6ull:~# cansend can0 1F#1122334455667788
interface = can0, family = 29, type = 3, proto = 1
root@colibri-imx6ull:~#

But at the same time on another window, I get nothing with:

root@colibri-imx6ull:~# candump
interface = can0, family = 29, type = 3, proto = 1

Thanks for reading through this :slight_smile:

Hi

Note that the MCP2515 is a CAN controller which is connected to a CPU over SPI. On the Colibri Evaluation Board we did connect an MCP2515 to the Colibri Module. Its functionality is similar to what the i.MX6ULL provides with its internal FlexCAN controller.

Since the Viola carrier board does not have an MCP2515 it is expected that the driver for it will complain that it can not find the device on the SPI bus. So while the first chunk of your patch does not do any harm, it also does not help your issue with CAN.

I believe you are missing the proper pinmuxing for the FlexCAN1 pins you want to use, e.g. you have to add a pinctrl group to the iomuxc node and you have to use that in your addition to the flexcan1 node.

pinctrl_flexcan1: flexcan1grp{
        fsl,pins = <
                MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX   0x1b020
                MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX   0x1b020
        >;
};

&flexcan1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_flexcan1>;
        status = "okay";
};

Additionally you must ensure that the two pins now assigned to flexcan1 are not claimed by another driver.
Both pins are currently part of the pinctrl_hog_1 group, so you either have to remove the two pins from the pinctrl_hog_1 group or you have to remove the whole group from the iomuxc’s pinctrl-0 property. (Note that in your patch you removed pinctrl_hog_2, something not needed to get FlexCAN1 working.)

Max

P.S. I guess you are aware that signals from the FlexCAN controller need a CAN transceiver. Example schematics can be found on the Colibri Evaluation Board.

Hello @max.tx,

First, your answer was spot on, thank you very much.

Second, yes we have a MCP2561 transceiver between the Viola TX/RX and the motor CAN low/high.

Finally, out of interest I have a quick question. I don’t get why we have to remove those two pins from the group.

If I look at the imx6ul-pinfunc.h file they look different:

#define MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX		0x00c4 0x0350 0x0000 4 0
#define MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00		0x00c4 0x0350 0x0000 5 0
#define MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX		0x00c8 0x0354 0x0584 4 1
#define MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01		0x00c8 0x0354 0x0000 5 0

For future reference here is the patch I used:

diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
index 36a9dc1..2fff058 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
@@ -22,6 +22,12 @@
 	};
 };
 
+&flexcan1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2 &pinctrl_hog_3
diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/imx6ull-colibri.dtsi
index 25aad26..14529df 100644
--- a/arch/arm/boot/dts/imx6ull-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri.dtsi
@@ -224,8 +224,8 @@
 	imx6ull-colibri {
 		pinctrl_hog_1: hoggrp-1 {
 			fsl,pins = <
-				MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00	0x74 /* SODIMM 55 */
-				MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01	0x74 /* SODIMM 63 */
+				// MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00	0x74 /* SODIMM 55 */
+				// MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01	0x74 /* SODIMM 63 */
 				MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25	0X14 /* SODIMM 77 */
 				MX6UL_PAD_JTAG_TCK__GPIO1_IO14		0x14 /* SODIMM 99 */
 				MX6UL_PAD_NAND_CE1_B__GPIO4_IO14	0x14 /* SODIMM 133 */
@@ -313,6 +313,13 @@
 			>;
 		};
 
+		pinctrl_flexcan1: flexcan1grp{
+			fsl,pins = <
+				MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX   0x1b020
+				MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX   0x1b020
+			>;
+		};
+
 		pinctrl_flexcan2: flexcan2grp {
 			fsl,pins = <
 				MX6UL_PAD_ENET1_TX_DATA0__FLEXCAN2_RX	0x1b020

Hi

Great that it works!

To answer your follow up question:

 #define MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX        0x00c4 0x0350 0x0000 4 0
 #define MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00        0x00c4 0x0350 0x0000 5 0

Both definitions relate to the pin settings of the PAD_ENET1_RX_DATA0. The first one if you want to use the pin with the FLEXCAN1_TX functionality, the second when you want to use it with the GPIO2_IO00 functionality.

So if you do not remove the two pins from the pinctrl-hog1 both the iomuxc and the flexcan driver would request these two pins. The first one to request them will get them, the second driver will be denied the pins and thus will not be instantiated.

Max

Thanks, once again, for your time.

Mathieu

You are welcome.
Best regards.