Browse Source

soc/mediatek: Ruffify python scripts

These in-tree scripts fail the new ruff checks.  Clean things up so
modifications can merge.

Signed-off-by: Andy Ross <andyross@google.com>
pull/82291/head
Andy Ross 7 months ago committed by Benjamin Cabé
parent
commit
09495c9e48
  1. 94
      soc/mediatek/mt8xxx/gen_img.py
  2. 106
      soc/mediatek/mt8xxx/mtk_adsp_load.py

94
soc/mediatek/mt8xxx/gen_img.py

@ -1,8 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright 2023 The ChromiumOS Authors # Copyright 2023 The ChromiumOS Authors
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import sys
import struct import struct
import sys
import elftools.elf.elffile import elftools.elf.elffile
import elftools.elf.sections import elftools.elf.sections
@ -19,13 +20,11 @@ import elftools.elf.sections
# #
# No padding or uninterpreted bytes. # No padding or uninterpreted bytes.
FILE_MAGIC = 0xe463be95 FILE_MAGIC = 0xE463BE95
elf_file = sys.argv[1] elf_file = sys.argv[1]
out_file = sys.argv[2] out_file = sys.argv[2]
ef = elftools.elf.elffile.ELFFile(open(elf_file, "rb"))
sram = bytearray() sram = bytearray()
dram = bytearray() dram = bytearray()
@ -34,11 +33,13 @@ dram = bytearray()
# SOCs, but it's always a <=1M region in 0x4xxxxxxx. Just use what we # SOCs, but it's always a <=1M region in 0x4xxxxxxx. Just use what we
# get, but validate that it fits. # get, but validate that it fits.
sram_block = 0 sram_block = 0
def sram_off(addr): def sram_off(addr):
global sram_block global sram_block
if addr < 0x40000000 or addr >= 0x50000000: if addr < 0x40000000 or addr >= 0x50000000:
return -1 return -1
block = addr & ~0xfffff block = addr & ~0xFFFFF
assert sram_block in (0, block) assert sram_block in (0, block)
sram_block = block sram_block = block
@ -46,44 +47,53 @@ def sram_off(addr):
assert off < 0x100000 assert off < 0x100000
return off return off
# Similar heuristics: current platforms put DRAM either at 0x60000000 # Similar heuristics: current platforms put DRAM either at 0x60000000
# or 0x90000000 with no more than 16M of range # or 0x90000000 with no more than 16M of range
def dram_off(addr): def dram_off(addr):
if (addr >> 28 not in [6, 9]) or (addr & 0x0f000000 != 0): if (addr >> 28 not in [6, 9]) or (addr & 0x0F000000 != 0):
return -1 return -1
return addr & 0xffffff return addr & 0xFFFFFF
for seg in ef.iter_segments():
h = seg.header def read_elf(efile):
if h.p_type == "PT_LOAD": ef = elftools.elf.elffile.ELFFile(efile)
soff = sram_off(h.p_paddr)
doff = dram_off(h.p_paddr) for seg in ef.iter_segments():
if soff >= 0: h = seg.header
buf = sram if h.p_type == "PT_LOAD":
off = soff soff = sram_off(h.p_paddr)
elif doff >= 0: doff = dram_off(h.p_paddr)
buf = dram if soff >= 0:
off = doff buf = sram
else: off = soff
print(f"Invalid PT_LOAD address {h.p_paddr:x}") elif doff >= 0:
sys.exit(1) buf = dram
off = doff
dat = seg.data() else:
end = off + len(dat) print(f"Invalid PT_LOAD address {h.p_paddr:x}")
if end > len(buf): sys.exit(1)
buf.extend(b'\x00' * (end - len(buf)))
dat = seg.data()
# pylint: disable=consider-using-enumerate end = off + len(dat)
for i in range(len(dat)): if end > len(buf):
buf[i + off] = dat[i] buf.extend(b'\x00' * (end - len(buf)))
for sec in ef.iter_sections(): # pylint: disable=consider-using-enumerate
if isinstance(sec, elftools.elf.sections.SymbolTableSection): for i in range(len(dat)):
for sym in sec.iter_symbols(): buf[i + off] = dat[i]
if sym.name == "mtk_adsp_boot_entry":
boot_vector = sym.entry['st_value'] for sec in ef.iter_sections():
if isinstance(sec, elftools.elf.sections.SymbolTableSection):
of = open(out_file, "wb") for sym in sec.iter_symbols():
of.write(struct.pack("<III", FILE_MAGIC, len(sram), boot_vector)) if sym.name == "mtk_adsp_boot_entry":
of.write(sram) boot_vector = sym.entry['st_value']
of.write(dram)
with open(out_file, "wb") as of:
of.write(struct.pack("<III", FILE_MAGIC, len(sram), boot_vector))
of.write(sram)
of.write(dram)
with open(elf_file, "rb") as f:
read_elf(f)

