mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-26 16:30:17 +00:00
120 lines
3.4 KiB
Python
120 lines
3.4 KiB
Python
|
# SPDX-License-Identifier: MIT
|
||
|
|
||
|
from enum import Enum
|
||
|
|
||
|
from m1n1.trace.i2c import I2CTracer, I2CDevTracer
|
||
|
|
||
|
class HpmTracer(I2CDevTracer):
|
||
|
class State(Enum):
|
||
|
UNKNOWN = 0
|
||
|
REQUEST = 1
|
||
|
WRITE = 2
|
||
|
READ = 3
|
||
|
|
||
|
def __init__(self, addr=128, name=None, verbose=True):
|
||
|
print(f"CD3217Tracer.__init__(addr={addr}, name={name}, verbose={verbose})")
|
||
|
super().__init__(addr, name, verbose)
|
||
|
self.reset()
|
||
|
|
||
|
def reset(self):
|
||
|
self.reg = None
|
||
|
self.state = CD3217Tracer.State.UNKNOWN
|
||
|
self.length = None
|
||
|
self.data = []
|
||
|
|
||
|
def start(self, addr, read):
|
||
|
if addr != self.addr:
|
||
|
return
|
||
|
|
||
|
if self.state == CD3217Tracer.State.UNKNOWN:
|
||
|
if read:
|
||
|
self.state = CD3217Tracer.State.READ
|
||
|
else:
|
||
|
self.state = CD3217Tracer.State.REQUEST
|
||
|
elif self.state == CD3217Tracer.State.REQUEST and read:
|
||
|
pass
|
||
|
else:
|
||
|
self.log(f"unexpected state in start(read={read}): state:{self.state} reg:{self.reg} data:{self.data}")
|
||
|
|
||
|
def stop(self):
|
||
|
if self.state == CD3217Tracer.State.REQUEST and len(self.data) == 0:
|
||
|
return
|
||
|
|
||
|
msg = f"Txn: {self.addr:02x}."
|
||
|
if self.state == CD3217Tracer.State.REQUEST:
|
||
|
msg += f"r [{self.reg:02x}]"
|
||
|
elif self.state == CD3217Tracer.State.WRITE:
|
||
|
msg += f"w [{self.reg:02x}]"
|
||
|
elif self.state == CD3217Tracer.State.READ:
|
||
|
msg += f"r [xx]"
|
||
|
else:
|
||
|
self.log(f"unexpected state in stop(): state:{self.state} reg:{self.reg} data:{self.data}")
|
||
|
self.reset()
|
||
|
return
|
||
|
|
||
|
# only for debugging as some mismatches are expected as
|
||
|
# cd3217 seems to report the register size and not the number
|
||
|
# of requested bytes (or I2CDevTracer truncates reads).
|
||
|
#if self.length is not None and self.length > len(self.data):
|
||
|
# self.log(f"length {self.length:02x} mismatch received data: {len(self.data):02x}")
|
||
|
|
||
|
for data in self.data:
|
||
|
msg += f" {data:02x}"
|
||
|
|
||
|
self.log(msg)
|
||
|
self.reset()
|
||
|
|
||
|
def read(self, data):
|
||
|
self.data.append(data)
|
||
|
|
||
|
def write(self, data):
|
||
|
if self.reg is None:
|
||
|
self.reg = data
|
||
|
elif self.length is None:
|
||
|
self.length = data
|
||
|
self.state = CD3217Tracer.State.WRITE
|
||
|
else:
|
||
|
self.data.append(data)
|
||
|
|
||
|
class CD3217Tracer(HpmTracer):
|
||
|
def read(self, data):
|
||
|
if self.length is None:
|
||
|
self.length = data - 1
|
||
|
else:
|
||
|
self.data.append(data)
|
||
|
|
||
|
|
||
|
i2c_tracers = {}
|
||
|
|
||
|
for node in hv.adt["/arm-io"]:
|
||
|
if not node.name.startswith("i2c"):
|
||
|
continue
|
||
|
|
||
|
n = int(node.name[3:])
|
||
|
bus = I2CTracer(hv, f"/arm-io/{node.name}")
|
||
|
|
||
|
for mngr_node in node:
|
||
|
if "compatible" not in mngr_node._properties: # thanks Apple
|
||
|
continue
|
||
|
|
||
|
if mngr_node.compatible[0] != "usbc,manager":
|
||
|
continue
|
||
|
|
||
|
addr = mngr_node.reg[0] & 0xff
|
||
|
bus.add_device(addr, HpmTracer(addr=addr, name=mngr_node.name))
|
||
|
|
||
|
for devnode in mngr_node:
|
||
|
|
||
|
dcls = {
|
||
|
"usbc,cd3217": CD3217Tracer,
|
||
|
}.get(devnode.compatible[0], None)
|
||
|
if dcls:
|
||
|
addr = devnode.hpm_iic_addr & 0xff
|
||
|
bus.add_device(addr, dcls(addr=addr, name=devnode.name))
|
||
|
|
||
|
if len(bus.state.devices) > 1:
|
||
|
i2c_tracers[n] = bus
|
||
|
|
||
|
for bus in i2c_tracers.values():
|
||
|
bus.start()
|