For a year or so I have been having a problem whereby no matter what I could not get the L5 to be able to pick up the wifi card. I had a ton of trouble figuring it out and even flashed the phone once when it came back for 1 reboot and then started failing again. I largely did this with Grok obviously but hopefully it helps some people experiencing the same issue.
The phone boots, Settings shows no Wi-Fi hardware, nmcli has no wlan0, and a reboot does not help. The radio is usually still there. The Redpine RS9116 driver fails its first probe, then never creates the interface.
Access when Wi-Fi is down is USB serial and/or USB Ethernet (the gadget NCM interface).
What you see
- Settings / Phosh: no Wi-Fi device
ip -br linkhaslo,usb0,wwan0, maybelxcbr0β nowlan0- Hardware kill switch for WLAN is unblocked
- Bluetooth may be missing too (same chip)
That looks like a missing card. Check before you RMA it.
Two different failures
A. The chip never enumerates on SDIO
ls /sys/bus/sdio/devices
# empty
sudo dmesg | grep -iE 'mmc1|9116|redpine'
No 041B:9116, mmc1 may be power mode: off. Then you are in kill-switch / 3V3 / pwrseq / hardware territory. Toggling the WLAN switch or a full power-off is the usual advice.
B. The chip enumerates, then the driver dies (the post-update case)
ls /sys/bus/sdio/devices
# mmc1:fffd:1
cat /sys/bus/sdio/devices/mmc1:fffd:1/uevent
# SDIO_ID=041B:9116
# no DRIVER= line
lsmod | grep redpine
# redpine_sdio and redpine_91x are loaded
ip link show wlan0
# Device does not exist
dmesg looks like this:
redpine_91x: rsi_probe: ***** 9116 Module *****
redpine_91x: rsi_load_firmware: Loading file RS9116_NLINK_WLAN_BT_IMAGE.rps
redpine_91x: Burn Command Pass.. Upgrading the firmware
redpine_91x: Firmware upgradation Done
redpine_91x: ***** Loaded Firmware *****
mmc1: Timeout waiting for hardware interrupt.
redpine_91x: rsi_sdio_read_register_multiple: Synch Cmd53 read failed
redpine_91x: redpine_hal_device_init: Failed to load TA instructions
redpine_91x: rsi_probe: Failed in device init
RSI-SDIO WLAN: probe of mmc1:fffd:1 failed with error 1
The module answered on SDIO. Firmware even flashed. Then a Cmd53 timed out and probe exited. NetworkManager never gets a netdev, so the UI says βno adapter.β
On 6.6.147 the device tree also has cd-gpios on mmc1 (GPIO2_IO12 / SD2_CD_B). If you unbind that host to βresetβ it, USDHC often leaves the bus powered off (mmc1 clock 0, no SDIO devices). Do not unbind 30b50000.mmc.
Immediate recovery (do not unbind mmc1)
If mmc1:fffd:1 exists and wlan0 does not:
- Unload the vendor driver.
- Keep
3V3_WIFIon. - Pulse the two pwrseq reset GPIOs (GPIO3_IO25 and GPIO4_IO29, active-high in the DT), then deassert them.
- Load
redpine_91xandredpine_sdioagain. - Wait for
wlan0(often a few seconds; firmware can take ~15β25 s).
A compact script (needs root and /dev/mem):
#!/usr/bin/env python3
import mmap, os, struct, time, subprocess, sys
GPIO3, GPIO4 = 0x30220000, 0x30230000
WIFI_3V3, RST0, RST1 = 10, 25, 29
def mp(base):
fd = os.open("/dev/mem", os.O_RDWR | os.O_SYNC)
m = mmap.mmap(fd, 0x1000, mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE, offset=base)
os.close(fd)
return m
def rd(m, o):
return struct.unpack_from("<I", m, o)[0]
def wr(m, o, v):
struct.pack_into("<I", m, o, v & 0xFFFFFFFF)
def setb(m, n, lvl):
dr, gdir = rd(m, 0), rd(m, 4)
if not (gdir >> n) & 1:
wr(m, 4, gdir | (1 << n))
dr = rd(m, 0)
wr(m, 0, (dr | (1 << n)) if lvl else (dr & ~(1 << n)))
g3, g4 = mp(GPIO3), mp(GPIO4)
subprocess.call(["modprobe", "-r", "redpine_sdio"])
subprocess.call(["modprobe", "-r", "redpine_91x"])
time.sleep(0.4)
setb(g3, WIFI_3V3, 1)
setb(g3, RST0, 1); setb(g4, RST1, 1)
time.sleep(0.12)
setb(g3, RST0, 0); setb(g4, RST1, 0)
time.sleep(0.4)
subprocess.call(["modprobe", "redpine_91x"])
subprocess.call(["modprobe", "redpine_sdio"])
for i in range(40):
time.sleep(1)
if "wlan0" in os.listdir("/sys/class/net"):
subprocess.call(["ip", "link", "set", "wlan0", "up"])
print("wlan0 up after", i + 1, "s")
sys.exit(0)
print("failed"); sys.exit(1)
Run it as root. If it works, Settings will show Wi-Fi and NetworkManager will reconnect to a saved SSID.
Make it survive reboot
The first probe still fails after an update. Install a oneshot that retries.
Put the recover logic in /usr/local/sbin/librem5-wifi-up: wait for SDIO; if wlan0 never appears, run the recover sequence above. Log to /var/log/librem5-wifi-up.log.
/etc/systemd/system/librem5-wifi-up.service:
[Unit]
Description=Recover Librem 5 RS9116 Wi-Fi after failed first probe
After=systemd-modules-load.service sysinit.target
Before=NetworkManager.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/librem5-wifi-up
TimeoutStartSec=120
[Install]
WantedBy=multi-user.target
Optional udev so it also fires when the SDIO function appears:
ACTION=="add", SUBSYSTEM=="sdio", ATTR{device}=="0x9116", TAG+="systemd", ENV{SYSTEMD_WANTS}="librem5-wifi-up.service"
sudo chmod 755 /usr/local/sbin/librem5-wifi-up
sudo systemctl daemon-reload
sudo udevadm control --reload-rules
sudo systemctl enable --now librem5-wifi-up.service
On a cold boot, wait about a minute. The first probe may still fail; the service then pulses reset and reloads the driver.
How to get a shell when Wi-Fi is dead
USB gadget serial:
screen /dev/cu.usbmodem01234567891 115200 # macOS
# or /dev/ttyACM0 on Linux
Then give USB Ethernet a pair of addresses (example):
# on the phone
sudo ip link set usb0 up
sudo ip addr add 192.168.42.2/24 dev usb0
sudo systemctl start ssh
# on the computer
sudo ip addr add 192.168.42.1/24 dev <usb-ncm-if>
ssh purism@192.168.42.2
Do not use mmcli for this. That is the WWAN modem.