BSP Reference Manual - phyCORE-i.MX 8M (L-1001e.Ax)
Document TitleBSP Reference Manual - phyCORE-i.MX 8M (L-1001e.Ax)
Document TypeBSP Manual
Yocto PageL-813e.A10 Yocto Reference Manual
Article NumberL-1001e.Ax
Release Date
Is Branch ofBSP Reference Manual - phyCORE-i.MX 8M (L-1001e.Ax) Head


Yocto Introduction

Please read the L-813e.A10 Yocto Reference Manual for a better understanding of Yocto and this BSP. Furthermore, the meta-yogurt layer cannot be used for the alpha release. Look at the NXP documentation i.MX Yocto Project User's Guide for more information.

PHYTEC Documentation

PHYTEC will provide a variety of hardware and software documentation for all of our products. This includes any or all of the following:

On top of these standard manuals and guides, PHYTEC will also provide Product Change Notifications, Application Notes, and Technical Notes. These will be done on a case-by-case basis. Most of the documentation can be found in the download page of our product: https://www.phytec.de/produkte/system-on-modules/phycore-imx-8m/#downloads/

BSP Introduction

Supported Hardware

This BSP supports the phyBOARD-Polaris with 2GB and 1GB RAM. Visit our web page at https://www.phytec.de/produkt/system-on-modules/phycore-imx-8m-download/. Click the corresponding BSP release and look for the article number of your module in the column "Article Number". Finally, look for the correct machine name in the corresponding cell under "Machine Name".

Building the BSP

This section will guide you through the general build process of the i.MX 8M BSP using the phyLinux script. If you want to use our software without phyLinux and the Repo tool managed environment, you can find all Git repositories at:

git://git.phytec.de  

Used u-boot repository:

git://git.phytec.de/u-boot-imx

Our u-boot is based on the u-boot-imx and adds only a few patches which will be sent upstream in future releases.

Used Linux kernel repository:

git://git.phytec.de/linux-imx

Our i.MX 8M kernel is based on the linux-imx kernel.

To find out which tag is used for a specific board, take a look at your BSP source folder under:

meta-phytec/recipes-bsp/u-boot/u-boot-imx_*.bb 
meta-phytec/dynamic-layers/freescale-layer/recipes-kernel/linux/linux-imx_*.bb

Get the BSP

host$ mkdir ~/yocto
host$ cd ~/yocto
host$ wget https://download.phytec.de/Software/Linux/Yocto/Tools/phyLinux
host$ chmod +x phyLinux
host$ ./phyLinux init

Basic Set-Up

There are a few important steps that have to be done before the main build process.

Finding the Right Software Platform

The i.MX 8M BSP is a unified BSP, which means it supports a set of different PHYTEC carrier boards (CB) with different Systems on Module (SOMs).

Example phyboard-polaris-imx8m-3 machine configuration file:

#@TYPE: Machine                                                                  
#@NAME: phyboard-polaris-imx8m-3                                                 
#@DESCRIPTION: PHYTEC phyBOARD-POLARIS i.MX8M Quad 2GB RAM, 8GB eMMC           
#@ARTICLENUMBERS: PB-02419-100I.A0

Software Platform Selection

host$ ./phyLinux init


host$ ./phyLinux init -p imx8m -r PD21.1.0

Please read the Initialization section for more information.

Starting the Build Process

Refer to Start the Build.

BSP Images

All images generated by Bitbake are deployed to ~/yocto/build/deploy/images/<machine>.

The following list shows, for example, all files generated for the i.MX 8M phyboard-polaris-imx8m-3 machine:

The default Linux image phytec-qt5demo-image will start a Wayland Weston, even if there is no display connected.

System Booting

The default boot source for the i.MX 8M module phyBOARD-Polaris is the eMMC. Boot switch information can be found here: Boot Mode Selection.

To update the software from eMMC, Updating Software.

Booting from eMMC

To boot from eMMC, make sure the BSP image is flashed correctly to the flash. Also the switch S1 POS1 has to be set to OFF. The location of the DIP switch S1 can be found on phyBOARD-Polaris Components.

U-Boot SPL 2020.04 (Aug 23 2021 - 10:39:16 +0000)
PMIC:  PFUZE100 ID=0x10
SoM: PCL-066-1012010I.A0 PCB rev: 3
DDRINFO: start DRAM init
DDRINFO: DRAM rate 3200MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
Normal Boot
Trying to boot from MMC2


U-Boot 2020.04 (Aug 23 2021 - 10:39:16 +0000)

CPU:   i.MX8MD rev2.1 1300 MHz (running at 800 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 49C
Reset cause: POR
Model: PHYTEC phyCORE-i.MX8MQ
       Watchdog enabled
DRAM:  1 GiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
In:    serial
Out:   serial
Err:   serial
flash target is MMC:0
Net:   
Warning: ethernet@30be0000 (eth0) using random MAC address - 22:18:55:70:43:56
eth0: ethernet@30be0000
Fastboot: Normal
Normal Boot

Booting from SD Card

Booting from an SD card is useful in several situations, e.g. if the board does not start anymore due to a damaged bootloader. To boot from an SD card, switch S1 POS1 and POS3 has to be set to ON.

There are two ways to create a bootable SD card. You can either use:
- a single prebuild SD card image, or
- the four individual images (imx-boot, kernel, device tree, and root filesystem)

Single, Prebuild SD Card Image

The first possibility is to use the SD card image built by Bitbake, a tool integrated in Yocto. This image has the ending *.sdcard and can be found under build/deploy/images/<MACHINE>/MACHINENAME>-<MACHINE>.sdcard. It contains all BSP files in correctly preformatted partitions and can be copied to the SD card easily using the single Linux command dd.

The created file phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard is only a link to a file like phytec-qt5demo-image-phyboard-polaris-imx8m-3-<BUILD-TIME>.rootfs.sdcard.


To create your bootable SD card with the dd command, you must have root privileges. Because of this, you must be very careful when selecting the destination device for the dd command! All files on the selected destination device will be erased immediately without any further query! Consequently, having selected the wrong device can also erase your hard drive!

To create your bootable SD card, you must first find out the correct device name of your SD card and possible partitions. Then, unmount the partitions before you start copying the image to the SD card.

Now that you have the device name /dev/<your_device> (e.g. /dev/sde), you can see the partitions which must be unmounted if the SD card is formatted. In this case, you will also find /dev/<your_device> with an appended number (e.g. /dev/sde1) in the output. These represent the partition(s) that need to be unmounted.

host$ umount /dev/<your_device><number>
host$ sudo dd if=<IMAGENAME>-<MACHINE>.sdcard of=/dev/<your_device> bs=1M conv=fsync status=progress
host$ sudo dd if=<IMAGENAME>-<MACHINE>-<BUILD-TIME>.rootfs.sdcard of=/dev/<your_device> bs=1M conv=fsync status=progress

Use the device name (<your_device>) without appended number (e.g. sde) which stands for the whole device. The parameter conv=fsync forces a sync operation on the device before dd returns. This ensures that all blocks are written to the SD card and are not still in memory. The parameter status=progress will print out information on how much data is and still has to be copied until it is finished.

<BUILD-TIME> has the format: YYYYMMDDHHMMSS

example: 
    Date = 22.05.2021
    Time = 08:06:37
    <BUILD-TIME> = 20210522080637

Four Individual Images (imx-boot, kernel image, device tree image, root filesystem)

Option two uses imx-boot and an image (a kernel or device tree image together with the root filesystem) to create a bootable SD card manually.

For this method, a new card must be set up with 2 partitions and 8 MB of free space at the beginning of the card. Use the following procedure with fdisk under Linux:

Example:

host$ sudo fdisk -l /dev/sdc
Disk /dev/sdc: 4025 MB, 4025483264 bytes
4 heads, 32 sectors/track, 61424 cylinders, total 7862272 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x26edf128
 
Device Boot      Start         End      Blocks   Id  System
/dev/sdc1         8192       24575        8192    c  W95 FAT32 (LBA)
/dev/sdc2        24576      655359      315392   83  Linux
host$ sudo mkfs.vfat /dev/sde1
host$ sudo mkfs.ext4 -L "rootfs" /dev/sde2

Now, the images need to be copied to the SD card.

host$ dd if=imx-boot-phyboard-polaris-imx8m-3-sd.bin of=/dev/sde bs=1k seek=33 conv=fsync
host$ sudo mount /dev/sd<X>1 /mnt


Make sure that the images are named exactly as previously mentioned as the bootloader expects them to be named as such.

host$ sudo mount /dev/sd<X>2 /media
host$ sudo tar jxf <IMAGENAME>-<MACHINE>.tar.gz -C /media/
host$ sudo umount /media

Booting the Kernel from a Network

Booting from a network means loading the kernel over TFTP and the root filesystem over NFS. The bootloader itself must already be loaded from another boot device that is available.

Host Preparation Developments 

On the development host, a TFTP server must be installed and configured. The following tools will be needed to boot the kernel from Ethernet:

For Ubuntu, install:

host$ sudo apt-get install tftpd-hpa xinetd

After the installation, there are two ways to configure the TFTP server.

TFTP Server Setup

  1. As a stand-alone daemon
  2. Controlled and handled by xinetd
host$ sudo mkdir /tftpboot
host$ sudo chmod -R 777 /tftpboot
host$ sudo chown -R nobody /tftpboot

Then copy your BSP image files to this directory. You also need to configure a static IP address for the appropriate interface. The default IP address of the PHYTEC evaluation boards is 192.168.3.11. So setting 192.168.3.10 with netmask 255.255.255.0 as a host address is a good choice.

host$ ifconfig eth0

You will receive:

eth0	Link encap:Ethernet	 HWadr 00:11:6b:98:e3:47
	 	inet addr:192.168.3.10	Bcast:192.168.3.255 Mask:255.255.255.0

TFTP as a Stand-Alone Daemon

# /etc/default/tftpd-hpa
 
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-s -c"
host$ man tftpd
host$ sudo service tftpd-hpa restart

Usually, TFTP servers are using the /tftpboot directory to fetch files from. If you built your own images, please copy them from the BSP’s build directory to the /tftpboot directory.

We also need a network connection between the embedded board and the TFTP server. The server should be set to IP 192.168.3.10 and netmask 255.255.255.0.

NFS Server Setup

After the installation of the TFTP server, an NFS server needs to be installed, too.

host$ sudo apt-get install nfs-kernel-server

The NFS server is not restricted to a certain file system location, so all we have to do on most distributions is modify the file /etc/exports and export our root filesystem to the embedded network. In this example file, the whole directory is exported and the "lab network" address of the development host is 192.168.3.10. The IP address has to be adapted to the local needs:

/home/<user>/<rootfspath> 192.168.3.11/255.255.255.0(rw,no_root_squash,sync,no_subtree_check)

<user> must be replaced with your home directory name.
<rootfspath> can be set to a folder that contains a rootfs tar.gz image extracted with sudo.

Now the NFS-Server has to read the /etc/expots file again:

host$ sudo exportfs -ra

Embedded Board Preparations

u-boot=> printenv ipaddr serverip netmask nfsroot ethaddr netargs netboot

With your development host set to IP 192.168.3.10 and netmask 255.255.255.0, the target should return:

ipaddr=192.168.3.11
serverip=192.168.3.10
netmask=255.255.255.0
nfsroot=/nfs
ethaddr=xx:xx:xx:xx:xx:xx
netargs=setenv bootargs console=${console} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; run netargs;  if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fdt} = yes || te
u-boot=> setenv <parameter> <value>

