pm: Only resize power domains

Instead of resizing all devices handles, we just resize devices that are
power domains. This means that a power domain has to be declared as
compatbile with "power-domain" in device tree node.

Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Flavio Ceolin 2022-03-20 21:53:42 -07:00 committed by Marti Bolivar
commit d02a1e9879
2 changed files with 78 additions and 1 deletions

View file

@ -5,6 +5,8 @@
*/
#include <device.h>
#include <pm/device.h>
#ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_
#define ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_
@ -97,5 +99,17 @@ GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_SIZEOF, sizeof(const struct device));
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_HANDLES_OFFSET,
offsetof(struct device, handles));
#ifdef CONFIG_PM_DEVICE
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_PM_OFFSET,
offsetof(struct device, pm));
#endif
/* member offsets in the pm_device structure. Used in image post-processing */
GEN_ABSOLUTE_SYM(_PM_DEVICE_STRUCT_FLAGS_OFFSET,
offsetof(struct pm_device, flags));
GEN_ABSOLUTE_SYM(_PM_DEVICE_FLAG_PD, PM_DEVICE_FLAG_PD);
/* LCOV_EXCL_STOP */
#endif /* ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_ */

View file

@ -137,6 +137,7 @@ class Device:
# assigned by correlating the device struct handles pointer
# value with the addr of a Handles instance.
self.__handles = None
self.__pm = None
@property
def obj_handles(self):
@ -157,6 +158,55 @@ class Device:
self.__handles = struct.unpack(format, data[offset:offset + size])[0]
return self.__handles
@property
def obj_pm(self):
"""
Returns the value from the device struct pm field, pointing to the
pm struct for this device.
"""
if self.__pm is None:
data = symbol_data(self.elf, self.sym)
format = "<" if self.elf.little_endian else ">"
if self.elf.elfclass == 32:
format += "I"
size = 4
else:
format += "Q"
size = 8
offset = self.ld_constants["_DEVICE_STRUCT_PM_OFFSET"]
self.__pm = struct.unpack(format, data[offset:offset + size])[0]
return self.__pm
class PMDevice:
"""
Represents information about a pm_device object and its references to other objects.
"""
def __init__(self, elf, ld_constants, sym, addr):
self.elf = elf
self.ld_constants = ld_constants
self.sym = sym
self.addr = addr
# Point to the device instance associated with the pm_device;
self.__flags = None
def is_domain(self):
"""
Checks if the device that this pm struct belongs is a power domain.
"""
if self.__flags is None:
data = symbol_data(self.elf, self.sym)
format = "<" if self.elf.little_endian else ">"
if self.elf.elfclass == 32:
format += "I"
size = 4
else:
format += "Q"
size = 8
offset = self.ld_constants["_PM_DEVICE_STRUCT_FLAGS_OFFSET"]
self.__flags = struct.unpack(format, data[offset:offset + size])[0]
return self.__flags & (1 << self.ld_constants["_PM_DEVICE_FLAG_PD"])
class Handles:
def __init__(self, sym, addr, handles, node):
self.sym = sym
@ -177,6 +227,7 @@ def main():
with open(edtser, 'rb') as f:
edt = pickle.load(f)
pm_devices = {}
devices = []
handles = []
# Leading _ are stripped from the stored constant key
@ -184,6 +235,10 @@ def main():
want_constants = set([args.start_symbol,
"_DEVICE_STRUCT_SIZEOF",
"_DEVICE_STRUCT_HANDLES_OFFSET"])
if args.num_dynamic_devices != 0:
want_constants.update(["_PM_DEVICE_FLAG_PD",
"_DEVICE_STRUCT_PM_OFFSET",
"_PM_DEVICE_STRUCT_FLAGS_OFFSET"])
ld_constants = dict()
for section in elf.iter_sections():
@ -208,6 +263,10 @@ def main():
node = edt.dep_ord2node[hdls[0]] if (hdls and hdls[0] != 0) else None
handles.append(Handles(sym, addr, hdls, node))
debug("handles %s %d %s" % (sym.name, hdls[0] if hdls else -1, node))
if sym.name.startswith("__pm_device__") and not sym.name.endswith("_slot"):
addr = sym.entry.st_value
pm_devices[addr] = PMDevice(elf, ld_constants, sym, addr)
debug("pm device %s" % (sym.name,))
assert len(want_constants) == len(ld_constants), "linker map data incomplete"
@ -339,7 +398,11 @@ def main():
else:
sup_paths.append('(%s)' % dn.path)
hdls.extend(dn.__device.dev_handle for dn in sn.__supports)
hdls.extend(DEVICE_HANDLE_NULL for dn in range(args.num_dynamic_devices))
if args.num_dynamic_devices != 0:
pm = pm_devices.get(dev.obj_pm)
if pm and pm.is_domain():
hdls.extend(DEVICE_HANDLE_NULL for dn in range(args.num_dynamic_devices))
# Terminate the array with the end symbol
hdls.append(DEVICE_HANDLE_ENDS)