raspberrypi / firmware

This repository contains pre-compiled binaries of the current Raspberry Pi kernel and modules, userspace libraries, and bootloader/GPU firmware.
5.14k stars 1.68k forks source link

[Raspberry Pi 3+] Disabling WiFi breaks Bluetooth in some cases #1611

Open MichaIng opened 3 years ago

MichaIng commented 3 years ago

Describe the bug On some Raspberry Pi 3+ devices, when onboard WiFi is disabled via dtoverlay=disable-wifi, Bluetooth also stops working. According to some forum threads this seems to be the case when WiFi and Bluetooth share the same reset line:

However, there are Raspberry Pi 3+ devices without this issue: https://github.com/MichaIng/DietPi/issues/4512#issuecomment-878613153 This is unexpected since there is only a single revision a020d3. This makes it difficult to know for installers/scripts whether the WiFi disable overlay needs to be removed as well to enable Bluetooth or not.

To reproduce

sed -i '/dtoverlay=disable-/d' /boot/config.txt
echo 'dtoverlay=disable-wifi' > /boot/config.txt
reboot
apt install pi-bluetooth
journalctl -u hciuart

Expected behaviour Disabling WiFi does not disable Bluetooth as well.

Actual behaviour Disabling WiFi disables Bluetooth as well.

System Copy and paste the results of the raspinfo command in to this section. Alternatively, copy and paste a pastebin link, or add answers to the following questions:

Logs

systemd[1]: Starting Configure Bluetooth Modems connected by UART...
btuart[209]: Initialization timed out.
btuart[209]: bcm43xx_init
systemd[1]: hciuart.service: Control process exited, code=exited, status=1/FAILURE
systemd[1]: hciuart.service: Failed with result 'exit-code'.
systemd[1]: Failed to start Configure Bluetooth Modems connected by UART.

Additional context It this is a hardware-wise limitation, not sure if there is a way to have dtoverlay=disable-wifi ignored automatically, as long as Bluetooth is not disabled as well on affected devices? On the other hand I'm not sure whether it's more important to have Bluetooth enabled, when it's expected to be, or to have WiFi disabled, when it's set explicitly via overlay. But probably more important for scripting is whether there is a way to find out in the first place, if the RPi model/system is affected by the issue or not, as the revision code is not sufficient.

pelwell commented 3 years ago

After some discussion in the office the view is that it is possible that the version number wasn't bumped for the 3B+ change, which is a shame. The rev 1.3 3B+ schematic I have still shows the enable signals as two distinct traces, while the 3A+ clearly shows that WL_ON is also wired to the BT_ON of the modem for layout reasons.

Without a revision change it's going to be difficult to distinguish them. Apart from giving the user a way to override the default for the 1.3 3B+ based on experience, the best bet would probably be to probe for the BT modem with the usual BT_ON (GPIO 0 on the expander) low.

You can use a test script something like this:

#!/usr/bin/perl
my $fd;
system("sudo stty -F /dev/serial1 115200 raw time 2 min 0");
die "* failed to open UART\n" if (!open($fd, '+<', "/dev/serial1"));
$fd->autoflush(1);
print $fd ("\x01\x03\x0c\x00");
my $len = sysread($fd, $buf, 10);
printf("BT: %s (%d)\n", $len ? "on" : "off", $len);
close($fd);

This test would be run during installation or before Bluetooth starts up, but for testing purposes disable the HCI startup script (on RPiOS, sudo systemctl disable hciuart).

With the BT_ON line to the modem enabled, the script will provoke it to return a short sequence (usually 7 bytes). When disabled, there is no response and the read returns a length of 0. A manual test might look something like this:

pi@raspberrypi:~$ gpioset gpiochip1 0=0
pi@raspberrypi:~$ ./btprobe
BT: off (0)
pi@raspberrypi:~$ gpioset gpiochip1 0=1
pi@raspberrypi:~$ ./btprobe
BT: on (7)

On a 3B+ with BT_ON slaved to WL_ON both btprobes would succeed.

For a production script you would probably replace the printf with a return code indicating whether or not the modem responded.

MichaIng commented 3 years ago

Many thanks for your detailed answer. Good to know that it is a known behaviour on 3A+.

If I understand it right, this means that dtoverlay=disable-bt has not effect on the affected models, but dtoverlay=disable-wifi disables both, WiFi+BT, and in absence, both are enabled?

Related to the above, does it play a role whether WiFi/BT is enabled or disabled via device tree overlay for doing the probe, or is the state basically overridden by the GPIO state?

pelwell commented 3 years ago

If I understand it right, this means that dtoverlay=disable-bt has not effect on the affected models, but dtoverlay=disable-wifi disables both, WiFi+BT, and in absence, both are enabled?

The disable-bt should have exactly the same effect on both 3B+ variants in that it releases ttyAMA0 for console (or other) use, disables UART1, doesn't enable any UART onto GPIOs 30-33, configures the serial aliases appropriately and leaves enough clues to effectively disable the hciuart service. But in the sense that it also causes the firmware to set GPIO0 on the expander to 0 then yes - it has no effect on devices with the shared enables.

disable-wifi disables the SDIO interface, meaning that the WiFi half of the 43455 should not be accessed. However, it also causes the firmware to pull WL_ON (and hence BT_ON in these cases) low. That's the result of a power-saving patch introduced late in 2019 (it can save 450mW if both WiFi and BT and disabled), but as you've discovered it has undesirable effects on a subset of the 1.3 3B+s.

If all you are wanting to do is disable WiFi then you shouldn't have to deal with this corner case - the firmware should leave WL_ON alone. Given that the big power savings are to be had with both disabled, I think it's reasonable in this case to disable the WL_ON lowering unless the BT is also disabled. This logic is probably going to have to apply to all 1.3 3B+s.

MichaIng commented 3 years ago

Okay, thanks for clarification. So disable-bt must not be set for the probe to work, and when changing GPIO 0 state has an effect on the BT probe, disable-wifi does not break BT, if GPIO 0 has no effect on the probe result, disable-wifi needs to be absent/off for BT to function.

It is practically not that trivial to apply for a config script, as, if disable-bt is currently set, the Pi needs to be rebooted first, before the probing can be done.

The alternative is indeed to simply remove disable-wifi on all RPi 3+ models when Bluetooth is enabled and skip the probe. We also blacklist the Broadcom WiFi modules, so WiFi will be definitely disabled, no interface present, either way and the additional benefit of disable-wifi is, as you stated, negligible.

Many thanks for taking the time to dig into this and I think we have collected all information required to deal with it properly. Not a big issue after all, when known. Is it worth a note in the README?

pelwell commented 3 years ago

Sorry, my final paragraph probably wasn't clear enough - I'm fixing it in the firmware.

MichaIng commented 3 years ago

Ah, got it, that is great 👍.

pelwell commented 3 years ago

There's a trial firmware (just start.elf and fixup.dat) that should fix this issue: https://drive.google.com/file/d/10gBNYX6UcFFwjZircjbfgOd7uKzBSnzA/view?usp=sharing

popcornmix commented 3 years ago

Fix should be in latest rpi-update firmware.

MichaIng commented 3 years ago

Many thanks, I'm still waiting for reply/test of our user. ~I'll also inform users in the forum threads.~ (EDIT: Ah nope, topics are locked)

For completeness, here two forum threads where users faced the issue, which might be happy to know that a fix is coming:

popcornmix commented 3 years ago

I've posted to those threads (directing here) in case any users are following.