GPIO descriptor fixes (#578)

This commit is contained in:
Ken Van Hoeylandt
2026-07-22 22:43:34 +02:00
committed by GitHub
parent a3fda9ad8f
commit 8b92aa8e5a
116 changed files with 376 additions and 541 deletions
@@ -86,9 +86,7 @@
vsync-back-porch = <8>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 40 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
pin-de = <&gpio0 42 GPIO_FLAG_NONE>;
@@ -89,9 +89,7 @@
vsync-back-porch = <12>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 39 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
pin-de = <&gpio0 40 GPIO_FLAG_NONE>;
@@ -205,5 +205,4 @@
backlight = <&display_backlight>;
};
};
};
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
#include "papers3_power.h"
#include <tactility/check.h>
#include <tactility/driver.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/power_supply.h>
#include <tactility/drivers/pwm.h>
@@ -13,7 +15,7 @@
#include <new>
#define TAG "Papers3Power"
constexpr auto* TAG = "Papers3Power";
#define GET_CONFIG(device) (static_cast<const Papers3PowerConfig*>((device)->config))
// Power-off signal timing, ported from the old deprecated-HAL PaperS3Power::powerOff().
@@ -192,17 +194,8 @@ static void destroy_power_supply_child(Device* child) {
// region Driver lifecycle
static error_t acquire_input(const GpioPinSpec& pin, GpioDescriptor** out_descriptor) {
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_INPUT);
if (error != ERROR_NONE) {
gpio_descriptor_release(descriptor);
return error;
}
*out_descriptor = descriptor;
return ERROR_NONE;
*out_descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
return (*out_descriptor != nullptr) ? ERROR_NONE : ERROR_RESOURCE;
}
static error_t start(Device* device) {
@@ -226,13 +219,8 @@ static error_t start(Device* device) {
return ERROR_RESOURCE;
}
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, GPIO_OWNER_GPIO);
if (internal->power_off_descriptor == nullptr ||
gpio_descriptor_set_flags(internal->power_off_descriptor, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
LOG_E(TAG, "Failed to configure power-off pin");
if (internal->power_off_descriptor != nullptr) {
gpio_descriptor_release(internal->power_off_descriptor);
}
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (internal->power_off_descriptor == nullptr) {
gpio_descriptor_release(internal->usb_detect_descriptor);
gpio_descriptor_release(internal->charge_status_descriptor);
delete internal;
@@ -7,8 +7,10 @@
#include <tactility/bindings/esp32_grove.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_i2s.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/gpio_hog.h>
#include <bindings/aw88298.h>
#include <bindings/aw9523b.h>
#include <bindings/axp2101.h>
@@ -20,8 +22,6 @@
#include <bindings/ili9341.h>
#include <bindings/ina226.h>
#include <bindings/py32ioexpander.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/gpio_hog.h>
// Reference: https://docs.m5stack.com/en/StackChan
/ {
@@ -101,7 +101,7 @@
aw9523_sdcard_switch {
compatible = "gpio-hog";
pin = <&aw9523b 4 GPIO_FLAG_NONE>;
mode = <GPIO_HOG_MODE_OUTPUT_HIGH>;
mode = <GPIO_HOG_MODE_INPUT>;
};
aw9523_boost_enable {
@@ -36,14 +36,14 @@ static void apply_gt911_int_workaround() {
LOG_W(TAG, "display_detect: gpio0 not found, GT911 INT workaround not applied");
return;
}
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_OWNER_GPIO);
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
device_put(gpio0);
if (int_pin == nullptr) {
LOG_W(TAG, "display_detect: failed to acquire GPIO23 for GT911 INT workaround");
return;
}
gpio_descriptor_set_flags(int_pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_PULL_UP);
gpio_descriptor_set_level(int_pin, false);
gpio_descriptor_set_level(int_pin, true);
gpio_descriptor_release(int_pin);
}
@@ -67,8 +67,6 @@ static void create_gt911_touch(Device* i2c0) {
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.pin_interrupt = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.interrupt_active_high = false,
};
gt911_device.config = &gt911_config;
@@ -103,7 +101,6 @@ void tab5_create_devices_v1(Device* i2c0) {
// LCD reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a
// direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.ldo_channel = 3,
.ldo_voltage_mv = 2500,
.dsi_bus_id = 0,
@@ -50,8 +50,6 @@ static void create_st7123_touch(Device* i2c0) {
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
.pin_reset = GPIO_PIN_SPEC_NONE,
.pin_interrupt = pin_interrupt,
.reset_active_high = false,
.interrupt_active_high = false,
};
st7123_touch_device.config = &st7123_touch_config;
@@ -82,7 +80,6 @@ void tab5_create_devices_v2(Device* i2c0) {
.mirror_x = false,
.mirror_y = false,
.pin_reset = GPIO_PIN_SPEC_NONE,
.reset_active_high = false,
.ldo_channel = 3,
.ldo_voltage_mv = 2500,
.dsi_bus_id = 0,
@@ -1,6 +1,5 @@
#include "detect.h"
#include "../../../../TactilityKernel/include/tactility/log.h"
#include "devices_common.h"
#include "devices_v1.h"
#include "devices_v2.h"
@@ -8,6 +7,7 @@
#include <tactility/device.h>
#include <tactility/device_listener.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/log.h>
@@ -36,8 +36,8 @@ constexpr auto GPIO_EXP0_PIN_LCD_RESET = 4;
constexpr auto GPIO_EXP0_PIN_TOUCH_RESET = 5;
bool pulse_display_reset_pins(Device* io_expander0) {
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_OWNER_GPIO);
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_OWNER_GPIO);
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
if (lcd_reset_pin == nullptr || touch_reset_pin == nullptr) {
LOG_E(TAG, "display_detect: failed to acquire LCD/touch reset pins on io_expander0");
if (lcd_reset_pin != nullptr) {
@@ -51,11 +51,11 @@ bool pulse_display_reset_pins(Device* io_expander0) {
gpio_descriptor_set_flags(lcd_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_flags(touch_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(lcd_reset_pin, false);
gpio_descriptor_set_level(touch_reset_pin, false);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_descriptor_set_level(lcd_reset_pin, true);
gpio_descriptor_set_level(touch_reset_pin, true);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_descriptor_set_level(lcd_reset_pin, false);
gpio_descriptor_set_level(touch_reset_pin, false);
gpio_descriptor_release(lcd_reset_pin);
gpio_descriptor_release(touch_reset_pin);
@@ -1,6 +1,7 @@
#include "tab5_headphone_detect.h"
#include <tactility/device.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/log.h>
@@ -35,7 +36,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
return; // Not ready yet, will retry on next tick
}
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
if (!hp_pin) {
LOG_W(TAG, "hp_detect: HP_DET pin busy");
return;
@@ -53,7 +54,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
LOG_D(TAG, "hp_detect: HP_DET=%d", (int)hp);
if (!hp_detect_initialized || hp != hp_detect_last) {
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (!spk_pin) {
LOG_W(TAG, "hp_detect: SPK_EN pin busy, will retry");
return;
@@ -3,6 +3,7 @@
#include <tactility/device.h>
#include <tactility/driver.h>
#include <tactility/drivers/gpio.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/power_supply.h>
#include <tactility/log.h>
@@ -51,15 +52,12 @@ static error_t ps_set_allowed_to_charge(Device* device, bool allowed) {
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_W(TAG, "Failed to acquire CHG_EN pin");
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
if (error == ERROR_NONE) {
error = gpio_descriptor_set_level(pin, allowed);
}
auto error = gpio_descriptor_set_level(pin, allowed);
gpio_descriptor_release(pin);
if (error != ERROR_NONE) {
LOG_W(TAG, "Failed to set CHG_EN pin");
@@ -83,15 +81,12 @@ static error_t ps_set_quick_charge_enabled(Device* device, bool enabled) {
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_W(TAG, "Failed to acquire nCHG_QC_EN pin");
return ERROR_RESOURCE;
}
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
if (error == ERROR_NONE) {
error = gpio_descriptor_set_level(pin, !enabled); // active-low
}
auto error = gpio_descriptor_set_level(pin, !enabled); // active-low
gpio_descriptor_release(pin);
if (error != ERROR_NONE) {
LOG_W(TAG, "Failed to set nCHG_QC_EN pin");
@@ -108,7 +103,7 @@ static bool ps_supports_power_off(Device*) {
static error_t ps_power_off(Device* device) {
auto* io_expander1 = device_get_parent(device);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (pin == nullptr) {
LOG_E(TAG, "Failed to acquire DEVICE_POWER pin");
return ERROR_RESOURCE;
@@ -153,9 +148,8 @@ static error_t start(Device* device) {
// as an idle-low output up front so it's in a known state (previously done by Configuration.cpp's
// initExpander1(), now owned here - see that function's comment for why it no longer touches it).
auto* io_expander1 = device_get_parent(device);
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (device_power_pin != nullptr) {
gpio_descriptor_set_flags(device_power_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(device_power_pin, false);
gpio_descriptor_release(device_power_pin);
} else {
+4 -6
View File
@@ -1,4 +1,5 @@
#include <tactility/module.h>
#include <tactility/check.h>
#include <tactility/device.h>
#include <tactility/device_listener.h>
@@ -25,14 +26,11 @@ constexpr auto GPIO_EXP0_PIN_HEADPHONE_DETECT = 7;
static void tab5_init_expander0(Device* io_expander0) {
// Speaker and heapdhone pins are managed at runtime, so we can't have them as a hog in the dts file
// We have to init them manually.
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(speaker_enable_pin);
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
check(headphone_detect_pin);
gpio_descriptor_set_flags(speaker_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_flags(headphone_detect_pin, GPIO_FLAG_DIRECTION_INPUT);
gpio_descriptor_set_level(speaker_enable_pin, false);
gpio_descriptor_release(speaker_enable_pin);
@@ -40,7 +38,7 @@ static void tab5_init_expander0(Device* io_expander0) {
}
static void tab5_enable_speaker_amp(Device* io_expander0) {
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(speaker_enable_pin, "Failed to acquire speaker enable pin");
error_t error = gpio_descriptor_set_level(speaker_enable_pin, true);
gpio_descriptor_release(speaker_enable_pin);
+1 -3
View File
@@ -21,10 +21,8 @@ bool BatteryManager::initGpioExpander() {
return false;
}
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_OWNER_GPIO);
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
check(expanderPowerPin != nullptr);
gpio_descriptor_set_flags(expanderPowerPin, GPIO_FLAG_DIRECTION_OUTPUT);
device_put(expander);
return true;
@@ -90,21 +90,19 @@ static int32_t nav_buttons_thread_main(UnphoneNavButtonsInternal* internal) {
// region Pin acquisition
static error_t acquire_button(const GpioPinSpec& pin, void (*callback)(void*), void* arg, GpioDescriptor** out_descriptor) {
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
// Digital pull-up; the buttons pull the pin low while pressed. Listen for the release
// (positive edge) rather than the press - if we listen to the press, these buttons can
// generate more than one signal when held down (mirrors the original unPhone init).
gpio_flags_t flags = GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
flags = GPIO_FLAG_INTERRUPT_TO_OPTIONS(flags, GPIO_INTERRUPT_POS_EDGE);
error_t error = gpio_descriptor_set_flags(descriptor, flags);
if (error == ERROR_NONE) {
error = gpio_descriptor_add_callback(descriptor, callback, arg);
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, flags, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
return ERROR_RESOURCE;
}
auto error = gpio_descriptor_add_callback(descriptor, callback, arg);
if (error == ERROR_NONE) {
error = gpio_descriptor_enable_interrupt(descriptor);
}
@@ -25,18 +25,12 @@ extern Module unphone_module;
static error_t start(Device* device) {
const auto* config = GET_CONFIG(device);
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, GPIO_OWNER_GPIO);
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
if (descriptor == nullptr) {
LOG_E(TAG, "Failed to acquire GPIO descriptor");
return ERROR_RESOURCE;
}
if (gpio_descriptor_set_flags(descriptor, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT) != ERROR_NONE) {
LOG_E(TAG, "Failed to configure power switch pin as input");
gpio_descriptor_release(descriptor);
return ERROR_RESOURCE;
}
gpio_num_t native_pin;
if (gpio_descriptor_get_native_pin_number(descriptor, &native_pin) != ERROR_NONE) {
LOG_E(TAG, "Power switch pin has no native pin number");
@@ -96,9 +96,8 @@
vsync-back-porch = <8>;
vsync-front-porch = <8>;
pclk-active-neg;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
num-fbs = <1>;
bounce-buffer-size-px = <4000>;
pin-hsync = <&gpio0 46 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 3 GPIO_FLAG_NONE>;
pin-de = <&gpio0 5 GPIO_FLAG_NONE>;