diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index e27b84288f0..d7298863c38 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -5,6 +5,8 @@ */ #include +#include + #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_ */ diff --git a/scripts/gen_handles.py b/scripts/gen_handles.py index ba027e1ff16..a55436ff716 100755 --- a/scripts/gen_handles.py +++ b/scripts/gen_handles.py @@ -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)