Source code for ska_low_sps_tpm_api.plugins.eep

from ska_low_sps_tpm_api.base.definitions import *
from ska_low_sps_tpm_api.base.utils import *
from ska_low_sps_tpm_api.plugins.firmwareblock import FirmwareBlock

__author__ = "Gabriele Sorrenti"

MAX_RETRY = 1000


[docs] class TpmEEP(FirmwareBlock): """TpmEEP plugin"""
[docs] @compatibleboards(BoardMake.TpmBoard) @friendlyname("tpm_eep") @maxinstances(1) def __init__(self, board, logger=None, **kwargs): """ TpmEEP initialiser. :param board: Pointer to board instance """ super(TpmEEP, self).__init__(board, logger=logger) self.phy_addr = 0xA0 # self.ba = 0x40000000 #self.board["board.i2c"] # I2C IF Base Add self.i2c_shadow = 0x90000270 self.i2c_req_reg = 0x50 self.i2c_ack_reg = 0x54 self.eep_sec = { "ip_address": { "offset": 0x00, "size": 4, "name": "ip_address", "type": "ip", "protected": False, }, "netmask": { "offset": 0x04, "size": 4, "name": "netmask", "type": "ip", "protected": False, }, "gateway": { "offset": 0x08, "size": 4, "name": "gateway", "type": "ip", "protected": False, }, "password": { "offset": 0x0C, "size": 3, "name": "password", "type": "bytearray", "protected": False, }, "eep_rev": { "offset": 0x0F, "size": 1, "name": "eep_rev", "type": "uint", "protected": True, }, "EXT_LABEL_SN": { "offset": 0x30, "size": 16, "name": "EXT_LABEL_SN", "type": "string", "protected": True, }, "SN": { "offset": 0x40, "size": 16, "name": "SN", "type": "string", "protected": True, }, "PN": { "offset": 0x50, "size": 16, "name": "PN", "type": "string", "protected": True, }, "BOARD_MODE": { "offset": 0x60, "size": 1, "name": "BOARD_MODE", "type": "uint", "protected": True, }, # 0 ada,0xff no-ada "HARDWARE_REV": { "offset": 0x61, "size": 3, "name": "HARDWARE_REV", "type": "bytearray", "protected": True, }, # v00.00.00 "PCB_REV": { "offset": 0x64, "size": 1, "name": "PCB_REV", "type": "string", "protected": True, }, "DDR_SIZE_GB": { "offset": 0x65, "size": 1, "name": "DDR_SIZE_GB", "type": "uint", "protected": True, }, "EXT_LABEL_2": { "offset": 0x6A, "size": 6, "name": "EXT_LABEL_2", "type": "string", "protected": True, }, "pre_adu_0_rev": { "offset": 0x70, "size": 1, "name": "pre_adu_0_rev", "type": "uint", "protected": False, }, "pre_adu_1_rev": { "offset": 0x71, "size": 1, "name": "pre_adu_1_rev", "type": "uint", "protected": False, }, "EXT_LABEL_PN": { "offset": 0x72, "size": 14, "name": "EXT_LABEL_PN", "type": "string", "protected": True, }, "MAC": { "offset": 0xFA, "size": 6, "name": "MAC", "type": "bytearray", "protected": True, }, # READ-ONLY }
#######################################################################################
[docs] def poll_reg(self, reg, exit_condition, exception_val): retry = 0 while True: if (self.board[reg]) == exit_condition: break else: time.sleep(0.001) retry = retry + 1 self.board._i2c_lock.refresh() if retry >= MAX_RETRY: self.logger.error("EEP Polling Reg timeout: ", exception_val) raise LibraryError(exception_val)
[docs] def rd8( self, offset, use_password=False, release_lock=True, size=1, mux=0, add=None ): """Read 8-bit value from EEP ROM""" if self.board.i2c_old_mode: self.set_passwd() if add is None: add = self.phy_addr >> 1 else: add = add >> 1 nof_rd_byte = size if offset is not None: nof_wr_byte = 1 else: nof_wr_byte = 0 cmd = (mux << 16) + (nof_rd_byte << 12) + (nof_wr_byte << 8) + add if offset is not None: self.board["board.i2c.transmit"] = offset & 0xFF self.board["board.i2c.command"] = cmd while self.board["board.i2c.status"] != 0: pass self.remove_passwd() read_data = self.board["board.i2c.receive"] if size > 1: read_data = sum( ((read_data >> (8 * i)) & 0xFF) << (8 * (size - 1 - i)) for i in range(size) ) return read_data else: self.board._i2c_lock.lock() if self.board[self.i2c_shadow + self.i2c_req_reg] == 1: self.logger.warning("Detected Incomplete Previous I2C operation") self.board[self.i2c_shadow + self.i2c_req_reg] = 0 self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP not ready!") self.set_passwd() if add is None: add = self.phy_addr >> 1 else: add = add >> 1 nof_rd_byte = size if offset is not None: nof_wr_byte = 1 else: nof_wr_byte = 0 cmd = (mux << 16) + (nof_rd_byte << 12) + (nof_wr_byte << 8) + add # print(f"rd8 {hex(offset)} {hex(cmd)}") if offset is not None: self.board[self.i2c_shadow + 0x4] = offset & 0xFF self.board[self.i2c_shadow + 0x0] = cmd # send request self.board[self.i2c_shadow + self.i2c_req_reg] = 1 # wait req acknowledge self.logger.debug("i2c read wait req acknowledge") self.poll_reg( self.i2c_shadow + self.i2c_ack_reg, 1, "I2C/EEP request not accepted!" ) # check passwd self.logger.debug("i2c read check passwd") self.check_passwd() # check i2c op status: 0 ok, 1 busy, 2 NACK self.logger.debug("i2c read check status") self.poll_reg(self.i2c_shadow + 0xC, 0, "I2C/EEP busy or not acknowledge!") read_data = self.board[self.i2c_shadow + 0x8] & ((1 << (size * 8)) - 1) # Endianness swap if size > 1: read_data = sum( ((read_data >> (8 * i)) & 0xFF) << (8 * (size - 1 - i)) for i in range(size) ) # self.remove_passwd() # self.board[self.i2c_shadow+self.i2c_ack_reg] = 0 self.board[self.i2c_shadow + self.i2c_req_reg] = 0 self.logger.debug("i2c read check end operation") self.poll_reg( self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP operation complete detected!", ) if release_lock: self.board._i2c_lock.unlock() return read_data
[docs] def rd16(self, offset, use_password=False, release_lock=True, mux=0, add=None): """Read 16-bit value from EEP ROM""" if add is None: add = self.phy_addr return self.rd8( offset, size=2, use_password=use_password, release_lock=release_lock, mux=mux, add=add, )
[docs] def rd32(self, offset, use_password=False, release_lock=True, mux=0, add=None): """Read 32-bit value from EEP ROM""" if add is None: add = self.phy_addr return self.rd8( offset, size=4, use_password=use_password, release_lock=release_lock, mux=mux, add=add, )
[docs] def wr8(self, offset, data): """Write 8-bit value to EEP ROM""" if self.board.i2c_old_mode: self.set_passwd() add = self.phy_addr >> 1 nof_rd_byte = 0 nof_wr_byte = 2 cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add while True: data = data & 0xFF offset = offset & 0xFF self.board["board.i2c.transmit"] = (data << 8) + offset self.board["board.i2c.command"] = cmd while True: rd = self.board["board.i2c.status"] if rd == 2: time.sleep(0.1) break elif rd == 0: time.sleep(0.005) self.remove_passwd() return else: time.sleep(0.1) else: self.board._i2c_lock.lock() if self.board[self.i2c_shadow + self.i2c_req_reg] == 1: self.logger.warning("Detected Incomplete Previous I2C operation") self.board[self.i2c_shadow + self.i2c_req_reg] = 0 self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP not ready!") self.set_passwd() add = self.phy_addr >> 1 nof_rd_byte = 0 nof_wr_byte = 2 cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add self.board[self.i2c_shadow + 0x4] = ((data & 0xFF) << 8) + (offset & 0xFF) self.board[self.i2c_shadow + 0x0] = cmd # send request self.board[self.i2c_shadow + self.i2c_req_reg] = 1 # wait req acknowledge self.logger.debug("wait req acknowledge") self.poll_reg( self.i2c_shadow + self.i2c_ack_reg, 1, "I2C/EEP request not accepted!" ) # check passwd self.logger.debug("check passwd") self.check_passwd() # check i2c op status: 0 ok, 1 busy, 2 NACK self.logger.debug("check status") self.poll_reg(self.i2c_shadow + 0xC, 0, "I2C/EEP busy or not acknowledge!") # read_data = self.board[self.i2c_shadow + 0x8] # self.remove_passwd() self.board[self.i2c_shadow + self.i2c_req_reg] = 0 self.logger.debug("check end operation") self.poll_reg( self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP operation complete!", ) self.board._i2c_lock.unlock() time.sleep(0.020)
[docs] def wr32(self, offset, data): for n in range(4): self.wr8(offset + n, (data >> 8 * (3 - n)) & 0xFF) return
[docs] def wr_string(self, partition, string): return self._wr_string(partition["offset"], string, partition["size"])
def _wr_string(self, offset, string, max_len=16): addr = offset for i in range(len(string)): self.wr8(addr, ord(string[i])) addr += 1 if addr >= offset + max_len: break if addr < offset + max_len: self.wr8(addr, ord("\n"))
[docs] def rd_string(self, partition): return self._rd_string(partition["offset"], partition["size"])
def _rd_string(self, offset, max_len=16, mux=0, add=None): if add is None: add = self.phy_addr string = "" for i in range(0, max_len, 4): length = min(4, max_len - i) data = self.rd8(offset + i, size=length, mux=mux, add=add) for j in range(length): byte = (data >> (8 * (length - 1 - j))) & 0xFF if byte == ord("\n") or byte == 0xFF: return string string += chr(byte) return string def _rd_bytearray(self, offset, max_len=16, mux=0, add=None): if add is None: add = self.phy_addr arr = bytearray() for i in range(0, max_len, 4): length = min(4, max_len - i) data = self.rd8(offset + i, size=length, mux=mux, add=add) for j in range(length): byte = (data >> (8 * (length - 1 - j))) & 0xFF arr.append(byte) return arr
[docs] def set_passwd(self): if self.board.i2c_old_mode: rd = self.board["board.i2c.mac_hi"] self.board["board.i2c.password"] = rd rd = self.board["board.i2c.mac_lo"] self.board["board.i2c.password_lo"] = rd rd = self.board["board.i2c.password"] if rd & 0x10000 == 0: raise LibraryError("I2C/EEP password not accepted!") else: rd = self.board["board.i2c.mac_hi"] self.board[self.i2c_shadow + 0x3C] = rd rd = self.board["board.i2c.mac_lo"] self.board[self.i2c_shadow + 0x38] = rd
[docs] def check_passwd(self): rd = self.board[self.i2c_shadow + 0x3C] if (rd & 0x10000) != 0x10000: self.logger.error("I2C/EEP password not accepted!") raise LibraryError("I2C/EEP password not accepted!")
[docs] def remove_passwd(self): if self.board.i2c_old_mode: self.board["board.i2c.password"] = 0 self.board["board.i2c.password_lo"] = 0 else: self.board[self.i2c_shadow + 0x3C] = 0 self.board[self.i2c_shadow + 0x38] = 0
[docs] def get_field(self, key): if self.eep_sec[key]["type"] == "ip": return long2ip(self.rd32(self.eep_sec[key]["offset"])) elif self.eep_sec[key]["type"] == "bytearray": arr = bytearray() for offset in range(self.eep_sec[key]["size"]): arr.append(self.rd8(self.eep_sec[key]["offset"] + offset)) return arr elif self.eep_sec[key]["type"] == "string": return self.rd_string(self.eep_sec[key]) elif self.eep_sec[key]["type"] == "uint": val = 0 for offset in range(self.eep_sec[key]["size"]): val = val * 256 + self.rd8(self.eep_sec[key]["offset"] + offset) return val
[docs] def set_field(self, key, value, override_protected=False): if self.eep_sec[key]["protected"] is False or override_protected: if self.eep_sec[key]["type"] == "ip": self.wr32(self.eep_sec[key]["offset"], ip2long(value)) elif self.eep_sec[key]["type"] == "bytearray": for offset in range(self.eep_sec[key]["size"]): self.wr8(self.eep_sec[key]["offset"] + offset, ((value & (0xff << (8*(self.eep_sec[key]["size"]-1-offset)))) >> (8*(self.eep_sec[key]["size"]-1-offset))) & 0xff) # fmt: skip elif self.eep_sec[key]["type"] == "string": self.wr_string(self.eep_sec[key], value) elif self.eep_sec[key]["type"] == "uint": val = value for offset in range(self.eep_sec[key]["size"]): self.wr8(self.eep_sec[key]["offset"] + offset, val & 0xFF) val = val >> 8 else: raise LibraryError("Writing attempt on protected sector %s" % key)