aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/usrp3/include/wb_soft_reg.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usrp3/include/wb_soft_reg.h')
-rw-r--r--firmware/usrp3/include/wb_soft_reg.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/firmware/usrp3/include/wb_soft_reg.h b/firmware/usrp3/include/wb_soft_reg.h
new file mode 100644
index 000000000..cbfc311bb
--- /dev/null
+++ b/firmware/usrp3/include/wb_soft_reg.h
@@ -0,0 +1,135 @@
+//
+// Copyright 2014 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_SOFT_REG_H
+#define INCLUDED_SOFT_REG_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <wb_utils.h>
+
+/* Keeps track of all metadata associated with a soft register.
+ * Use this struct when you need to manage a hardware register that needs
+ * to be accessed from different sections of software. If a register contains
+ * several unrelated bitfields, this object can be used to ensure coherency.
+ * It is recommended that the client hold this as a global/static object.
+ */
+typedef struct
+{
+ uint32_t wr_addr;
+ uint32_t rd_addr;
+ uint32_t soft_copy;
+} soft_reg_t;
+
+/* A register field is defined as a tuple of the mask and the shift.
+ * It can be used to make read-modify-write operations more convenient
+ * For efficiency reasons, it is recommended to always use a constant
+ * of this type because it will get optimized out by the compiler and
+ * will result in zero memory overhead
+ */
+typedef struct
+{
+ uint8_t num_bits;
+ uint8_t shift;
+} soft_reg_field_t;
+
+
+/*!
+ * Initialize the soft_reg_t struct as a read-write register.
+ * Params:
+ * - reg: Pointer to the soft_reg struct
+ * - wr_addr: The address used to flush the register to HW
+ * - rd_addr: The address used to read the register from HW
+ */
+static inline void initialize_readwrite_soft_reg(soft_reg_t* reg, uint32_t wr_addr, uint32_t rd_addr)
+{
+ reg->wr_addr = wr_addr;
+ reg->rd_addr = rd_addr;
+ reg->soft_copy = 0;
+}
+
+/*!
+ * Initialize the soft_reg_t struct as a write-only register.
+ * Params:
+ * - reg: Pointer to the soft_reg struct
+ * - addr: The address used to flush the register to HW
+ */
+static inline void initialize_writeonly_soft_reg(soft_reg_t* reg, uint32_t addr)
+{
+ reg->wr_addr = addr;
+ reg->rd_addr = 0;
+ reg->soft_copy = 0;
+}
+
+/*!
+ * Update specified field in the soft-copy with the arg value.
+ * Performs a read-modify-write operation so all other field are preserved.
+ * NOTE: This does not write the value to hardware.
+ */
+static inline void soft_reg_set(soft_reg_t* reg, const soft_reg_field_t field, const uint32_t field_value)
+{
+ const uint32_t mask = ((1<<field.num_bits)-1)<<field.shift;
+ reg->soft_copy = (reg->soft_copy & ~mask) | ((field_value << field.shift) & mask);
+}
+
+/*!
+ * Write the contents of the soft-copy to hardware.
+ */
+static inline void soft_reg_flush(const soft_reg_t* reg)
+{
+ wb_poke32(reg->wr_addr, reg->soft_copy);
+}
+
+/*!
+ * Shortcut for a set and a flush.
+ */
+static inline void soft_reg_write(soft_reg_t* reg, const soft_reg_field_t field, const uint32_t field_value)
+{
+ soft_reg_set(reg, field, field_value);
+ soft_reg_flush(reg);
+}
+
+/*!
+ * Get the value of the specified field from the soft-copy.
+ * NOTE: This does not read anything from hardware.
+ */
+static inline uint32_t soft_reg_get(const soft_reg_t* reg, const soft_reg_field_t field)
+{
+ const uint32_t mask = ((1<<field.num_bits)-1)<<field.shift;
+ return (reg->soft_copy & mask) >> field.shift;
+}
+
+/*!
+ * Read the contents of the register from hardware and update the soft copy.
+ */
+static inline void soft_reg_refresh(soft_reg_t* reg)
+{
+ if (reg->rd_addr) {
+ reg->soft_copy = wb_peek32(reg->rd_addr);
+ }
+}
+
+/*!
+ * Shortcut for refresh and get
+ */
+static inline uint32_t soft_reg_read(soft_reg_t* reg, const soft_reg_field_t field)
+{
+ soft_reg_refresh(reg);
+ return soft_reg_get(reg, field);
+}
+
+#endif /* INCLUDED_SOFT_REG_H */