The changes you made are temporary for now. To save these:

u-boot=> saveenv

Here you can also change the IP address to DHCP instead of using a static one.

u-boot=> setenv ip dhcp
u-boot=> setenv nfsroot /home/user/nfssrc

Please note that these modifications will only affect the bootloader settings.

Booting from an Embedded Board

u-boot=> run netboot

Updating Software

In this chapter, we explain how to use the u-boot bootloader on target or Linux on target/host to update the images in eMMC.

Updating from Network

i.MX 8M boards have an Ethernet connector and can be updated over a network. Be sure to set up the development host correctly. The IP needs to be set to 192.168.3.10, the netmask to 255.255.255.0, and a TFTP server needs to be available. From a high-level point of view, an eMMC device is like an SD card. Therefore, it is possible to flash the image <name>.sdcard from the Yocto build system directly to the eMMC. The image contains the imx-boot, kernel, device trees, and root filesystem.

Updating eMMC from Network in u-boot on Target

These steps will show how to update the eMMC via a network, but they only work if the size of the image file is less than 1GB. If the image file is larger, go to Updating eMMC from SD card in Linux on Target. Configure the boot switch to boot from SD Card (Switch S1 is ON) and put in an SD card. Power on the board and stop in u-boot.

A working network is necessary!

 u-boot=> tftp ${loadaddr} phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard
 Using ethernet@30be0000 device
 TFTP from server 192.168.3.10; our IP address is 192.168.3.11
 Filename 'small_test-image.sdcard'.
 Load address: 0x43000000
 Loading: #################################################################
          #################################################################
          #################################################################
          ...
          ...
          ...
          #################################################################
          #################################################################
          ######################
          20.3 MiB/s
 done
 Bytes transferred = 524288000 (1f400000 hex)
u-boot=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
u-boot=> mmc write ${loadaddr} 0x0 0xFA000

MMC write: dev # 0, block # 0, count 1024000 ... 1024000 blocks written: OK

Updating eMMC from USB in u-boot on Target

These steps will show how to update the eMMC via a USB device, but they only work if the size of the image file is less than 2GB. If the image file is larger, go to the section Updating eMMC from SD Card in Linux on Target. Configure the boot switch to boot from SD Card (Switch S1 is ON) and put in an SD card. Power on the board and stop in u-boot. Insert a USB device with the proper *.sdcard image to the micro USB slot.

u-boot=> usb start
starting USB...
USB0:   USB EHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
u-boot=> fatload usb 0:1 ${loadaddr} *.sdcard
497444864 bytes read in 31577 ms (15 MiB/s)
u-boot=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
u-boot=> mmc write ${loadaddr} 0x0 0xFA000
 
MMC write: dev # 0, block # 0, count 1024000 ... 1024000 blocks written: OK
u-boot=> setenv mmcdev 0
u-boot=> boot

Updating eMMC via Network in Linux on Target

You can update the eMMC from your target.

A working network is necessary!

target$ ssh <USER>@192.168.3.10 "dd if=<path_to_file>/phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard" | dd of=/dev/mmcblk0

Updating eMMC in Linux on Host

It is also possible to update the eMMC from your Linux host. As before, you need a complete image on your host.

A working network is necessary!

host$ ls
phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard
host$ dd if=phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard status=progress | ssh root@192.168.3.11 "dd of=/dev/mmcblk0"

Updating eMMC from SD Card

Even if there is no network available, you can update the eMMC. For that, you only need a ready-to-use image file (*.sdcard) located on SD card. Because the image file is quite large, you have to enlarge your SD card to use its full space (if it was not enlarged before). To enlarge your SD card, see Resizing ext4 Root Filesystem.

Updating eMMC from SD Card in u-boot on Target

Configure SD Card for Flashing

First, we create a new partition on the SD card to store the image.

host$ dmesg | tail
...
[30436.175412] sd 4:0:0:0: [sdb] 62453760 512-byte logical blocks: (32.0 GB/29.8 GiB)
[30436.179846]  sdb: sdb1 sdb2
...
host$ sudo fdisk /dev/sdb
Welcome to fdisk (util-linux 2.27.1).                                                  
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
 
Command (m for help): p
Disk /dev/sdb: 29,8 GiB, 31976325120 bytes, 62453760 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xd28c31b9
 
Device     Boot Start     End Sectors  Size Id Type
/dev/sdb1       16384   81919   65536   32M  c W95 FAT32 (LBA)
/dev/sdb2       81920 3375103 3293184  1,6G 83 Linux
 
Command (m for help): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3): 3
First sector (2048-62453759, default 2048): 3440640
Last sector, +sectors or +size{K,M,G,T,P} (3440640-62453759, default 62453759): 

Created a new partition 3 of type 'Linux' and of size 28,1 GiB.

Command (m for help): t
Partition number (1-3, default 3): 3
Partition type (type L to list all types): c
 
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.
 
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
host$ sudo mkfs.vfat -n "data" /dev/sdb3 
mkfs.fat 3.0.28 (2015-05-16)
mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows
host$ sudo mount /dev/sdb3 /mnt
host$ sudo cp phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard /mnt/ ; sync

