diff options
author | Toni Jones <toni.jones@ni.com> | 2019-01-09 19:33:35 +0000 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-02-22 10:15:13 -0600 |
commit | 394530777b3ac656609cf98b3c9e35238e3fc296 (patch) | |
tree | a88bf88dc138dcfa3c0ea680f895890c90bc997f /mpm | |
parent | 2e441d296b1f98fd4939d4008430e8814e777e0c (diff) | |
download | uhd-394530777b3ac656609cf98b3c9e35238e3fc296.tar.gz uhd-394530777b3ac656609cf98b3c9e35238e3fc296.tar.bz2 uhd-394530777b3ac656609cf98b3c9e35238e3fc296.zip |
mpm: Add an LMK03328 base chip driver
Added an LMK03328 base chip driver which does basic register access, ID
validation, and PLL lock validation. This will act as the base class for
device specific drivers which control the chip. The code it similar to
the LMK04828 and LMK04832 base driver classes but has a different
register map structure. Register bitfield definitions were omitted and
will be added on an as needed basis.
Diffstat (limited to 'mpm')
-rw-r--r-- | mpm/python/usrp_mpm/chips/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/chips/__init__.py | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/chips/lmk03328.py | 84 |
3 files changed, 86 insertions, 0 deletions
diff --git a/mpm/python/usrp_mpm/chips/CMakeLists.txt b/mpm/python/usrp_mpm/chips/CMakeLists.txt index 9bd7b9372..1f64d8e2d 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}/lmk04832.py + ${CMAKE_CURRENT_SOURCE_DIR}/lmk03328.py ${CMAKE_CURRENT_SOURCE_DIR}/adf400x.py ${CMAKE_CURRENT_SOURCE_DIR}/ds125df410.py ) diff --git a/mpm/python/usrp_mpm/chips/__init__.py b/mpm/python/usrp_mpm/chips/__init__.py index 60368ad6a..453ab5c2a 100644 --- a/mpm/python/usrp_mpm/chips/__init__.py +++ b/mpm/python/usrp_mpm/chips/__init__.py @@ -10,3 +10,4 @@ Chips submodule from .adf400x import ADF400x from .lmk04828 import LMK04828 from .lmk04832 import LMK04832 +from .lmk03328 import LMK03328 diff --git a/mpm/python/usrp_mpm/chips/lmk03328.py b/mpm/python/usrp_mpm/chips/lmk03328.py new file mode 100644 index 000000000..461cf7f38 --- /dev/null +++ b/mpm/python/usrp_mpm/chips/lmk03328.py @@ -0,0 +1,84 @@ +# +# Copyright 2020 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +""" +LMK03328 parent driver class +""" + +from usrp_mpm.mpmlog import get_logger + +class LMK03328(): + """ + Generic driver class for LMK03328 access. + """ + LMK_CHIP_ID = 0x32 + + def __init__(self, regs_iface, parent_log=None): + self.log = \ + parent_log.getChild("LMK03328") if parent_log is not None \ + else get_logger("LMK03328") + self.regs_iface = regs_iface + assert hasattr(self.regs_iface, 'peek8') + assert hasattr(self.regs_iface, 'poke8') + self.poke8 = regs_iface.poke8 + self.peek8 = regs_iface.peek8 + + def pokes8(self, addr_vals): + """ + Apply a series of pokes. + pokes8([(0,1),(0,2)]) is the same as calling poke8(0,1), poke8(0,2). + """ + for addr, val in addr_vals: + self.poke8(addr, val) + + def get_chip_id(self): + """ + Read back the chip ID + """ + chip_id = self.peek8(0x02) + self.log.trace("Chip ID Readback: {}".format(chip_id)) + return chip_id + + def verify_chip_id(self): + """ + Returns True if the chip ID matches what we expect, False otherwise. + """ + chip_id = self.get_chip_id() + if chip_id != self.LMK_CHIP_ID: + self.log.error("Wrong Chip ID 0x{:X}".format(chip_id)) + return False + return True + + def check_pll_locked(self, pll_num): + """ + Returns True if the specified PLL is locked, False otherwise. + """ + if pll_num not in (1, 2): + self.log.warning("PLL{} is not a valid PLL" + .format(pll_num)) + return False + pll_lock_status = self.peek8(13) + + # Lock status for PLL1 is bits [7:6] and PLL2 is bits [4:3] + pll_lock_mask = 0xC0 if pll_num == 1 else 0x18 + + if (pll_lock_status & pll_lock_mask) != 0x0: + self.log.debug("PLL{} reporting unlocked... Status: 0x{:x}" + .format(pll_num, pll_lock_status)) + return False + return True + + def soft_reset(self, value=True): + """ + Performs a soft reset of the LMK03328 by setting or unsetting the software + reset register. The adjacent contents of the register are preserved by + reading their value prior to re-writing the corresponding byte. + """ + reset_bit = 0x80 + reset_addr = 12 + old_reg_val = self.peek8(reset_addr) + # The reset register is active low so if value is True, write 0. Otherwise, write 1 + new_reg_val = (old_reg_val & (~reset_bit)) if value else (old_reg_val | reset_bit) + self.poke8(reset_addr, new_reg_val) |