Allwinner Nezha

The Allwinner Nezha is the first D1 based board made available to the general public. It was sold through several distributors, including RVBoards and Sipeed (Indiegogo campaign).

The indiegogo campaign page states that "Nezha is Open Source". But the hardware itself is not OSHW, and the open source SDK that that page refers to requires registering for an "Allwinner account". Seems like the Nezha is just as open source as all the other devices who are based on u-boot and the linux kernel, and who follow the basic premise of the GPL.

In fact, the disclaimer that Allwinner requires you to click through reads the following: "This deliverable may not be altered, copied, reversed, sold, distributed, or otherwise engaged in commercial activities without prior written permission of the company." And they seem to be using this disclaimer since at least 2018-11-21 according to the date on that disclaimer. This disclaimer is 100% at odds with the GPL license that Allwinners whole business depends on.

= Identification =

There are at least two known revisions of the board. The older version is silkscreened D1_DEV_DDR3_16X2_V1_0 on the top and does not have the AWOL logo. The newer version has the AWOL anagram silkscreened on the front (d1.docs.aw-ol.com being the official documentation website with the same logo), and the identifier D1_DEV_DDR3_16X2_V1_2 on the back.

The front side of both PCB versions has a variant of the Nezha logo.

The back also has a sticker containing a QR code, with the board serial number below it. Scanning the QR code reveals the following URL:
 * https://d1.docs.allwinnertech.com?device=d1nezha#serial (with #serial replaced by the serial number)

= General Notes = The device is are sometimes being shipped with an SD with Debian installed. Console logs: https://gist.github.com/heitbaum/e4dceeb7b236560b94cc66fce91cdd11

Sometimes the device only ships with TinaLinux in NAND. Console logs booting into TinaLinux: https://ovsienko.info/D1/minicom1.cap.txt

The Debian images for the D1 can be found here: https://ovsienko.info/D1/

It is unknown how to boot from any of those images on the NAND only device.

= Sunxi support =

Current status
The BSP U-Boot/kernel use a NAND layout which merges a pair of pages from consecutive blocks into a super-page. Mainline uses the physical layout as-is. So while SPI NAND contents are accessible from both mainline and BSP kernels, they are only usable by one driver or the other. For this reason, it is recommended to install mainline software to an SD card, and leave the SPI NAND alone.

Disabling the CONFIG_AW_SPINAND_SIMULATE_MULTIPLANE option in the BSP kernel should make its layout compatible with mainline, but this has not been tested.

Manual build
You can build things for yourself by following the instructions below. There are some differences from the normal build howto because it needs a modified boot0 for early MMC and DRAM init, not U-Boot SPL.

U-Boot
Boot firmware on the D1 consists of three parts, which largely correspond to the components used by 64-bit ARM SoCs:
 * 1) boot0 or U-Boot SPL (Secondary Program Loader) which is responsible for initializing DRAM and loading further firmware from storage.
 * 2) OpenSBI, which runs in machine mode and provides a standard "SBI" interface to less privileged modes. This is similar to how TF-A runs in EL3 and provides PSCI on 64-bit ARM.
 * 3) U-Boot proper, which initializes additional hardware and loads Linux from storage or the network.

BSP boot0 SPL
Because the early sunxi device drivers in U-Boot are tightly intertwined with the ARM architecture, and because DRAM init has not yet been reverse engineered, we are using the BSP's boot0 as SPL. Download it from here: https://github.com/smaeul/sun20i_d1_spl

This version has been modified so it can be built outside the BSP's build system, so it compiles with mainline GCC, and so it cooperates better with mainline firmware binaries. See the commit history for more details. Below is the process for building it and writing it to an SD card:

git clone https://github.com/smaeul/sun20i_d1_spl -b mainline pushd sun20i_d1_spl make CROSS_COMPILE=riscv64-linux-gnu- p=sun20iw1p1 mmc sudo dd if=nboot/boot0_sdcard_sun20iw1p1.bin of=/dev/sdX bs=8192 seek=1 popd

The Nezha boot ROM can read the boot0 SPL from two different locations:
 * starting at sector 16
 * starting at sector 256

The location in sector 16 is incompatible with GPT partioning which by default uses 34 sectors. In gdisk you will have to reduce the number of entries in the partition table to &#x2264; 56 via the expert settings. So it may be preferable to write boot0 starting at sector 256 instead:

