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:
1 parent
93d8becce3
commit
3310b3d6de
11 files changed
+210
-38
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user