Zephyr usage for NPM1300 GPIO use as On/Off Control input for BUCK0 and BUCK1

I am working on a project where I am using the npm1300 with host nrf5340. The BUCK1 powers a sensor and BUCK2 powers the nrf5340. I have a SPDT switch connected to GPIO0 and GND and the third pin is floating. I don't have a pull up or pull down on the GPIO0 line. I want to use the switch as the On/Off control for both BUCK1 and BUCK2. I used the zephyr device tree overlay file to do this configuration for me but I can't find any documentation to configure it as input  with pull up (optionally also enable the debounce) and then enable the BUCKENCTRL as mentioned in the npm1300 datasheet to use the GPIO0 as on off control. 

This is the overlay file that I managed to generate with the nrf PowerUp application but I don't know which flags go into the gpio to configure as above.

/*
 * Copyright (C) 2023 Nordic Semiconductor ASA
 * SPDX-License-Identifier: Apache-2.0
 */

#include <dt-bindings/regulator/npm1300.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>

&arduino_i2c {
    npm1300_ek_pmic: pmic@6b {
        compatible = "nordic,npm1300";
        reg = <0x6b>;


        // ship-to-active-time = <96>;


        // long-press-reset = "one_button";


        npm1300_ek_gpio: gpio-controller {
            compatible = "nordic,npm1300-gpio";
            gpio-controller;
            #gpio-cells = <2>;
            ngpios = <5>;
        };

        npm1300_ek_regulators: regulators {
            compatible = "nordic,npm1300-regulator";


            npm1300_ek_buck1: BUCK1 {
                regulator-min-microvolt = <1000000>;
                regulator-max-microvolt = <3300000>;

                retention-microvolt = <1000000>;
                enable-gpios = <&npm1300_ek_gpio 0 GPIO_ACTIVE_HIGH>;




            };



            npm1300_ek_buck2: BUCK2 {
                regulator-min-microvolt = <1000000>;
                regulator-max-microvolt = <3300000>;

                retention-microvolt = <1000000>;
                enable-gpios = <&npm1300_ek_gpio 0 GPIO_ACTIVE_HIGH>;




            };



            npm1300_ek_ldo1: LDO1 {
                regulator-min-microvolt = <1000000>;
                regulator-max-microvolt = <3300000>;

                regulator-initial-mode = <NPM1300_LDSW_MODE_LDSW>;


            };



            npm1300_ek_ldo2: LDO2 {
                regulator-min-microvolt = <1000000>;
                regulator-max-microvolt = <3300000>;

                regulator-initial-mode = <NPM1300_LDSW_MODE_LDSW>;


            };

        };


        npm1300_ek_charger: charger {
            compatible = "nordic,npm1300-charger";
            term-microvolt = <4200000>;
            term-warm-microvolt = <4000000>;
            // term-current-percent = <10>;
            current-microamp = <500000>;
            // trickle-microvolt = <2900000>;
            dischg-limit-microamp = <270000>;
            vbus-limit-microamp = <500000>;
            thermistor-ohms = <10000>;
            thermistor-beta = <3380>;

            charging-enable;
            vbatlow-charge-enable;
        };


        npm1300_ek_leds: leds {
            compatible = "nordic,npm1300-led";
            nordic,led0-mode = "error";
            nordic,led1-mode = "charging";
            nordic,led2-mode = "host";
        };

        npm1300_ek_buttons: buttons {
            compatible = "gpio-keys";
            pmic_button0: pmic_button_0 {
                gpios = <&npm1300_ek_gpio 0 GPIO_ACTIVE_LOW>;
                label = "Pmic button switch 0";
                zephyr,code = <INPUT_KEY_0>;
            };
        };
    };
};


I have managed to configure the gpio manually by using the mfd driver file (mfd_npm1300.c) from zephyr as follows, this works well but is there a better way through zephyr overlay?
uint8_t reg_val = 0;
err = mfd_npm1300_reg_read(pmic, 0x06U, 0x00U, &reg_val);
if (err < 0) {
	LOG_ERR("Failed to read PMIC register: %d", err);
	return 0;
}
LOG_INF("PMIC GPIO0 mode: 0x%02X", reg_val);

err = mfd_npm1300_reg_write(pmic, 0x06U, 0x19U, 1); // enable debounce for gpio0
if (err < 0) {
	LOG_ERR("Failed to write PMIC register: %d", err);
	return 0;
}
reg_val = 0;
err = mfd_npm1300_reg_read(pmic, 0x06U, 0x19U, &reg_val);
LOG_INF("PMIC GPIO0 debounce: 0x%02X", reg_val);

err = mfd_npm1300_reg_write(pmic, 0x06U, 0x0FU, 0); // disable PD for gpio0
if (err < 0) {
	LOG_ERR("Failed to write PMIC register: %d", err);
	return 0;
}
reg_val = 0;
err = mfd_npm1300_reg_read(pmic, 0x06U, 0x0FU, &reg_val);
LOG_INF("PMIC GPIO0 PD: 0x%02X", reg_val);

