Pine64

The Pine64 is a cost-optimized board sporting ARMv8 (64-bit ARM) capable cores.

= Identification = There is a pine cone like logo next to the uSD slot, also it says "Pine64" under the logo. Also on the SoC there is a quite prominent "A64" print.

On the back of the device, the following is printed: Designed in Silicon Valley, California. Built in Silicon Delta, China.

The PCB has the following silkscreened on it: A64-DB-Rev B 2015-12-17

In android, under Settings->About Tablet, you will find:
 * Model Number: Pine A64
 * Build Number: tulip_t1-eng 5.1.1 LVY4BE 20151210 test-keys

Different models
So far there are three different models:
 * The Pine64 with 512MB DRAM
 * The Pine64+ with 1GB DRAM
 * The Pine64+ with 2GB DRAM

The last two seem to be identical apart from the installed DRAM size. Differences between the Pine64 and the Pine64+ are:
 * The Pine64 only supports Fast Ethernet. So the PHY chip will be a Realtek 8201 instead of the 8211 on the bigger model. The 8211 speaks RGMII, while the 8201 is using the MII interface. This requires differences in the DT.
 * The smaller model will lack the connectors for the touchscreen, LCD screen and the camera port.

= Sunxi support =

Current status
Boots recent kernel (4.4) with some patches and basic support: SMP, UART, MMC (uSD card), RTC, GPIO (and clocks, timer, pinctrl, of course). At the moment uses the firmware from the Android image, which requires the kernel (and if needed the initrd) to be packaged into an Android kernel image and dd'ed to an Android partition on the SD card. Booted Ubuntu-Core 14.04-3 AArch64 from an SD partition successfully.

Find more information in the firmware log and kernel dmesg.

Images
Get a first, basic image here. For instructions see the README.md in there for now.

longsleep has also built a mimimal Ubuntu image combined with the the BSP Kernel that can be downloaded here. You will find instructions here on how to set it up.

This image is intended for developers and comes with the following:


 * BSP Linux Kernel 3.10.65+
 * BSP U-Boot
 * Ubuntu Ubuntu 16.04 (Xenial Xerus) aarch64
 * HDMI at 1080P
 * HDMI analog audio (alsa, pulseaudio)
 * Ethernet (including 1000M)
 * USB
 * Wifi

BSP
Allwinner's BSP contains an arm64 Linux kernel based on Linaro's LSK-3.10.65 (includes Linaro and Android patches). It has some nasty patches on top which require the kernel to be entered in Aarch64 EL3 mode. This violates the Linux arm64 booting protocol and prevents upstream kernels to be booted with the Allwinner firmware in that bundle.

This released/leaked code does not match what's on the provided Android images. The firmware in the image enters the kernel in (secure) EL1, which is officially not supported, but happens to work so far.

Manual build
You can build things for yourself by following our Manual build howto and by choosing from the configurations available below.

Sunxi/Legacy U-Boot
The U-Boot tree in the BSP package (using a sun50iw1p1 target) does not compile, also the port in there is only for 32-bit. To boot 64-bit kernels, they use a custom smc call into the Allwinner version of the ARM Trusted Firmware code, which returns to a given address in 64-bit state. It will thus enter the kernel in the non-secure EL1 AArch64 exception level, which denies any virtualization (KVM or Xen) to be used.

