Configure I2C port for the M4 core

Hello,
I have used toradex apalis imx8 customize board. I want to use I2C port for the M4 core [ M41_I2C_SDA and M41.I2C_SCL lines of Pin number 122 and 124 respectively ].
What do I changes in the device tree file and which file ?
How to configure this pin in device tree and What is the I2C bus number of this I2C lines in I2Cdetect tool ?
Please give us solution on this issue as soon as possible.

Hi @dipakshetye,

These pins are defined inside imx8-apalis-v1.1.dtsi:

		/* Apalis UART1_ */
		pinctrl_lpuart1ctrl: lpuart1ctrlgrp {
			fsl,pins = <
				/* Apalis UART1_DTR */
				IMX8QM_M40_I2C0_SCL_LSIO_GPIO0_IO06		0x00000021
				/* Apalis UART1_DSR */
				IMX8QM_M40_I2C0_SDA_LSIO_GPIO0_IO07		0x00000021
				/* Apalis UART1_DCD */
				IMX8QM_M41_I2C0_SCL_LSIO_GPIO0_IO10		0x00000021
				/* Apalis UART1_RI */
				IMX8QM_M41_I2C0_SDA_LSIO_GPIO0_IO11		0x00000021
			>;
		};

Which are assigned to the iomuxc node:

	pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
		    <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
		    <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,
		    <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,
		    <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
		    <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
		    <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,
		    <&pinctrl_sata1_act>, <&pinctrl_sim0_gpios>,
		    <&pinctrl_usdhc1_gpios>;

To disable them, you can remove the group from the iomuxc node:

diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
index 0ece42889af8..631aa3d5d493 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -421,7 +421,7 @@
 	pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
 		    <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
 		    <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,
-		    <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,
+		    <&pinctrl_gpio_usbh_oc_n>,
 		    <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
 		    <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
 		    <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,

This can be done with the device tree or with a device tree overlay, it’s up to you.

I’m not sure they will be visible under I2CDetect since they’re under the M41 domain. Unless you connect the I2C from the M4 to one of the I2C lines of the Cortex-A. In this case, it will appear under the I2C you connected.

Best Regards,
Hiago.

Thank you for reply.
How to check the this I2C bus working?
I connected M41_I2C0_SCL and M41_I2C0_SDA lines to our slave device but let us know how test this bus ?
Please send me the command to check the slave address and read/write data.

Hello,
Please update on this issue.

Hi @dipakshetye ,

Please download the SDK as mentioned here. Inside the SDK you will find various demos including how to use I2C and documentation on how to run examples on your MCU.
I would suggest you to first test by running the hello_world demo. This will confirm that the MCU is up and running.
For pins that you want to use with your MCU, you need to first disable it from the device tree if the pins are already occupied.
You can use device tree overlays to do that.
Let me know if this helps.

Hello,
Thanks for your reply.
I configured the I2 port for the M4 core in device tree as per your suggestion.
I connected this I2C port lines to my other slave device, now I want to test this I2C port is working or not.
Please send me the test code to test this lines and what is the filename of this I2C port like “/dev/i2c-xx” ?
Please send me the sample test for this.

Hi @dipakshetye ,
You need to download the demos from the nxp website . You need to select your SDK as mentioned here (see “get the freeros source code”).
Again, I will suggest you to first run a hello-world demo on your mcu before running I2C demo

Thank you for your reply.
I download the SDK from link given by you but I have some confusion which application I have use for test I2C 2 port for the M4 core ?
Can you share me the proper steps to test I2C port using SDK application ?

Hi @dipakshetye ,
The demos are inside the SDK package.
eg hello_world demo
SDK\boards\mekmimx8qm\demo_apps\hello_world
i2c_Demos
SDK\boards\mekmimx8qm\driver_examples\lpi2c
SDK\boards\mekmimx8qm\rtos_examples
Documentation
SDK\docs

Please understand that there can not be 2 seperate demo for I2C1 and I2C2. its the pin configuration you need to change accordingly.

See how to run the demos

note : demos are not developed and tested by toradex

Hi Team,

I am using the same hardware platform and am currently working on porting from Dunfell to Scarthgap.

My use case involves communicating with the M4 core via RPMsg, where the M4 core subsequently communicates with peripheral devices over I2C.

On Dunfell, I am able to successfully communicate with the I2C peripherals from a Linux application through the M4 core.

With Scarthgap, the startup process appears to complete successfully; however, I am currently investigating whether the RPMsg communication path is functioning correctly.

