#+TODO: TODO(t) IN-PROGRESS DONE
#+STARTUP: indent
#+TITLE: The Librem-5 Devkit Setup
#+AUTHOR: Guido Günther
#+EMAIL: agx@sigxcpu.org

* Installing the SOM
  If the SOM is not yet installed
** power board without SOM via USB-C
** Check the voltages

   #+CAPTION: The voltage points to measure
   [[./pics/voltage-points.png]]

| Point    | Voltage         |
|----------+-----------------|
| VBUS     | 5.2V            |
| VBAT     | 4.2V            |
| VBAT_REG | 4.2V            |
| 5V_SOM   | 5.0V            |
| 3V3      | 3.3V            |
| 3V3_P    | ~0(without SOM) |

Each voltage is measured against ground (green circle in above image)


** Plugin the SOM

* Attach USB to serial adapter
** Solder in the UART debug plug
** Attach USB to serial Adapter

   #+CAPTION: UART pintout
   [[./pics/uart-pinout.png]]


   | PIN | Color |
   |-----+-------|
   |   1 | black |
   |   2 | n/c   |
   |   3 | n/c   |
   |   4 | green |
   |   5 | white |
   |   6 | n/c   |

PIN 1 is the one closest to the volume button while PIN6 is the one closest to
the power button.

* Power on/off
If the user holds the power button for ~2 seconds, a power down/reboot dialog
would pop up; a quick press & release would turn the display on/off.
If the button is held for ~5 seconds, the SoC triggers an event to shut down,
pressing it again for ~2 seconds will turn it back on.
The button is also attached to the charge controller's QON# pin, which, when
held for ~15 seconds, is able to put the dev kit into a "shipping mode" where
the charge controller is turned completely off, or holding it for ~18 seconds
will cause it to perform a complete power cycle.

* Booting via nfsroot
The SOM comes with a pre flashed u-boot so you can connect the
USB-to-UART-Debug cable and boot the device.
Breaking into uboot, you can boot using a nfsroot filesystem via:

#+BEGIN_SRC
setenv nfsrootboot "setenv bootargs ${args_common} debug root=/dev/nfs ip=:::::eth0:dhcp nfsrootdebug nfsroot=<nfsserverip>:<nfsrootpath>,v3,tcp; dhcp ${loadaddr} Image-librem5-devkit; dhcp ${fdt_addr} librem5-devkit.dtb; booti ${loadaddr} - ${fdt_addr}"
setenv bootcmd run nfsrootboot
saveenv
boot
#+END_SRC

You need to fill in *nfsrootpath* and *nfsserverip* above. At
*nfsrootpath* there needs to be a armhf or arm64 root filesystem which
you can e.g. create via Debian's deboostrap.

For that to work, the *BOOT MODE* switch needs to be set to *eMMC*
(instead of *USB*).

* Installing a minimal Linux to the eMMC
You can dd a prebuilt image on there or you can just debootstrap from
scratch. This can be useful if you don't want that many services
starting up by default:

#+BEGIN_SRC sh
e2fsck /dev/mmcblk0p2
mount /dev/mmcblk0p2 /mnt
debootstrap --arch=arm64 buster /mnt
#+END_SRC

Back in u-boot, we can switch to using the rootfs on the eMMC then (we're still
pulling kernel and device tree via tftp though):

#+BEGIN_SRC
setenv emmcboot "setenv bootargs ${args_common} debug root=/dev/mmcblk0p2; dhcp ${loadaddr} Image-librem5-devkit; dhcp ${fdt_addr} librem5-devkit.dtb; booti ${loadaddr} - ${fdt_addr}"
#+END_SRC

* Install uuu
** By hand

The NXP mfgtool uuu is required to boot a board that has no bootloader or is
"bricked" in another way. To download, build, and install uuu:

#+BEGIN_SRC
git clone https://github.com/NXPmicro/mfgtools
cd mfgtools
cmake ./
make
sudo make install
#+END_SRC

** Using the handy script

#+BEGIN_SRC
scripts/build_uuu.sh -i
#+END_SRC

* Udev Rules
If you want to run *uuu* as non-root, add the following udev rules

#+BEGIN_SRC sh
cat <<EOF > /etc/udev/rules.d/99_librem5_devkit.rules
SUBSYSTEM!="usb", GOTO="librem5_devkit_rules_end"
# Devkit USB flash
ATTR{idVendor}=="1fc9", ATTR{idProduct}=="012b", GROUP+="plugdev", TAG+="uaccess"
ATTR{idVendor}=="0525", ATTR{idProduct}=="a4a5", GROUP+="plugdev", TAG+="uaccess"
ATTR{idVendor}=="0525", ATTR{idProduct}=="b4a4", GROUP+="plugdev", TAG+="uaccess"
LABEL="librem5_devkit_rules_end"
EOF
sudo udevadm control -R
sudo adduser <youruser> plugdev
newgrp plugdev
#+END_SRC

Make sure you replug the serial cable in case you have plugged it in
already. With the above rules, you can skip the =sudo= in front of the
uuu invocations below.

