1#!/usr/bin/python 2 3# Python library for in-band SCom access 4# (based on xscom-utils from OPAL firmware) 5# 6# Copyright 2018 IBM Corp. 7# 8# Licensed under the Apache License, Version 2.0 (the "License"); 9# you may not use this file except in compliance with the License. 10# You may obtain a copy of the License at 11# 12# http://www.apache.org/licenses/LICENSE-2.0 13# 14# Unless required by applicable law or agreed to in writing, software 15# distributed under the License is distributed on an "AS IS" BASIS, 16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 17# implied. 18# See the License for the specific language governing permissions and 19# limitations under the License. 20 21import os, sys, struct, getopt 22 23class XSCom(object): 24 def __init__(self): 25 self.name = "xscom" 26 self.base = "/sys/kernel/debug/powerpc/scom/" 27 self.enabled = False 28 self.setup = False 29 self.chips = [] 30 self.dirs = [] 31 self.key_val_bin = {} 32 self.file = "/access" 33 34 if os.path.exists(self.base): 35 self.enabled = True 36 37 if not self.scan_chips(): 38 raise ValueError 39 40 def scan_chips(self): 41 if not self.enabled: 42 print("Not supported") 43 return False 44 45 for i in os.listdir(self.base): 46 if os.path.isdir(self.base+i): 47 self.dirs.append(i) 48 self.chips.append(int(i,16)) 49 50 for i in self.dirs: 51 try: 52 b = open(self.base+i+self.file, "rb+") 53 self.key_val_bin[int(i,16)] = b 54 except: 55 print("Count not open"+self.base+i+self.file) 56 return False 57 58 self.setup = True 59 return True 60 61 def is_supported(self): 62 return self.enabled 63 64 def get_chip_ids(self): 65 return list(self.key_val_bin.keys()) 66 67 def mangle_addr(self, addr): 68 tmp = (addr & 0xf000000000000000) >> 4 69 addr = (addr & 0x00ffffffffffffff) 70 addr = addr | tmp 71 return (addr << 3) 72 73 def xscom_read(self, chip_id, addr): 74 if not isinstance(chip_id, int) or not isinstance(addr, int): 75 print("xscom_read: Input paramater type mismatch") 76 return -1 77 78 if chip_id not in self.key_val_bin: 79 print("Invalid Chip id") 80 return -1 81 82 saddr = self.mangle_addr(addr) 83 fd = self.key_val_bin.get(chip_id) 84 fd.seek(saddr, 0) 85 return struct.unpack('Q',fd.read(8))[0] 86 87 def xscom_read_spl(self, chip_id, addr): 88 if not isinstance(chip_id, int) or not isinstance(addr, int): 89 print("xscom_read: Input paramater type mismatch") 90 return -1 91 92 if chip_id not in self.key_val_bin: 93 print("Invalid Chip id") 94 return -1 95 96 saddr = self.mangle_addr(addr) 97 fd = self.key_val_bin.get(chip_id) 98 fd.seek(saddr, 0) 99 val = struct.unpack('Q',fd.read(8))[0] 100 fd.close() 101 try: 102 b = open(self.key_val_path.get(chip_id), "rb+") 103 except: 104 print("Reopen failed") 105 return val 106 self.key_val_bin[chip_id] = b 107 return val 108 109 def xscom_write(self, chip_id, addr, val): 110 if chip_id not in self.key_val_bin: 111 print("Invalid Chip id") 112 return -1 113 114 c = struct.pack('Q',val) 115 saddr = self.mangle_addr(addr) 116 fd = self.key_val_bin.get(chip_id) 117 118 try: 119 fd.seek(saddr, 0) 120 fd.write(c) 121 # write again just to be sure 122 fd.seek(saddr, 0) 123 fd.write(c) 124 except: 125 print("Write() error") 126 return -1 127 128 def xscom_read_ex(self, ex_target_id, addr): 129 if not isinstance(ex_target_id, int) or not isinstance(addr, int): 130 print("xscom_read_ex: Input paramater type mismatch") 131 return -1 132 133 chip_id = ex_target_id >> 4 134 addr |= (ex_target_id & 0xf) << 24; 135 return self.xscom_read(chip_id, addr, val); 136 137 def xscom_write_ex(self, ex_target_id, addr, val): 138 chip_id = ex_target_id >> 4 139 addr |= (ex_target_id & 0xf) << 24; 140 return self.xscom_write(chip_id, addr, val) 141 142class GetSCom(object): 143 def __init__(self): 144 self.name = "getscom" 145 self.backend = XSCom() 146 self.listchip = False 147 self.chip_id = 0 148 self.chips = False 149 self.addr = 0 150 self.flg_addr = False 151 152 if not self.backend.is_supported(): 153 print("In-Band SCom not supported Exiting....") 154 raise ValueError 155 156 def set_chip(self, chip_id): 157 self.chip_id = chip_id 158 self.chips = True 159 160 def set_addr(self, scom_addr): 161 self.addr = scom_addr 162 self.flg_addr = True 163 164 def print_usage(self): 165 print("usage: getscom [-c|--chip chip-id] addr") 166 print(" getscom -l|--list-chips") 167 print(" getscom -h|--help") 168 sys.exit(0) 169 170 171 def chip_info(self, chip_id): 172 val = self.backend.xscom_read(chip_id, 0xf000f) 173 if val < 0: 174 print("Error in scom read") 175 raise ValueError 176 177 c_id = val >> 44 178 id = c_id & 0xff 179 if id == 0xef: 180 name = "P8E (Murano) processor" 181 elif id == 0xea: 182 name = "P8 (Venice) processor" 183 elif id == 0xd3: 184 name = "P8NVL (Naples) processor" 185 elif id == 0xd1: 186 name = "P9 (Nimbus) processor" 187 elif id == 0xd4: 188 name = "P9 (Cumulus) processor" 189 elif id == 0xe9: 190 name = "Centaur memory buffer" 191 else: 192 name = "Unknown ID 0x%x"%id 193 194 print(("%08x | DD%s.%s | %s"%(chip_id, ((c_id >> 16) & 0xf), ((c_id >> 8) & 0xf), name))) 195 196 def parse_args(self): 197 try: 198 optlist, sys.argv = getopt.getopt(sys.argv[1:], "lhc:", ["chip", "list-chips", "help"]) 199 except getopt.GetoptError as err: 200 print(str(err)) 201 self.print_usage() 202 sys.exit(0) 203 204 if len(optlist) == 0: 205 self.print_usage() 206 sys.exit(0) 207 208 for opt, arg in optlist: 209 if opt in [ "-h", "--help"]: 210 self.print_usage() 211 sys.exit(0) 212 213 elif opt in [ "-l", "--list-chips"]: 214 self.listchip = True 215 216 elif opt in ["-c", "--chip"]: 217 self.chip_id = int(arg, 16) 218 self.chips = True 219 220 if sys.argv: 221 self.addr = int(sys.argv.pop(), 16) 222 self.flg_addr = True 223 224 if self.listchip: 225 print("Chip ID | Rev | Chip type") 226 print("---------|-------|-----------") 227 for i in self.backend.get_chip_ids(): 228 self.chip_info(i) 229 230 sys.exit(0) 231 232 def run_command(self): 233 if self.chips and self.flg_addr: 234 print(hex(self.backend.xscom_read(self.chip_id, self.addr))) 235 236 def list_chips(self): 237 print("Chip ID | Rev | Chip type") 238 print("---------|-------|-----------") 239 for i in self.backend.get_chip_ids(): 240 self.chip_info(i) 241 242 raise ValueError 243 244 def execute(self, chip_id, addr): 245 return self.backend.xscom_read(chip_id, addr) 246 247 def execute_spl(self, chip_id, addr): 248 return self.backend.xscom_read_spl(chip_id, addr) 249 250class PutSCom(object): 251 def __init__(self): 252 self.name = "putscom" 253 self.backend = XSCom() 254 self.chip_id = 0 255 self.chips = False 256 self.addr = 0 257 self.value = 0 258 259 if not self.backend.is_supported(): 260 print("In-Band SCom not supported Exiting....") 261 raise ValueError 262 263 def set_addr(self, addr): 264 self.addr = addr 265 266 def set_value(self, value): 267 self.value = value 268 269 def print_usage(self): 270 print("usage: putscom [-c|--chip chip-id] addr value") 271 print(" putscom -h|--help") 272 sys.exit(0) 273 274 def parse_args(self): 275 try: 276 optlist, sys.argv = getopt.getopt(sys.argv[1:], "hc:", ["chip", "help"]) 277 except getopt.GetoptError as err: 278 print(str(err)) 279 self.print_usage() 280 sys.exit(0) 281 282 if len(optlist) == 0: 283 self.print_usage() 284 sys.exit(0) 285 286 for opt, arg in optlist: 287 if opt in [ "-h", "--help"]: 288 self.print_usage() 289 sys.exit(0) 290 291 elif opt in ["-c", "--chip"]: 292 self.chip_id = int(arg, 16) 293 self.chips = True 294 295 if sys.argv: 296 self.value = int(sys.argv.pop(), 16) 297 self.addr = int(sys.argv.pop(), 16) 298 299 if self.chips: 300 self.backend.xscom_write(self.chip_id, self.addr, self.value) 301 302 def run_command(self): 303 if self.chips: 304 self.backend.xscom_write(self.chip_id, self.addr, self.value) 305 306 def execute(self, chip_id, addr, value): 307 self.backend.xscom_write(chip_id, addr, value) 308 309