Flash eMMC from u-boot

This step only works if the size of the image file is less than 1GB. If the image file is larger, go to Updating eMMC from SD Card in Linux on Target.

u-boot=> fatload mmc 1:3 ${loadaddr} small_test-image.sdcard
reading small_test-image.sdcard
524288000 bytes read in 22334 ms (22.4 MiB/s)
 
u-boot=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
u-boot=> mmc write ${loadaddr} 0x0 0xFA000   
number of blocks to write. In this case 524288000 bytes / 512 = 0xFA000

MMC write: dev # 0, block # 0, count 1024000 ... 1024000 blocks written: OK
u-boot=> reset	  
...	  
u-boot=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
u-boot=> mmc part	 
Partition Map for MMC device 0  --   Partition Type: DOS
 
Part    Start Sector    Num Sectors          UUID        Type
  1       16384           65536           c4792a6c-01     0c
  2       81920           3506176         c4792a6c-02     83

Updating eMMC from SD Card in Linux on Target

You can also update the eMMC under Linux. You only need a complete image saved on the SD card (e.q. phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard).

target$ ls
phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard
target$ ls /dev | grep mmc
mmcblk0
mmcblk0boot0
mmcblk0boot1
mmcblk0p1
mmcblk0p2
mmcblk0rpmb
mmcblk2
mmcblk1p1
mmcblk1p2
target$ dd if=phytec-qt5demo-image-phyboard-polaris-imx8m-3.sdcard of=/dev/mmcblk0 conv=sync

Before this will work, you need to toggle Switch S1 to OFF. If you do not, the board will boot from SD card again.

RAUC

The Robust Auto-Update Controller (RAUC) mechanism is a new addition to Yogurt. PHYTEC has written an online manual on how we have intergraded RAUC into our BSPs (L-1006e.A1 RAUC Update & Device Management Manual)

Device Tree (DT)

Introduction

The following text briefly describes the Device Tree and can be found in the Linux kernel (linux/Documentation/devicetree/usage-model.txt).

"The "Open Firmware Device Tree", or simply Device Tree (DT), is a data structure and language for describing hardware. More specifically, it is a description of hardware that is readable by an operating system so that the operating system doesn't need to hardcode details of the machine.
Structurally, the DT is a tree or acyclic graph with named nodes, and nodes may have an arbitrary number of named properties encapsulating arbitrary data. A mechanism also exists to create arbitrary links from one node to another outside of the natural tree structure.
Conceptually, a common set of usage conventions called 'bindings', is defined for how data should appear in the tree to describe typical hardware characteristics including data busses, interrupt lines, GPIO connections, and peripheral devices."

The kernel is a really good source for a DT introduction. An overview of the device tree data format can be found on the device tree usage page at devicetree.org.

PHYTEC i.MX 8M BSP Device Tree Concept

DT Structure

The module includes file Modul .dtsi which contains all devices which are mounted on the module, such as PMIC and RAM. Devices that come from the i.MX 8M SoC but are just routed down to the carrier board are not part of the Module .dtsi. These devices are included in the Carrierboard .dtsi. The Board .dts includes the carrier board and module nodes. It also adds partition tables and enables all hardware configurable nodes of the carrier board or the module (i.e. the Board .dts shows the special characteristics of the board configuration). For example, there are phyCORE-i.MX 8M SOMs which may or may not have Wifi mounted. The Wifi is enabled (if available) in the Board .dts and not in the Module .dtsi.

The PHYTEC i.MX8MP device trees for the PD21.1.1 release can be found in our linux-imx git repository: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale?h=v5.4.70_2.3.2-phy

Accessing Peripherals

To find out which boards and modules are supported by the release of PHYTEC’s i.MX8 BSP described herein, visit our web page at https://www.phytec.de/produkte/system-on-modules/phycore-imx-8m/ and click the corresponding BSP release. here you can find all hardware supported in the columns "Hardware Article Number" and the correct machine name in the corresponding cell under "Machine Name".

