zephyr/subsys/power/device.c
Peter Bigot e70de6ee82 power: device: fix name for Nordic clock driver
The device power management infrastructure maintains a hard-coded list
of critical devices to ensure suspend and resume are performed in the
proper order.  PR #21298 combined the 32 KiHz and 16 MHz clock devices
into a single driver, changing the name so the clock driver is not
handled at the correct time, but rather at whatever point it appears
in the general device list.

Update the list to the current clock driver name.  Also store the
device names as standard strings rather than padding them to a fixed
length.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
2020-03-16 15:54:36 +01:00

151 lines
3.2 KiB
C

/*
* Copyright (c) 2018 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <kernel.h>
#include <string.h>
#include <soc.h>
#include <device.h>
#include "policy/pm_policy.h"
#if defined(CONFIG_SYS_POWER_MANAGEMENT)
#define LOG_LEVEL CONFIG_SYS_PM_LOG_LEVEL /* From power module Kconfig */
#include <logging/log.h>
LOG_MODULE_DECLARE(power);
/*
* FIXME: Remove the conditional inclusion of
* core_devices array once we enble the capability
* to build the device list based on devices power
* and clock domain dependencies.
*/
#if defined(CONFIG_SOC_FAMILY_NRF)
#define MAX_PM_DEVICES 15
static const char *const core_devices[] = {
"CLOCK",
"sys_clock",
"UART_0",
};
#else
#error "Add SoC's core devices list for PM"
#endif
/*
* Ordered list to store devices on which
* device power policies would be executed.
*/
static int device_ordered_list[MAX_PM_DEVICES];
static int device_retval[MAX_PM_DEVICES];
static struct device *pm_device_list;
static int device_count;
const char *device_pm_state_str(u32_t state)
{
switch (state) {
case DEVICE_PM_ACTIVE_STATE:
return "active";
case DEVICE_PM_LOW_POWER_STATE:
return "low power";
case DEVICE_PM_SUSPEND_STATE:
return "suspend";
case DEVICE_PM_FORCE_SUSPEND_STATE:
return "force suspend";
case DEVICE_PM_OFF_STATE:
return "off";
default:
return "";
}
}
static int _sys_pm_devices(u32_t state)
{
for (int i = device_count - 1; i >= 0; i--) {
int idx = device_ordered_list[i];
/* TODO: Improve the logic by checking device status
* and set the device states accordingly.
*/
device_retval[i] = device_set_power_state(&pm_device_list[idx],
state,
NULL, NULL);
if (device_retval[i]) {
LOG_DBG("%s did not enter %s state",
pm_device_list[idx].config->name,
device_pm_state_str(state));
return device_retval[i];
}
}
return 0;
}
int sys_pm_suspend_devices(void)
{
return _sys_pm_devices(DEVICE_PM_SUSPEND_STATE);
}
int sys_pm_low_power_devices(void)
{
return _sys_pm_devices(DEVICE_PM_LOW_POWER_STATE);
}
int sys_pm_force_suspend_devices(void)
{
return _sys_pm_devices(DEVICE_PM_FORCE_SUSPEND_STATE);
}
void sys_pm_resume_devices(void)
{
int i;
for (i = 0; i < device_count; i++) {
if (!device_retval[i]) {
int idx = device_ordered_list[i];
device_set_power_state(&pm_device_list[idx],
DEVICE_PM_ACTIVE_STATE, NULL, NULL);
}
}
}
void sys_pm_create_device_list(void)
{
int count;
int i, j;
bool is_core_dev;
/*
* Create an ordered list of devices that will be suspended.
* Ordering should be done based on dependencies. Devices
* in the beginning of the list will be resumed first.
*/
device_list_get(&pm_device_list, &count);
/* Reserve for 32KHz, 16MHz, system clock, etc... */
device_count = ARRAY_SIZE(core_devices);
for (i = 0; (i < count) && (device_count < MAX_PM_DEVICES); i++) {
/* Check if the device is core device */
for (j = 0, is_core_dev = false;
j < ARRAY_SIZE(core_devices);
j++) {
if (!strcmp(pm_device_list[i].config->name,
core_devices[j])) {
is_core_dev = true;
break;
}
}
if (is_core_dev) {
device_ordered_list[j] = i;
} else {
device_ordered_list[device_count++] = i;
}
}
}
#endif /* defined(CONFIG_SYS_POWER_MANAGEMENT) */