#!/usr/bin/python # Python library for in-band SCom access # (based on xscom-utils from OPAL firmware) # # Copyright 2018 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os, sys, struct, getopt class XSCom(object): def __init__(self): self.name = "xscom" self.base = "/sys/kernel/debug/powerpc/scom/" self.enabled = False self.setup = False self.chips = [] self.dirs = [] self.key_val_bin = {} self.file = "/access" if os.path.exists(self.base): self.enabled = True if not self.scan_chips(): raise ValueError def scan_chips(self): if not self.enabled: print("Not supported") return False for i in os.listdir(self.base): if os.path.isdir(self.base+i): self.dirs.append(i) self.chips.append(int(i,16)) for i in self.dirs: try: b = open(self.base+i+self.file, "rb+") self.key_val_bin[int(i,16)] = b except: print("Count not open"+self.base+i+self.file) return False self.setup = True return True def is_supported(self): return self.enabled def get_chip_ids(self): return list(self.key_val_bin.keys()) def mangle_addr(self, addr): tmp = (addr & 0xf000000000000000) >> 4 addr = (addr & 0x00ffffffffffffff) addr = addr | tmp return (addr << 3) def xscom_read(self, chip_id, addr): if not isinstance(chip_id, int) or not isinstance(addr, int): print("xscom_read: Input paramater type mismatch") return -1 if chip_id not in self.key_val_bin: print("Invalid Chip id") return -1 saddr = self.mangle_addr(addr) fd = self.key_val_bin.get(chip_id) fd.seek(saddr, 0) return struct.unpack('Q',fd.read(8))[0] def xscom_read_spl(self, chip_id, addr): if not isinstance(chip_id, int) or not isinstance(addr, int): print("xscom_read: Input paramater type mismatch") return -1 if chip_id not in self.key_val_bin: print("Invalid Chip id") return -1 saddr = self.mangle_addr(addr) fd = self.key_val_bin.get(chip_id) fd.seek(saddr, 0) val = struct.unpack('Q',fd.read(8))[0] fd.close() try: b = open(self.key_val_path.get(chip_id), "rb+") except: print("Reopen failed") return val self.key_val_bin[chip_id] = b return val def xscom_write(self, chip_id, addr, val): if chip_id not in self.key_val_bin: print("Invalid Chip id") return -1 c = struct.pack('Q',val) saddr = self.mangle_addr(addr) fd = self.key_val_bin.get(chip_id) try: fd.seek(saddr, 0) fd.write(c) # write again just to be sure fd.seek(saddr, 0) fd.write(c) except: print("Write() error") return -1 def xscom_read_ex(self, ex_target_id, addr): if not isinstance(ex_target_id, int) or not isinstance(addr, int): print("xscom_read_ex: Input paramater type mismatch") return -1 chip_id = ex_target_id >> 4 addr |= (ex_target_id & 0xf) << 24; return self.xscom_read(chip_id, addr, val); def xscom_write_ex(self, ex_target_id, addr, val): chip_id = ex_target_id >> 4 addr |= (ex_target_id & 0xf) << 24; return self.xscom_write(chip_id, addr, val) class GetSCom(object): def __init__(self): self.name = "getscom" self.backend = XSCom() self.listchip = False self.chip_id = 0 self.chips = False self.addr = 0 self.flg_addr = False if not self.backend.is_supported(): print("In-Band SCom not supported Exiting....") raise ValueError def set_chip(self, chip_id): self.chip_id = chip_id self.chips = True def set_addr(self, scom_addr): self.addr = scom_addr self.flg_addr = True def print_usage(self): print("usage: getscom [-c|--chip chip-id] addr") print(" getscom -l|--list-chips") print(" getscom -h|--help") sys.exit(0) def chip_info(self, chip_id): val = self.backend.xscom_read(chip_id, 0xf000f) if val < 0: print("Error in scom read") raise ValueError c_id = val >> 44 id = c_id & 0xff if id == 0xef: name = "P8E (Murano) processor" elif id == 0xea: name = "P8 (Venice) processor" elif id == 0xd3: name = "P8NVL (Naples) processor" elif id == 0xd1: name = "P9 (Nimbus) processor" elif id == 0xd4: name = "P9 (Cumulus) processor" elif id == 0xe9: name = "Centaur memory buffer" else: name = "Unknown ID 0x%x"%id print(("%08x | DD%s.%s | %s"%(chip_id, ((c_id >> 16) & 0xf), ((c_id >> 8) & 0xf), name))) def parse_args(self): try: optlist, sys.argv = getopt.getopt(sys.argv[1:], "lhc:", ["chip", "list-chips", "help"]) except getopt.GetoptError as err: print(str(err)) self.print_usage() sys.exit(0) if len(optlist) == 0: self.print_usage() sys.exit(0) for opt, arg in optlist: if opt in [ "-h", "--help"]: self.print_usage() sys.exit(0) elif opt in [ "-l", "--list-chips"]: self.listchip = True elif opt in ["-c", "--chip"]: self.chip_id = int(arg, 16) self.chips = True if sys.argv: self.addr = int(sys.argv.pop(), 16) self.flg_addr = True if self.listchip: print("Chip ID | Rev | Chip type") print("---------|-------|-----------") for i in self.backend.get_chip_ids(): self.chip_info(i) sys.exit(0) def run_command(self): if self.chips and self.flg_addr: print(hex(self.backend.xscom_read(self.chip_id, self.addr))) def list_chips(self): print("Chip ID | Rev | Chip type") print("---------|-------|-----------") for i in self.backend.get_chip_ids(): self.chip_info(i) raise ValueError def execute(self, chip_id, addr): return self.backend.xscom_read(chip_id, addr) def execute_spl(self, chip_id, addr): return self.backend.xscom_read_spl(chip_id, addr) class PutSCom(object): def __init__(self): self.name = "putscom" self.backend = XSCom() self.chip_id = 0 self.chips = False self.addr = 0 self.value = 0 if not self.backend.is_supported(): print("In-Band SCom not supported Exiting....") raise ValueError def set_addr(self, addr): self.addr = addr def set_value(self, value): self.value = value def print_usage(self): print("usage: putscom [-c|--chip chip-id] addr value") print(" putscom -h|--help") sys.exit(0) def parse_args(self): try: optlist, sys.argv = getopt.getopt(sys.argv[1:], "hc:", ["chip", "help"]) except getopt.GetoptError as err: print(str(err)) self.print_usage() sys.exit(0) if len(optlist) == 0: self.print_usage() sys.exit(0) for opt, arg in optlist: if opt in [ "-h", "--help"]: self.print_usage() sys.exit(0) elif opt in ["-c", "--chip"]: self.chip_id = int(arg, 16) self.chips = True if sys.argv: self.value = int(sys.argv.pop(), 16) self.addr = int(sys.argv.pop(), 16) if self.chips: self.backend.xscom_write(self.chip_id, self.addr, self.value) def run_command(self): if self.chips: self.backend.xscom_write(self.chip_id, self.addr, self.value) def execute(self, chip_id, addr, value): self.backend.xscom_write(chip_id, addr, value)