Any guidance or suggestions would be greatly appreciated.

  1. Rpmsg display in sys path

root@apalis-imx8-07106399:~# ls -l /dev/rpmsg*

crw-rw---- 1 root rpmsg 253, 4 Sep 20 10:44 /dev/rpmsg0

crw-rw---- 1 root rpmsg 253, 0 Sep 20 10:44 /dev/rpmsg_ctrl0

crw-rw---- 1 root rpmsg 253, 1 Sep 20 10:44 /dev/rpmsg_ctrl1

crw-rw---- 1 root rpmsg 253, 2 Sep 20 10:44 /dev/rpmsg_ctrl2

crw-rw---- 1 root rpmsg 253, 3 Sep 20 10:44 /dev/rpmsg_ctrl3

  1. Find the kernel log below

imx-rpmsg 90000000.rpmsg0: assigned reserved memory node vdevbuffer@90400000

virtio_rpmsg_bus virtio0: rpmsg host is online

mmc0: new HS400 MMC card at address 0001

mmcblk0: mmc0:0001 S0J56X 14.8 GiB

virtio_rpmsg_bus virtio1: rpmsg host is online

mmcblk0: p1 p2

imx-rpmsg 90100000.rpmsg1: assigned reserved memory node vdevbuffer@90400000

mmcblk0boot0: mmc0:0001 S0J56X 31.5 MiB

virtio_rpmsg_bus virtio2: rpmsg host is online

mmcblk0boot1: mmc0:0001 S0J56X 31.5 MiB

virtio_rpmsg_bus virtio3: rpmsg host is online

When I try to communicate to m4 core I encounter below error

rpmsg_ctrl virtio3.rpmsg_ctrl.0.0: virtqueue_add_outbuf failed: -5

Below are the code changes I made

1. Board Hardware & Peripheral Configuration (Device Tree)

I2C3 Clock Frequency Increase - Increases &i2c3 bus speed from 100 kHz to 400 kHz (Fast Mode).

— a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi

/* Apalis I2C1 */
@@ -468,7 +471,8 @@ &i2c3 {
pinctrl-0 = <&pinctrl_lpi2c3>;
#address-cells = <1>;
#size-cells = <0>;

  •    clock-frequency = <100000>;
    
  •    clock-frequency = <400000>;
    
  •    status = "okay";
    

};

Pin Muxing Conflict Fix - Removes &pinctrl_lpuart1ctrl from &iomuxc default pinctrl group to resolve signal conflicts on pin multiplexing lines.

