power: npcx: add leakage-io support for better power consumption

This CL adds a DT node, 'power_leakage_io', which property,
'leak-gpios', contains GPIOs that have leakage current. In oerder to get
better power consumption, npcx power driver will disable the connections
between these io pads and input buffers before entering deep sleep.
Then, restore the connections after ec wakes up.

The users can overwrite this property at board DT file. Here is an
example:

    &power_leakage_io {
        leak-gpios = <&gpio0 0 0
                      &gpiob 1 0>;
    };

Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
This commit is contained in:
Mulin Chao 2022-07-18 19:07:32 -07:00 committed by Carles Cufí
commit 8cf0feb3e2
3 changed files with 89 additions and 0 deletions

View file

@ -52,6 +52,14 @@
status = "okay"; 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 { soc {
bbram: bb-ram@400af000 { bbram: bb-ram@400af000 {
compatible = "nuvoton,npcx-bbram"; compatible = "nuvoton,npcx-bbram";

View file

@ -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.

View file

@ -47,10 +47,12 @@
#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h> #include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
#include <zephyr/zephyr.h> #include <zephyr/zephyr.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/espi.h> #include <zephyr/drivers/espi.h>
#include <zephyr/pm/pm.h> #include <zephyr/pm/pm.h>
#include <soc.h> #include <soc.h>
#include "soc_gpio.h"
#include "soc_host.h" #include "soc_host.h"
#include "soc_power.h" #include "soc_power.h"
@ -84,6 +86,57 @@ enum {
NPCX_STANDARD_WAKE_UP, 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) static void npcx_power_enter_system_sleep(int slp_mode, int wk_mode)
{ {
/* Disable interrupts */ /* 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, npcx_clock_control_turn_on_system_sleep(slp_mode == NPCX_DEEP_SLEEP,
wk_mode == NPCX_INSTANT_WAKE_UP); 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. */ /* Turn on eSPI/LPC host access wake-up interrupt. */
if (IS_ENABLED(CONFIG_ESPI_NPCX)) { if (IS_ENABLED(CONFIG_ESPI_NPCX)) {
npcx_host_enable_access_interrupt(); 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(); 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. */ /* Turn off system sleep mode. */
npcx_clock_control_turn_off_system_sleep(); npcx_clock_control_turn_off_system_sleep();
} }