diff options
author | Alex Williams <alex.williams@ni.com> | 2018-10-15 12:16:16 -0700 |
---|---|---|
committer | Brent Stapleton <bstapleton@g.hmc.edu> | 2018-11-07 18:26:13 -0800 |
commit | 5c991d82f718c2f51c2f4b2cb183aeb3c910de3e (patch) | |
tree | f9223bab1644b3756539296c63891b03d03e1b95 /mpm/python/usrp_mpm/chips | |
parent | 738b9ec102cdb307413cab23fdcf7fb2522f9895 (diff) | |
download | uhd-5c991d82f718c2f51c2f4b2cb183aeb3c910de3e.tar.gz uhd-5c991d82f718c2f51c2f4b2cb183aeb3c910de3e.tar.bz2 uhd-5c991d82f718c2f51c2f4b2cb183aeb3c910de3e.zip |
mpm: Add basic driver for QSFP board's retimer
Diffstat (limited to 'mpm/python/usrp_mpm/chips')
-rw-r--r-- | mpm/python/usrp_mpm/chips/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/chips/ds125df410.py | 107 |
2 files changed, 108 insertions, 0 deletions
diff --git a/mpm/python/usrp_mpm/chips/CMakeLists.txt b/mpm/python/usrp_mpm/chips/CMakeLists.txt index 94b62f33d..ff4f61bdd 100644 --- a/mpm/python/usrp_mpm/chips/CMakeLists.txt +++ b/mpm/python/usrp_mpm/chips/CMakeLists.txt @@ -9,6 +9,7 @@ SET(USRP_MPM_CHIP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/lmk04828.py ${CMAKE_CURRENT_SOURCE_DIR}/adf400x.py + ${CMAKE_CURRENT_SOURCE_DIR}/ds125df410.py ) LIST(APPEND USRP_MPM_FILES ${USRP_MPM_CHIP_FILES}) SET(USRP_MPM_FILES ${USRP_MPM_FILES} PARENT_SCOPE) diff --git a/mpm/python/usrp_mpm/chips/ds125df410.py b/mpm/python/usrp_mpm/chips/ds125df410.py new file mode 100644 index 000000000..5cea7e67a --- /dev/null +++ b/mpm/python/usrp_mpm/chips/ds125df410.py @@ -0,0 +1,107 @@ +# +# Copyright 2018 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +""" +DS125DF410 driver class + +For use with TI's retimer chip +""" + +import math +from builtins import object +from usrp_mpm.mpmlog import get_logger + +LINE_RATE_PRESETS = {'Ethernet': 0xF6, 'CPRI1': 0x36, 'CPRI2': 0x46} +ALL_CHANS = range(4) + + +class DS125DF410(object): + """ + Driver class for DS125DF410 access. + + Inputs: + regs_iface : regs_iface bus driver to access device + parent_log : logger of parent + """ + + # (deemphasis, swing) + DRIVER_PRESETS = {} + + def __init__(self, regs_iface, parent_log=None): + self.log = \ + parent_log.getChild("DS125DF410") if parent_log is not None \ + else get_logger("DS125DF410") + self.regs_iface = regs_iface + # Set channel select register to control set + self.regs_iface.poke8(0xFF, 0) + # Probe chip ID + chip_id = self.regs_iface.peek8(0x01) + assert chip_id == 0xd1 + self.log.debug("Probed DS125DF410 retimer") + for chan in ALL_CHANS: + self._set_chan_select(chan) + # Reset channel registers + self.regs_iface.poke8(0x00, 0x04) + # Enable DFE mode + self.regs_iface.poke8(0x1E, 0xE1) + self.regs_iface.poke8(0x31, 0x40) + + def _rmw(self, addr, data, mask): + """ Read, modify, write """ + base = self.regs_iface.peek8(addr) & ~mask + data = (data & mask) | base + self.regs_iface.poke8(addr, data) + + def _set_chan_select(self, chan): + """ + Channel select + """ + assert chan in ALL_CHANS + self.regs_iface.poke8(0xFF, chan + 4) + + def set_rate_preset(self, preset, channels=None): + """ + Set rate preset + """ + channels = channels or ALL_CHANS + assert preset in LINE_RATE_PRESETS.keys() + for chan in channels: + self._set_chan_select(chan) + self.regs_iface.poke8(0x2F, LINE_RATE_PRESETS[preset]) + + def set_rate(self, rate, channels=None): + """ + Set rate + """ + channels = channels or ALL_CHANS + self.log.trace("Writing custom line rate {}".format(rate)) + ppm_val = int(math.ceil(rate*1280.0)) + assert ppm_val <= 0x7FFF + for chan in channels: + assert chan in ALL_CHANS + self._set_chan_select(chan) + # Set VCO divider to 1 + self.regs_iface.poke8(0x2F, 0xC6) + # Set frequency range detection + self.regs_iface.poke8(0x60, (ppm_val & 0x00FF)) + self.regs_iface.poke8(0x62, (ppm_val & 0x00FF)) + self.regs_iface.poke8(0x61, 0x80 | ((ppm_val >> 8) & 0x00FF)) + self.regs_iface.poke8(0x63, 0x80 | ((ppm_val >> 8) & 0x00FF)) + # Set VCO tolerance range to max + self.regs_iface.poke8(0x64, 0xFF) + + def set_driver_preset(self, preset, channels=None): + """ + Set driver preset + """ + channels = channels or ALL_CHANS + assert preset in self.DRIVER_PRESETS.keys() + self.log.trace("Setting retimer's driver for " + preset + " preset") + deemphasis, swing = self.DRIVER_PRESETS[preset] + for chan in channels: + self._set_chan_select(chan) + self._rmw(0x15, deemphasis, 0x47) + self._rmw(0x2D, swing, 0x07) + |