i.MX 6 UL + Linux Notes (2)

2018-05-16

Continue of the last post.

Decompress U-boot format initrd

$ mkimage -l uImage

Display image info

$ tail -c+65 < uImage > out

Remove file header

$ tail -c+65  < uImage | gunzip > out

If the file is gzipped, it could be decompressed to get the data.

If it's initramfs, cpio -t < out or pax < out could be used to view the content.

Or try to mount it:

$ mount -ro loop out /mnt

Pack initrd into U-boot format

$ umount /mnt
$ mdconfig -d -u 0

Compress with gzip

$ gzip initrd

Create uboot image

$ mkimage -A arm -T ramdisk -C none -n ramdisk -d initrd.gz ramdisk.uImage

U-Boot related

Create boot script

$ mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n 'Boot script' -d normal.cmd boot.scr

Manual boot

From SD card

fatload mmc 0:1 0x80800000 bin/zImage
fatload mmc 0:1 0x83000000 bin/imx6ul-14x14-evk.dtb
setenv bootargs console=ttymxc0,115200 cma=64M root=/dev/mmcblk0p2 rootwait
bootz 0x80800000 - 0x83000000

Using script on SD

fatload mmc 0 0x80700000 /bin/boot.scr
source 0x80700000

From NAND Flash

nand read 0x80800000 0xa00000 0x800000
nand read 0x83000000 0x700000 0x40000
setenv bootargs console=ttymxc0,115200 cma=64M root=/dev/mtdblock5 rootwait
bootz 0x80800000 - 0x83000000

Disable screen timeout

Screen timeout is provided by VT, which could be disabled by writing control commands:

 f = open("/dev/tty0", O_RDWR);
 write(f, "/033[9;0]", 8);
 close(f);

Pack SquashFS

Pack the directory into an image

$ mksquashfs /some/dir dir.sqsh

Mount the packed filesystem:

$ mkdir /mnt/dir
$ mount dir.sqsh /mnt/dir -t squashfs -o loop

Directly pack the directory in to target device

$ mksquashfs /some/dir /dev/fd0

ADC

ADC is only available on i.MX6UL and i.MX6SX in the i.MX6 product line.

The device driver is in Device Drivers -> Industrial IO -> Analog to Digital devices -> Freescale vf610. Add the following content in the device tree:

&adc1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_adc1>;
    vref-supply = <&reg_vref_3v3>;
    status = "okay";
};

pinctrl_adc1: adc1grp {
    fsl,pins = <
        MX6UL_PAD_GPIO1_IO07__GPIO1_IO07 0xb0
    >;
};

Testing

$ cat /sys/bus/iio/devices/iio\:device0/in_voltage7_raw

Beeper

Use the standard pwm-buzzer. Seems like people love abusing pwm-leds or pwm-backlight for beepers, not sure why though.

The driver is located in Device Drivers -> Input Devices -> Misc Devices -> PWM Buzzer. Add the following in the device tree:

beeper {
    compatible = "pwm-beeper";
    pwms = <&pwm6 0 50000>;
};


pinctrl_pwm6: pwm6grp {
    fsl,pins = <
        MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD     0xb808
        MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK        0x11
        MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B      0xb810
        MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN       0xb810
        MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD       0xb811
        MX6UL_PAD_CSI_DATA02__GPIO4_IO23        0x3008
        MX6UL_PAD_ENET1_TX_EN__PWM6_OUT   0x110b0
    >;
};

/* Buzzer */
&pwm6 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm6>;
    status = "okay";
};

Note that in the kernel of iMX6UL BSP, PWM2-8 didn't have clock allocated, which needs fixing:

@@ -455,8 +455,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x02084000 0x4000>;
                interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM2>,
+                    <&clks IMX6UL_CLK_PWM2>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -465,8 +465,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x02088000 0x4000>;
                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM3>,
+                    <&clks IMX6UL_CLK_PWM3>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -475,8 +475,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x0208c000 0x4000>;
                interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM4>,
+                    <&clks IMX6UL_CLK_PWM4>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -811,8 +811,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f0000 0x4000>;
                interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM5>,
+                    <&clks IMX6UL_CLK_PWM5>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -821,8 +821,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f4000 0x4000>;
                interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM6>,
+                    <&clks IMX6UL_CLK_PWM6>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -831,8 +831,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f8000 0x4000>;
                interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM7>,
+                    <&clks IMX6UL_CLK_PWM7>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
@@ -841,8 +841,8 @@
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020fc000 0x4000>;
                interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clks IMX6UL_CLK_DUMMY>,
-                    <&clks IMX6UL_CLK_DUMMY>;
+               clocks = <&clks IMX6UL_CLK_PWM8>,
+                    <&clks IMX6UL_CLK_PWM8>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };

Another issue is that usleep_range doesn't work, Use udelay as a replacement, not sure about the implications:

    } else {
        writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
        do {
-           usleep_range(200, 1000);
+           udelay(10);
+           //usleep_range(200, 1000);
            cr = readl(imx->mmio_base + MX3_PWMCR);
        } while ((cr & MX3_PWMCR_SWR) &&
             (wait_count++ < MX3_PWM_SWR_LOOP));

Boot log should show:

input: pwm-beeper as /devices/platform/beeper/input/input2

To test it:

echo -ne '\007' > /dev/tty0

LED

Simple enough

leds {
    compatible = "gpio-leds";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_leds>;

    heartbeat {
        label = "heartbeat";
        gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>;
        linux,default-trigger = "heartbeat";
    };
};

pwmleds {
    compatible = "pwm-leds";
    green {
        label = "green";
        pwms = <&pwm2 0 100000>;
        max-brightness = <255>;
    };

    uv {
        label = "uv";
        pwms = <&pwm4 0 100000>;
        max-brightness = <255>;
    };
};