To achieve maximum software re-use, the Linux kernel offers a sophisticated infrastructure that layers software components into board-specific parts. The BSP tries to modularize the kit features as far as possible. This means that when a customized baseboard or even a customer-specific module is developed, most of the software support can be re-used without error-prone copy-and-paste. The kernel code corresponding to the boards can be found in device trees (DT) under linux/arch/arm64/boot/dts/freescale/*.dts*.

In fact, software re-use is one of the most important features of the Linux kernel, especially of the ARM implementation which always has to fight with an insane number of possibilities of the System-on-Chip CPUs. The whole board-specific hardware is described in DTs and is not part of the kernel image itself. The hardware description is in its own separate binary, called the Device Tree Blob (DTB) (section Device Tree (DT)).

Please read section PHYTEC i.MX 8M BSP Device Tree Concept to get an understanding of our i.MX8 BSP device tree model.

The following sections provide an overview of the supported hardware components and their operating system drivers on the i.MX8 platform.

Further changes can be ported upon customer request.

i.MX 8M Pin Muxing

The i.MX 8M SoC contains many peripheral interfaces. In order to reduce package size and lower overall system cost while maintaining maximum functionality, many of the i.MX 8M terminals can multiplex up to eight signal functions. Although there are many combinations of pin multiplexing that are possible, only a certain number of sets called IO sets, are valid due to timing limitations. These valid IO sets were carefully chosen to provide many possible application scenarios for the user.

Please refer to the NXP i.MX 8M Reference Manual for more information about the specific pins and the muxing capabilities:

The IO set configuration, also called muxing, is done in the Device Tree. The driver pinctrl-single reads the DT's node fsl,pins and does the appropriate pin muxing. The following is an example of the pin muxing of the UART1 device in phytec-imx8mq-phyboard-polaris.dtsi:

 pinctrl_uart1: uart1grp {
         fsl,pins = <
                 MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX      0x49
                 MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX      0x49
          >;
 };

The first part of the string MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX names the pad (in this example UART1_RXD). The second part of the string (UART1_DCE_RX) is the desired muxing option for this pad. There is currently no documentation from NXP for pad setting value (hex value on the right).

RS232

The i.MX 8M SoC provides up to 4 UART units. phyBOARD-Pollux has an SP330e multi-protocol transceiver supporting RS-232 and RS-485 connected to UART2. The configuration of the SP330e is done by jumpers on the baseboard. For more information about the setup please refer to the Hardware Manual - UART.

The device tree representation for serial TTYs: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy#n285

RS232

Configuration of the UART interface can be done with stty. For example:

target$ stty -F /dev/ttymxc1 115200 crtscts raw -echo

With a simple echo and cat, basic communication can be tested. Example:

host$ cat /dev/ttyUSB2

Make sure that the baud rate configuration has been done correctly set on the host side as well. Then:

target$ echo 123 > /dev/ttymxc1

The host should print out "123".

Network

Gigabit ethernet is provided by our module and board. All interfaces offer a standard Linux network port which can be programmed using the BSD socket interface. The whole network configuration is handled by the systemd-networkd daemon. The relevant configuration files can be found on the target in /lib/systemd/network/ and also in the BSP in meta-freescale/recipes-core/systemd/system-machine-units.

IP addresses can be configured within *.network files. The default IP address and netmask for eth0 is:

eth0: 192.168.3.11/24

The DT Ethernet setup might be split into two files depending on your hardware configuration: the module DT, and the board-specific DT.

The device tree set up for the FEC ethernet IP core can be found here: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phycore-som.dtsi?h=v5.4.70_2.3.2-phy2#n65

USB Host Controller

The USB controller of the i.MX 8M SoC provides a low-cost connectivity solution for numerous consumer portable devices by providing a mechanism for data transfer between USB devices with a line/bus speed up to 5 Gbps (SuperSpeed 'SS'). The USB subsystem has two independent USB controller cores. Both cores are On-The-Go (OTG) controller cores and capable of acting as a USB peripheral device or a USB host. Each is connected to a USB 2.0 PHY and a USB 3.0 PHY macrocell and supports USB Type-C connectors.

The unified BSP includes support for mass storage devices and keyboards. Other USB-related device drivers must be enabled in the kernel configuration on demand. Due to udev, all mass storage devices connected get unique IDs and can be found in /dev/disks/by-id. These IDs can be used in /etc/fstab to mount the different USB memory devices in different ways.

USB USB3 (host) configuration is in the kernel device tree imx8mq-phyboard-polaris.dtsi. See: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n282

USB OTG

Most PHYTEC boards provide a USB OTG interface. USB OTG ports automatically act as a USB device or USB host. The mode depends on the USB hardware attached to the USB OTG port. If, for example, a USB mass storage device is attached to the USB OTG port, the device will show up as /dev/sda.

USB Device

In order to connect the board's USB device to a USB host port (for example a PC), you need to configure the appropriate USB gadget. With USB configfs you can define the parameters and functions of the USB gadget. The BSP includes USB configfs support as a kernel module.

target$ modprobe libcomposite

Example:

target$ cd /sys/kernel/config/usb_gadget/
target$ mkdir g1
target$ cd g1/
target$ echo "0x1d6b" > idVendor
target$ echo "0x0104" > idProduct
target$ mkdir strings/0x409
target$ echo "0123456789" > strings/0x409/serialnumber
target$ echo "Foo Inc." > strings/0x409/manufacturer
target$ echo "Bar Gadget" > strings/0x409/product
target$ dd if=/dev/zero of=/tmp/file.img bs=1M count=64
target$ cd /sys/kernel/config/usb_gadget/g1
target$ mkdir functions/acm.GS0
target$ mkdir functions/ecm.usb0
target$ mkdir functions/mass_storage.0
target$ echo /tmp/file.img > functions/mass_storage.0/lun.0/fi

- acm: Serial gadget, creates serial interface like /dev/ttyGS0

- ecm: Ethernet gadget, creates ethernet interface, e.g. usb0

- mass_storage: The host can partition, format, and mount the gadget mass storage the same way as any other USB mass storage.

target$ cd /sys/kernel/config/usb_gadget/g1
target$ mkdir configs/c.1
target$ mkdir configs/c.1/strings/0x409
target$ echo "CDC ACM+ECM+MS" > configs/c.1/strings/0x409/configuration
target$ ln -s functions/acm.GS0 configs/c.1/
target$ ln -s functions/ecm.usb0 configs/c.1/
target$ ln -s functions/mass_storage.0 configs/c.1/
target$ cd /sys/kernel/config/usb_gadget/g1
target$ ls /sys/class/udc/
ci_hdrc.0
target$ echo "ci_hdrc.0" >UDC

If your system has more than one USB Device or OTG port, you can pass the right one to the USB Device Controller (UDC).

target$ echo "" > /sys/kernel/config/usb_gadget/g1/UDC

User USB OTG configuration in the kernel device tree imx8mq-phyboard-polaris.dtsi. See: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n287

WLAN

For WLAN and Bluetooth support, we use the Sterling-LWB module from LSR. This module supports 2,4 GHz bandwidth and can be run in several modes, like client mode, Access Point (AP) mode using WEP, WPA, and WPA2 encryption, and more. More information about the module can be found at https://connectivity-staging.s3.us-east-2.amazonaws.com/2019-09/CS-DS-SterlingLWB%20v7_2.pdf


More information about Wlan configuration can be found here: https://www.phytec.de/cdocuments/?doc=kQFvCw#L813e-A9YoctoReferenceManual-ChangingtheWirelessNetworkConfiguration

Enabling WLAN

WLAN is not available with sdcard-boot. It is only usable with emmc-boot and the dip switch POS1 and POS3 to OFF. It is needed to load the devicetree for the Sterling-LWB:

bootloader$ setenv fdt_file imx8mq-phyboard-polaris-rdk-emmc-sterling.dtb

Exchange the oftree with imx8mq-phyboard-polaris-rdk-emmc-sterling.dtb and save it.

bootloader$ saveenv
bootloader$ boot

Bluetooth

Similar to the WLAN, the Bluetooth functionality is only given if the Sterling-DTB is loaded and emmc boot is active. The Bluetooth is connected with the UART2 interface. More information about the module can be found at https://connectivity-staging.s3.us-east-2.amazonaws.com/2019-09/CS-DS-SterlingLWB%20v7_2.pdf. To use Bluetooth, you have to load the firmware manually:

target$ hciconfig hci0 up

target$ hciconfig
 
hci0:   Type: Primary  Bus: UART
        BD Address: 00:25:CA:2F:39:96  ACL MTU: 1021:8  SCO MTU: 64:1
        DOWN 
        RX bytes:668 acl:0 sco:0 events:34 errors:0
        TX bytes:423 acl:0 sco:0 commands:34 errors:0
 
target$ hciconfig -a
 
hci0:   Type: Primary  Bus: UART
        BD Address: 00:25:CA:2F:39:96  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN 
        RX bytes:1392 acl:0 sco:0 events:76 errors:0
        TX bytes:1198 acl:0 sco:0 commands:76 errors:0
 
target$ hciconfig -a
 
hci0:   Type: Primary  Bus: UART
        BD Address: 00:25:CA:2F:39:96  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN 
        RX bytes:3179 acl:8 sco:0 events:104 errors:0
        TX bytes:1599 acl:8 sco:0 commands:85 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
        Link policy: RSWITCH SNIFF 
        Link mode: SLAVE ACCEPT 
        Name: 'phyboard-polaris-imx8m-2'
        Class: 0x200000
        Service Classes: Audio
        Device Class: Miscellaneous, 
        HCI Version: 4.1 (0x7)  Revision: 0x60
        LMP Version: 4.1 (0x7)  Subversion: 0x2209
        Manufacturer: Broadcom Corporation (15)

Now you can scan your environment for visible Bluetooth devices. Bluetooth is not visible during a default startup.

target$ hcitool scan
Scanning ...
       XX:XX:XX:XX:XX:XX       <SSID>

Visibility

To activate visibility:

target$ hciconfig hciX piscan

To disable visibility:

target$ hciconfig hciX noscan

Connecting via Bluetooth

target$ bluetoothctl
[bluetooth]# discoverable on
Changing discoverable on succeeded
[bluetooth]# pairable on
Changing pairable on succeeded
[bluetooth]# agent on
Agent registered
[bluetooth]# default-agent 
Default agent request successful
[bluetooth]# scan on
[NEW] Device XX:XX:XX:XX:XX:XX <name>
[bluetooth]# connect XX:XX:XX:XX:XX:XX

SD / MMC Card

The i.MX 8M alpha release kit supports a slot for Secure Digital Cards and Multi-Media Cards to be used as general-purpose block devices. These devices can be used in the same way as any other block device.

These kinds of devices are hot-pluggable. Nevertheless, you must ensure not to unplug the device while it is still mounted. This may result in data loss!

After inserting an MMC/SD card, the kernel will generate new device nodes in /dev. The full device can be reached via its /dev/mmcblk0 device node. MMC/SD card partitions will show up in the following way:

/dev/mmcblk0p<Y>

<Y> counts as the partition number starting from 1 to the max. count of partitions on this device. The partitions can be formatted with any kind of file system and also handled in a standard manner, e.g. the mount and umount command work as expected.

These partition device nodes will only be available if the card contains a valid partition table (”hard disk” like handling). If no partition table is present, the whole device can be used as a file system (”floppy” like handling). In this case, /dev/mmcblk0 must be used for formatting and mounting. The cards are always mounted as being writable.

DT configuration for the MMC (SD card slot) interface can be found here:

https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris-sdcard.dtsi?h=v5.4.70_2.3.2-phy2#n7

DT configuration for the MMC interface can be found here:

https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phycore-som.dtsi?h=v5.4.70_2.3.2-phy2#n241

eMMC Devices

PHYTEC modules like phyCORE-i.MX 8M are populated with an eMMC memory chip as main storage. eMMC devices contain raw MLC memory cells combined with a memory controller that handles ECC and wear leveling. They are connected via an MMC/SD interface to the i.MX 8M and are represented as block devices in the Linux kernel like SD cards, flash drives, or hard disks.

The electric and protocol specifications are provided by JEDEC (https://www.jedec.org/standards-documents/technology-focus-areas/flash-memory-ssds-ufs-emmc/e-mmc). The eMMC manufacturer's datasheet is relatively short and meant to be read together with the supported version of the JEDEC eMMC standard.

PHYTEC currently utilizes the eMMC chips:

eMMC ChipSizeJEDEC Version
MTFC8GAKAJCN-4M IT8 GB5.0

Extended CSD Register

eMMC devices have an extensive amount of extra information and settings that are available via the Extended CSD registers. For a detailed list of the registers, see manufacturer datasheets and the JEDEC standard.

target$ mmc extcsd read /dev/mmcblk0

You will see:

 =============================================
   Extended CSD rev 1.7 (MMC 5.0)
 =============================================
 
 Card Supported Command sets [S_CMD_SET: 0x01]
 [...]

Enabling Background Operations (BKOPS)

In contrast to raw NAND Flash, an eMMC device contains a Flash Transfer Layer (FTL) that handles the wear leveling, block management, and ECC of the raw MLC cells. This requires some maintenance tasks (for example erasing unused blocks) that are performed regularly. These tasks are called Background Operations (BKOPS).

By default (which depends on the chip), the background operations may or may not be executed periodically which impacts the worst-case read and write latency.

The JEDEC Standard has specified a method since version v4.41 that the host can issue BKOPS manually. See the JEDEC Standard chapter Background Operations and the description of registers BKOPS_EN (Reg: 163) and BKOPS_START (Reg: 164) in the eMMC datasheet for more details.

Meaning of Register BKOPS_EN (Reg: 163) Bit MANUAL_EN (Bit 0):

The mechanism to issue background operations has already been implemented in the Linux kernel since v3.7. You only have to enable BKOPS_EN on the eMMC device (see below for details).

The JEDEC standard v5.1 introduces a new automatic BKOPS feature. It frees the host to trigger the background operations regularly because the device starts BKOPS itself when it is idle (see the description of bit AUTO_EN in register BKOPS_EN (Reg: 163)).

eMMC chips deployed by PHYTEC do not currently support the new standard v5.1. Neither the Linux kernel nor userspace tool mmc support this feature.

target$ mmc extcsd read /dev/mmcblk0 | grep BKOPS_EN

The output will be for example:

Enable background operations handshake [BKOPS_EN]: 0x01
#OR
Enable background operations handshake [BKOPS_EN]: 0x00

Where value 0x00 means BKOPS_EN is disabled and device write performance suffers. Where value 0x01 means BKOPS_EN is enabled and the host will issue background operations from time to time.

target$ mmc bkops enable /dev/mmcblk0
target$ poweroff

and perform a power cycle.


The BKOPS_EN bit is a one-time-programmable only. It cannot be reversed.

eMMC Boot Partitions

An eMMC device contains four different hardware partitions: userboot1boot2, and rpmb.

The user partition is called the User Data Area in the JEDEC standard and is the main storage partition. The partitions boot1 and boot2 can be used to host the bootloader and are more reliable. Which partition the i.MX 8M uses to load the bootloader is controlled by the boot configuration of the eMMC device. The partition rpmb is a small partition and can only be accessed via Trusted Mechanism.

Furthermore, the user partition can be divided into four user-defined General Purpose Area Partitions. An explanation of this feature exceeds the scope of this document. For further information, see the JEDEC Standard chapter "7.2 Partition Management".

Do not confuse eMMC partitions with partitions of a DOS, MBR, or GPT partition table.

The current PHYTEC BSP does not use the extra partitioning feature of eMMC devices. The uboot is flashed at the beginning of the user partition. The uboot environment is placed at a fixed location before the u-boot. An MBR partition table is used to create two partitions, a FAT32 boot, and ext4 rootfs partition. They are located right after the u-boot. The FAT32 boot partition contains the kernel and device tree.

There are two ways to flash the bootloader to one of the two boot partitions and to switch the boot device, either via bootloader or via userspace commands, as shown in the following examples.

1. Via bootloader:

bootloader$ mmc rescan
bootloader$ mmc list
FSL_SDHC: 0
FSL_SDHC: 1 (SD)
bootloader$ mmc dev 0 
switch to partitions #0, OK 
mmc0(part 0) is current device
bootloader$ mmc info
Device: FSL_SDHC
Manufacturer ID: 11
OEM: 100
Name: 008G3
Bus Speed: 52000000
Mode : MMC DDR52 (52MHz)
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 7.3 GiB
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 4 MiB
User Capacity: 7.3 GiB WRREL
Boot Capacity: 8 MiB ENH
RPMB Capacity: 4 MiB ENH
bootloader$ tftp ${loadaddr} ${serverip}:imx-boot-phyboard-polaris-imx8m-3-sd.bin
bootloader$ mmc write ${loadaddr} 0x21 0x990D

- assumed bootloader file size 638910 Bytes = 0x9BFBE
- assumed block length of eMMC 512 Bytes = 0x200
-> size to write to eMMC should be <bootloader file size>/<block length> = 0x9BFBE/0x200 = 0x4E0 (rounded)
-> as wrote before, offset to write bootloader should be 33 blocks = 0x21

2. Via userspace commands:

target$ dd if=<path to bootloader>/imx-boot-phyboard-polaris-imx8m-3-sd.bin of=/dev/mmcblk0 bs=1k seek=33

Reliable Write

There are two different Reliable Write options:

  1. Reliable Write option for a whole eMMC device/partition.
  2. Reliable Write for single write transactions.

Do not confuse eMMC partitions with partitions of a DOS, MBR, or GPT partition table (see the previous section).

The first Reliable Write option can be enabled with the mmc tool:

target$ mmc --help
 
[...]
mmc write_reliability set <-y|-n> <partition> <device>

The second Reliable Write option is the configuration bit Reliable Write Request parameter (bit 31) in command CMD23. It has been used in the kernel since v3.0 by file systems, e.g. ext4 for the journal and user space applications such as fdisk for the partition table. In the Linux kernel source code, it is handled via flag REQ_META.

Conclusion: ext4 file system with mount option data=journal should be safe against power cuts. The file system check can recover the file system after a power failure, but data that was written just before the power cut may be lost. In any case, a consistent state of the file system can be recovered. To ensure data consistency for the files of an application, the system functions fdatasync, or fsync should be used in the application.

Resizing ext4 Root Filesystem

fdisk can be used to expand the root filesystem. The example works for any block device such as eMMC, SD card, or hard disk.

target$ fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbfdf196d
 
Device         Boot Start      End  Sectors  Size  Id  Type
/dev/mmcblk0p1      16384    81919    65536   32M   c  W95 FAT32 (LBA)
/dev/mmcblk0p2      81920  3440639  3358720  1.6G  83  Linux
target$ fdisk /dev/mmcblk0
 
Welcome to fdisk (util-linux 2.28.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbfdf196d
 
Device         Boot Start      End  Sectors  Size  Id  Type
/dev/mmcblk0p1      16384    81919    65536   32M   c  W95 FAT32 (LBA)
/dev/mmcblk0p2      81920  3440639  3358720  1.6G  83  Linux
  
Command (m for help): d
Partition number (1,2, default 2): 2
 
Partition 2 has been deleted.
 
Command (m for help): p
Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbfdf196d

Device         Boot Start   End Sectors Size Id Type
/dev/mmcblk0p1      16384 81919   65536  32M  c W95 FAT32 (LBA)

Command (m for help): n
Partition type
  p   primary (1 primary, 0 extended, 3 free)
  e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-15269887, default 2048): 81920 
Last sector, +sectors or +size{K,M,G,T,P} (81920-15269887, default 15269887): 

Created a new partition 2 of type 'Linux' and of size 7.3 GiB.

Command (m for help): p
Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbfdf196d

Device         Boot Start        End    Sectors   Size  Id  Type
/dev/mmcblk0p1      16384      81919      65536    32M   c  W95 FAT32 (LBA)
/dev/mmcblk0p2      81920   15269887   15187968   7.3G  83  Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

target$

Increasing the file system size can be done while it is mounted. An online resizing operation is performed. But you can also boot the board from an SD card and then resize the file system on the eMMC partition while it is not mounted. Furthermore, the board has to be rebooted so that the new partition table will be read.

Erasing the Device

It is possible to erase the eMMC device directly rather than overwriting it with zeros. The eMMC block management algorithm will erase the underlying MLC memory cells or mark these blocks as discard. The data on the device is lost and will be read back as zeros.

target$ blkdiscard --secure /dev/mmcblk0

The option --secure ensures that the command waits until the eMMC device has erased all blocks.

dd if=/dev/zero of=/dev/mmcblk0 also destroys all information on the device, but this command is bad for wear leveling and takes much longer!

GPIOs

The phyBOARD-Polaris has a set of pins especially dedicated as user I/Os. Those pins are connected directly to i.MX 8M pins and are muxed as GPIOs. They are directly usable in Linux userspace. The processor has organized its GPIOs into five banks of 32 GPIOs each (GPIO1 – GPIO5) and one bank with 14 GPIOs. gpiochip0gpiochip32gpiochip64gpiochip96, and gpiochip128 are the sysfs representation of these internal i.MX 8M GPIO banks GPIO1 – GPIO5.

The GPIOs are identified as GPIO<X>_<Y> (e.g. GPIO5_07). <X> identifies the GPIO bank and counts from 1 to 5, while <Y> stands for the GPIO within the bank. <Y> is counted from 0 to 31 (32 GPIOs on each bank).

By contrast, the Linux kernel uses a single integer to enumerate all available GPIOs in the system. The formula to calculate the correct number is:

Linux GPIO number: <N> = (<X> - 1) * 32 + <Y>

Accessing GPIOs from userspace will be done using the libgpiod. It provides a library and tools for interacting with the Linux GPIO character device. Examples of the usage for some of the tools:

target$ gpiodetect
gpiochip0 [30200000.gpio] (32 lines)
gpiochip1 [30210000.gpio] (32 lines)
gpiochip2 [30220000.gpio] (32 lines)
gpiochip3 [30230000.gpio] (32 lines)
gpiochip4 [30240000.gpio] (32 lines)
target$ gpioinfo gpiochip0
target$ gpioget gpiochip0 20
target$ gpioset --mode=exit gpiochip0 20=0
target$ gpioset --help
Usage: gpioset [OPTIONS] <chip name/number> <offset1>=<value1> <offset2>=<value2> ...
Set GPIO line values of a GPIO chip
 
Options:
  -h, --help:           display this message and exit
  -v, --version:        display the version and exit
  -l, --active-low:     set the line active state to low
  -m, --mode=[exit|wait|time|signal] (defaults to 'exit'):
                tell the program what to do after setting values
  -s, --sec=SEC:        specify the number of seconds to wait (only valid for --mode=time)
  -u, --usec=USEC:      specify the number of microseconds to wait (only valid for --mode=time)
  -b, --background:     after setting values: detach from the controlling terminal
 
Modes:
  exit:         set values and exit immediately
  wait:         set values and wait for user to press ENTER
  time:         set values and sleep for a specified amount of time
  signal:       set values and wait for SIGINT or SIGTERM
 
Note: the state of a GPIO line controlled over the character device reverts to default
when the last process referencing the file descriptor representing the device file exits.
This means that it's wrong to run gpioset, have it exit and expect the line to continue
being driven high or low. It may happen if given pin is floating but it must be interpreted
as undefined behavior.


Some of the user IOs are used for special functions. Before using a user IO, refer to the schematic or the hardware manual of your board to ensure that it is not already in use.

Pinmuxing of some GPIO pins in the device tree phytec-imx8mq-phyboard-polaris.dtsi:

                pinctrl__leds: leds1grp {
                        fsl,pins = <
                               MX8MQ_IOMUXC_GPIO1_IO01_GPIO1_IO1   0x16
                               MX8MQ_IOMUXC_I2C3_SCL_GPIO5_IO18    0x16
                               MX8MQ_IOMUXC_SAI1_RXD6_GPIO4_IO8    0x16
                        >;
                };

LEDs

If any LEDs are connected to GPIOs, you have the possibility to access them by a special LED driver interface instead of the general GPIO interface (section GPIOs). You can then access them using /sys/class/leds/ instead of /sys/class/gpio/. The maximum brightness of the LEDs can be read from the max_brightness file. The brightness file will set the brightness of the LED (taking a value from 0 up to max_brightness). Most LEDs do not have hardware brightness support and will just be turned on by all non-zero brightness settings.

Below is a simple example:

target$ ls /sys/class/leds
led-blue@  led-green@ led-red@   mmc0::@    mmc1::@    user-led1@ user-led2@ 

Here the LEDs user-led1 and user-led2 are on the expansion board PEB-EVAL-01 and the others are on phyBOARD-Polaris.

target$ echo 255 > /sys/class/leds/user-led1/brightness
target$ echo 0 > /sys/class/leds/user-led1/brightness

User I/O configuration in device tree file can be found here: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n17

User I/O configuration in device tree file can be found here: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris-peb-eval-01.dtsi?h=v5.4.70_2.3.2-phy2#n28

I2C Bus

The i.MX 8M contains two Multimaster fast-mode I²C modules, I2C1 and I2C2. PHYTEC boards provide plenty of different I²C devices connected to the two I²C modules of the i.MX 8M. This section describes the basic device usage and its DT representation of some I²C devices integrated on our phyBOARD-Polaris.

General I²C1 bus configuration (e.g. phytec-imx8mq-phycore-som.dtsi): https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phycore-som.dtsi?h=v5.4.70_2.3.2-phy2#n100

General I²C2 bus configuration (e.g. phytec-imx8mq-phyboard-polaris.dtsi): https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n185

EEPROM

The I2C EEPROM on the phyCORE-i.MX8M SoM is connected to I2C address 0x50 on I2C-0 bus.

It is possible to read and write directly to the device:

target$ cat /sys/class/i2c-dev/i2c-0/device/0-0050/eeprom
target$ dd if=/sys/class/i2c-dev/i2c-0/device/0-0050/eeprom bs=1 count=1024  | od -x
target$ dd if=/dev/zero of=/sys/class/i2c-dev/i2c-0/device/0-0050/eeprom bs=4096 count=1

DT representation, e.g. in phyCORE-i.MX 8M file phytec-imx8mq-phycore-som.dtsi. See: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phycore-som.dtsi?h=v5.4.70_2.3.2-phy2#n194

The first 256 bytes are reserved for future purposes!

EEPROM ID Page SoM detection

The I2C EEPROM, populated on the phyCORE-i.MX 8M has a separate ID page that is addressable over I2C address 58 on bus 0. PHYTEC uses this data area of 32 Byte to store information about the SoM. This includes PCB revision and mounting options.

The EEPROM data is read at a really early stage during startup. It is used to select the correct RAM configuration. This makes it possible to use the same bootloader image for different RAM sizes. More features will be implemented in future releases.

If the EEPROM ID page data is deleted, the bootloader will fall back to the phyCORE-i.MX8M Kit RAM setup, which is 2GB of LPDDR4 RAM.

The EEPROM ID page (bus: I2C-0 addr: 0x58) should not be erased or overwritten. As this will influence the behavior of the bootloader. The board might not boot correctly anymore.

SoMs that are flashed with data format API revision 2 will print out information of the module in the early stage:

U-Boot SPL 2020.04 (Aug 23 2021 - 10:39:16 +0000)
PMIC:  PFUZE100 ID=0x10
SoM: PCL-066-1012010I.A0 PCB rev: 3
...

RTC

RTCs can be accessed via /dev/rtc*. Because PHYTEC boards have often more than one RTC, there might be more than one RTC device file.

target$ cat /sys/class/rtc/rtc*/name
rtc-rv3028 0-0052
snvs_rtc 30370000.snvs:snvs-rtc-lp


