Skip to content

Commit

Permalink
#25: fix reading device tree nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
algrant-arm committed Jan 17, 2025
1 parent 470efba commit da08e7a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 13 deletions.
41 changes: 34 additions & 7 deletions coresight-tools/cs_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def __init__(self, platform, device_type, is_hidden=False, name=None, type_name=
self.part_vendor = None
self.part_number = None # e.g. 0x906
self.cpu_number = None # CPU (PE) number within the system, e.g. as seen by Linux
self.affine_cpu = None
self.affine_cpu = None # a CS_DEVTYPE_CORE Device object we are affine to
self.type = device_type
if device_type == CS_DEVTYPE_CORE:
self.affine_cpu = self
Expand Down Expand Up @@ -156,13 +156,26 @@ def type_str(self):
return str(self.type)

def __str__(self):
"""
Generate a string representation for the device, including its name (if known)
and base address. This could unfortunately duplicate the address, if the naming
convention includes the address, e.g.
etm2@0x80000
but
etm@0x0080000@0x80000
So we try to be clever and only append the base address if it's not already
in the name.
"""
s = ""
if self.name is not None:
s = self.name
else:
s += "<%s>" % self.type_str()
if self.is_memory_mapped():
s += "@" + self.address_str()
if self.name is not None and '@' in self.name:
pass
else:
s += "@" + self.address_str()
return s

def links(self, type, end=None):
Expand Down Expand Up @@ -208,7 +221,7 @@ def set_affine_cpu(self, cpu_dev):
"""
if self.affine_cpu != cpu_dev:
assert self.affine_cpu is None, "set_affine_cpu() called twice with different devices"
assert cpu_dev.type == CS_DEVTYPE_CORE
assert cpu_dev.type == CS_DEVTYPE_CORE, "set_affine_cpu needs a core device: %s" % cpu_dev
self.affine_cpu = cpu_dev
cpu_dev.affine_devices.append(self)
if self.cpu_number is None:
Expand All @@ -218,9 +231,22 @@ def set_cpu_number(self, n):
self.cpu_number = n
if n > self.platform.max_cpu_number:
self.platform.max_cpu_number = n
if type == CS_DEVTYPE_CORE:
if self.type == CS_DEVTYPE_CORE:
# Core cpu number is now known, so update all its affine devices
# to get the same CPU number.
for d in self.affine_devices:
assert d.affine_cpu == self
d.cpu_number = n
# Some devices may already have got a CPU number, but because the core
# has only just got its own number, they're not tied together.
# Do that now.
for d in self.platform.devices:
if d.cpu_number == n and d.affine_cpu is not self:
d.set_affine_cpu(self)
elif self.affine_cpu is None:
cpu_dev = self.platform.device_by_cpu(n)
if cpu_dev is not None:
self.set_affine_cpu(cpu_dev)

def set_arm_part_number(self, pid):
assert pid <= 0xfff, "expected 3 hex digit part number: 0x%x" % pid
Expand Down Expand Up @@ -552,10 +578,10 @@ def show(self):
print(" %20s" % name, end="")
print(" %12s" % (d.type_str()), end="")
if d.is_affine_to_cpu():
if d.cpu_number is not None:
print(" %4u" % d.cpu_number, end="")
if d.affine_cpu is not None:
print("%5s" % str(d.affine_cpu), end="")
else:
print("%5u" % d.cpu_number, end="")
print(" %4s" % str(d.affine_cpu), end="")
else:
print(" ", end="")
if d.is_hidden:
Expand Down Expand Up @@ -651,6 +677,7 @@ def test():
Link(df1, ds2, CS_LINK_ATB)
p.show()
p.check()
print("Self-tests completed.")


if __name__ == "__main__":
Expand Down
46 changes: 40 additions & 6 deletions coresight-tools/cs_topology_sysfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
"ptm": CS_DEVTYPE_TRACE_CORE,
"etm": CS_DEVTYPE_TRACE_CORE,
"stm": CS_DEVTYPE_TRACE_SW,
"cti_cpu": CS_DEVTYPE_CTI,
"cti_sys": CS_DEVTYPE_CTI,
}


Expand Down Expand Up @@ -113,6 +115,7 @@ def get_cs_from_sysfs(p=None):
devtype = devtypes[base]
d = Device(p, devtype, name=sd)
d.sysfs_path = dp
# See if the device is affine to a (single) CPU
try:
cn = int(read_file(os.path.join(dp, "cpu")))
d.set_cpu_number(cn)
Expand All @@ -128,7 +131,10 @@ def get_cs_from_sysfs(p=None):
of_node = os.path.join(os.path.dirname(rp), "of_node")
if os.path.exists(of_node):
d.of_node = os.path.realpath(of_node) # /sys/firmware/devicetree
d.set_mem_address(device_tree_node_address(d.of_node))
addr = device_tree_node_address(d.of_node)
if addr == 0:
print("warning: %s has zero address" % (d.of_node), file=sys.stderr)
d.set_mem_address(addr)
firmware_node = os.path.join(os.path.dirname(rp), "firmware_node")
if os.path.exists(firmware_node):
firmware_node = os.path.realpath(firmware_node)
Expand Down Expand Up @@ -172,6 +178,9 @@ def get_cs_from_sysfs(p=None):


def device_tree_node_compatibility(dtn):
"""
Get the list of compatibility strings for a device tree node
"""
compat = read_file(os.path.join(dtn, "compatible")).split(",")
cl = []
for s in compat:
Expand Down Expand Up @@ -206,11 +215,14 @@ def device_tree_node_reg(dtn, reg_name="reg"):


def device_tree_node_property_length(dtn, prop):
"""
For a device tree node, find the #size-cells or #address-cells value,
by looking exactly one level upwards in its directory hierarchy.
(Note that if #address-cells file exists in a node, it indicates the
size of the address field in any childrens' "reg", not its own "reg".)
"""
prop = "#" + prop + "-cells"
assert dtn.startswith("/proc/device-tree/"), "unexpected device tree node: %s" % dtn
while len(dtn) > 18 and not os.path.isfile(os.path.join(dtn, prop)):
dtn = os.path.dirname(dtn)
assert dtn != "/proc/device-tree"
dtn = os.path.dirname(dtn) # Go exactly one level up
alen = device_tree_node_reg(dtn, reg_name=prop)
alen = alen * 4 # it's counted in words
return alen
Expand Down Expand Up @@ -240,7 +252,9 @@ def device_tree_node_size_length(dtn):

def device_tree_nodes():
"""
Iterate through nodes in /proc/device-tree
Iterate through nodes in the device tree.
The device tree is exported at /sys/firmware/devicetree/base
and as an alias at /proc/device-tree .
"""
for root, dirs, files in os.walk("/proc/device-tree"):
for d in dirs:
Expand All @@ -265,6 +279,9 @@ def compat_is_coresight(dcompat):
return None


#
# Map device-tree compatibility strings (minus "coresight-") into device types.
#
cs_device_tree_types = {
"etm3x": CS_DEVTYPE_TRACE_CORE,
"ptm": CS_DEVTYPE_TRACE_CORE,
Expand All @@ -276,6 +293,9 @@ def compat_is_coresight(dcompat):
"tpiu": CS_DEVTYPE_PORT,
"etb10": CS_DEVTYPE_BUFFER,
"tmc": CS_DEVTYPE_BUFFER,
"cti": CS_DEVTYPE_CTI,
"cti-v8-arch": CS_DEVTYPE_CTI,
"cpu-debug": CS_DEVTYPE_CORE,
}


Expand Down Expand Up @@ -399,6 +419,20 @@ def get_cs_from_device_tree(p=None):
return p


def list_device_tree_nodes():
"""
Debugging: just list the device tree nodes.
"""
for (dp, phandle, dcompat) in device_tree_nodes():
dc = compat_is_coresight(dcompat)
if not dc:
continue
print(" %-20s %4s %-40s" % (dc, phandle, dp), end="")
reg = read_binary_file(os.path.join(dp, "reg"))
print(" reg:%3u" % len(reg), end="")
print(" %s" % str(os.listdir(dp)))


if __name__ == "__main__":
p = get_cs_from_sysfs()
if True or p is None or not p.links:
Expand Down

0 comments on commit da08e7a

Please sign in to comment.