From 394530777b3ac656609cf98b3c9e35238e3fc296 Mon Sep 17 00:00:00 2001 From: Toni Jones Date: Wed, 9 Jan 2019 19:33:35 +0000 Subject: 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. --- mpm/python/usrp_mpm/chips/CMakeLists.txt | 1 + mpm/python/usrp_mpm/chips/__init__.py | 1 + mpm/python/usrp_mpm/chips/lmk03328.py | 84 ++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 mpm/python/usrp_mpm/chips/lmk03328.py (limited to 'mpm/python') 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) -- cgit v1.2.3