diff --git a/include/device.h b/include/device.h index 8263af3b4e8..1bb12b423a9 100644 --- a/include/device.h +++ b/include/device.h @@ -692,11 +692,27 @@ int device_busy_check(const struct device *chk_dev); #define Z_DEVICE_EXTRA_HANDLES(...) \ FOR_EACH_NONEMPTY_TERM(IDENTITY, (,), __VA_ARGS__) +/* If device power management is enabled, this macro defines a pointer to a + * device in the z_pm_device_slots region. When invoked for each device, this + * will effectively result in a device pointer array with the same size of the + * actual devices list. This is used internally by the device PM subsystem to + * keep track of suspended devices during system power transitions. + */ +#if CONFIG_PM_DEVICE +#define Z_DEVICE_DEFINE_PM_SLOT(dev_name) \ + static const Z_DECL_ALIGN(struct device *) \ + _CONCAT(__pm_device_slot_, DEVICE_NAME_GET(dev_name)) __used \ + __attribute__((__section__(".z_pm_device_slots"))); +#else +#define Z_DEVICE_DEFINE_PM_SLOT(dev_name) +#endif + /* Construct objects that are referenced from struct device. These * include power management and dependency handles. */ #define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \ - Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) + Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \ + Z_DEVICE_DEFINE_PM_SLOT(dev_name) /* Initial build provides a record that associates the device object diff --git a/include/linker/common-ram.ld b/include/linker/common-ram.ld index a1828cf82cf..e8754cf851c 100644 --- a/include/linker/common-ram.ld +++ b/include/linker/common-ram.ld @@ -37,6 +37,15 @@ __device_end = .; } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#if CONFIG_PM_DEVICE + SECTION_DATA_PROLOGUE(pm_device_slots, (NOLOAD),) + { + __pm_device_slots_start = .; + KEEP(*(".z_pm_device_slots")); + __pm_device_slots_end = .; + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif + SECTION_DATA_PROLOGUE(initshell,,) { /* link in shell initialization objects for all modules that diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index d5b6fdfaaef..1ba64f2da71 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -60,11 +60,6 @@ config DEVICE_POWER_MANAGEMENT help This option is deprecated, please use CONFIG_PM_DEVICE instead. -config PM_MAX_DEVICES - int "Max number of devices support power management" - depends on PM_DEVICE - default 15 - config PM_DEVICE_RUNTIME bool "Runtime Device Power Management" depends on PM_DEVICE diff --git a/subsys/pm/device.c b/subsys/pm/device.c index 9c49bd360cb..ec683d43fde 100644 --- a/subsys/pm/device.c +++ b/subsys/pm/device.c @@ -18,10 +18,7 @@ LOG_MODULE_DECLARE(power); extern const struct device __device_start[]; extern const struct device __device_end[]; -/* Indexes into all_devices for devices that support pm, - * in dependency order (later may depend on earlier). - */ -static const struct device *pm_devices[CONFIG_PM_MAX_DEVICES]; +extern const struct device *__pm_device_slots_start[]; /* Number of devices successfully suspended. */ static size_t num_susp; @@ -77,10 +74,8 @@ static int _pm_devices(uint32_t state) return rc; } - pm_devices[num_susp] = dev; + __pm_device_slots_start[num_susp] = dev; num_susp++; - __ASSERT(num_susp < CONFIG_PM_MAX_DEVICES, - "Number of pm devices > CONFIG_PM_MAX_DEVICES"); } } @@ -107,7 +102,7 @@ void pm_resume_devices(void) size_t i; for (i = 0; i < num_susp; i++) { - pm_device_state_set(pm_devices[i], + pm_device_state_set(__pm_device_slots_start[i], PM_DEVICE_STATE_ACTIVE, NULL, NULL); }