diff --git a/dts/arm/nuvoton/npcx.dtsi b/dts/arm/nuvoton/npcx.dtsi index 19598e09baf..38369308a18 100644 --- a/dts/arm/nuvoton/npcx.dtsi +++ b/dts/arm/nuvoton/npcx.dtsi @@ -52,6 +52,14 @@ status = "okay"; }; + /* Dummy node of IOs that have leakage current. The user can override + * 'leak-gpios' prop. at board DT file to save more power consumption. + */ + power_leakage_io: power-leakage-io { + compatible = "nuvoton,npcx-leakage-io"; + status = "okay"; + }; + soc { bbram: bb-ram@400af000 { compatible = "nuvoton,npcx-bbram"; diff --git a/dts/bindings/pinctrl/nuvoton,npcx-leakage-io.yaml b/dts/bindings/pinctrl/nuvoton,npcx-leakage-io.yaml new file mode 100644 index 00000000000..f16f6083d18 --- /dev/null +++ b/dts/bindings/pinctrl/nuvoton,npcx-leakage-io.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCX power leakage IOs + +compatible: "nuvoton,npcx-leakage-io" + +include: [base.yaml] + +properties: + leak-gpios: + type: phandle-array + required: false + description: | + Array of IOs that have leakage current. The user can overwrite this + property at the board level DT file to save more power consumption. diff --git a/soc/arm/nuvoton_npcx/common/power.c b/soc/arm/nuvoton_npcx/common/power.c index 94363560669..0ab072b4a7b 100644 --- a/soc/arm/nuvoton_npcx/common/power.c +++ b/soc/arm/nuvoton_npcx/common/power.c @@ -47,10 +47,12 @@ #include #include +#include #include #include #include +#include "soc_gpio.h" #include "soc_host.h" #include "soc_power.h" @@ -84,6 +86,57 @@ enum { NPCX_STANDARD_WAKE_UP, }; +#define NODE_LEAKAGE_IO DT_INST(0, nuvoton_npcx_leakage_io) +#if DT_NODE_HAS_PROP(NODE_LEAKAGE_IO, leak_gpios) +struct npcx_leak_gpio { + const struct device *gpio; + gpio_pin_t pin; +}; + +#define NPCX_POWER_LEAKAGE_IO_INIT(node_id, prop, idx) { \ + .gpio = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \ + .pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \ +}, + +/* + * Get io array which have leakage current from 'leak-gpios' property of + * 'power_leakage_io' DT node. User can overwrite this prop. at board DT file to + * save power consumption when ec enter deep sleep. + * + * &power_leakage_io { + * leak-gpios = <&gpio0 0 0 + * &gpiob 1 0>; + * }; + */ +static struct npcx_leak_gpio leak_gpios[] = { + DT_FOREACH_PROP_ELEM(NODE_LEAKAGE_IO, leak_gpios, NPCX_POWER_LEAKAGE_IO_INIT) +}; + +static void npcx_power_suspend_leak_io_pads(void) +{ + for (int i = 0; i < ARRAY_SIZE(leak_gpios); i++) { + npcx_gpio_disable_io_pads(leak_gpios[i].gpio, leak_gpios[i].pin); + } +} + +static void npcx_power_restore_leak_io_pads(void) +{ + for (int i = 0; i < ARRAY_SIZE(leak_gpios); i++) { + npcx_gpio_enable_io_pads(leak_gpios[i].gpio, leak_gpios[i].pin); + } +} +#else +void npcx_power_suspend_leak_io_pads(void) +{ + /* do nothing */ +} + +void npcx_power_restore_leak_io_pads(void) +{ + /* do nothing */ +} +#endif /* DT_NODE_HAS_PROP(NODE_LEAKAGE_IO, leak_gpios) */ + static void npcx_power_enter_system_sleep(int slp_mode, int wk_mode) { /* Disable interrupts */ @@ -99,6 +152,12 @@ static void npcx_power_enter_system_sleep(int slp_mode, int wk_mode) npcx_clock_control_turn_on_system_sleep(slp_mode == NPCX_DEEP_SLEEP, wk_mode == NPCX_INSTANT_WAKE_UP); + /* + * Disable the connection between io pads that have leakage current and + * input buffer to save power consumption. + */ + npcx_power_suspend_leak_io_pads(); + /* Turn on eSPI/LPC host access wake-up interrupt. */ if (IS_ENABLED(CONFIG_ESPI_NPCX)) { npcx_host_enable_access_interrupt(); @@ -129,6 +188,12 @@ static void npcx_power_enter_system_sleep(int slp_mode, int wk_mode) npcx_host_disable_access_interrupt(); } + /* + * Restore the connection between io pads that have leakage current and + * input buffer. + */ + npcx_power_restore_leak_io_pads(); + /* Turn off system sleep mode. */ npcx_clock_control_turn_off_system_sleep(); }