How to use UART4 on iMX8M from Linux User Space
The UART4 on iMX8MM-EVK and iMX8MN-EVK are thinking of debugging the M core which is not usable on Linux user space by default on pre-compiled images.
To use the UART4 on Linux user space you have to do the next modifications on the device tree and atf to assign that peripheral to Linux User Space
https://github.com/nxp-imx/imx-atf/blob/lf_v2.6/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
iMX8MN-EVK
imx8mn_bl31_setup.c
https://github.com/nxp-imx/imx-atf/blob/lf_v2.6/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
/* Master domain assignment */
RDC_MDAn(RDC_MDA_M7, DID1),
/* peripherals domain permission */
- RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
RDC_PDAPn(RDC_PDAP_RDC, D0R | D0W | D1R),
Device tree configurations for iMX8MN-EVK
iMX8MN-EVK.dtsi
https://github.com/nxp-imx/linux-imx/blob/lf-6.1.y/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
assigned-clocks = <&clk IMX8MN_CLK_UART3>;
assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_80M>;
uart-has-rtscts;
status = "okay";
};
+ &uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MN_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_80M>;
+ status = "okay";
+ };
**********************
pinctrl_uart3: uart3grp {
fsl,pins = <
MX8MN_IOMUXC_ECSPI1_SCLK_UART3_DCE_RX 0x140
MX8MN_IOMUXC_ECSPI1_MOSI_UART3_DCE_TX 0x140
MX8MN_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x140
MX8MN_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x140
>;
};
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140
+ MX8MN_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140
+ >;
+ };
iMX8MM-EVK
https://github.com/nxp-imx/imx-atf/blob/lf_v2.6/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
imx8mm_bl31_setup.c
/* Master domain assignment */
RDC_MDAn(RDC_MDA_M7, DID1),
/* peripherals domain permission */
- RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
RDC_PDAPn(RDC_PDAP_RDC, D0R | D0W | D1R),
Device tree configurations for iMX8MM-EVK
iMX8MM-EVK.dtsi
https://github.com/nxp-imx/linux-imx/blob/lf-6.1.y/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
assigned-clocks = <&clk IMX8MM_CLK_UART3>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
uart-has-rtscts;
status = "okay";
};
+ &uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "okay";
+ };
**********************
pinctrl_uart3: uart3grp {
fsl,pins = <
MX8MM_IOMUXC_ECSPI1_SCLK_UART3_DCE_RX 0x140
MX8MM_IOMUXC_ECSPI1_MOSI_UART3_DCE_TX 0x140
MX8MM_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x140
MX8MM_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x140
>;
};
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140
+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140
+ >;
+ };
iMX8MP-EVK
https://github.com/nxp-imx/imx-atf/blob/lf_v2.6/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
imx8mp_bl31_setup.c
RDC_MDAn(RDC_MDA_M7, DID1),
RDC_MDAn(RDC_MDA_LCDIF, DID2),
RDC_MDAn(RDC_MDA_LCDIF2, DID2),
RDC_MDAn(RDC_MDA_HDMI_TX, DID2),
/* peripherals domain permission */
+ RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
RDC_PDAPn(RDC_PDAP_WDOG1, D0R | D0W),
RDC_PDAPn(RDC_PDAP_RDC, D0R | D0W | D1R),
Device tree configurations for iMX8MP-EVK
iMX8MP-EVK.dts
https://github.com/nxp-imx/linux-imx/blob/lf-6.1.y/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
assigned-clocks = <&clk IMX8MP_CLK_UART3>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
fsl,uart-has-rtscts;
status = "okay";
};
+ &uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MP_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ status = "okay";
+ };
************************************
pinctrl_uart3: uart3grp {
fsl,pins = <
MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x140
MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX 0x140
MX8MP_IOMUXC_ECSPI1_SS0__UART3_DCE_RTS 0x140
MX8MP_IOMUXC_ECSPI1_MISO__UART3_DCE_CTS 0x140
>;
};
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x140
+ MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x140
+ >;
+ };
After compiling the image with the changes previously shown, we obtained this result:
From Linux User Space?
What is the case, which is not using /dev/tty* device open in user space?
Bluetooth? Some Bluetooth is also a case open serial port under the /dev/ and sending AT command.
serial device is a device file in the user space.
Should be very few case directly call serial core api in the kernel space.
If it is used in kernel space, it is just another driver calling serial core api?
The concept here is RDC
What is different between change a debug console domain and keep orignal debug console at the same time move another uart4 from M7 domain to A53 domain?
Could be another case and new knowledge?