Device migrations and driver improvements (#576)

This commit is contained in:
Ken Van Hoeylandt
2026-07-22 21:11:12 +02:00
committed by GitHub
parent 2fbc44466a
commit a3fda9ad8f
100 changed files with 707 additions and 3838 deletions
+57 -8
View File
@@ -49,15 +49,24 @@ struct Axp2101VoltRange {
uint8_t code_base;
};
/** Validates millivolts against a single known range and encodes it. No search: caller has
* already picked which range applies (e.g. by channel). */
static error_t encode_single_range(uint16_t millivolts, const Axp2101VoltRange& range, uint8_t* out_code) {
if (millivolts < range.min || millivolts > range.max || (millivolts - range.min) % range.step != 0U) {
return ERROR_INVALID_ARGUMENT;
}
*out_code = static_cast<uint8_t>(range.code_base + (millivolts - range.min) / range.step);
return ERROR_NONE;
}
/** Finds which of several (possibly non-contiguous) sub-ranges of a single channel contains
* millivolts, and encodes it. Only meaningful when ranges all belong to the SAME channel
* (e.g. DCDC3's three piecewise sub-ranges) - never pass ranges from different channels,
* since their spans can legitimately overlap and this would silently pick the first match. */
static error_t encode_ranged_voltage(uint16_t millivolts, const Axp2101VoltRange* ranges, size_t range_count, uint8_t* out_code) {
for (size_t i = 0; i < range_count; i++) {
const Axp2101VoltRange& range = ranges[i];
if (millivolts >= range.min && millivolts <= range.max) {
if ((millivolts - range.min) % range.step != 0U) {
return ERROR_INVALID_ARGUMENT;
}
*out_code = static_cast<uint8_t>(range.code_base + (millivolts - range.min) / range.step);
return ERROR_NONE;
if (millivolts >= ranges[i].min && millivolts <= ranges[i].max) {
return encode_single_range(millivolts, ranges[i], out_code);
}
}
return ERROR_INVALID_ARGUMENT;
@@ -253,8 +262,9 @@ error_t axp2101_set_ldo_voltage(Device* device, Axp2101Ldo ldo, uint16_t millivo
};
uint8_t code;
error_t err = encode_ranged_voltage(millivolts, &LDO_RANGE[ldo], 1, &code);
error_t err = encode_single_range(millivolts, LDO_RANGE[ldo], &code);
if (err != ERROR_NONE) {
LOG_E(TAG, "Failed to encode %u mV", millivolts);
return err;
}
@@ -518,6 +528,45 @@ static error_t start(Device* device) {
return error;
}
// All 9 LDO channels: voltage and enable states are applied independently if configured.
// Boards that need it enable/voltage-set the channel via config instead of per-board imperative code.
// Order matches enum Axp2101Ldo.
static constexpr Axp2101Ldo LDO_CHANNELS[9] = {
AXP2101_ALDO1, AXP2101_ALDO2, AXP2101_ALDO3, AXP2101_ALDO4,
AXP2101_BLDO1, AXP2101_BLDO2, AXP2101_CPUSLDO, AXP2101_DLDO1, AXP2101_DLDO2,
};
static constexpr const char* LDO_NAMES[9] = {
"ALDO1", "ALDO2", "ALDO3", "ALDO4", "BLDO1", "BLDO2", "CPUSLDO", "DLDO1", "DLDO2",
};
const auto* config = GET_CONFIG(device);
const uint16_t ldo_millivolts[9] = {
config->aldo1_millivolt, config->aldo2_millivolt, config->aldo3_millivolt, config->aldo4_millivolt,
config->bldo1_millivolt, config->bldo2_millivolt, config->cpusldo_millivolt,
config->dldo1_millivolt, config->dldo2_millivolt,
};
const bool ldo_enabled[9] = {
config->aldo1_enabled, config->aldo2_enabled, config->aldo3_enabled, config->aldo4_enabled,
config->bldo1_enabled, config->bldo2_enabled, config->cpusldo_enabled,
config->dldo1_enabled, config->dldo2_enabled,
};
for (size_t i = 0; i < 9; i++) {
if (ldo_millivolts[i] != 0) {
error_t err = axp2101_set_ldo_voltage(device, LDO_CHANNELS[i], ldo_millivolts[i]);
if (err != ERROR_NONE) {
LOG_E(TAG, "Failed to set %s voltage", LDO_NAMES[i]);
return err;
}
}
if (ldo_enabled[i]) {
error_t err = axp2101_set_ldo_enabled(device, LDO_CHANNELS[i], true);
if (err != ERROR_NONE) {
LOG_E(TAG, "Failed to enable %s", LDO_NAMES[i]);
return err;
}
}
}
auto* internal = new(std::nothrow) Axp2101Internal();
if (internal == nullptr) {
return ERROR_OUT_OF_MEMORY;