This will list all RTCs including the non-I²C RTCs. Linux assigns RTC devices IDs based on the device tree/aliases entries if present.

Date and time can be manipulated with the hwclock tool, using the -w (systohc) and -s (hctosys) options. To set the date, first use date and then run hwclock -w -u to store the new date into the RTC. For more information about this tool, refer to the main page of hwclock.

RTC Wakealarm

 It is possible to issue an interrupt from the RTC to wake up the system. The format used is the Unix epoch time, which is the number of seconds since UTC midnight 1 January 1970. To wake up the system after 4 minutes from suspend to ram state, type:

target$ echo "+240" > /sys/class/rtc/rtc0/wakealarm
target$ echo mem > /sys/power/state


Internally the wake alarm time will be rounded up to the next minute since the alarm function doesn't support seconds.

DT representation for I²C RTCs: phytec-imx8mq-phycore-som.dtsi: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phycore-som.dtsi?h=v5.4.70_2.3.2-phy2#n200

PCIe

The phyCORE-i.MX 8M has one Mini-PCIe slot. In general, PCIe autodetects new devices on the bus. After connecting the device and booting up the system, you can use the command lspci to see all PCIe devices recognized.

target$ lspci -v
 00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00 [Normal decode])
        Flags: bus master, fast devsel, latency 0, IRQ 209
        Memory at 20000000 (32-bit, non-prefetchable) [size=1M]
        Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
        Memory behind bridge: 20100000-201fffff
        [virtual] Expansion ROM at 20200000 [disabled] [size=64K]
        Capabilities: [40] Power Management version 3
        Capabilities: [50] MSI: Enable+ Count=1/1 Maskable+ 64bit+
        Capabilities: [70] Express Root Port (Slot-), MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [148] L1 PM Substates
        Kernel driver in use: pcieport
 
 01:00.0 Network controller: Intel Corporation WiFi Link 5100
        Subsystem: Intel Corporation WiFi Link 5100 AGN
        Flags: fast devsel, IRQ 241
        Memory at 20100000 (64-bit, non-prefetchable) [size=8K]
        Capabilities: [c8] Power Management version 3
        Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [e0] Express Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [140] Device Serial Number 00-24-d6-ff-ff-84-0d-1e
        Kernel modules: iwlwifi

