After upgrading nRF Connect SDK from 3.1.1 to 3.2.1, our fixed regulator stopped working. We are on nRF54L15. Tracking it down further, this seems to be some sort of GPIO value config/retention bug. The reason I'm saying "bug" is that this was working as expected on 3.1.1. Our regulator is defined in the dts to go high on boot.
load_3v3: load-3v3 { compatible = "regulator-fixed"; status = "okay"; regulator-name = "3V3_LOAD_EN"; enable-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; regulator-boot-on; };If you look at regulator_fixed_init() in the latest SDK, it configures the output pin, then reads the value. That value is passed regulator_common_init(), which only toggles the line high if it's not already `is_enabled`. However, for some reason, the gpio read of the pin reads HIGH immediately after config. This causes regulator_common_init() to think it's already on, when it's not actually on. If I add a 10ms delay and read the same value again, it correctly reads 0. In the logs below, the reading of value after sleep doesn't change is_enabled because that was added by me, is_enabled is still based on the value after the first read like in the unmodified code.
[00:00:00.323,296] <wrn> regulator_fixed: Regulator before config: 0[00:00:00.323,296] <wrn> regulator_fixed: Regulator after config 1[00:00:00.323,296] <wrn> regulator_fixed: Sleeping for 10ms[00:00:00.333,408] <wrn> regulator_fixed: Regulator after 10ms sleep: 0[00:00:00.333,408] <wrn> regulator_fixed: Calling regulator_common_init with is_enabled=1
Why does gpio_pin_get_dt() return 1 temporarily? This breaks the regulator setup.
Instrumented regulator_fixed_init with logs, but otherwise unchanged:
static int regulator_fixed_init(const struct device *dev){ const struct regulator_fixed_config *cfg = dev->config; bool is_enabled = false; regulator_common_data_init(dev); if (cfg->enable.port != NULL) { if (!gpio_is_ready_dt(&cfg->enable)) { LOG_ERR("GPIO port: %s not ready", cfg->enable.port->name); return -ENODEV; } // DEBUG CODE LOG_WRN("Regulator before config: %d", gpio_pin_get_dt(&cfg->enable)); // END DEBUG CODE int ret = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT); if (ret < 0) { return ret; } ret = gpio_pin_get_dt(&cfg->enable); if (ret < 0) { return ret; } is_enabled = ret; // DEBUG CODE LOG_WRN("Regulator after config %d", is_enabled); LOG_WRN("Sleeping for 10ms"); k_sleep(K_MSEC(10)); LOG_WRN("Regulator after 10ms sleep: %d", gpio_pin_get_dt(&cfg->enable)); // END DEBUG CODE } LOG_WRN("Calling regulator_common_init with is_enabled=%d", is_enabled); return regulator_common_init(dev, is_enabled);}This issue has surfaced because of this commit in zephyr: https://github.com/nrfconnect/sdk-zephyr/commit/7fa815c92967f26a7c9af33776677015013e18d0, which checks the value of the pin before deciding if it should be toggled.
