Identity
| Part | Voltafield AF8133J |
| Role | 3-axis magnetometer (compass) |
| Bus / address | DTS &i2c4 addr 0x1c; FreeBSD logs shifted addr 0x38 on iicbus3 |
| GPIO / IRQ | Reset on GPIO1_A1 per mainline Linux DTS; DRDY IRQ delivery is not wired yet |
| Datasheet | AF8133J (Voltafield, datasheet behind login); Linux driver and DTS are the public references |
| Pine64 wiki | PinePhone Pro — Sensors |
| Schematic | sheet 11 (sensor cluster on i2c4, shared with MPU-6500) |
Status — ● working
Verified live on 2026-05-03 (kernel #141, head 3b6cb7b):
magnetometer0: <PinePhone Pro magnetometer (AF8133J)> at addr 0x38 on iicbus3
magnetometer0: af8133j detected (reg[0x01]=0x00 reg[0x00]=0x5e)
$ sysctl dev.magnetometer.0
dev.magnetometer.0.x_raw: -1553
dev.magnetometer.0.y_raw: -211
dev.magnetometer.0.z_raw: 992
dev.magnetometer.0.raw_id_reg00: 94 # 0x5e — AF8133J product code
dev.magnetometer.0.chip_variant: af8133j
dev.magnetometer.0.last_sample_error: 0
The earlier “partial” status hid two real bugs that took the 2026-05-02 dtb refresh and a follow-up driver fix to clear:
- Stale dtb on the phone. The compass node only entered the
PinePhone Pro DTS on 2026-04-30 (
83ab0d0magnetometer: i2c4@0x0c probe scaffold (AK09911 vs AF8133J) ), but the phone was still booting the Apr-22 base dtb that lacked it. Without the DT node, FreeBSD’s iicbus probe never reached the driver. Redeploying/boot/dtb/rk3399-pinephone-pro.dtbfixed that half. - Reset-gpio polarity. AF8133J holds its I2C interface in
NACK while the active-low reset line is asserted, so the
driver’s WIA read returned errno 2 (
IIC_ENOACK). Thereset-gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_LOW>property in DT was being ignored — the driver did no GPIO setup at all.31c69f6magnetometer: deassert reset-gpio before first I2C read added the lookup;3b6cb7bmagnetometer: fix reset-gpio polarity in attach pulse fixed the polarity (the release sequence has to end withset_active(false)for an active-low pin, otherwise the chip stays held in reset).
Earlier project notes mixed the original PinePhone’s AK09911/LIS3MDL
alternatives into the PinePhone Pro table. The PPP wiki and mainline
Linux DTS identify the populated part as AF8133J at &i2c4/0x1c,
so the local DTS uses
compatible = "voltafield,af8133j" and reg = <0x1c>. The driver still
keeps the AK09911 detection arm as harmless fallback code, but the bench
predicate for this phone is AF8133J attach and a moving raw sample:
sysctl dev.magnetometer.0.chip_variant
sysctl dev.magnetometer.0.x_raw dev.magnetometer.0.y_raw dev.magnetometer.0.z_raw
sysctl dev.magnetometer.0.last_status dev.magnetometer.0.last_sample_error
The implementation deliberately stays in polling mode for first bring-up.
Single-shot samples are serialized with a sleepable sx lock so the I2C
transfer path is not hidden under a default mutex. The DRDY GPIO interrupt
path can land after the raw samples move when the phone rotates.
Validation state: working on hardware. The PinePhone Pro boot on
2026-05-03 identified the populated part as AF8133J and returned raw XYZ
samples (x_raw=-1553, y_raw=-211, z_raw=992) with the expected
chip_variant=af8133j. Remaining work is calibration and event delivery,
not first samples.
Driver
- Our tree:
src/sys/dev/iicbus/magnetometer.c— probe + AF8133J polled single-shot raw axis reads. - Linux mainline (AF8133J):
drivers/iio/magnetometer/af8133j.cand mainlinerk3399-pinephone-pro.dtscompass@1c. - PINE64 wiki: lists the PinePhone Pro geo magnetic sensor as AF8133J, with Linux exposing it at
/sys/bus/i2c/devices/4-001c/.
The AF8133J needs a periodic temperature-compensation kick. It can report ready samples on a DRDY GPIO; the first FreeBSD pass polls instead at modest power cost.
Parity verification
The artifact set is small but high-signal — it tells us whether the chip
answers on the documented address. mise run debug:sensors:phone
captures these magnetometer
predicates in the same read-only receipt as the proximity, accel/gyro,
thermal, and eFuse sysctls:
-
dmesg at attach:
magnetometer0: <PinePhone Pro magnetometer (AF8133J)> at addr 0x38 on iicbus3 magnetometer0: af8133j detected (reg[0x01]=0xNN reg[0x00]=0x5e) -
sysctl:
$ sysctl dev.magnetometer.0.chip_variant dev.magnetometer.0.chip_variant: af8133j $ sysctl dev.magnetometer.0.raw_id_reg01 dev.magnetometer.0.raw_id_reg00 dev.magnetometer.0.raw_id_reg01: NN dev.magnetometer.0.raw_id_reg00: 94raw_id_reg00should normally be0x5e, Linux’s AF8133J product-code constant. The driver still accepts0x33as older-project-note evidence, but any other byte should be treated as a board/DTS mismatch until proven otherwise. -
Raw sample:
$ sysctl dev.magnetometer.0.x_raw dev.magnetometer.0.y_raw dev.magnetometer.0.z_raw dev.magnetometer.0.x_raw: -123 dev.magnetometer.0.y_raw: 456 dev.magnetometer.0.z_raw: -789The absolute numbers are not useful until calibrated. The bench predicate is motion: rotate the phone 90 degrees on a table and at least two axes should change sign or magnitude materially.
last_sample_error=0means the last single-shot read completed;ETIMEDOUTmeans the data-ready bit never set. -
Cross-check from a Linux PPP image:
pmos$ cat /sys/bus/iio/devices/iio:device*/name af8133jFreeBSD’s
chip_variantsysctl should match. -
Falsifier: if the attach line prints
unknown magnetometer: reg[0x01]=0xXX reg[0x00]=0xYY, the populated part is not the AF8133J documented for the PinePhone Pro. Capture both bytes and look them up before adding another dispatch arm.
Implementation plan
The remaining work is now calibration and event delivery, not first samples:
-
AF8133J path:
- Raw sysctls perform software reset, select the Linux-default 12-gauss
range at attach,
put the chip into work state, poll
STATUS.ACQ, and read 6 bytes fromOUT. - Next: add scaled values using Linux’s range table and calibrate against known orientations.
- Reference:
drivers/iio/magnetometer/af8133j.c.
- Raw sysctls perform software reset, select the Linux-default 12-gauss
range at attach,
put the chip into work state, poll
-
Compass heading in userland —
atan2(my, mx) * 180/π, tilt-compensated using the MPU-6500 accelerometer once both sensors are calibrated against a known orientation. -
DRDY GPIO IRQ wiring — the DTS currently mirrors mainline Linux’s
reset-gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_LOW>. Add a real interrupt resource only after the polled path is proven and the AF8133J DRDY wiring is confirmed.
Related
- Where we are — current sensor status.
- Hardware reference — chip manifest.