aboutsummaryrefslogtreecommitdiffstats
path: root/mpm
diff options
context:
space:
mode:
authorToni Jones <toni.jones@ni.com>2019-01-09 19:33:35 +0000
committerAaron Rossetto <aaron.rossetto@ni.com>2021-02-22 10:15:13 -0600
commit394530777b3ac656609cf98b3c9e35238e3fc296 (patch)
treea88bf88dc138dcfa3c0ea680f895890c90bc997f /mpm
parent2e441d296b1f98fd4939d4008430e8814e777e0c (diff)
downloaduhd-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.txt1
-rw-r--r--mpm/python/usrp_mpm/chips/__init__.py1
-rw-r--r--mpm/python/usrp_mpm/chips/lmk03328.py84
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)