sudo dd if=nboot/boot0_sdcard_sun20iw1p1.bin of=/dev/sdX bs=8192 seek=16

A boot message tells you which location was used for booting: Loading boot-pkg Succeed(index=1)

Note that boot0 does some magic like enabling the T-HEAD ISA and MMU extensions. Those stay enabled all the way through entering Linux, which expects the custom PTE format.

OpenSBI
Mainline OpenSBI supports the C906 out of the box, but it needs a few tweaks and a new reset driver for the sunxi watchdog. Download a patched version and compile it like so: git clone https://github.com/smaeul/opensbi -b d1-wip pushd opensbi CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic FW_PIC=y make popd

Mainline U-Boot
Mainline U-Boot is very hacked up, but the basic function of booting Linux from an SD card works. Some major refactoring of the various sunxi device drivers will be needed before any RISC-V sunxi platforms can be upstreamed. Download a patched version and compile it like so: git clone https://github.com/smaeul/u-boot -b d1-wip pushd u-boot make CROSS_COMPILE=riscv64-linux-gnu- nezha_defconfig make CROSS_COMPILE=riscv64-linux-gnu-

boot0 expects to load a TOC1 image containing OpenSBI and U-Boot (and a DTB). This is similar to, but incompatible with, mainline U-Boot SPL, which expects a FIT image.

The version of mkimage you just compiled contains rudimentary support for making TOC1 images. Since a TOC1 can contain multiple items, we must create a config file telling mkimage where to find them. Use the following content, adjusting the path to OpenSBI as needed: [opensbi] file = ../opensbi/build/platform/generic/firmware/fw_dynamic.bin addr = 0x40000000 [dtb] file = arch/riscv/dts/sun20i-d1-nezha.dtb addr = 0x44000000 [u-boot] file = u-boot-nodtb.bin addr = 0x4a000000

Now, continuing in the U-Boot build directory, create the TOC1: vim toc1.cfg # or your editor of choice; see above tools/mkimage -T sunxi_toc1 -d toc1.cfg u-boot.toc1

You should get output that looks like this: Allwinner TOC1 Image Size: 592896 bytes Contents: 3 items 00000000:00000490 Headers 00000600:00018720 => 40000000 opensbi 00018e00:00007387 => 44000000 dtb 00020200:00070820 => 4a000000 u-boot

Now you can write this TOC1 to your SD card. Note the large (16+ MiB) offset! You will need to leave a gap before your first partition; 20 MiB should be plenty. (Or you can change UBOOT_START_SECTOR_IN_SDMMC</tt> in include/spare_head.h</tt> in boot0.) sudo dd if=u-boot.toc1 of=/dev/sdX bs=512 seek=32800

If boot0 fails to load from the SD card sector 32800, it falls back to loading from the backup sector 24576. So it makes sense to write a U-Boot backup there: sudo dd if=u-boot.toc1 of=/dev/sdX bs=512 seek=24576