In this example, the PCIe device is the Intel Corporation WiFi Link 5100.

For PCIe devices, you have to enable the correct driver in the kernel configuration. This WLAN card, for example, is manufactured by IntelKconfig. The option for the driver, which must be enabled, is named CONFIG_IWLWIFI and can be found under Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimat in the kernel configuration.

host$ bitbake virtual/kernel -c menuconfig

For some devices, like this WLAN card, additional binary firmware blobs are needed. These firmware blobs have to be placed in /lib/firmware/ before the device can be used.

host$ scp -r <firmware> root@192.168.3.11:/lib/firmware
target$ ip link set up wlp1s0
 [   58.682104] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
 [   58.690822] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
 [   58.696577] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0
 [   58.831022] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
 [   58.839679] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
 [   58.845435] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0
 [   58.902797] IPv6: ADDRCONF(NETDEV_UP): wlp1s0: link is not ready

PCIe configuration is in the kernel device tree phytec-imx8mq-phyboard-polaris.dtsi: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n206

Some PCIe devices, e.g. this Ethernet card, may function properly even if no firmware blob could be loaded from /lib/firmware/ and you received an error message as shown in the first line of the output above. This is because some manufacturers provide the firmware as fallback on the card itself. In this case, the behavior and output strongly depend on the manufacturer's firmware.

