Hi,
I have two rk322x TV boxes (RK3229 with SSV6051 SDIO wifi) where wlan0 is created
but never comes up on Armbian. Both boxes had working wifi on their original Android
firmware. I instrumented the driver to trace this and would appreciate input from
anyone familiar with ssv6051.
SYSTEM
Board rk322x-box (Generic RK322x TV Box, RK3229)
Armbian 26.11.0-trunk.25 trixie, BRANCH=current
Kernel 6.18.46-current-rockchip
Wifi chip SDIO 0x3030:0x3030, "SouthSiliconValleyInc. / Cabrio"
Driver ssv6051 (in-tree, from Armbian's wifi-driver-ssv6051.patch)
Firmware /lib/firmware/ssv6051-sw.bin and ssv6051-wifi.cfg both present
SYMPTOM
The SDIO card enumerates and wlan0 appears, but bringing it up fails:
# ip link set wlan0 up
RTNETLINK answers: Operation not permitted
dmesg:
ssv6051 mmc1:0001:1: device id: 3030:3030
SSV WLAN driver ssv6200: Chip identity from efuse: 00000000
SSV WLAN driver ssv6200: Using SSV6051Q setting
SSV WLAN driver ssv6200: Unexpected register value
WARNING: CPU: 0 PID: 282 at drivers/net/wireless/ssv6051/smac/init.c:1044
ssv6xxx_dev_probe+0x1540/0x1870 [ssv6051]
...
SSV WLAN driver ssv6200: chip id: RSV6200A0-201311, tag: 2014012420010960
SSV WLAN driver ssv6200: Failed to allocate packet buffer of 904 bytes in 0 type.
SSV WLAN driver ssv6200: opps allocate pbuf error
WARNING: CPU: 2 PID: 2652 at drivers/net/wireless/ssv6051/smac/init.c:608
ssv6xxx_init_mac+0xc28/0xc30 [ssv6051]
SSV WLAN driver ssv6200: Failed to initialize mac, ret=1
The two WARNINGs are the two places in the driver that verify a register write by
reading it back: init.c:1044 (ADR_TRX_DUMMY_REGISTER) and init.c:608 (pbuf alloc).
WHAT I DID
I rebuilt ssv6051 out-of-tree against 6.18.46 headers with logging added to
ssv6xxx_sdio_write_reg() and ssv6xxx_pbuf_alloc(), so every register write shows
its address, value, the ioport it went through, and the return code.
FINDING 1 - the SDIO transport reports no problem at all
- ioport_reg = 0x10020, read correctly via cmd52 in ssv6xxx_sdio_read_parameter()
- all 303 register writes during probe return ret=0 from sdio_memcpy_toio()
- /sys/kernel/debug/mmc1/err_stats is all zeros, including during the failure:
no command timeout, no command CRC, no data timeout, no data CRC, no controller
timeout, no unexpected IRQ
- the driver's own counter reports "sdio cmd52 fail: 0"
- reads are stable and repeatable: the ROM ID reads back "RSV6200A0-201311"
identically on every attempt
FINDING 2 - but no register write ever persists, in any block
Test run from inside the driver (not through debugfs), writing 0x12345678 to one
register in each hardware block, immediately after the MAC reset in
ssv6xxx_init_mac():
address block original wrote read back result
0xce010040 RF 0x00550800 0x12345678 0x00550800 not written
0xce000050 PHY 0x00000000 0x12345678 0x00000000 not written
0xc0001d10 SYS 0x00000000 0x12345678 0x00000000 not written
0xc6002508 MAC 0x00000000 0x12345678 0x00000000 not written
0xc1000034 HCI 0x00000008 0x12345678 0x00000008 not written
0xcd010008 ID_MNG 0x00000000 0x12345678 0x00000000 not written
0xcf000004 MMU 0x00000000 0x12345678 0x00000000 not written
Same picture for the driver's real init_mac() writes. Every one of these registers
still holds the reset default defined in ssv6200_reg.h:
register address driver wrote chip contains reset default
ADR_CONTROL 0xc1000000 0x12000006 0x02700008 0x02700008
TRX_ID_THRESHOLD 0xcd010020 0x01ee3c13 0x01ee3c3c 0x01ee3c3c
ID_LEN_THRESHOLD1 0xcd010038 0x000e6731 0x000f0641 0x000f0641
TXQ4_MTX_Q_AIFSN 0xc6002504 0xffff2101 0x0000a502 0x0000a502
MMU_CTRL 0xcf000000 0x00ff6042 0x00006042 -
So the chip answers reads perfectly and acknowledges writes at the SDIO layer, but
the values never land.
FINDING 3 - this is what makes pbuf allocation fail
ssv6xxx_pbuf_alloc() writes the requested size to ADR_WR_ALC and reads it back,
retrying up to 20 times:
SSVDBG wr addr=0xcd010000 val=0x00000388 ioport_reg=0x10020 ret=0 (x20)
SSVDBG pbuf size=904 type=0 alc=0x00000000 mmu=0x00006042 r04=0x00000213
ctl=0x02700008
alc reads back 0 on all 20 attempts, so the driver hits "opps allocate pbuf error"
and takes the goto exit. Because that exit happens before SMAC_LOAD_FW(), the
firmware is never downloaded: "attempt to load firmware" never appears in dmesg,
and ssv_cmd reports "Firmware image version: 0".
Worth noting: the MAC soft reset immediately before this (the ADR_BRG_SW_RST poll
loop) does not report "MAC reset fail", so that particular write-then-poll appears
to succeed.
WHAT I HAVE ALREADY RULED OUT
Kernel version
Tested 6.6.16-current-rockchip (Feb 2024) on the same box. Byte-identical
failure: same warnings, same addresses, same messages. So this is not a
regression introduced between 6.6 and 6.18.
Device tree
I extracted the original Android DTB from the resource partition of a box that
was never reflashed, decompiled it, and compared against Armbian's
rk322x-box.dtb. Each difference was tested with a real reboot:
- GPIO polarity. Android declares
WIFI,poweren_gpio = <&gpio2 26 GPIO_ACTIVE_HIGH>
while Armbian uses
reset-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>
Same pin, opposite polarity. Rebuilding the DTB with ACTIVE_HIGH makes the
card stop enumerating entirely ("mmc1: Failed to initialize a non-removable
card"), so Armbian's polarity is the correct one.
- SDIO pin drive strength. Android uses 4mA (pull-none on clk, pull-up on
cmd/data); Armbian uses 2mA (pull-down on clk). Rebuilt the DTB with 4mA to
match Android. No change.
- SDIO clock. Forced max-frequency to 12.5 MHz and added
post-power-on-delay-ms = 200 to the pwrseq node. No change.
- io-domains. Both already map vccio2 to vccio_1v8. Identical.
Power sequence
Rockchip's own ssv6051-generic-wlan.c has the rockchip_wifi_power() and
rockchip_wifi_set_carddetect() calls commented out inside ssv_wifi_power();
the function only does msleep(150). Armbian's generic-wlan does msleep(120).
Functionally equivalent, so there is no missing power-on step.
Driver build configuration
CONFIG_PLATFORM_SDIO_OUTPUT_TIMING=3, CONFIG_PLATFORM_SDIO_BLOCK_SIZE=128 and
CONFIG_SSV_CABRIO_E are identical between the Android build (readable in the
debug_info of the Android .ko) and Armbian's platform-config.mak.
ret_if_not_ready()
Fires 0 times during probe and during the up. It only appears on module unload,
so it is not blocking any of the writes.
Driver-level config options
Tried force_triger_reset, force_chip_identity, disabling HT/AMPDU/AP to reduce
buffer demand, and switching volt_regulator between LDO and DCDC. No change.
Hardware
Two independent boxes behave identically, and both had working wifi under their
original Android firmware, so I do not believe this is a dead chip.
QUESTION
Has anyone got SSV6051 working on rk322x with a mainline kernel?
Reads work perfectly, cmd52/cmd53 report no errors, err_stats stays at zero, and
writes are acknowledged at the SDIO layer, yet nothing lands in the chip. My
remaining suspicion is something in the SDIO write path itself - sdio_memcpy_toio()
to ioport_reg, or block-mode versus byte-mode transfer - that differs from what the
3.10 Android driver did. I could not confirm that without a logic analyzer on the
bus.
I am happy to run any test you suggest. I can also provide the full instrumented
dmesg, the extracted Android DTB, and the Android ssv6051.ko (vermagic 3.10.104)
if any of that is useful for comparison.
Thanks
android_1536.dtb
rfkill-wlan.c
sec0.bin