— a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -1028,7 +1028,8 @@ &iomuxc {
pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
<&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
<&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,

  •                <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,
    
  •                /\*<&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,\*/
    
  •                    <&pinctrl_gpio_usbh_oc_n>,
                   <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
    

2. Dual-Core Inter-Processor Communication (RPMsg & Mailbox DTS)

Dual Cortex-M4 RPMsg Node Definitions - Defines RPMsg nodes (rpmsg0 and rpmsg1) targeting messaging units &lsio_mu5 (partition 3) and &lsio_mu6 (partition 4), with reserved memory references (0x90000000 & 0x90100000).

— a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -133,6 +133,39 @@ reg_vref_1v8: regulator-vref-1v8 {
regulator-max-microvolt = <1800000>;
};

  •    rpmsg0: rpmsg0{
    
  •            compatible = "fsl,imx8qm-rpmsg";
    
  •            mbox-names = "tx", "rx", "rxdb";
    
  •            mboxes = <&lsio_mu5 0 1
    
  •                      &lsio_mu5 1 1
    
  •                      &lsio_mu5 3 1>;
    
  •            mub-partition = <3>;
    
  •            vdev-nums = <2>;
    
  •            reg = <0x0 0x90000000 0x0 0x20000>;
    
  •            memory-region = <&vdevbuffer>;
    
  •            status = "okay";
    
  •    };
    
  •    rpmsg1: rpmsg1{
    
  •            compatible = "fsl,imx8qm-rpmsg";
    
  •            mbox-names = "tx", "rx", "rxdb";
    
  •            mboxes = <&lsio_mu6 0 1
    
  •                      &lsio_mu6 1 1
    
  •                      &lsio_mu6 3 1>;
    
  •            mub-partition = <4>;
    
  •            vdev-nums = <2>;
    
  •            reg = <0x0 0x90100000 0x0 0x20000>;
    
  •            memory-region = <&vdevbuffer>;
    
  •            status = "okay";
    
  •    };
    

Shared VirtIO DMA Memory Pools - Configures reserved non-cacheable DMA shared vring memory regions (vdev0vring0 to vdev3vring1) for bidirectional M4 communication.

— a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -169,6 +199,48 @@ rpmsg_reserved: rpmsg@90200000 {
no-map;
};

  •            vdev0vring0: vdev0vring0@90000000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90000000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev0vring1: vdev0vring1@90008000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90008000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev1vring0: vdev1vring0@90010000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90010000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev1vring1: vdev1vring1@90018000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90018000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev2vring0: vdev0vring0@90100000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90100000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev2vring1: vdev0vring1@90108000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90108000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev3vring0: vdev1vring0@90110000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90110000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    
  •            vdev3vring1: vdev1vring1@90118000 {
    
  •                    compatible = "shared-dma-pool";
    
  •                    reg = <0 0x90118000 0 0x8000>;
    
  •                    no-map;
    
  •            };
    

Hardware Mailboxes Activation (&lsio_mu5 & &lsio_mu6) - Enables Messaging Unit mailbox nodes (lsio_mu5 and lsio_mu6) for M4 IPC interrupt signaling.

— a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -345,6 +345,14 @@ touchscreen: touchscreen {

};

+&lsio_mu5 {

  • status = “okay”;
    +};

+&lsio_mu6 {

  • status = “okay”;
    +};

3. RPMsg / VirtIO Buffer Sizing (Kernel Drivers)

Increases single packet payload capacity from 512 bytes to 2048 bytes while decreasing buffer count from 512 to 128 in both i.MX RPMsg and VirtIO RPMsg drivers.

— a/drivers/rpmsg/imx_rpmsg.c
+++ b/drivers/rpmsg/imx_rpmsg.c
@@ -70,8 +70,8 @@ struct imx_rpmsg_vproc {
*/
#define REMOTE_READY_WAIT_MAX_RETRIES 500

-#define RPMSG_NUM_BUFS (512)
-#define RPMSG_BUF_SIZE (512)
+#define RPMSG_NUM_BUFS (128)
+#define RPMSG_BUF_SIZE (2048)

— a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -127,8 +127,8 @@ struct virtio_rpmsg_channel {
* can change this without changing anything in the firmware of the remote
* processor.
*/
-#define MAX_RPMSG_NUM_BUFS (512)
-#define MAX_RPMSG_BUF_SIZE (512)
+#define MAX_RPMSG_NUM_BUFS (128)
+#define MAX_RPMSG_BUF_SIZE (2048)

4. RPMsg & VirtIO Error Diagnostics (Kernel Drivers)

Mailbox Failure Logging in imx_rpmsg.c - Logs error message with exact error code whenever mbox_send_message() fails in imx_rpmsg_notify().

— a/drivers/rpmsg/imx_rpmsg.c
+++ b/drivers/rpmsg/imx_rpmsg.c
@@ -132,13 +132,17 @@ static bool imx_rpmsg_notify(struct virtqueue *vq)
rpdev->first_notify–;
rpdev->cl.tx_tout = 20;
ret = mbox_send_message(rpdev->tx_ch, &rpvq->mmsg);

  •            if (ret < 0)
    
  •            if (ret < 0) {
    
  •                    dev_err(&rpdev->pdev->dev, "failed to send mailbox message: %d\\n", ret);
                       return false;
    
  •            }
       } else {
               rpdev->cl.tx_tout = 1000;
               ret = mbox_send_message(rpdev->tx_ch, &rpvq->mmsg);
    
  •            if (ret < 0)
    
  •            if (ret < 0) {
    
  •                    dev_err(&rpdev->pdev->dev, "failed to send mailbox message: %d\\n", ret);
                       return false;
    
  •            }
       }
    

Virtqueue Notify Failure Logging in virtio_ring.c - Adds explicit dev_err() logging identifying the specific virtqueue name when virtqueue_notify() fails right before marking vq->broken = true.

— a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2367,6 +2367,8 @@ bool virtqueue_notify(struct virtqueue *_vq)

     /\* Prod other side to tell it about changes. \*/
     if (!vq->notify(\_vq)) {
  •            dev_err(&vq->vq.vdev->dev,
    
  •                    "virtqueue_notify failed for virtqueue %s\\n", vq->vq.name);
               vq->broken = true;
               return false;
       }