LAN966x MCAN

SoC Resources

LAN966x SoC supports two instances of CAN-FD(Control Area Network with Flexible Data-Rate) which is compliant with CAN 2.0 Part A and 2.0 Part B.

Kernel configurations

Following kernel config options should be enabled to use LAN966x MCAN:

  • CONFIG_CAN - CAN driver config option.

  • CONFIG_CAN_M_CAN - Bosch MCAN config option.

  • CONFIG_CAN_M_CAN_PLATFORM - Bosch M_CAN support for io-mapped devices.

Devicetree Configuration

To enable MCAN interface, following configurations are required in device tree:

  • compatible string must be set to bosch,m_can.

  • reg property must be set to <0xe081c000 0xfc> and <0x00100000 0x4000> for mcan0, <0xe0820000 0xfc> and <0x00100000 0x8000> for mcan1.

  • reg-names must be set to m_can and message_ram.

  • interrupts property must be set with interrupt details as <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH> and <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>.

MCAN ID Shared Peripheral Interrupt(int0) CPU INTR(int0) Shared Peripheral Interrupt(int1) CPU INR(int1)

mcan0

104

72

106

74

mcan1

105

73

107

75

Note

Shared peripheral interrupt lines start at index ID32. So, CPU INTR must be calculated as [Shared peripheral interrupt number - 32].

  • interrupt-names must be set to int0 and int1.

  • clocks property must be set to <&clks GCK_ID_MCANx>, <&clks GCK_ID_MCANx>, where x is MCAN ID (0-1).

  • clock-names must be set to hclk and cclk.

  • bosch,mram-cfg property must be set to <0x0 0 0 64 0 0 32 32> for mcan0 and <0x4000 0 0 64 0 0 32 32> for mcan1.

  • Verify that CAN_STBY pin of transceiver is set to low. If not, set the GPIO pin mapped to CAN_STBY to low using standby-gpios property as <&gpio 54 GPIO_ACTIVE_HIGH>.

Example

Following example shows how a CAN controller should be defined in DT:

dtsi file:

can0: can@e081c000 {
	compatible = "bosch,m_can";
	reg = <MCAN_0_ADDR MCAN_0_SIZE>, <0x00100000 0x4000>;
	reg-names = "m_can", "message_ram";
	interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
		   <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
	interrupt-names = "int0", "int1";
	clocks = <&clks GCK_ID_MCAN0>, <&clks GCK_ID_MCAN0>;
	clock-names = "hclk", "cclk";
	assigned-clocks = <&clks GCK_ID_MCAN0>;
	assigned-clock-rates = <40000000>;
	bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>;
	status = "disabled";
};

dts file changes:

&can0 {
	pinctrl-0 = <&can0_b_pins>;
	pinctrl-names = "default";
	standby-gpios = <&gpio 54 GPIO_ACTIVE_HIGH>;
	status = "okay";
};

UserSpace

Confirm instances are created

  • Check if can interface is created using ifconifg -a command.

Example on how to use

  • Enable can-utils to send/receive data on CAN interface. Use candump to show received message from the CAN bus and cansend to send message on CAN bus.

Loopback test

# ifconfig -a
bond0     Link encap:Ethernet  HWaddr 92:0D:C6:5E:32:18
          BROADCAST MASTER MULTICAST  MTU:1500  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:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          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)
          Interrupt:36

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  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:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

sit0      Link encap:IPv6-in-IPv4
          NOARP  MTU:1480  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:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 92:0d:c6:5e:32:18 brd ff:ff:ff:ff:ff:ff
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can
4: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
#
# ip link set can0 type can loopback on
#
# ip link show can0
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can
#
# ip link set can0 up type can bitrate 1000000
[  450.113274] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
#
#
# ifconfig can0
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)
          Interrupt:36

# candump can0 &
#
#
# ip link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can
# cansend can0 123#1122334455667788
  can0  123   [8]  11 22 33 44 55 66 77 88
  can0  123   [8]  11 22 33 44 55 66 77 88
#
#
# cansend can0 123#1234123412341234
  can0  123   [8]  12 34 12 34 12 34 12 34
  can0  123   [8]  12 34 12 34 12 34 12 34
#

Two DUT test

Following example is demostrated on Carrier boards(pcb8309).

On Sender DUT
  • Set bitrate of can0 interface.

  • Check if can0 interface is up.

  • Use cansend to send message on CAN bus.

# ifconfig can0
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          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)
          Interrupt:36
#
# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 5e:a3:1f:b8:c5:e3 brd ff:ff:ff:ff:ff:ff
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can
4: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:13:e4:88:b1:21 brd ff:ff:ff:ff:ff:ff
5: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:13:e4:88:b1:22 brd ff:ff:ff:ff:ff:ff
6: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:13:e4:88:b1:23 brd ff:ff:ff:ff:ff:ff
7: eth3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether fe:13:e4:88:b1:24 brd ff:ff:ff:ff:ff:ff
8: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
#
# ip link set can0 up type can bitrate 1000000
[ 1282.198583] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
# ip link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can
#
# cansend can0 5A1#11.22.33.44.55.66.77.88
#
# cansend can0 123#1122334455667788
#
# ifconfig can0
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:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
          RX bytes:0 (0.0 B)  TX bytes:16 (16.0 B)
          Interrupt:36
On Receiver DUT
  • Set bitrate of can0 interface.

  • Check if can0 interface is up.

  • Use candump to receive message sent from Sender on CAN bus.

# ip link set can0 up type can bitrate 1000000
[  174.322126] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
#
# ip link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can
#
#
# candump can0
  can0  5A1   [8]  11 22 33 44 55 66 77 88
  can0  123   [8]  11 22 33 44 55 66 77 88
^C#

# ifconfig can0
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:2 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:16 (16.0 B)  TX bytes:0 (0.0 B)
          Interrupt:36

Verify that message received on Receiver DUT is same as sent from Sender DUT.