mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
mpm: x4xx: Move MB CPLD creation to factory
Main changes: - x4xx_mb_cpld.MboardCPLD is renamed to X4xxMboardCPLD and is now a base class. Specific implementations of the MB CPLD require derived classes and have to provide their corresponding signature. - In x4xx.py, we don't init the MB CPLD and then assert we have a specific signature. Instead, we init the MB CPLD, and choose a derived class based on the signature. If there is no such class, then the same error is generated as before (by itself, this means there is no behavioural change). - The MB CPLD image for the X410 (ZBX daughterboards) is moved to a derived class X410MboardCPLD. - New: The ZBX daughterboard driver verifies that the MB CPLD image is in fact compatible with the daughterboard. For this, the MB CPLD control classes require a COMPATIBLE_DB_PIDS attribute. By itself, this change has no behavioural- or API changes. However, it allows easily slotting in new CPLD images with different signatures. Without further modifications, it does not allow *any* CPLD image though: The PS API (e.g., enable/disable daughterboards, CMI status, etc.) remain the same.
This commit is contained in:
parent
4b007c42b3
commit
01ccb69459
3 changed files with 82 additions and 34 deletions
|
|
@ -56,6 +56,7 @@ class X4xxDbMixin:
|
|||
rev_compat = kwargs.get('rev_compat') if 'rev_compat' in kwargs else \
|
||||
self.get_eeprom()['rev_compat']
|
||||
self._assert_rev_compatibility(rev_compat)
|
||||
self._assert_mb_cpld_compatibility(self.db_iface.mboard.cpld_control)
|
||||
|
||||
###########################################################################
|
||||
# Init helpers
|
||||
|
|
@ -87,6 +88,20 @@ class X4xxDbMixin:
|
|||
self.log.error(err)
|
||||
raise RuntimeError(err)
|
||||
|
||||
def _assert_mb_cpld_compatibility(self, mb_cpld_ctrl):
|
||||
"""
|
||||
Verify that the MB CPLD is compatible with this daughterboard.
|
||||
|
||||
Throws a RuntimeError() if that's not the case.
|
||||
"""
|
||||
if not any(pid in self.pids for pid in mb_cpld_ctrl.COMPATIBLE_DB_PIDS):
|
||||
err = \
|
||||
f"This {self.product_name} daughterboard is not compatible with " \
|
||||
f"the motherboard CPLD image (CPLD signature: {mb_cpld_ctrl.SIGNATURE:X}). " \
|
||||
f"Please update the motherboard CPLD image."
|
||||
self.log.error(err)
|
||||
raise RuntimeError(err)
|
||||
|
||||
@no_rpc
|
||||
def enable_base_power(self, enable=True):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ from usrp_mpm.periph_manager.x4xx_periphs import CtrlportRegs
|
|||
from usrp_mpm.periph_manager.x4xx_dio_control import DioControl
|
||||
from usrp_mpm.periph_manager.x4xx_periphs import QSFPModule
|
||||
from usrp_mpm.periph_manager.x4xx_periphs import get_temp_sensor
|
||||
from usrp_mpm.periph_manager.x4xx_mb_cpld import MboardCPLD
|
||||
from usrp_mpm.periph_manager.x4xx_mb_cpld import make_mb_cpld_ctrl
|
||||
from usrp_mpm.periph_manager.x4xx_clk_aux import ClockingAuxBrdControl
|
||||
from usrp_mpm.periph_manager.x4xx_clk_mgr import X4xxClockMgr
|
||||
from usrp_mpm.periph_manager.x4xx_gps_mgr import X4xxGPSMgr
|
||||
|
|
@ -462,10 +462,9 @@ class x4xx(ZynqComponents, PeriphManagerBase):
|
|||
|
||||
# Init CPLD before talking to clocking ICs
|
||||
cpld_spi_node = dt_symbol_get_spidev('mb_cpld')
|
||||
self.cpld_control = MboardCPLD(cpld_spi_node, self.log)
|
||||
self.cpld_control.check_signature()
|
||||
self.cpld_control.check_compat_version()
|
||||
self.cpld_control.trace_git_hash()
|
||||
# This factory function will check signature and compat-rev, and
|
||||
# therefore could throw if the CPLD is not compatible.
|
||||
self.cpld_control = make_mb_cpld_ctrl(cpld_spi_node, self.log)
|
||||
|
||||
self._assert_rfdc_powered()
|
||||
# Init clocking after CPLD as the SPLL communication is relying on it.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,17 @@
|
|||
X4xx motherboard CPLD control
|
||||
"""
|
||||
|
||||
import sys
|
||||
import inspect
|
||||
from usrp_mpm import lib # Pulls in everything from C++-land
|
||||
from usrp_mpm.mpmutils import parse_encoded_git_hash
|
||||
from usrp_mpm.dboard_manager import ZBX
|
||||
|
||||
class MboardCPLD:
|
||||
class X4xxMboardCPLD:
|
||||
"""
|
||||
Control for the CPLD.
|
||||
Base class for the CPLD control
|
||||
|
||||
Derive from this class for a specific implementation of the X4xx MB CPLD.
|
||||
"""
|
||||
# pylint: disable=bad-whitespace
|
||||
SIGNATURE_OFFSET = 0x0000
|
||||
|
|
@ -26,10 +31,10 @@ class MboardCPLD:
|
|||
SERIAL_NO_HI_OFFSET = 0x0038
|
||||
CMI_OFFSET = 0x003C
|
||||
|
||||
# change these revisions only on breaking changes
|
||||
OLDEST_REQ_COMPAT_REV = 0x20122114
|
||||
REQ_COMPAT_REV = 0x20122114
|
||||
SIGNATURE = 0x0A522D27
|
||||
# These need to be filled out by derived classes
|
||||
OLDEST_REQ_COMPAT_REV = None
|
||||
REQ_COMPAT_REV = None
|
||||
SIGNATURE = None
|
||||
|
||||
# Bit fields in DB_ENABLE_OFFSET
|
||||
DB0_CLOCK_ENABLED = 1 << 0
|
||||
|
|
@ -47,19 +52,13 @@ class MboardCPLD:
|
|||
RELEASE_RST_DB1 = 1 << 17
|
||||
ASSERT_RST_DB0 = 1 << 20
|
||||
ASSERT_RST_DB1 = 1 << 21
|
||||
|
||||
COMPATIBLE_DB_PIDS = []
|
||||
# pylint: enable=bad-whitespace
|
||||
|
||||
def __init__(self, spi_dev_node, log):
|
||||
self.log = log.getChild("CPLD")
|
||||
self.regs = lib.spi.make_spidev_regs_iface(
|
||||
spi_dev_node,
|
||||
1000000, # Speed (Hz)
|
||||
0, # SPI mode
|
||||
32, # Addr shift
|
||||
0, # Data shift
|
||||
0, # Read flag
|
||||
1<<47 # Write flag
|
||||
)
|
||||
def __init__(self, regs, log):
|
||||
self.log = log
|
||||
self.regs = regs
|
||||
self.poke32 = self.regs.poke32
|
||||
self.peek32 = self.regs.peek32
|
||||
|
||||
|
|
@ -87,6 +86,7 @@ class MboardCPLD:
|
|||
|
||||
def enable_daughterboard(self, db_id, enable=True):
|
||||
""" Enable or disable clock forwarding to a given DB """
|
||||
assert db_id in (0, 1)
|
||||
if db_id == 0:
|
||||
release_reset = self.RELEASE_RST_DB0
|
||||
assert_reset = self.ASSERT_RST_DB0
|
||||
|
|
@ -119,18 +119,6 @@ class MboardCPLD:
|
|||
value = (value | clk_disable) & (~clk_enable)
|
||||
self.poke32(self.DB_ENABLE_OFFSET, value)
|
||||
|
||||
def check_signature(self):
|
||||
"""
|
||||
Assert that the CPLD signature is correct. If the CPLD 'signature'
|
||||
register returns something unexpectected, throws a RuntimeError.
|
||||
"""
|
||||
read_signature = self.peek32(self.SIGNATURE_OFFSET)
|
||||
if self.SIGNATURE != read_signature:
|
||||
self.log.error('MB PS CPLD signature {:X} does not match '
|
||||
'expected value {:X}'.format(read_signature, self.SIGNATURE))
|
||||
raise RuntimeError('MB PS CPLD signature {:X} does not match '
|
||||
'expected value {:X}'.format(read_signature, self.SIGNATURE))
|
||||
|
||||
def check_compat_version(self):
|
||||
"""
|
||||
Check oldest compatible revision offset of HW against required revision.
|
||||
|
|
@ -205,3 +193,49 @@ class MboardCPLD:
|
|||
Return true if upstream CMI device was found.
|
||||
"""
|
||||
return bool(self.peek32(self.CMI_OFFSET))
|
||||
|
||||
|
||||
class X410MboardCPLD(X4xxMboardCPLD):
|
||||
"""
|
||||
MB CPLD Image for USRP X410 (which means there are ZBX daughterboards
|
||||
installed).
|
||||
"""
|
||||
# pylint: disable=bad-whitespace
|
||||
# change these revisions only on breaking changes
|
||||
OLDEST_REQ_COMPAT_REV = 0x20122114
|
||||
REQ_COMPAT_REV = 0x20122114
|
||||
SIGNATURE = 0x0A522D27
|
||||
COMPATIBLE_DB_PIDS = ZBX.pids
|
||||
# pylint: enable=bad-whitespace
|
||||
|
||||
|
||||
def make_mb_cpld_ctrl(spi_dev_node, log):
|
||||
"""
|
||||
Factory function for the X4xx MB CPLD core
|
||||
"""
|
||||
log = log.getChild("CPLD")
|
||||
regs = lib.spi.make_spidev_regs_iface(
|
||||
spi_dev_node,
|
||||
1000000, # Speed (Hz)
|
||||
0, # SPI mode
|
||||
32, # Addr shift
|
||||
0, # Data shift
|
||||
0, # Read flag
|
||||
1<<47 # Write flag
|
||||
)
|
||||
cpld_signature = regs.peek32(X4xxMboardCPLD.SIGNATURE_OFFSET)
|
||||
log.trace("Found MB CPLD signature: %x", cpld_signature)
|
||||
def _map_sig_to_class(signature):
|
||||
for name, obj in sys.modules[__name__].__dict__.items():
|
||||
if inspect.isclass(obj) and \
|
||||
issubclass(obj, X4xxMboardCPLD) and \
|
||||
getattr(obj, 'SIGNATURE') == signature:
|
||||
log.debug("Found MB CPLD control class: %s", name)
|
||||
return obj
|
||||
raise RuntimeError(
|
||||
"Unable to find a MB CPLD controller for CPLD with signature "
|
||||
f"{cpld_signature:X}!")
|
||||
cpld_control = _map_sig_to_class(cpld_signature)(regs, log)
|
||||
cpld_control.check_compat_version()
|
||||
cpld_control.trace_git_hash()
|
||||
return cpld_control
|
||||
|
|
|
|||
Loading…
Reference in a new issue