The U-Boot from the supplied Android image is severely crippled:
 * It can only read from its own partitions. Those partitions are described in a table located at exactly 20 MB in the SD card and follow their NAND partitioning scheme, described also here. They can, but don't need to follow the DOS partitioning scheme on the card. A tool to create this table will be published later.
 * Although there is a MMC command and U-Boot apparently can access the SD card, it does not allow any U-Boot magic with it, so no direct loading or accessing filesystems.
 * Of course there is no network support whatsoever.
 * Booting kernels is also limited to either the bootm or boota commands. bootm expects an U-Boot image file (uImage), but it needs to be tagged as architecture "arm" (not arm64), because the running U-Boot is actually 32-bit. Consequently it also just treats it as an ARM(32) kernel, so it will not boot an arm64 kernel (but haven't actually tested whether an ARM(32) kernel would work).
 * So only boota works, because only this is wired up to do the RMR access to reach 64-bit mode. Boota expects an "Android boot image", which is described here and can be created with the Python script from the same location.
 * Although this U-Boot version is very DTB savvy (it uses the DTB for itself even), the DT is full of non-standard nodes and properties. No upstream kernel can even closely boot with that. Although the DT can be found (and changed) at the offset 0x1383000 on the SD card, replacing it is not a real option, since U-Boot will most likely refuse to boot unless given the expected DTB. It needs to be worked out whether one could provide a DT that satisfies both world, but that sounds quite hackish anyway.
 * Loading a DT at an arbitrary address in memory will not work either, because the boota command will always supply the U-Boot internal DTB to the kernel. The only way to get something working is to actually replace the DTB in the U-Boot data segment(!) and hope for the best. Luckily the supplied DT is rather big (68K), so there is plenty of space to use for that. Just be sure to not write beyond that or U-Boot will crash (tested ;-)

Mainline U-Boot
No support yet.

Mainline kernel
No support yet, but being worked on.

= Tips, Tricks, Caveats =

Boot sequence
The A64 SoC is wired to come out of reset in 32-bit monitor mode. As other Allwinner devices, the A64 SoC starts executing BROM code (mapped at address 0), which is consequently ARM32 code. The complete BROM code can be found at address 0x2c00 and has a total length of 32KB. To enter FEL mode, power on the board without a SD card inserted. If the code does not detect a FEL condition, it will load 32KB from sector 16 (8 KByte) of the microSD card to SRAM and will execute this. At least the first instructions of this code need to be still 32-bit ARM code.

The Allwinner firmware continues in 32-bit, loading U-Boot (32-bit also) from the microSD card at sector 38192 (19.096 KByte). It also loads a (hacked) version of ARM Trusted Firmware (ATF) into DRAM and code for the arisc management core into SRAM. Finally it does a RMR write to warm-reset the SoC in AArch64 execution state and jumps to the ATF entry point by putting its address in the RVBAR register. ATF will then initialize the boot core for non-secure execution and drop to non-secure AArch32 EL1 to run U-Boot.

U-Boot then runs happily in 32-bit. Only just before it starts the kernel, it uses a custom smc service call back into (Allwinner's version of) ARM Trusted Firmware to hand over the kernel entry point. The ATF code will then return into _AArch64_ non-secure EL1, but using the provided kernel entry point instead of returning to U-Boot.

FEL mode
The Pine64 board will fail over to FEL mode if it doesn't detect a card present in the µSD slot.

A tricky and potentially confusing part is that the only Micro USB receptacle (labelled as "POWER JACK") is used exclusively for providing power to the board and is not connected to any USB controller in the SoC. The actual USB OTG controller in the SoC is connected to the upper USB host receptacle. So it needs a somewhat special USB cable (A male to A male) or an adapter (A male to Mini/Micro B female) to connect your Pine64 board to your desktop PC, which is running the sunxi-fel tool.

As soon as you boot your Pine64 into FEL mode (remember, don't insert a SD card) you should find a new USB device:

$ lsusb Bus 001 Device 005: ID 1f3a:efe8

$ ./sunxi-fel version AWUSBFEX soc=00001689(A64) 00000001 ver=0001 44 08 scratchpad=00017e00 00000000 00000000

Expansion headers
Documentation about the pin assignments and more specifications (like the physical dimensions of the board) can be found in the Hardware section of the official Pine64 Wiki.

AXP803 PMIC
The default voltages after cold boot seem to be at least a little bit off. For example, the voltage on the Euler connector's 3.3V pin is in fact 3.0V until the Allwinner's bootloader configures the PMIC (very likely the default voltage from DCDC1). It means that the U-Boot bootloader will have to configure AXP803 early and relying on the defaults is not a very good idea.

The DRAM voltage is provided from DCDC5, which is set to 1.5V by default according to the AXP803 manual. Moreover, the AXP803 manual is explicitly recommending to use DCDC5 specifically for DRAM. This is safe even with 1.35V DDR3L chips, because they are compatible with 1.5V too.

CPU clock speed limit
The voltage-frequency table for Allwinner A64 can be found in FEX files included in the A64 SDK: Based on the data from this table, 1152MHz @1.3V is the fastest cpufreq operating point. Additionally, the AXP803 PMIC uses 1.1V default voltage for DCDC2/DCDC3 (VDD-CPU). Which means that the the CPU can be safely clocked up to 816MHz before the PMIC is initialized.
 * dvfs voltage-frequency table configuration
 * max_freq: cpu maximum frequency, based on Hz
 * min_freq: cpu minimum frequency, based on Hz
 * lv_count: count of lv_freq/lv_volt, must be < 16
 * lv1: core vdd is 1.30v if cpu frequency is (1104Mhz, 1152Mhz]
 * lv2: core vdd is 1.26v if cpu frequency is (1008Mhz, 1104Mhz]
 * lv3: core vdd is 1.20v if cpu frequency is (816Mhz, 1008Mhz]
 * lv4: core vdd is 1.10v if cpu frequency is (648Mhz,  816Mhz]
 * lv5: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv6: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv7: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv8: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv6: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv7: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]
 * lv8: core vdd is 1.04v if cpu frequency is (480Mhz,  648Mhz]

= Serial port / UART =



The board connects 4 of the SoCs UART to easily accessible header pins. There is UART2 on the RPi connector, also UART3 and UART4 on the Euler connector. UART0 is the main UART used by Allwinner's firmware for boot and debug messages and is accessible on pins 29 (TXD), 30 (RXD), 25/34 (GND) on the Euler connector (this is not mentioned in the official connector description). Alternatively you can use the UART0 on the EXP connector, accessible on pins 7 (TXD), 8 (RXD), 9 (GND). The RX pin on there is connected via a FET to the SoC's pin, so it prevents injecting power via this line.

Using screen to connect to the UART0 for example on OS X:

$ sudo screen /dev/cu.usbserial 115200

All of the UARTs use 3.3V voltage levels. Look at UART howto for further instructions.

A connected UART cable is leaking power and this causes some annoyances. For example, unplugging and plugging back a power cable does not reboot the board cleanly. Thus ensuring the availability of a reset button is recommended for doing any reasonable software development.

The board does not have a hardware reset button out of the box, but a button can be easily connected to the appropriate pin on the expansion connector. Also a standard micro switch (upright version) can be soldered on the board next to the USB sockets to ease early development ;-)

Successful UART Serial Console
This paragraph describes a successful connection providing a UART Serial Console on a Linux Host. The PINE64 board used is a 2GB version (A64-DB-2B-Rev 6). The connection is provided by a FTDI TTL-232R-RPi 3-wire cable purchased from Digikey:


 * FTDI TTL-232R-RPi

The successful connection is made on the EXP connector:


 * Connect the Black GND wire to Pin 6 of the EXP connector.
 * Connect the Yellow RX wire to Pin 7 of the EXP connector.
 * Connect the Orange TX wire to Pin 8 of the EXP connector.

Plug the FTDI TTL-232R-RPi USB end into your Linux host. Note the power LED on the PINE64 will illuminate at about half intensity. Now find the tty that has been assigned to the FTDI TTL-232R-RPi by opening a terminal window and typing $dmesg. The last group of messages will show you how Linux has mapped the FTDI TTL-232R-RPi to the tty. In my case the output appears as:

[308564.376087] usb 3-1.1: new full-speed USB device number 10 using ehci-pci [308564.474534] usb 3-1.1: New USB device found, idVendor=0403, idProduct=6001 [308564.474541] usb 3-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [308564.474545] usb 3-1.1: Product: TTL232R-3V3 [308564.474548] usb 3-1.1: Manufacturer: FTDI [308564.474551] usb 3-1.1: SerialNumber: FT99JN2P [308564.476846] ftdi_sio 3-1.1:1.0: FTDI USB Serial Device converter detected [308564.476906] usb 3-1.1: Detected FT232RL [308564.477263] usb 3-1.1: FTDI USB Serial Device converter now attached to ttyUSB0

The final line of the output indicates the FTDI USB Serial Device has been assigned to ttyUSB0. Now open a screen session with:

$sudo screeen /dev/ttyUSB0 115200

Boot the PINE64 and you should see output in the terminal window on your Linux host.

= Pictures =

Pine64 (512 MB)
= See also = wiki.pine64.org Further info on the hardware and firmware

forum.pine64.org Discussion on pine64

Manufacturer images
Pine A64 Android release and Linux BSP