pm: Use stats subsys for tracking system states
Uses the stats subsys to provide simple but useful debugging stats for power management state changes and timing. Removes the no longer needed PM_DEBUG config option Replaces the use of PM_DEBUG for a test clock output pin for mec1501 and adds in its place an SoC Kconfig option to enable it. Adds a STATS_SET macro for assigning a value to a stat group field Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
parent
46db2b491d
commit
f523c336ef
|
@ -462,7 +462,7 @@ static int board_pinmux_init(const struct device *dev)
|
|||
#endif /* DT_NODE_HAS_STATUS(DT_INST(0, microchip_xec_qmspi), okay) */
|
||||
#endif /* CONFIG_SPI_XEC_QMSPI */
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
#ifdef CONFIG_SOC_MEC1501_TEST_CLK_OUT
|
||||
/*
|
||||
* Deep sleep testing: Enable TEST_CLK_OUT on GPIO_060 function 2.
|
||||
* TEST_CLK_OUT is the PLL 48MHz conditioned output.
|
||||
|
|
|
@ -452,7 +452,7 @@ static int board_pinmux_init(const struct device *dev)
|
|||
#endif /* DT_NODE_HAS_STATUS(DT_INST(0, microchip_xec_qmspi), okay) */
|
||||
#endif /* CONFIG_SPI_XEC_QMSPI */
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
#ifdef CONFIG_SOC_MEC1501_TEST_CLK_OUT
|
||||
/*
|
||||
* Deep sleep testing: Enable TEST_CLK_OUT on GPIO_060 function 2.
|
||||
* TEST_CLK_OUT is the PLL 48MHz conditioned output.
|
||||
|
|
|
@ -77,18 +77,6 @@ struct pm_notifier {
|
|||
*/
|
||||
void pm_power_state_force(struct pm_state_info info);
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
/**
|
||||
* @brief Dump Low Power states related debug info
|
||||
*
|
||||
* Dump Low Power states debug info like LPS entry count and residencies.
|
||||
*/
|
||||
void pm_dump_debug_info(void);
|
||||
#else
|
||||
static inline void pm_dump_debug_info(void) { }
|
||||
|
||||
#endif /* CONFIG_PM_DEBUG */
|
||||
|
||||
/**
|
||||
* @brief Register a power management notifier
|
||||
*
|
||||
|
|
|
@ -155,6 +155,19 @@ struct stats_hdr {
|
|||
#define STATS_INC(group__, var__) \
|
||||
STATS_INCN(group__, var__, 1)
|
||||
|
||||
/**
|
||||
* @brief Set a statistic entry to the specified amount.
|
||||
*
|
||||
* Set a statistic entry to the specified amount. Compiled out if
|
||||
* CONFIG_STATS is not defined.
|
||||
*
|
||||
* @param group__ The group containing the entry to increase.
|
||||
* @param var__ The statistic entry to increase.
|
||||
* @param n__ The amount to set the statistic entry to.
|
||||
*/
|
||||
#define STATS_SET(group__, var__, n__) \
|
||||
((group__).var__ = (n__))
|
||||
|
||||
/**
|
||||
* @brief Sets a statistic entry to zero.
|
||||
*
|
||||
|
@ -349,6 +362,7 @@ struct stats_hdr *stats_group_find(const char *name);
|
|||
#define STATS_SIZE_INIT_PARMS(group__, size__)
|
||||
#define STATS_INCN(group__, var__, n__)
|
||||
#define STATS_INC(group__, var__)
|
||||
#define STATS_SET(group__, var__)
|
||||
#define STATS_CLEAR(group__, var__)
|
||||
#define STATS_INIT_AND_REG(group__, size__, name__) (0)
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ CONFIG_LOG=y
|
|||
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=2100
|
||||
|
||||
CONFIG_THREAD_NAME=y
|
||||
# Enable PM debug in MEC1501 this will give indication in MCHP_060
|
||||
# Enable test clock out in MEC1501 this will give indication in MCHP_060
|
||||
|
||||
# This consumes additional power (VTR_PLL)
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_SOC_MEC1501_TEST_CLK_OUT=y
|
||||
|
||||
# Enable additional drivers to evaluate power consumption without activity
|
||||
CONFIG_PECI=y
|
||||
CONFIG_KSCAN=y
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
CONFIG_PM_DEVICE_RUNTIME=y
|
||||
CONFIG_PM_STATS=y
|
||||
CONFIG_STATS=y
|
||||
|
|
|
@ -77,6 +77,11 @@ config SOC_MEC1501_VCI_PINS_AS_GPIOS
|
|||
Set this if VCI pin block HW logic is not required in the board
|
||||
design.
|
||||
|
||||
config SOC_MEC1501_TEST_CLK_OUT
|
||||
bool "Enable test clock out pin"
|
||||
help
|
||||
Enables a test clock out pin
|
||||
|
||||
choice
|
||||
prompt "MEC1501 debug interface general configuration"
|
||||
default SOC_MEC1501_DEBUG_WITHOUT_TRACING
|
||||
|
|
|
@ -21,10 +21,11 @@ menuconfig PM
|
|||
|
||||
if PM
|
||||
|
||||
config PM_DEBUG
|
||||
bool "System Power Management debug hooks"
|
||||
config PM_STATS
|
||||
bool "System Power Management Stats"
|
||||
depends on STATS
|
||||
help
|
||||
Enable System Power Management debugging hooks.
|
||||
Enable System Power Management Stats.
|
||||
|
||||
source "subsys/pm/policy/Kconfig"
|
||||
|
||||
|
|
|
@ -26,58 +26,78 @@ static struct pm_state_info z_power_state;
|
|||
static sys_slist_t pm_notifiers = SYS_SLIST_STATIC_INIT(&pm_notifiers);
|
||||
static struct k_spinlock pm_notifier_lock;
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
#ifdef CONFIG_PM_STATS
|
||||
|
||||
struct pm_state_debug_info {
|
||||
uint32_t count;
|
||||
uint32_t last_res;
|
||||
uint32_t total_res;
|
||||
};
|
||||
#include <stats/stats.h>
|
||||
#include <sys/util_macro.h>
|
||||
|
||||
struct pm_cpu_debug_info {
|
||||
|
||||
struct pm_cpu_timing {
|
||||
uint32_t timer_start;
|
||||
uint32_t timer_end;
|
||||
struct pm_state_debug_info state_info[PM_STATES_LEN];
|
||||
};
|
||||
|
||||
static struct pm_cpu_debug_info pm_cpu_dbg_info[CONFIG_MP_NUM_CPUS];
|
||||
static struct pm_cpu_timing pm_cpu_timings[CONFIG_MP_NUM_CPUS];
|
||||
|
||||
static inline void pm_debug_start_timer(void)
|
||||
static inline void pm_start_timer(void)
|
||||
{
|
||||
pm_cpu_dbg_info[_current_cpu->id].timer_start = k_cycle_get_32();
|
||||
pm_cpu_timings[_current_cpu->id].timer_start = k_cycle_get_32();
|
||||
}
|
||||
|
||||
static inline void pm_debug_stop_timer(void)
|
||||
static inline void pm_stop_timer(void)
|
||||
{
|
||||
pm_cpu_dbg_info[_current_cpu->id].timer_end = k_cycle_get_32();
|
||||
pm_cpu_timings[_current_cpu->id].timer_end = k_cycle_get_32();
|
||||
}
|
||||
|
||||
static void pm_log_debug_info(enum pm_state state)
|
||||
{
|
||||
uint32_t res = pm_cpu_dbg_info[_current_cpu->id].timer_end
|
||||
- pm_cpu_dbg_info[_current_cpu->id].timer_start;
|
||||
STATS_SECT_START(pm_cpu_stats)
|
||||
STATS_SECT_ENTRY32(state_count)
|
||||
STATS_SECT_ENTRY32(state_last_cycles)
|
||||
STATS_SECT_ENTRY32(state_total_cycles)
|
||||
STATS_SECT_END;
|
||||
|
||||
pm_cpu_dbg_info[_current_cpu->id].state_info[state].count++;
|
||||
pm_cpu_dbg_info[_current_cpu->id].state_info[state].last_res = res;
|
||||
pm_cpu_dbg_info[_current_cpu->id].state_info[state].total_res += res;
|
||||
}
|
||||
STATS_NAME_START(pm_cpu_stats)
|
||||
STATS_NAME(pm_cpu_stats, state_count)
|
||||
STATS_NAME(pm_cpu_stats, state_last_cycles)
|
||||
STATS_NAME(pm_cpu_stats, state_total_cycles)
|
||||
STATS_NAME_END(pm_cpu_stats);
|
||||
|
||||
void pm_dump_debug_info(void)
|
||||
#define PM_STAT_NAME_LEN sizeof("pm_cpu_XXX_state_X_stats")
|
||||
static char pm_cpu_stat_names[CONFIG_MP_NUM_CPUS][PM_STATES_LEN][PM_STAT_NAME_LEN];
|
||||
static struct stats_pm_cpu_stats pm_cpu_stats[CONFIG_MP_NUM_CPUS][PM_STATES_LEN];
|
||||
|
||||
static int pm_stats_init(const struct device *unused)
|
||||
{
|
||||
for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||
for (int j = 0; j < PM_STATES_LEN; j++) {
|
||||
LOG_DBG("PM:cpu = %d state = %d, count = %u last_res = %u, "
|
||||
"total_res = %u\n", i, j,
|
||||
pm_cpu_dbg_info[i].state_info[j].count,
|
||||
pm_cpu_dbg_info[i].state_info[j].last_res,
|
||||
pm_cpu_dbg_info[i].state_info[j].total_res);
|
||||
snprintk(pm_cpu_stat_names[i][j], PM_STAT_NAME_LEN,
|
||||
"pm_cpu_%03d_state_%1d_stats", i, j);
|
||||
stats_init(&(pm_cpu_stats[i][j].s_hdr), STATS_SIZE_32, 3,
|
||||
STATS_NAME_INIT_PARMS(pm_cpu_stats));
|
||||
stats_register(pm_cpu_stat_names[i][j], &(pm_cpu_stats[i][j].s_hdr));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pm_stats_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
static void pm_stats_update(enum pm_state state)
|
||||
{
|
||||
uint8_t cpu = _current_cpu->id;
|
||||
uint32_t time_total =
|
||||
pm_cpu_timings[cpu].timer_end -
|
||||
pm_cpu_timings[cpu].timer_start;
|
||||
|
||||
STATS_INC(pm_cpu_stats[cpu][state], state_count);
|
||||
STATS_INCN(pm_cpu_stats[cpu][state], state_total_cycles, time_total);
|
||||
STATS_SET(pm_cpu_stats[cpu][state], state_last_cycles, time_total);
|
||||
}
|
||||
#else
|
||||
static inline void pm_debug_start_timer(void) { }
|
||||
static inline void pm_debug_stop_timer(void) { }
|
||||
static void pm_log_debug_info(enum pm_state state) { }
|
||||
static inline void pm_start_timer(void) {}
|
||||
static inline void pm_stop_timer(void) {}
|
||||
|
||||
|
||||
static void pm_stats_update(enum pm_state state) {}
|
||||
#endif
|
||||
|
||||
static inline void exit_pos_ops(struct pm_state_info info)
|
||||
|
@ -173,10 +193,10 @@ void pm_power_state_force(struct pm_state_info info)
|
|||
pm_state_notify(true);
|
||||
|
||||
k_sched_lock();
|
||||
pm_debug_start_timer();
|
||||
pm_start_timer();
|
||||
/* Enter power state */
|
||||
pm_state_set(z_power_state);
|
||||
pm_debug_stop_timer();
|
||||
pm_stop_timer();
|
||||
|
||||
pm_system_resume();
|
||||
k_sched_unlock();
|
||||
|
@ -262,11 +282,11 @@ enum pm_state pm_system_suspend(int32_t ticks)
|
|||
* sent the notification in pm_system_resume().
|
||||
*/
|
||||
k_sched_lock();
|
||||
pm_debug_start_timer();
|
||||
pm_start_timer();
|
||||
/* Enter power state */
|
||||
pm_state_notify(true);
|
||||
pm_state_set(z_power_state);
|
||||
pm_debug_stop_timer();
|
||||
pm_stop_timer();
|
||||
|
||||
/* Wake up sequence starts here */
|
||||
#if CONFIG_PM_DEVICE
|
||||
|
@ -275,7 +295,7 @@ enum pm_state pm_system_suspend(int32_t ticks)
|
|||
pm_resume_devices();
|
||||
}
|
||||
#endif
|
||||
pm_log_debug_info(z_power_state.state);
|
||||
pm_stats_update(z_power_state.state);
|
||||
pm_system_resume();
|
||||
k_sched_unlock();
|
||||
SYS_PORT_TRACING_FUNC_EXIT(pm, system_suspend, ticks, z_power_state.state);
|
||||
|
|
|
@ -2,5 +2,6 @@ CONFIG_LOG=y
|
|||
CONFIG_ZTEST=y
|
||||
CONFIG_PM=y
|
||||
CONFIG_THREAD_NAME=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_STATS=y
|
||||
CONFIG_PM_STATS=y
|
||||
CONFIG_IDLE_STACK_SIZE=640
|
||||
|
|
Loading…
Reference in a new issue