Audio

Playback devices supported for phyBOARD-Polaris are HDMI and the onboard TI TLV320AIC3007 audio codec. On the baseboard, there is a Molex connector for a mono speaker and a 6-pin header. The 6-pin header contains headphones and line-in signals.

To check if your soundcard driver is loaded correctly and what the device is called, type for playback devices:

target$ aplay -L

Or type for record devices:

target$ arecord -L

Alsamixer

To inspect the capabilities of your soundcard, call:

target$ alsamixer

The default card for Alsamixer is the TLV320- codec, the Dummy Card and HDMI can be selected by pressing F6. You should see a lot of options as the TLV320-IC has many features you can experiment with. It might be better to open Alsamixer via ssh instead of the serial console, as the console graphical effects are better. You have either mono or stereo gain controls for all mix points. "MM" means the feature is muted (both output, left & right), which can be toggled by hitting m. You can also toggle by hitting '<' for left and ''>' for right output.

ALSA configuration

Our BSP comes with an ALSA configuration file /etc/asound.conf which sets the TLV320-codec as default. To set a different playback device as output, the config file can be edited:

target$ vi /etc/asound.conf

To set HDMI as output for example set playback.pcm from "codecplayback" to "hdmiplayback":

[...] 

pcm.asymed {
        type asym
        playback.pcm "hdmiplayback"
        capture.pcm "codeccapture"
}

[...]

Pulseaudio configuration

For applications using Pulseaudio, check for available sinks:

target$ pactl list short sinks  
0	alsa_output.platform-snd_dummy.0.stereo-fallback	module-alsa-card.c	s16le 2ch 44100HzSUSPENDED
1	alsa_output.platform-sound-hdmi.stereo-fallback	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED
2	alsa_output.platform-sound.stereo-fallback	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED

To select HDMI, type:

target$ pactl set-default-sink 1

Playback

Run speaker-test to check playback availability:

target$ speaker-test -c 2 -t wav

To playback simple audio streams, you can use aplay. For example to play the ALSA test sounds:

