power: device: reduce space required to identify pm-capable devices

Use a smaller ordinal type than int to hold the global index
identifying devices that support power management.

Use an upper bound instead of an array of flags to identify the
devices that were successfully suspended.

Only attempt pm on devices that provide a non-default pm control
function.

Use shorter more descriptive names for state variables.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2020-03-14 15:51:31 -05:00 committed by Carles Cufí
commit cce7165ea4

View file

@ -44,14 +44,25 @@ static const char *const core_devices[] = {
#error "Add SoC's core devices list for PM" #error "Add SoC's core devices list for PM"
#endif #endif
/* /* Ordinal of sufficient size to index available devices. */
* Ordered list to store devices on which typedef u16_t device_idx_t;
* device power policies would be executed.
/* The maximum value representable with a device_idx_t. */
#define DEVICE_IDX_MAX ((device_idx_t)(-1))
/* An array of all devices in the application. */
static struct device *all_devices;
/* Indexes into all_devices for devices that support pm,
* in dependency order (later may depend on earlier).
*/ */
static int device_ordered_list[MAX_PM_DEVICES]; static device_idx_t pm_devices[MAX_PM_DEVICES];
static int device_retval[MAX_PM_DEVICES];
static struct device *pm_device_list; /* Number of devices that support pm */
static int device_count; static device_idx_t num_pm;
/* Number of devices successfully suspended. */
static device_idx_t num_susp;
const char *device_pm_state_str(u32_t state) const char *device_pm_state_str(u32_t state)
{ {
@ -73,21 +84,26 @@ const char *device_pm_state_str(u32_t state)
static int _sys_pm_devices(u32_t state) static int _sys_pm_devices(u32_t state)
{ {
for (int i = device_count - 1; i >= 0; i--) { num_susp = 0;
int idx = device_ordered_list[i];
for (int i = num_pm - 1; i >= 0; i--) {
device_idx_t idx = pm_devices[i];
struct device *dev = &all_devices[idx];
int rc;
/* TODO: Improve the logic by checking device status /* TODO: Improve the logic by checking device status
* and set the device states accordingly. * and set the device states accordingly.
*/ */
device_retval[i] = device_set_power_state(&pm_device_list[idx], rc = device_set_power_state(dev, state, NULL, NULL);
state,
NULL, NULL); if (rc != 0) {
if (device_retval[i]) { LOG_DBG("%s did not enter %s state: %d",
LOG_DBG("%s did not enter %s state", dev->config->name,
pm_device_list[idx].config->name, device_pm_state_str(state), rc);
device_pm_state_str(state)); return rc;
return device_retval[i];
} }
++num_susp;
} }
return 0; return 0;
@ -110,51 +126,59 @@ int sys_pm_force_suspend_devices(void)
void sys_pm_resume_devices(void) void sys_pm_resume_devices(void)
{ {
int i; device_idx_t pmi = num_pm - num_susp;
for (i = 0; i < device_count; i++) { num_susp = 0;
if (!device_retval[i]) { while (pmi < num_pm) {
int idx = device_ordered_list[i]; device_idx_t idx = pm_devices[pmi];
device_set_power_state(&pm_device_list[idx], device_set_power_state(&all_devices[idx],
DEVICE_PM_ACTIVE_STATE, NULL, NULL); DEVICE_PM_ACTIVE_STATE,
} NULL, NULL);
++pmi;
} }
} }
void sys_pm_create_device_list(void) void sys_pm_create_device_list(void)
{ {
int count; int count;
int i, j; device_idx_t pmi;
bool is_core_dev;
/* /*
* Create an ordered list of devices that will be suspended. * Create an ordered list of devices that will be suspended.
* Ordering should be done based on dependencies. Devices * Ordering should be done based on dependencies. Devices
* in the beginning of the list will be resumed first. * in the beginning of the list will be resumed first.
*/ */
device_list_get(&pm_device_list, &count); device_list_get(&all_devices, &count);
/* Reserve for 32KHz, 16MHz, system clock, etc... */ __ASSERT_NO_MSG((0 <= count) && (count <= DEVICE_IDX_MAX));
device_count = ARRAY_SIZE(core_devices);
for (i = 0; (i < count) && (device_count < MAX_PM_DEVICES); i++) { /* Reserve initial slots for core devices. */
num_pm = ARRAY_SIZE(core_devices);
/* Check if the device is core device */ for (pmi = 0; (pmi < count) && (num_pm < MAX_PM_DEVICES); pmi++) {
for (j = 0, is_core_dev = false; device_idx_t cdi = 0;
j < ARRAY_SIZE(core_devices); const struct device *dev = &all_devices[pmi];
j++) {
if (!strcmp(pm_device_list[i].config->name, /* Ignore "device"s that don't support PM */
core_devices[j])) { if (dev->config->device_pm_control == device_pm_control_nop) {
is_core_dev = true; continue;
break;
}
} }
if (is_core_dev) { /* Check if the device is a core device, which has a
device_ordered_list[j] = i; * reserved slot.
} else { */
device_ordered_list[device_count++] = i; while (cdi < ARRAY_SIZE(core_devices)) {
if (strcmp(dev->config->name, core_devices[cdi]) == 0) {
pm_devices[cdi] = pmi;
break;
}
++cdi;
}
/* Append the device if it doesn't have a reserved slot. */
if (cdi == ARRAY_SIZE(core_devices)) {
pm_devices[num_pm++] = pmi;
} }
} }
} }