diff options
author | Keith Short <keithshort@chromium.org> | 2021-04-24 14:26:16 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-04-29 18:34:01 +0000 |
commit | 13a437909f984da73327a8e4ce6ed8adb0ccdce6 (patch) | |
tree | 2091a3e14d33ae6bf9bc390f7cb450304ff7fbc4 | |
parent | 85ea1cd0acb35b141d9f5deef26ff96e32d87365 (diff) | |
download | chrome-ec-13a437909f984da73327a8e4ce6ed8adb0ccdce6.tar.gz |
zephyr: npcx: Add power management support
Add power management support for the NPCX family.
BUG=b:184653704
BRANCH=none
TEST=zmake testall
TEST=Verify deep sleep on Volteer (with next CL) and measure power.
Signed-off-by: Keith Short <keithshort@chromium.org>
Change-Id: I86eef50c13742e7ca717da38a92636e589af6c58
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2855527
Reviewed-by: Wealian Liao <whliao@nuvoton.corp-partner.google.com>
-rw-r--r-- | zephyr/Kconfig.stacks | 2 | ||||
-rw-r--r-- | zephyr/drivers/cros_system/cros_system_npcx.c | 9 | ||||
-rw-r--r-- | zephyr/include/cros/nuvoton/npcx.dtsi | 19 | ||||
-rw-r--r-- | zephyr/include/drivers/cros_system.h | 29 | ||||
-rw-r--r-- | zephyr/shim/chip/npcx/CMakeLists.txt | 1 | ||||
-rw-r--r-- | zephyr/shim/chip/npcx/power_policy.c | 39 | ||||
-rw-r--r-- | zephyr/shim/src/system.c | 22 |
7 files changed, 120 insertions, 1 deletions
diff --git a/zephyr/Kconfig.stacks b/zephyr/Kconfig.stacks index 48020d4c51..0efe1c008d 100644 --- a/zephyr/Kconfig.stacks +++ b/zephyr/Kconfig.stacks @@ -7,7 +7,7 @@ if SOC_SERIES_NPCX7 # Zephyr internal stack sizes config IDLE_STACK_SIZE - default 128 + default 192 config ISR_STACK_SIZE default 1024 diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c index d814a8967f..c5b8e1a2f8 100644 --- a/zephyr/drivers/cros_system/cros_system_npcx.c +++ b/zephyr/drivers/cros_system/cros_system_npcx.c @@ -515,6 +515,12 @@ static int cros_system_npcx_hibernate(const struct device *dev, return 0; } +__maybe_unused static uint64_t +cros_system_npcx_deep_sleep_ticks(const struct device *dev) +{ + return npcx_clock_get_sleep_ticks(); +} + static struct cros_system_npcx_data cros_system_npcx_dev_data; static const struct cros_system_npcx_config cros_system_dev_cfg = { @@ -531,6 +537,9 @@ static const struct cros_system_driver_api cros_system_driver_npcx_api = { .chip_vendor = cros_system_npcx_get_chip_vendor, .chip_name = cros_system_npcx_get_chip_name, .chip_revision = cros_system_npcx_get_chip_revision, +#ifdef CONFIG_SOC_POWER_MANAGEMENT_TRACE + .deep_sleep_ticks = cros_system_npcx_deep_sleep_ticks, +#endif }; DEVICE_DEFINE(cros_system_npcx_0, "CROS_SYSTEM", cros_system_npcx_init, NULL, diff --git a/zephyr/include/cros/nuvoton/npcx.dtsi b/zephyr/include/cros/nuvoton/npcx.dtsi index 62f4b6b861..8251a34ade 100644 --- a/zephyr/include/cros/nuvoton/npcx.dtsi +++ b/zephyr/include/cros/nuvoton/npcx.dtsi @@ -98,4 +98,23 @@ }; }; + power-states { + suspend_to_idle_instant: suspend_to_idle_instant { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <0>; + min-residency-us = <500>; + }; + + suspend_to_idle_normal: suspend_to_idle_normal { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <200100>; + }; + }; +}; + +&cpu0 { + cpu-power-states = <&suspend_to_idle_instant &suspend_to_idle_normal>; }; diff --git a/zephyr/include/drivers/cros_system.h b/zephyr/include/drivers/cros_system.h index fcd3ef3b6a..77b1174e26 100644 --- a/zephyr/include/drivers/cros_system.h +++ b/zephyr/include/drivers/cros_system.h @@ -82,6 +82,13 @@ typedef const char *(*cros_system_chip_name_api)(const struct device *dev); */ typedef const char *(*cros_system_chip_revision_api)(const struct device *dev); +/** + * @typedef cros_system_get_deep_sleep_ticks_api + * @brief Callback API for getting number of ticks spent in deep sleep. + * See cros_system_deep_sleep_ticks() for argument descriptions + */ +typedef uint64_t (*cros_system_deep_sleep_ticks_api)(const struct device *dev); + /** @brief Driver API structure. */ __subsystem struct cros_system_driver_api { cros_system_get_reset_cause_api get_reset_cause; @@ -90,6 +97,7 @@ __subsystem struct cros_system_driver_api { cros_system_chip_vendor_api chip_vendor; cros_system_chip_name_api chip_name; cros_system_chip_revision_api chip_revision; + cros_system_deep_sleep_ticks_api deep_sleep_ticks; }; /** @@ -229,6 +237,27 @@ z_impl_cros_system_chip_revision(const struct device *dev) } /** + * @brief Get total number of ticks spent in deep sleep. + * + * @param dev Pointer to the device structure for the driver instance. + * @retval Number of ticks spent in deep sleep. + */ +__syscall uint64_t cros_system_deep_sleep_ticks(const struct device *dev); + +static inline uint64_t +z_impl_cros_system_deep_sleep_ticks(const struct device *dev) +{ + const struct cros_system_driver_api *api = + (const struct cros_system_driver_api *)dev->api; + + if (!api->deep_sleep_ticks) { + return 0; + } + + return api->deep_sleep_ticks(dev); +} + +/** * @} */ #include <syscalls/cros_system.h> diff --git a/zephyr/shim/chip/npcx/CMakeLists.txt b/zephyr/shim/chip/npcx/CMakeLists.txt index 86b7a9ae2f..79d81f720e 100644 --- a/zephyr/shim/chip/npcx/CMakeLists.txt +++ b/zephyr/shim/chip/npcx/CMakeLists.txt @@ -12,3 +12,4 @@ zephyr_library_sources_ifdef(CONFIG_CROS_EC system.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_EXTERNAL_STORAGE system_external_storage.c) +zephyr_library_sources_ifdef(CONFIG_PM_POLICY_APP power_policy.c) diff --git a/zephyr/shim/chip/npcx/power_policy.c b/zephyr/shim/chip/npcx/power_policy.c new file mode 100644 index 0000000000..e3f280438f --- /dev/null +++ b/zephyr/shim/chip/npcx/power_policy.c @@ -0,0 +1,39 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <zephyr.h> +#include <power/power.h> +#include <soc.h> + +#include "console.h" +#include "system.h" + +static const struct pm_state_info pm_min_residency[] = + PM_STATE_INFO_DT_ITEMS_LIST(DT_NODELABEL(cpu0)); + +/* CROS PM policy handler */ +struct pm_state_info pm_policy_next_state(int32_t ticks) +{ + /* Deep sleep is allowed and console is not in use. */ + if (DEEP_SLEEP_ALLOWED != 0 && !npcx_power_console_is_in_use()) { + for (int i = ARRAY_SIZE(pm_min_residency) - 1; i >= 0; i--) { + /* Find suitable power state by residency time */ + if (ticks == K_TICKS_FOREVER || + ticks >= k_us_to_ticks_ceil32( + pm_min_residency[i] + .min_residency_us)) { + return pm_min_residency[i]; + } + } + } + + return (struct pm_state_info){ PM_STATE_ACTIVE, 0, 0 }; +} + +/* CROS PM device policy handler */ +bool pm_policy_low_power_devices(enum pm_state state) +{ + return pm_is_sleep_state(state); +} diff --git a/zephyr/shim/src/system.c b/zephyr/shim/src/system.c index c8b5c81341..4984759602 100644 --- a/zephyr/shim/src/system.c +++ b/zephyr/shim/src/system.c @@ -10,6 +10,7 @@ #include "bbram.h" #include "common.h" +#include "console.h" #include "cros_version.h" #include "system.h" #include "watchdog.h" @@ -105,6 +106,27 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) continue; } +#ifdef CONFIG_PM +/** + * Print low power idle statistics + */ +static int command_idle_stats(int argc, char **argv) +{ + const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); + + timestamp_t ts = get_time(); + uint64_t deep_sleep_ticks = cros_system_deep_sleep_ticks(sys_dev); + + ccprintf("Time spent in deep-sleep: %.6llds\n", + k_ticks_to_us_near64(deep_sleep_ticks)); + ccprintf("Total time on: %.6llds\n", ts.val); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, + "", + "Print last idle stats"); +#endif + const char *system_get_chip_vendor(void) { const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); |