target$ aplay /usr/share/sounds/alsa/*

To playback other formats like mp3 for example, you can use Gstreamer:

target$ gst-launch-1.0 playbin uri=file:/path/to/file.mp3

Capture

arecord is a command-line tool for capturing audio streams which uses Line In from the 6-pin header on the baseboard as the default input source.

target$ arecord -fS16_LE -r44100 -c2 -twav test.wav


Since playback and capture share hardware interfaces it is not possible to use different sampling rates and formats for simultaneous playback and capture operation with the TLV320 codec.

The audio configurations in the device tree can be found under phytec-imx8mq-phyboard-polaris.dtsi: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris.dtsi?h=v5.4.70_2.3.2-phy2#n194

Video

Videos with Gstreamer

The video is installed by default in the BSP:

target$ gst-launch-1.0 playbin uri=file:///usr/share/phytec-qtdemo/videos/caminandes.webm

#OR

target$ gst-launch-1.0 -v filesrc location=<video.mp4> \
! qtdemux  ! h264parse ! queue ! vpudec ! waylandsink async=false enable-last-sample=false \
qos=false sync=false

#OR 

target$ gplay-1.0 /usr/share/phytec-qtdemo/videos/caminandes.webm

kmssink Plugin ID Evaluation

The kmssink plugin needs a connector ID. To get the connector ID, you can use the tool modetest.

target$ modetest -c -M imx-drm

The output will show something like:

Connectors:
id      encoder status          name            size (mm)       modes   encoders
46      0       disconnected    HDMI-A-1        0x0             7       45
 
  props:
        1 EDID:
                flags: immutable blob
                blobs:
 
                value:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 0
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0
        7 non-desktop:
                flags: immutable range
                values: 0 1
                value: 0
        6 HDR_SOURCE_METADATA:
                flags: blob
                blobs:
 
                value:

To draw a test pattern, type connector_id@crtc_id:mode. For example LVDS-1:

target$ systemctl stop weston@root
target$ modetest -M imx-drm -s 39@33:#0

Display

The 10" Display is always active. If the PEB-AV-Connector is not connected, an error message may occur at boot. HDMI is defined as a default display.

In software, HDMI is defined as a default display output. This can be changed by modifying the /etc/wxdg/weston/weston.ini configuration:

target$ vi /etc/xdg/weston/weston.ini

Comment out this line:

#drm-device=card0

After a restart of the Weston compositor or the whole board, the output will appear on the display instead of HDMI.

target$ systemctl restart weston@root

With the phytec-qt5demo-image, Weston with the phytec-qt5demo starts during boot. The phytec-qt5demo can be stopped with:

target$ systemctl stop phytec-qtdemo
target$ systemctl start phytec-qtdemo
target$ systemctl disable phytec-qtdemo
target$ systemctl enable phytec-qtdemo
target$ systemctl stop weston@root

phytec-imx8mq-phyboard-polaris-peb-av-009.dtsi: https://git.phytec.de/linux-imx/tree/arch/arm64/boot/dts/freescale/imx8mq-phyboard-polaris-peb-av-009.dtsi?h=v5.4.70_2.3.2-phy2

Framebuffer

This driver gains access to displays connected to PHYTEC carrier boards by using an emulated frame buffer device /dev/fb0.

target$ fbtest -f /dev/fb0

This will show various test patterns on the display.

target$ fbset

which will return something like:

mode "1280x800-0"
       # D: 0.000 MHz, H: 0.000 kHz, V: 0.000 Hz
       geometry 1280 800 1280 800 32
       timings 0 0 0 0 0 0 0
       accel true
       rgba 8/16,8/8,8/0,0/0
endmode
target$ cat /sys/class/graphics/fb0/bits_per_pixel

Display Resolution

For displays with variable display resolution, the resolution can be changed by supplying the desired resolution as a cmdline argument during boot. But first, the correct interface name needs to be determined.

target$ ls /sys/class/drm/ -1

Possible output for the phyCORE-i.MX 8M mounted on the phyBOARD-Polaris Carrier Board:

The suffixes of "card0-*" are the identifiers that must be used to configure the corresponding interface.

bootloader$ editenv mmcargs
bootloader$ video=HDMI-A-1:1024x768-24
bootloader$ saveenv
fbset


Ensure the correct bits per pixel for your display are used, e.g. 18, 16, or 24, … . Otherwise, the colors will look very strange. Use fbtest to test them.

Backlight Control

If a display is connected to the PHYTEC board, you can control its backlight with the Linux kernel sysfs interface. All available backlight devices in the system can be found in the folder /sys/class/backlight. Reading the appropriate files and writing to them allows you to control the backlight.

target$ cat /sys/class/backlight/backlight/max_brightness

which will result in:

7

Valid brightness values are 0 to <max_brightness>.

target$ cat /sys/class/backlight/backlight/brightness

you will get for example:

6
target$ echo 0 > /sys/class/backlight/backlight/brightness

turns the backlight off,

target$ echo 6 > /sys/class/backlight/backlight/brightness

sets the brightness to the second-highest brightness level. For documentation of all files, see https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight.

Power Management

CPU Core Frequency Scaling

The CPU in the i.MX8M is able to scale the clock frequency and the voltage. This is used to save power when the full performance of the CPU is not needed. Scaling the frequency and the voltage is referred to as 'Dynamic Voltage and Frequency Scaling' (DVFS). The i.MX8M BSP supports the DVFS feature. The Linux kernel provides a DVFS framework that allows each CPU core to have a min/max frequency and a governor that governs it. Depending on the i.MX 8 variant used, several different frequencies are supported.

target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
1000000 1500000
target$ echo 1000000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
target$ echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

So-called governors are automatically selecting one of these frequencies in accordance with their goals.

target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors

The result will be:

conserative userspace powersave ondemand performance schedutil
  1. ondemand (default): switches between possible CPU core frequencies in reference to the current system load. When the system load increases above a specific limit, it increases the CPU core frequency immediately.
  2. conservative: is much like the ondem and governor. It differs in behavior in that it gracefully increases and decreases the CPU speed rather than jumping to max speed the moment there is any load on the CPU.
  3. powersave: always selects the lowest possible CPU core frequency.
  4. performance: always selects the highest possible CPU core frequency.
  5. schedutil: allows userspace to set the CPU frequency for the policy it is attached to by writing to the scaling_setspeed attribute of that policy.
  6. userspace: allows the user or userspace program running as root to set a specific frequency (e.g. to1500000 ).
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
target$ echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
target$ echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

For more detailed information about the governors, refer to the Linux kernel documentation in: linux/Documentation/admin-guide/pm/cpufreq.rst.

CPU Core Management

The i.MX 8M SOC can have multiple processor cores on the die. The i.MX 8M Quad, for example, has 4 ARM Cores which can be turned on and off individually at runtime.

target$ ls /sys/devices/system/cpu

This will show, for example:

cpu0    cpu1   cpu2   cpu3   cpufreq
[...]

Here the system has four processor cores. By default, all available cores in the system are enabled to get maximum performance.

target$ echo 0 > /sys/devices/system/cpu/cpu1/online
[  110.502295] CPU1: shutdown
[  110.505012] psci: CPU1 killed.

Now the core is powered down and no more processes are scheduled on this core.

target$ htop
target$ echo 1 > /sys/devices/system/cpu/cpu1/online

Suspend to RAM

The phyCORE-i.MX8M supports basic suspend and resume. Different wake-up sources can be used.

Basically, suspend/resume is possible with:

target$ echo mem > /sys/power/state
#resume with pressing on/off button

To wakeup with serial console run:

target$ echo enabled > /sys/class/tty/ttymxc0/power/wakeup
target$ echo mem > /sys/power/state

snvs Power Key

The X_ONOFF pin connected to the ON/OFF button can be pressed long to trigger Power OFF without SW intervention or used to wake up the system out of suspend. With the snvs_pwrkey driver, the KEY_POWER event is also reported to userspace when the button is pressed. On default, systemd is configured to ignore such events. The function of Power OFF without SW intervention and the wake-up from suspend are not configured. Triggering a power off with systemd when pushing the ON/OFF button can be configured under /etc/systemd/logind.conf  and set using:

HandlePowerKey=poweroff

Thermal Management

The Linux kernel has integrated thermal management which is capable of monitoring SOC temperatures, reducing the CPU frequency, driving fans, advising other drivers to reduce the power consumption of devices, and – worst-case – shutting down the system gracefully
(https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt).

This section describes how the thermal management kernel API is used for the i.MX 8M SOC platform. The i.MX8 has internal temperature sensors for the SOC.

target$ cat /sys/class/thermal/thermal_zone0/temp
49000

There are two trip points registered by the imx_thermal kernel driver:

trip_point_0: 85 °C type: passive

trip_point_1: 90 °C type: critical

(see kernel sysfs folder /sys/class/thermal/thermal_zone0/)

These trip points are used by the kernel thermal management to trigger events and change the cooling behavior. The following thermal policies (also named thermal governors) are available in the kernel: Step WiseFair ShareBang Bang, and Userspace. The default policy used in the BSP is step_wise. If the value of the SOC temperature in the sysfs file temp is above trip_point_0 (greater than 85 °C), the CPU frequency is set to the lowest CPU frequency. When the SOC temperature drops below trip_point_0 again, the throttling is released. If the SOC temperature reaches 90 °C, the thermal management of the kernel shuts down the systems.

The actual values of the thermal trip points may differ since we mount CPUs with different temperature grades.

GPIO Fan

A GPIO fan can be connected to the phyBOARD-Polaris-i.MX8M. lmsensors reads the temperature periodically and enables or disables the fan in a configurable threshold. For the phyBOARD-Polaris-i.MX8M this is 60°C. 

The settings can be configured in the configuration file:

/etc/fancontrol

Fan control is started by a systemd service during boot. This can be disabled with:

target$ systemctl disable fancontrol

Watchdog

The PHYTEC i.MX8M modules include a hardware watchdog that is able to reset the board when the system hangs. This section explains how to enable the watchdog in Linux using systemd to check for system hangs and during reboot. By default, the watchdog is enabled in the Linux kernel but disabled in systemd.

Watchdog Support in systemd

Systemd has included hardware watchdog support since version 183.

RuntimeWatchdogSec=60s
ShutdownWatchdogSec=10min

RuntimeWatchdogSec defines the timeout value of the watchdog, while ShutdownWatchdogSec defines the timeout when the system is rebooted. For more detailed information about hardware watchdogs under systemd can be found at http://0pointer.de/blog/projects/watchdog.html.

On-Chip OTP Controller (OCOTP_CTRL) - eFuses

The i.MX 8M provides one-time programmable fuses to store information such as the MAC address, boot configuration, and other permanent settings ("On-Chip OTP Controller (OCOTP_CTRL)" in the i.MX 8M Reference Manual). The following list is an abstract from the i.MX 8M Reference Manual and includes some useful fuse registers in the OCOTP_CTRL (at base address 0x30350000):

NameBankWordMemory offset to 0x30350000Description
OCOTP_MAC0900x640contains lower 32 bits of ENET0 MAC address
OCOTP_MAC1910x650contains upper 16 bits of ENET0 MAC address and the lower 16 bits of ENET1 MAC address
OCOTP_MAC2920x660

contains upper 32 bits of ENET1 MAC address

A complete list and a detailed mapping between the fuses in the OCOTP_CTRL and the boot/mac/... configuration are available in the section "Fuse Map" of the i.MX 8M Reference Manual.

Reading Fuse Values in uBoot

You can read the content of a fuse using memory-mapped shadow registers. To calculate the memory address, use the fuse Bank and Word in the following formula:

OCOTP_MAC0: addr

bootloader$ fuse read 9 0

Reading Fuse Values in Linux

To access the content of the fuses in Linux NXP provides the NVMEM_IMX_OCOTP module. All fuse content of the memory-mapped shadow registers is accessible via sysfs:

target$ hexdump /sys/devices/platform/soc\@0/soc\@0\:bus\@30000000/30350000.ocotp-ctrl/imx-ocotp0/nvmem

Reading the registers using /dev/mem will cause the system to hang unless the ocotp_root_clk is enabled. To enable this clock permanent, add to the device tree:

&clk {
		init-on-array = <IMX8MQ_CLK_OCOTP_ROOT>;
};