fix: Pi 4 Bluetooth - hold RTS deasserted across BT_ON power-on, require Read Local Version to sync, mini UART no flow control first

This commit is contained in:
daniel committed 2026-10-26 07:46:49 +01:00
1 parent 93d8becce3
commit 3310b3d6de
11 files changed
+210 -38

No files matched your search

+34 -9
View File
@@ -48,6 +48,8 @@ namespace Drivers::Platform::RpiFirmware {
static constexpr uint32_t TAG_GET_CLOCK_RATE = 0x00030002;
static constexpr uint32_t TAG_GET_GPIO_STATE = 0x00030041;
static constexpr uint32_t TAG_SET_GPIO_STATE = 0x00038041;
static constexpr uint32_t TAG_GET_GPIO_CONFIG = 0x00030043;
static constexpr uint32_t TAG_SET_GPIO_CONFIG = 0x00038043;
// The VideoCore sees the first GiB of SDRAM at bus address 0xC0000000
// (the uncached alias), and nothing above it, so the message buffer
@@ -199,18 +201,28 @@ namespace Drivers::Platform::RpiFirmware {
g_buffer[words++] = 0; // end tag
g_buffer[0] = words * 4;
// The firmware does not set the response bit for every tag: the
// expander GPIO tags answer through value[0] alone and leave the
// status word 0. Linux checks only the message code, so do the same
// and take the whole value buffer back when the bit is missing; each
// caller validates the values it gets.
int result = -1;
if (Call()) {
uint32_t status = g_buffer[valueStart - 1];
if (status & TAG_RESPONSE) {
uint32_t length = status & ~TAG_RESPONSE;
uint32_t copy = (length + 3) / 4;
if (copy > valueWords) copy = valueWords;
for (uint32_t i = 0; i < copy; i++) values[i] = g_buffer[valueStart + i];
result = (int)length;
}
bool answered = Call();
uint32_t status = g_buffer[valueStart - 1];
if (answered) {
uint32_t length = (status & TAG_RESPONSE) ? status & ~TAG_RESPONSE : valueWords * 4;
uint32_t copy = (length + 3) / 4;
if (copy > valueWords) copy = valueWords;
for (uint32_t i = 0; i < copy; i++) values[i] = g_buffer[valueStart + i];
result = (int)length;
}
uint32_t code = g_buffer[1];
g_lock.Release();
if (result < 0) {
KernelLogStream(WARNING, "RpiFw") << "Property tag 0x" << base::hex << (uint64_t)tag
<< " failed: message code 0x" << (uint64_t)code << base::dec;
}
return result;
}
@@ -228,6 +240,19 @@ namespace Drivers::Platform::RpiFirmware {
return PropertyCall(TAG_SET_GPIO_STATE, v, 2) >= 4 && v[0] == 0;
}
// As Linux's rpi_exp_gpio_dir_out: keep the line's polarity, make it an
// output driving `high`. A line the firmware still has as an input
// refuses SET_GPIO_STATE.
bool SetGpioOutput(uint32_t gpio, bool high) {
uint32_t polarity = 0;
uint32_t cfg[5] = { gpio, 0, 0, 0, 0 }; // gpio, direction, polarity, term_en, term_pull_up
if (PropertyCall(TAG_GET_GPIO_CONFIG, cfg, 5) >= 12 && cfg[0] == 0) polarity = cfg[2];
uint32_t v[6] = { gpio, 1 /* output */, polarity, 0, 0, high ? 1u : 0u };
if (PropertyCall(TAG_SET_GPIO_CONFIG, v, 6) < 4 || v[0] != 0) return false;
return true;
}
bool GetGpioState(uint32_t gpio, bool& high) {
uint32_t v[2] = { gpio, 0 };
if (PropertyCall(TAG_GET_GPIO_STATE, v, 2) < 8 || v[0] != 0) return false;