(While the above instructions will compile both U-Boot proper and U-Boot's SPL, this SPL is unused for now and can be ignored.)

Mainline kernel
A WIP branch is available at https://github.com/smaeul/linux/commits/riscv/d1-wip which supports enough hardware for headless use (Audio, Ethernet, MMC, SPI NAND, USB). It relies on some T-HEAD MMU patches that may not get merged upstream.

Use the devicetree from U-Boot (already in DRAM at $fdtcontroladdr</tt>). Do not load a DTB from storage.

= Tips, Tricks, Caveats =

FEL mode
The FEL</tt> button triggers FEL mode.

The xfel tool has support for the D1 chip. Currently sunxi-fel</tt> (from Sunxi-tools) lists the SoC as unknown</tt>.

JTAG
While in FEL mode, run `xfel jtag` to enable JTAG access.

Use an adjusted copy of Sipeed's config file ( https://github.com/orangecms/RV-Debugger-BL702/tree/nezha ) with OpenOCD for RISC-V:

openocd --file tools/openocd/openocd-usb-sipeed.cfg Open On-Chip Debugger 0.11.0-rc1+dev-00001-g0dd3b7fa6-dirty (2020-12-24-20:50) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html SiPEED USB-JTAG/TTL Ready for Remote Connections Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : clock speed 1000 kHz Info : JTAG tap: riscv.cpu tap/device found: 0x08052b43 (mfg: 0x5a1, part: 0x8052, ver: 0x0) Error: riscv.cpu: IR capture error; saw 0x1f not 0x01 Warn : Bypassing JTAG setup events due to errors Error: dtmcontrol is 0. Check JTAG connectivity/board power. Warn : target riscv.cpu.0 examination failed Info : starting gdb server for riscv.cpu.0 on 3333 Info : Listening on port 3333 for gdb connections Info : accepting 'gdb' connection on tcp/3333

TODO: figure out the "examination"

Enabling U-Boot command line
The preinstalled version of U-Boot requires holding down "S" during boot to enter the command line. From a booted Linux system (like the Tina Linux preinstalled in the on-board NAND) run the following command to set a three second delay during which it's possible to enter the command line on the built-in serial port:

fw_setenv bootdelay 3

Note: With the Debian image being shipped - http://mirrors.perfxlab.cn/debian-ports the fw_setenv and fw_printenv are not aligned to the saveenv location. Debian GNU/Linux 11 RVBoards ttyS0 Linux RVBoards 5.4.61 #22 PREEMPT Wed Jun 16 07:27:49 UTC 2021 riscv64 Configuration file wrong or corrupted
 * 1) fw_printenv

Default Firmware Environment
The default firmware environment for the TinaLinux board:

root[at]TinaLinux:/# fw_printenv earlyprintk=sunxi-uart,0x02500000 initcall_debug=0 console=ttyS0,115200 nand_root=/dev/ubiblock0_5 mmc_root=/dev/mmcblk0p5 mtd_name=sys rootfstype=squashfs root_partition=rootfs boot_partition=boot init=/sbin/init loglevel=8 cma=8M mac= wifi_mac= bt_mac= specialstr= keybox_list=widevine,ec_key,ec_cert1,ec_cert2,ec_cert3,rsa_key,rsa_cert1,rsa_cert2,rsa_cert3 dsp0_partition=dsp0 setargs_nand=setenv bootargs ubi.mtd=${mtd_name} ubi.block=0,${root_partition} earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} rootfstype=${rootfstype} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1 setargs_nand_ubi=setenv bootargs ubi.mtd=${mtd_name} ubi.block=0,${root_partition} earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} rootfstype=${rootfstype} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1 setargs_mmc=setenv bootargs earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root} rootwait  init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1 boot_dsp0=sunxi_flash read 45000000 ${dsp0_partition};bootr 45000000 0 0 boot_normal=sunxi_flash read 45000000 ${boot_partition};bootm 45000000 boot_recovery=sunxi_flash read 45000000 recovery;bootm 45000000 boot_fastboot=fastboot bootcmd=run setargs_nand boot_dsp0 boot_normal bootdelay=0

= Adding a serial port =



The DEBUG</tt> header at the top-right corner of the board can be used as a serial port. See the UART howto for instructions about how to attach to it. The default baud rate is 115200.

= Adding a reset pin =

The test pin T6, as per the manual and verified, is the reset pin (RST). A wire can be attached to it, and for convenience, routed to one of the N/C (not connected) pins on the GPIO header. It can be used for test and development automation.

= Development and test automation =

A simple strategy for test automation and bringup development is as follows:


 * attach a wire to the FEL button (possibly route to an N/C pin on the GPIO header)
 * attach a wire to the reset pin
 * attach to the UART interface
 * connect to the USB-C OTG
 * connect to the ethernet port

To test an firmware/OS image, hold FEL, trigger reset, release FEL, then use xfel to bring up DRAM, load the image, and execute it. Watch the output on the UART, try input, and see if the device becomes visible on the network.

This can be fully automated, e.g., using another development board offering all the necessary interfaces. It can be instrumented via CI, e.g., as a GitLab runner using ConTest.

= Pictures =

= Schematic =


 * V1.0 board schematic
 * V1.0 board layout and silkscreen

= Also known as =

= See also =


 * IndieGogo campaign
 * Data gathering thread on whycan.com (chinese)

Manufacturer images

 * D1_Nezha_HDMI_test_firmware Image from whycan.com (requires regristration)