Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions proxyclient/experiments/mmio_sweep.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
print(dev.name)
sys.exit(0)

granule = 0x4000
if chip_id in (0x8960, 0x7000, 0x7001):
granule = 0x1000
else:
granule = 0x4000

lp = LinkedProgram(u)
lp.load_inline_c(f'''
Expand Down Expand Up @@ -96,7 +99,7 @@ def describe_mask(mask, maskrange):

pd_did_enable = set()
pmgr = u.adt["/arm-io/pmgr"]
ps_dev_by_id = {dev.id: dev for dev in pmgr.devices}
ps_dev_by_id = {u.adt.pmgr_dev_get_id(dev): dev for dev in pmgr.devices}
ps_deps = dict()
ps_addrs = dict()

Expand All @@ -110,7 +113,7 @@ def describe_mask(mask, maskrange):
ps_addrs[dev.name] = addr
ps_deps[dev.name] = [
ps_dev_by_id[idx].name for idx
in dev.parents if idx in ps_dev_by_id
in u.adt.pmgr_dev_get_parents(dev) if idx in ps_dev_by_id
]

if lp.is_t6000():
Expand Down
37 changes: 31 additions & 6 deletions proxyclient/m1n1/adt.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,27 @@
"flags" / PMGRDeviceFlags,
"unk1_0" / Int8ul,
"unk1_1" / Int8ul,
"unk1_2" / Int8ul,
"parents" / Array(2, Int16ul),
"id1" / Int8ul,
"parents_un" / Union (0,
"u8id" / Struct(
"parents" / Array(2, Int8ul),
"unk_u8id" / Array(2, Int8ul),
),
"u16id" / Struct (
"parents" / Array(2, Int16ul),
),
),
"perf_idx" / Int8ul,
"perf_block" / Int8ul,
"psidx" / Int8ul,
"psreg" / Int8ul,
"unk2_0" / Int16ul,
"pd" / Int8ul,
"ps_cfg16" / Int8ul,
Const(0, Int32ul),
Const(0, Int32ul),
"unk2_1" / Int32ul,
"unk2_2" / Int32ul,
"unk2_3" / Int16ul,
"id" / Int16ul,
"id2" / Int16ul,
"unk3" / Int32ul,
"name" / PaddedString(16, "ascii")
))
Expand Down Expand Up @@ -801,8 +809,25 @@ def create_node(self, name):
self[name] = node
return node

def pmgr_init(self):
self.pmgr_u8id = (self["/arm-io/pmgr"].devices[0].id1 != self["/arm-io/pmgr"].devices[1].id1)

def pmgr_dev_get_id(self, dev):
if self.pmgr_u8id:
return dev.id1
else:
return dev.id2

def pmgr_dev_get_parents(self, dev):
if self.pmgr_u8id:
return dev.parents_un.u8id.parents
else:
return dev.parents_un.u16id.parents

def load_adt(data):
return ADTNode(ADTNodeStruct.parse(data))
node = ADTNode(ADTNodeStruct.parse(data))
node.pmgr_init()
return node

if __name__ == "__main__":
import sys, argparse, pathlib
Expand Down
4 changes: 2 additions & 2 deletions proxyclient/m1n1/hv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ def rh(base, off, width):

pmgr = self.adt["/arm-io/pmgr"]
dev_by_name = {dev.name: dev for dev in pmgr.devices}
dev_by_id = {dev.id: dev for dev in pmgr.devices}
dev_by_id = {self.adt.pmgr_dev_get_id(dev): dev for dev in pmgr.devices}

pmgr_hooks = []

Expand All @@ -1491,7 +1491,7 @@ def hook_pmgr_dev(dev):
if dev.psidx or dev.psreg:
addr = pmgr.get_reg(ps.reg)[0] + ps.offset + dev.psidx * 8
pmgr_hooks.append(addr)
for idx in dev.parents:
for idx in self.adt.pmgr_dev_get_parents(dev):
if idx in dev_by_id:
hook_pmgr_dev(dev_by_id[idx])

Expand Down
37 changes: 29 additions & 8 deletions proxyclient/m1n1/hw/pmu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from ..utils import *
from .spmi import SPMI
from .i2c import I2C

__all__ = ["PMU"]

Expand All @@ -11,26 +12,46 @@ class PMU:
def __init__(self, u, adt_path=None):
self.u = u
if adt_path is None:
adt_path = PMU.find_primary_pmu(u.adt)
(adt_path, bus_type) = PMU.find_primary_pmu(u.adt)

self.node = u.adt[adt_path]
self.spmi = SPMI(u, adt_path.rpartition('/')[0])
self.bus_type = bus_type
if bus_type == "spmi":
self.spmi = SPMI(u, adt_path.rpartition('/')[0])
self.primary = u.adt[adt_path].is_primary == 1
elif bus_type == "i2c":
self.i2c = I2C(u, adt_path.rpartition('/')[0])
self.primary = u.adt[adt_path].name == "pmu"
self.adt_path = adt_path
self.primary = u.adt[adt_path].is_primary == 1
self.reg = u.adt[adt_path].reg[0]

def reset_panic_counter(self):
if self.primary:
if self.primary and self.bus_type == "spmi":
leg_scrpad = self.node.info_leg__scrpad[0]
self.spmi.write8(self.reg, leg_scrpad + 2, 0) # error counts
elif self.primary and self.bus_type == "i2c":
if self.node.compatible[0] in ["pmu,d2255", "pmu,d2257", "pmu,d2333", "pmu,d2365", "pmu,d2400"]:
counter = 0x5002
elif self.node.compatible[0] in ["pmu,d2045", "pmu,d2089", "pmu,d2186", "pmu,d2207"]:
counter = 0x4002
else:
print("Reset panic unsupported")
return
self.i2c.write_reg(self.reg, counter, [0], regaddrlen=2)
else:
raise ValueError("Unsupported bus type") # should never happen

@staticmethod
def find_primary_pmu(adt):
for child in adt["/arm-io"]:
if child.name.startswith("nub-spmi"):
if child.name.startswith("nub-spmi") or child.name.startswith("spmi"):
for pmu in child:
compat = getattr(pmu, "compatible")[0] if hasattr(pmu, "compatible") else "unset"
primary = (getattr(pmu, "is-primary") == 1) if hasattr(pmu, "is-primary") else False
if compat == "pmu,spmi" and primary:
return pmu._path.removeprefix('/device-tree')
raise KeyError(f"primary 'pmu,spmi' node not found")
if compat in ("pmu,spmi", "pmu,d2422", "pmu,d2449") and primary:
return (pmu._path.removeprefix('/device-tree'), "spmi")
elif child.name.startswith("i2c"):
for dev in child:
if dev.name == "pmu":
return (dev._path.removeprefix('/device-tree'), "i2c")
raise KeyError(f"primary pmu node not found")
3 changes: 3 additions & 0 deletions proxyclient/m1n1/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ class M1N1Proxy(Reloadable):
P_REBOOT = 0x010
P_SLEEP = 0x011
P_EL3_CALL = 0x012
P_GET_CHIPID = 0x013

P_WRITE64 = 0x100
P_WRITE32 = 0x101
Expand Down Expand Up @@ -769,6 +770,8 @@ def el3_call(self, addr, *args):
if len(args) > 4:
raise ValueError("Too many arguments")
return self.request(self.P_EL3_CALL, addr, *args)
def get_chipid(self):
return self.request(self.P_GET_CHIPID)

def write64(self, addr, data):
'''write 8 byte value to given address'''
Expand Down
8 changes: 8 additions & 0 deletions proxyclient/m1n1/proxyutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,14 @@ def bootstrap_port(iface, proxy):
do_baud = False

if do_baud:
try:
chip_id = proxy.get_chipid()
# These chips are too slow for baudrate 1500000 at their default frequency
if chip_id in (0x8960, 0x7000, 0x7001, 0x8000, 0x8001, 0x8003, 0x8010, 0x8011, 0x8015):
proxy.cpufreq_init()
# Old m1n1 version, assume they are not one of those chips
except ProxyCommandError: {}

try:
iface.nop()
proxy.set_baud(1500000)
Expand Down
16 changes: 10 additions & 6 deletions proxyclient/tools/dump_pmgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

pmgr = dt["/arm-io/pmgr"]

dev_by_id = {dev.id: dev for dev in pmgr.devices}
dev_by_id = {dt.pmgr_dev_get_id(dev): dev for dev in pmgr.devices}
pd_by_id = {pd.id: pd for pd in pmgr.power_domains}
clk_by_id = {clk.id: clk for clk in pmgr.clocks}

Expand Down Expand Up @@ -47,8 +47,8 @@
print("=== Devices ===")
for i, dev in enumerate(pmgr.devices):
flags = ", ".join(k for k in dev.flags if k[0] != "_" and dev.flags[k])
s = f" #{i:3d} {dev.name:20s} id: {dev.id:3d} psreg: {dev.psreg:2d}:{dev.psidx:2d} "
s += f" flags: {flags:24s} unk1_0: {dev.unk1_0} unk1_1: {dev.unk1_1} unk1_2: {dev.unk1_2} "
s = f" #{i:3d} {dev.name:20s} id: {u.adt.pmgr_dev_get_id(dev):3d} psreg: {dev.psreg:2d}:{dev.psidx:2d} "
s += f" flags: {flags:24s} unk1_0: {dev.unk1_0} unk1_1: {dev.unk1_1} id1: {dev.id1} "
s += f" perf_reg: {dev.perf_block}:{dev.perf_idx:#04x} unk3: {dev.unk3:3d} {dev.unk2_0:2d} {dev.ps_cfg16:2d} {dev.unk2_3:3d}"

if not dev.flags.no_ps:
Expand All @@ -63,10 +63,10 @@
s += f" pd: {pd.name:20s}"
else:
s += " "
if any(dev.parents):
s += " parents: " + ", ".join(dev_by_id[idx].name if idx in dev_by_id else f"#{idx}" for idx in dev.parents if idx)
if any(dt.pmgr_dev_get_parents(dev)):
s += " parents: " + ", ".join(dev_by_id[idx].name if idx in dev_by_id else f"#{idx}" for idx in dt.pmgr_dev_get_parents(dev) if idx)
print(s)
for i in dev_users.get(dev.id, []):
for i in dev_users.get(dt.pmgr_dev_get_id(dev), []):
print(f" User: {i}")

print()
Expand Down Expand Up @@ -107,6 +107,10 @@
print(f" User: {j}")

print()

if chip_id in (0x8960, 0x7000, 0x7001, 0x8000, 0x8001, 0x8003, 0x8010, 0x8012, 0x8015):
exit(0)

print("=== Boot clocks ===")
for i, (freq, reg, nclk) in enumerate(zip(arm_io.clock_frequencies,
arm_io.clock_frequencies_regs,
Expand Down
6 changes: 3 additions & 3 deletions proxyclient/tools/pmgr_adt2dt.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

pmgr = dt["/arm-io/pmgr"]

dev_by_id = {dev.id: dev for dev in pmgr.devices}
dev_by_id = {dt.pmgr_dev_get_id(dev): dev for dev in pmgr.devices}

blocks = {}
maxaddr = {}
Expand Down Expand Up @@ -83,8 +83,8 @@ def die_label(s):
if dev.flags.critical:
print("\t\tapple,always-on;")

if any(dev.parents):
domains = [f"<&{die_node('ps_'+dev_by_id[idx].name.lower())}>" for idx in dev.parents if idx]
if any(dt.pmgr_dev_get_parents(dev)):
domains = [f"<&{die_node('ps_'+dev_by_id[idx].name.lower())}>" for idx in dt.pmgr_dev_get_parents(dev) if idx]
print(f"\t\tpower-domains = {', '.join(domains)};")

print( "\t};")
Expand Down
4 changes: 4 additions & 0 deletions src/proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
case P_EL3_CALL:
reply->retval = el3_call((void *)request->args[0], request->args[1], request->args[2],
request->args[3], request->args[4]);
break;
case P_GET_CHIPID:
reply->retval = chip_id;
break;

case P_WRITE64:
exc_guard = GUARD_SKIP;
Expand Down
1 change: 1 addition & 0 deletions src/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ typedef enum {
P_REBOOT,
P_SLEEP,
P_EL3_CALL,
P_GET_CHIPID,

P_WRITE64 = 0x100, // Generic register functions
P_WRITE32,
Expand Down