Banana Pi M64 (Allwinner A64): everything wired on the board works on FreeBSD 15.1

From: Andrey Bodrov <ap.bodrov_at_gmail.com>
Date: Mon, 12 Oct 2026 17:18:35 UTC
Hi,

I've been bringing up FreeBSD 15.1 on a Banana Pi M64 (Allwinner A64), and
every peripheral on the board that has something connected to it now works.
Here is a summary for anyone else with A64 hardware.

A caveat first: FreeBSD runs as a guest under a small EL2 hypervisor I
wrote (bzdk). It started because I could not be bothered to find a USB-TTL
adapter: the hypervisor gave me a console and a debugger over raw Ethernet
and the USB gadget port instead, and it grew from there. It keeps a few
blocks and gives them to FreeBSD as virtio devices or emulates them: EMAC
(virtio-net), SD and eMMC (virtio-blk), the HDMI/display engine
(framebuffer plus a DE2 video plane), the watchdog and the MUSB OTG port.
The RSB/PMIC bus is shared through trap emulation. FreeBSD drivers run
everything else directly.

Working:

- GPU: Mali-400 through a FreeBSD port of lima. DRM/KMS, PRIME and Mesa all
work, including zero-copy rendering to scanout.
- Video decode: Cedrus MPEG-2 and H.264 stateless decoders on a native V4L2
core (no LinuxKPI). H.264: 176 of the 231 streams of the JVT conformance
suite decode, with 19,028 of 19,028 frames identical to the reference
decode (JM/FFmpeg), including PAFF and MBAFF interlaced streams. The other
55 use 10/14-bit, 4:2:2, FMO or SP/SI and are refused by the driver; those
did not work in my measurements, and I have not proven that to be a silicon
limit. MPEG-2 is within ±2 per sample of FFmpeg (the IDCT is not
bit-exact). FFmpeg v4l2request playback goes to a KMS plane without a CPU
copy.
- WiFi: BCM43430 over SDIO with a port of OpenBSD's bwfm(4) to net80211.
Both STA (WPA2-PSK) and hostap work. The firmware does the 4-way handshake,
so no wpa_supplicant or hostapd is needed: the PSK goes in with "ifconfig
wlan0 wpakey ...".
- Bluetooth: the BCM43438 on uart1 works with a new bcmbt(4) and a revived
ng_h4(4). ng_h4 was removed in 2021 (79a100e28e3c) for lack of interest;
this version is rewritten on the ttyhook API. Patchram loads at boot, and
inquiry, remote name and l2ping to a laptop work. Nothing above L2CAP has
been tested yet, and the UART stays at 115200. The patches apply to both
15.1 and main and include man pages.
- Audio: analog codec, pcm playback and record.
- USB host (EHCI/OHCI), SPI, the four I2C buses plus R_I2C, PWM and R_PWM,
uart2-4 on the header, GPIO, LEDs, IR, thermal and RTC.
- PMU with hwpmc (counting and sampling), and cpufreq 648-1152 MHz with
powerd.

Left off:

- Camera: no sensor on the board.
- DSI: HDMI is used instead.
- LRADC: no buttons are wired to it.
- Crypto engine: armv8crypto is faster.
- SPDIF: nothing is connected.

Bugs found along the way in stock FreeBSD:

- drm-kmod: GitHub pull requests #512 and #514 are merged; #513 and #515
are open.
- ccu_a64: pll_gpu was missing AW_CLK_HAS_GATE (freebsd-src GitHub pull
request #2447). The same class of bug in ccu_a83t's CPUX PLLs is #2448.
- aw_rtc registers clock ids 0 and 2 but not 1, the 32 kHz fanout that the
WiFi/BT chip needs as its low-power clock.
- aw_clk_nkmp: a fixed factor was ORed into the M field, which ran
pll_audio and /dev/dsp 3.8% slow.
- mmc_fdt_parse() ignores node == 0, so mmc-pwrseq never resolves for
aw_mmc, bcm2835_sdhci and sdhci_xenon.
- aw_mmc arms auto-CMD12 for SDIO CMD53. sdiob(4) shares one CCB without
serialising it and does not retry CMD52. There are a few LinuxKPI issues
too. These three are already with the respective maintainers and being
discussed.

Code:

https://github.com/bzdOS/bzdk — hypervisor
https://github.com/bzdOS/lima-freebsd — Mali-400 / lima
https://github.com/bzdOS/freebsd-brcmfmac-sdio — bwfm(4) port, Bluetooth
(ng_h4, bcmbt), SDIO fixes
https://github.com/bzdOS/freebsd-media — V4L2 core, Cedrus decoders

To be clear about where the code comes from: it was written by LLM agents
working under my direction. I set the tasks and judged the results, and
acceptance was by measurement on the board; every number above is a
measurement, not something a model told me. The code is there for whoever
finds it useful. If any part of it is wanted in the tree, tell me what you
need from me.

--
Andrey Bodrov