106
soc/mediatek/mt8xxx/mtk_adsp_load.py

@ -2,13 +2,13 @@
# Copyright 2023 The ChromiumOS Authors # Copyright 2023 The ChromiumOS Authors
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import ctypes import ctypes
import mmap
import os import os
import re
import struct
import sys import sys
import mmap
import time import time
import struct
from glob import glob from glob import glob
import re
# MT8195 audio firmware load/debug gadget # MT8195 audio firmware load/debug gadget
@ -34,20 +34,21 @@ import re
# phandles pointing to "adsp_mem_region" and "adsp_dma_mem_region" # phandles pointing to "adsp_mem_region" and "adsp_dma_mem_region"
# nodes under "/reserved-memory"). # nodes under "/reserved-memory").
FILE_MAGIC = 0xe463be95 FILE_MAGIC = 0xE463BE95
# Runtime mmap objects for each MAPPINGS entry # Runtime mmap objects for each MAPPINGS entry
maps = {} maps = {}
# Returns a string (e.g. "mt8195", "mt8186", "mt8188") if a supported # Returns a string (e.g. "mt8195", "mt8186", "mt8188") if a supported
# adsp is detected, or None if not # adsp is detected, or None if not
def detect(): def detect():
compat = readfile(glob("/proc/device-tree/**/adsp@*/compatible", compat = readfile(glob("/proc/device-tree/**/adsp@*/compatible", recursive=True)[0], "r")
recursive=True)[0], "r")
m = re.match(r'.*(mt\d{4})-dsp', compat) m = re.match(r'.*(mt\d{4})-dsp', compat)
if m: if m:
return m.group(1) return m.group(1)
# Parse devicetree to find the MMIO mappings: there is an "adsp" node # Parse devicetree to find the MMIO mappings: there is an "adsp" node
# (in various locations) with an array of named "reg" mappings. It # (in various locations) with an array of named "reg" mappings. It
# also refers by reference to reserved-memory regions of system # also refers by reference to reserved-memory regions of system
@ -59,7 +60,7 @@ def mappings():
path = glob("/proc/device-tree/**/adsp@*/", recursive=True)[0] path = glob("/proc/device-tree/**/adsp@*/", recursive=True)[0]
rnames = readfile(path + "reg-names", "r").split('\0')[:-1] rnames = readfile(path + "reg-names", "r").split('\0')[:-1]
regs = struct.unpack(f">{2 * len(rnames)}Q", readfile(path + "reg")) regs = struct.unpack(f">{2 * len(rnames)}Q", readfile(path + "reg"))
maps = { n : (regs[2*i], regs[2*i+1]) for i, n in enumerate(rnames) } maps = {n: (regs[2 * i], regs[2 * i + 1]) for i, n in enumerate(rnames)}
for i, ph in enumerate(struct.unpack(">II", readfile(path + "memory-region"))): for i, ph in enumerate(struct.unpack(">II", readfile(path + "memory-region"))):
for rmem in glob("/proc/device-tree/reserved-memory/*/"): for rmem in glob("/proc/device-tree/reserved-memory/*/"):
phf = rmem + "phandle" phf = rmem + "phandle"
@ -69,16 +70,17 @@ def mappings():
break break
return maps return maps
# Register API for 8195 # Register API for 8195
class MT8195(): class MT8195:
def __init__(self, maps): def __init__(self, maps):
# Create a Regs object for the registers # Create a Regs object for the registers
r = Regs(ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"]))) r = Regs(ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"])))
r.ALTRESETVEC = 0x0004 # Xtensa boot address r.ALTRESETVEC = 0x0004 # Xtensa boot address
r.RESET_SW = 0x0024 # Xtensa halt/reset/boot control r.RESET_SW = 0x0024 # Xtensa halt/reset/boot control
r.PDEBUGBUS0 = 0x000c # Unclear, enabled by host, unused by SOF? r.PDEBUGBUS0 = 0x000C # Unclear, enabled by host, unused by SOF?
r.SRAM_POOL_CON = 0x0930 # SRAM power control: low 4 bits (banks?) enable r.SRAM_POOL_CON = 0x0930 # SRAM power control: low 4 bits (banks?) enable
r.EMI_MAP_ADDR = 0x981c # == host SRAM mapping - 0x40000000 (controls MMIO map?) r.EMI_MAP_ADDR = 0x981C # == host SRAM mapping - 0x40000000 (controls MMIO map?)
r.freeze() r.freeze()
self.cfg = r self.cfg = r
@ -86,61 +88,63 @@ class MT8195():
return range(0x700000, 0x800000) return range(0x700000, 0x800000)
def stop(self): def stop(self):
self.cfg.RESET_SW |= 8 # Set RUNSTALL: halt CPU self.cfg.RESET_SW |= 8 # Set RUNSTALL: halt CPU
self.cfg.RESET_SW |= 3 # Set low two bits: "BRESET|DRESET" self.cfg.RESET_SW |= 3 # Set low two bits: "BRESET|DRESET"
def start(self, boot_vector): def start(self, boot_vector):
self.stop() self.stop()
self.cfg.RESET_SW |= 0x10 # Enable "alternate reset" boot vector self.cfg.RESET_SW |= 0x10 # Enable "alternate reset" boot vector
self.cfg.ALTRESETVEC = boot_vector self.cfg.ALTRESETVEC = boot_vector
self.cfg.RESET_SW &= ~3 # Release reset bits self.cfg.RESET_SW &= ~3 # Release reset bits
self.cfg.RESET_SW &= ~8 # Clear RUNSTALL: go! self.cfg.RESET_SW &= ~8 # Clear RUNSTALL: go!
# Register API for 8186/8188 # Register API for 8186/8188
class MT818x(): class MT818x:
def __init__(self, maps): def __init__(self, maps):
# These have registers spread across two blocks # These have registers spread across two blocks
cfg_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"])) cfg_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"]))
sec_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["sec"])) sec_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["sec"]))
self.cfg = Regs(cfg_base) self.cfg = Regs(cfg_base)
self.cfg.SW_RSTN = 0x00 self.cfg.SW_RSTN = 0x00
self.cfg.IO_CONFIG = 0x0c self.cfg.IO_CONFIG = 0x0C
self.cfg.freeze() self.cfg.freeze()
self.sec = Regs(sec_base) self.sec = Regs(sec_base)
self.sec.ALTVEC_C0 = 0x04 self.sec.ALTVEC_C0 = 0x04
self.sec.ALTVECSEL = 0x0c self.sec.ALTVECSEL = 0x0C
self.sec.freeze() self.sec.freeze()
def logrange(self): def logrange(self):
return range(0x700000, 0x800000) return range(0x700000, 0x800000)
def stop(self): def stop(self):
self.cfg.IO_CONFIG |= (1<<31) # Set RUNSTALL to stop core self.cfg.IO_CONFIG |= 1 << 31 # Set RUNSTALL to stop core
time.sleep(0.1) time.sleep(0.1)
self.cfg.SW_RSTN |= 0x11 # Assert reset: SW_RSTN_C0|SW_DBG_RSTN_C0 self.cfg.SW_RSTN |= 0x11 # Assert reset: SW_RSTN_C0|SW_DBG_RSTN_C0
# Note: 8186 and 8188 use different bits in ALTVECSEC, but # Note: 8186 and 8188 use different bits in ALTVECSEC, but
# it's safe to write both to enable the alternate boot vector # it's safe to write both to enable the alternate boot vector
def start(self, boot_vector): def start(self, boot_vector):
self.cfg.IO_CONFIG |= (1<<31) # Set RUNSTALL self.cfg.IO_CONFIG |= 1 << 31 # Set RUNSTALL
self.sec.ALTVEC_C0 = boot_vector self.sec.ALTVEC_C0 = boot_vector
self.sec.ALTVECSEL = 0x03 # Enable alternate vector self.sec.ALTVECSEL = 0x03 # Enable alternate vector
self.cfg.SW_RSTN |= 0x00000011 # Assert reset self.cfg.SW_RSTN |= 0x00000011 # Assert reset
self.cfg.SW_RSTN &= 0xffffffee # Release reset self.cfg.SW_RSTN &= 0xFFFFFFEE # Release reset
self.cfg.IO_CONFIG &= 0x7fffffff # Clear RUNSTALL self.cfg.IO_CONFIG &= 0x7FFFFFFF # Clear RUNSTALL
class MT8196():
class MT8196:
def __init__(self, maps): def __init__(self, maps):
cfg_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"])) cfg_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["cfg"]))
sec_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["sec"])) sec_base = ctypes.addressof(ctypes.c_int.from_buffer(maps["sec"]))
self.cfg = Regs(cfg_base) self.cfg = Regs(cfg_base)
self.cfg.CFGREG_SW_RSTN = 0x0000 self.cfg.CFGREG_SW_RSTN = 0x0000
self.cfg.MBOX_IRQ_EN = 0x009c self.cfg.MBOX_IRQ_EN = 0x009C
self.cfg.HIFI_RUNSTALL = 0x0108 self.cfg.HIFI_RUNSTALL = 0x0108
self.cfg.freeze() self.cfg.freeze()
self.sec = Regs(sec_base) self.sec = Regs(sec_base)
self.sec.ALTVEC_C0 = 0x04 self.sec.ALTVEC_C0 = 0x04
self.sec.ALTVECSEL = 0x0c self.sec.ALTVECSEL = 0x0C
self.sec.freeze() self.sec.freeze()
def logrange(self): def logrange(self):
@ -162,6 +166,7 @@ class MT8196():
self.cfg.CFGREG_SW_RSTN &= ~0x11 self.cfg.CFGREG_SW_RSTN &= ~0x11
self.cfg.HIFI_RUNSTALL &= ~0x1000 self.cfg.HIFI_RUNSTALL &= ~0x1000
# Temporary logging protocol: watch the 1M null-terminated log # Temporary logging protocol: watch the 1M null-terminated log
# stream at 0x60700000 -- the top of the linkable region of # stream at 0x60700000 -- the top of the linkable region of
# existing SOF firmware, before the heap. Nothing uses this # existing SOF firmware, before the heap. Nothing uses this
@ -182,30 +187,37 @@ def log(dev):
sys.stdout.buffer.write(msg) sys.stdout.buffer.write(msg)
sys.stdout.buffer.flush() sys.stdout.buffer.flush()
# (Cribbed from cavstool.py) # (Cribbed from cavstool.py)
class Regs: class Regs:
def __init__(self, base_addr): def __init__(self, base_addr):
vars(self)["base_addr"] = base_addr vars(self)["base_addr"] = base_addr
vars(self)["ptrs"] = {} vars(self)["ptrs"] = {}
vars(self)["frozen"] = False vars(self)["frozen"] = False
def freeze(self): def freeze(self):
vars(self)["frozen"] = True vars(self)["frozen"] = True
def __setattr__(self, name, val): def __setattr__(self, name, val):
if not self.frozen and name not in self.ptrs: if not self.frozen and name not in self.ptrs:
addr = self.base_addr + val addr = self.base_addr + val
self.ptrs[name] = ctypes.c_uint32.from_address(addr) self.ptrs[name] = ctypes.c_uint32.from_address(addr)
else: else:
self.ptrs[name].value = val self.ptrs[name].value = val
def __getattr__(self, name): def __getattr__(self, name):
return self.ptrs[name].value return self.ptrs[name].value
def readfile(f, mode="rb"): def readfile(f, mode="rb"):
return open(f, mode).read() return open(f, mode).read()
def le4(bstr): def le4(bstr):
assert len(bstr) == 4 assert len(bstr) == 4
return struct.unpack("<I", bstr)[0] return struct.unpack("<I", bstr)[0]
def main(): def main():
dsp = detect() dsp = detect()
assert dsp assert dsp
@ -214,13 +226,18 @@ def main():
mmio = mappings() mmio = mappings()
# Open device and establish mappings # Open device and establish mappings
devmem_fd = open("/dev/mem", "wb+") with open("/dev/mem", "wb+") as devmem_fd:
for mp in mmio: for mp in mmio:
paddr = mmio[mp][0] paddr = mmio[mp][0]
mapsz = mmio[mp][1] mapsz = mmio[mp][1]
mapsz = int((mapsz + 4095) / 4096) * 4096 mapsz = int((mapsz + 4095) / 4096) * 4096
maps[mp] = mmap.mmap(devmem_fd.fileno(), mapsz, offset=paddr, maps[mp] = mmap.mmap(
flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE|mmap.PROT_READ) devmem_fd.fileno(),
mapsz,
offset=paddr,
flags=mmap.MAP_SHARED,
prot=mmap.PROT_WRITE | mmap.PROT_READ,
)
if dsp == "mt8195": if dsp == "mt8195":
dev = MT8195(maps) dev = MT8195(maps)
@ -230,12 +247,14 @@ def main():
dev = MT8196(maps) dev = MT8196(maps)
if sys.argv[1] == "load": if sys.argv[1] == "load":
dat = open(sys.argv[2], "rb").read() dat = None
assert le4(dat[0:4])== FILE_MAGIC with open(sys.argv[2], "rb") as f:
dat = f.read()
assert le4(dat[0:4]) == FILE_MAGIC
sram_len = le4(dat[4:8]) sram_len = le4(dat[4:8])
boot_vector = le4(dat[8:12]) boot_vector = le4(dat[8:12])
sram = dat[12:12+sram_len] sram = dat[12 : 12 + sram_len]
dram = dat[12 + sram_len:] dram = dat[12 + sram_len :]
assert len(sram) <= mmio["sram"][1] assert len(sram) <= mmio["sram"][1]
assert len(dram) <= mmio["dram1"][1] assert len(dram) <= mmio["dram1"][1]
@ -246,7 +265,7 @@ def main():
# pylint: disable=consider-using-enumerate # pylint: disable=consider-using-enumerate
for i in range(sram_len): for i in range(sram_len):
maps["sram"][i] = sram[i] maps["sram"][i] = sram[i]
#for i in range(sram_len, mmio["sram"][1]): # for i in range(sram_len, mmio["sram"][1]):
# maps["sram"][i] = 0 # maps["sram"][i] = 0
for i in range(len(dram)): for i in range(len(dram)):
maps["dram1"][i] = dram[i] maps["dram1"][i] = dram[i]
@ -266,5 +285,6 @@ def main():
else: else:
print(f"Usage: {sys.argv[0]} log | load <file>") print(f"Usage: {sys.argv[0]} log | load <file>")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

Loading…
Cancel
Save