* Flash the test image

The eMMC file used for flashing is files/devkit-test.img.
Put the "Boot Mode" switch in the USB position.

THIS WILL ERASE EVERYTHING ON YOUR eMMC.

#+BEGIN_SRC
scripts/get_image.sh
sudo uuu uuu_scripts/flash_librem5-devkit-test.lst
#+END_SRC

* Download Target Binaries

You can manually download or build the required binaries. There is also a
convenience script to download prebuilt binaries from the Purism servers.

#+BEGIN_SRC
scripts/fetch_latest.sh -xk
#+END_SRC

* Flash uboot
** Using SDP

The uboot file used for flashing is files/u-boot-devkit-recovery.imx.
Put the "Boot Mode" switch in the USB position.

#+BEGIN_SRC
sudo uuu uuu_scripts/u-boot_flash_librem5-devkit.lst
#+END_SRC

You can also just boot to u-boot without flashing anything:

#+BEGIN_SRC
sudo uuu uuu_scripts/u-boot_librem5-devkit.lst
#+END_SRC

** From u-boot using tftp

You must have a tftp server setup for this.

#+BEGIN_SRC
setenv ipaddr <tftp server ip>
setenv serverip <target ip addr>
tftp 0x43000000 u-boot-devkit-recovery.imx
mmc write 0x43000000 0x42 0x800
#+END_SRC

** From the kernel command line

Download the u-boot binary u-boot-devkit-recovery.imx.

#+BEGIN_SRC
dd if=u-boot-devkit-recovery.imx of=/dev/mmcblk0 bs=1024 seek=33
#+END_SRC

* Flash eMMC
** Using SDP

The eMMC file used for flashing is files/devkit.img.
Put the "Boot Mode" switch in the USB position.

THIS WILL ERASE EVERYTHING ON YOUR eMMC.

#+BEGIN_SRC
sudo uuu uuu_scripts/flash_librem5-devkit.lst
#+END_SRC

* Create test initramfs
** Download the latest image and kernel

Download the latest kernel and RS9116 out of tree modules.

#+BEGIN_SRC
./scripts/fetch_latest.sh -k
#+END_SRC

** Extract the kernel

The kernel needs to be extracted from the deb for the SDP boot.

#+BEGIN_SRC
./scripts/extract_kernel.sh
#+END_SRC

** Build the test filesystem tarball

This will create a minimal debian rootfs tarball that is used for creating an
initramfs. If you need additional packages, you can add them to the packages
variable in the script.

#+BEGIN_SRC
./scripts/create_tarball.sh
#+END_SRC

** Create the initramfs

This will take the tarball created above and customize it to be able to flash
the RS9116 module and also adds some test scripts.

#+BEGIN_SRC
./scripts/create_initramfs.sh -t build/test_rootfs.tgz -o files/test_initramfs.img
#+END_SRC

You can include a locally generated kernel, modules, and devicetree as well:

#+BEGIN_SRC
./scripts/create_initramfs.sh -t build/test_rootfs.tgz -o files/test_initramfs.img -i <path to kernel>
#+END_SRC

** Boot the initramfs

The initramfs can be booted on a board with an empty eMMC for testing and
RS9116 flashing. Ensure the boot mode switch is switched to USB boot. Run
the command below and then plug in the USB-C port of the devkit.

#+BEGIN_SRC
sudo uuu uuu_scripts/test_librem5.lst
#+END_SRC

** Reflash the RS9116

By default, no rsi_* modules get loaded. The modules without firmware are in
"/lib/modules/<kernel_ver>/drivers/net/wireless/rsi". The create_initramfs
script above adds the rsi firmware and reflashes the modules in "/usr/src".

There is a convenience script "flash_rsi.sh" that will perform the necessary
steps. The script backs up the rsi modules in /lib/modules, copies the firmware
into /lib/firmware and the modprobes for the rsi flashing modules.
It replaces the original modules when it's done.

Run the script on the target to reflash.

#+BEGIN_SRC
root@pureos-test:~# flash_rsi.sh
#+END_SRC

** RS9116 normal operation

To use the RS9116 without flashing just load the modules by hand.

#+BEGIN_SRC
root@pureos-test:~# modprobe rsi_sdio
#+END_SRC

* Hardware Components
** LCD Panel
The panel is a Rockchip JH057N00900 (5.7", TFT 720*1440 Pixels) using a ST7703
IC.

* Configure WiFi

For either method below, you must first make sure the module is loaded.

#+BEGIN_SRC
modprobe rsi_sdio
#+END_SRC

** Configure with nmtui

Just run "nmtui" and go to activate a network and then chose your WiFi network.
If the list is empty it sometimes takes 15 seconds after loading the module to
become populated.

** Configure with nmcli

If you know which network you want to connect to. You can just us nmcli
directly:

#+BEGIN_SRC
nmcli device wifi rescan
nmcli device wifi list
nmcli device wifi connect SSID-Name password wireless-password
#+END_SRC