err = mfd_npm1300_reg_write(pmic, 0x06U, 0x0AU, 1); // enable PU for gpio0
if (err < 0) {
	LOG_ERR("Failed to write PMIC register: %d", err);
	return 0;
}
reg_val = 0;
err = mfd_npm1300_reg_read(pmic, 0x06U, 0x19U, &reg_val);
LOG_INF("PMIC GPIO0 PU: 0x%02X", reg_val);



err = mfd_npm1300_reg_write(pmic, 0x04U, 0x0CU, 0b00001001); // set gpio0 for on/off control buck1/2
if (err < 0) {
	LOG_ERR("Failed to write PMIC register: %d", err);
	return 0;
}
reg_val = 0;
err = mfd_npm1300_reg_read(pmic, 0x04U, 0x0CU, &reg_val);
LOG_INF("PMIC BUCKENCTRL: 0x%02X", reg_val);


I have tried everything with the overlay file but I always get the GPIO0 mode as 0x03 which corresponds to GPI Rising Edge Event. Can someone explain what is going wrong here?

Parents
  • Hello,

    I have gone through the overlay file and the code snippet; what you have tried to do is correct approach. Currently we don't have configuration of controlling GPIO from ovelay fully. You must add these manually in your overlay or configure them in code. This is a known limitation and is planned to be improved in future releases. I have a previous case (10) nPM PowerUp Overlay generation - Nordic Q&A - Nordic DevZone - Nordic DevZone about this you can look at.

    Setting BUCKENCTRL for GPIO0 as on/off control must also be done in code and you have done this in the code.

    err = mfd_npm1300_reg_write(pmic, 0x04U, 0x0CU, 0b00001001); // set gpio0 for on/off control buck1/2
    if (err < 0) {
    	LOG_ERR("Failed to write PMIC register: %d", err);
    	return 0;
    }

    you can use the Zephyr GPIO API and nPM1300-specific flags (e.g., NPM1300_GPIO_DEBOUNCE_ONNPM1300_GPIO_PWRLOSSWARN_ON, etc.) to configure the GPIOs at runtime Zephyr API: nPM1300-specific GPIO Flags.

    #include <zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h>
    #include <zephyr/drivers/gpio.h>
    
    const struct device *npm1300_gpio = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_gpio));
    int err;
    
    err = gpio_pin_configure(npm1300_gpio, 1, NPM1300_GPIO_PWRLOSSWARN_ON);
    if (err) {
        printk("gpio_pin_configure=%d\n", err);
        return;
    }

    you use NPM1300_GPIO_PWRLOSSWARN_ON to enable the power loss warning feature on a GPIO pin, allowing your system to respond to imminent power loss events.

    Thanks.

    BR

    Kazi

  • I am using the nRF5340, which is powered from BUCK2 of an nPM1300 PMIC. I also wanted to control power to both the nRF5340 and external sensors using an SPDT switch. The 3.3V from BUCK2 powers the main VDD as well as the VDDIO domain.

    I tried configuring the switch pin with a pull-up and also used it to control the BUCK converters (BUCK1 and BUCK2). When I turn off the SPDT switch, both the nRF5340 and the sensors are powered down — as expected. But I noticed a problem:

    When VDDIO also drops, the GPIO loses its configuration and the pull-up no longer holds the pin high. The behavior is not reliable:

    • Sometimes it works — the pin stays pulled up and the PMIC remains off
    • Other times it fails — the pin floats and the PMIC restarts

    Also, when I connect the J-Link debugger (just GND, SWD, NRST, SWCLK), sometimes both BUCK converters turn ON unexpectedly, even though I did not request them to. I don’t understand why this is happening.

    Am I correct in thinking this is due to the fact that the VDDIO domain powers the GPIO controller — so when VDDIO drops, the GPIO settings are lost? Or is there some other behavior with the nRF5340 + nPM1300 that I’m missing?

Reply
  • I am using the nRF5340, which is powered from BUCK2 of an nPM1300 PMIC. I also wanted to control power to both the nRF5340 and external sensors using an SPDT switch. The 3.3V from BUCK2 powers the main VDD as well as the VDDIO domain.

    I tried configuring the switch pin with a pull-up and also used it to control the BUCK converters (BUCK1 and BUCK2). When I turn off the SPDT switch, both the nRF5340 and the sensors are powered down — as expected. But I noticed a problem:

    When VDDIO also drops, the GPIO loses its configuration and the pull-up no longer holds the pin high. The behavior is not reliable:

    • Sometimes it works — the pin stays pulled up and the PMIC remains off
    • Other times it fails — the pin floats and the PMIC restarts

    Also, when I connect the J-Link debugger (just GND, SWD, NRST, SWCLK), sometimes both BUCK converters turn ON unexpectedly, even though I did not request them to. I don’t understand why this is happening.

    Am I correct in thinking this is due to the fact that the VDDIO domain powers the GPIO controller — so when VDDIO drops, the GPIO settings are lost? Or is there some other behavior with the nRF5340 + nPM1300 that I’m missing?

Children
No Data
Related