m1n1/proxyclient/hv/trace_cd3217.py
Janne Grunau 2b4ed4abbf hv/trace_cd3217: Add tracing for TI/Apple cd3217 USB type C controller
Interface (as used by macOS) is simple enough to skip register
definitions.

Signed-off-by: Janne Grunau <j@jannau.net>
2023-01-28 10:49:04 +09:00

119 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()