aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLane Kolbly <lane.kolbly@ni.com>2021-10-14 13:15:48 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2021-10-27 07:56:33 -0700
commit62d467f3fc024f6a43abca9c3a2b194b5d3829bf (patch)
tree45e13cf7624f0539febb37478c305e05055d7cb5
parent4e6531f30648ede5be8f93fa49fdcd4973b73813 (diff)
downloaduhd-62d467f3fc024f6a43abca9c3a2b194b5d3829bf.tar.gz
uhd-62d467f3fc024f6a43abca9c3a2b194b5d3829bf.tar.bz2
uhd-62d467f3fc024f6a43abca9c3a2b194b5d3829bf.zip
host: gpio: Create gpio_atr_offsets to store GPIO registers
Refactors register addresses into a gpio_atr_offsets structure which contains the various register addresses. This allows creating other devices with different GPIO register layouts with greater ease, and eliminates the use of macros (yay!)
-rw-r--r--host/lib/include/uhdlib/usrp/cores/gpio_atr_3000.hpp71
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp5
-rw-r--r--host/lib/usrp/cores/gpio_atr_3000.cpp86
-rw-r--r--host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp21
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp14
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp14
-rw-r--r--host/lib/usrp/x300/x300_radio_control.cpp19
7 files changed, 136 insertions, 94 deletions
diff --git a/host/lib/include/uhdlib/usrp/cores/gpio_atr_3000.hpp b/host/lib/include/uhdlib/usrp/cores/gpio_atr_3000.hpp
index aa266cbcb..85f22d967 100644
--- a/host/lib/include/uhdlib/usrp/cores/gpio_atr_3000.hpp
+++ b/host/lib/include/uhdlib/usrp/cores/gpio_atr_3000.hpp
@@ -17,38 +17,66 @@
namespace uhd { namespace usrp { namespace gpio_atr {
-class gpio_atr_3000 : uhd::noncopyable
+struct gpio_atr_offsets
{
-public:
- typedef std::shared_ptr<gpio_atr_3000> sptr;
-
- static const uint32_t MASK_SET_ALL = 0xFFFFFFFF;
+ uhd::wb_iface::wb_addr_type idle;
+ uhd::wb_iface::wb_addr_type rx;
+ uhd::wb_iface::wb_addr_type tx;
+ uhd::wb_iface::wb_addr_type duplex;
+ uhd::wb_iface::wb_addr_type ddr;
+ uhd::wb_iface::wb_addr_type disable;
+ uhd::wb_iface::wb_addr_type readback;
- virtual ~gpio_atr_3000(void) {}
+ /*!
+ * Returns whether this GPIO regmap is write-only.
+ *
+ * \return whether the readback register is valid
+ */
+ bool is_writeonly() const;
/*!
- * Create a read-write GPIO ATR interface object
+ * Create a GPIO regmap according to the typical "defaults": Four
+ * sequential ATR registers followed immediately by, in order, duplex,
+ * direction, disable, and an explicitly specified readback address.
*
- * \param iface register iface to GPIO ATR registers
* \param base base settings offset for GPIO ATR registers
* \param rb_addr readback offset for GPIO ATR registers
- * \param reg_offset Delta between the register addresses
+ * \param stride Delta between the register addresses
*/
- static sptr make(uhd::wb_iface::sptr iface,
+ static gpio_atr_offsets make_default(
const uhd::wb_iface::wb_addr_type base,
const uhd::wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset = 4);
+ const size_t stride = 4);
/*!
- * Create a write-only GPIO ATR interface object
+ * Create a GPIO regmap according to the typical "defaults" (see
+ * make_default), with the readback register disabled.
*
- * \param iface register iface to GPIO ATR registers
* \param base base settings offset for GPIO ATR registers
- * \param reg_offset Delta between the register addresses
+ * \param rb_addr readback offset for GPIO ATR registers
+ * \param stride Delta between the register addresses
*/
- static sptr make_write_only(uhd::wb_iface::sptr iface,
+ static gpio_atr_offsets make_write_only(
const uhd::wb_iface::wb_addr_type base,
- const size_t reg_offset = 4);
+ const size_t stride = 4);
+};
+
+class gpio_atr_3000 : uhd::noncopyable
+{
+public:
+ typedef std::shared_ptr<gpio_atr_3000> sptr;
+
+ static const uint32_t MASK_SET_ALL = 0xFFFFFFFF;
+
+ virtual ~gpio_atr_3000(void) {}
+
+ /*!
+ * Create a GPIO ATR interface object using the given registers
+ *
+ * \param iface register iface to GPIO ATR registers
+ * \param registers Register offsets
+ */
+ static sptr make(uhd::wb_iface::sptr iface, gpio_atr_offsets registers);
/*!
* Select the ATR mode for all bits in the mask
@@ -124,17 +152,12 @@ public:
virtual ~db_gpio_atr_3000(void) {}
/*!
- * Create a read-write GPIO ATR interface object for a daughterboard connector
+ * Create a GPIO ATR interface object for a daughterboard connector
*
* \param iface register iface to GPIO ATR registers
- * \param base base settings offset for GPIO ATR registers
- * \param rb_addr readback offset for GPIO ATR registers
- * \param reg_offset Delta between the register addresses
+ * \param registers Register offsets
*/
- static sptr make(uhd::wb_iface::sptr iface,
- const uhd::wb_iface::wb_addr_type base,
- const uhd::wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset = 4);
+ static sptr make(uhd::wb_iface::sptr iface, gpio_atr_offsets registers);
/*!
* Configure the GPIO mode for all pins in the daughterboard connector
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 2e2ed5a98..ed685d536 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -749,7 +749,8 @@ b200_impl::b200_impl(
// front panel gpio
////////////////////////////////////////////////////////////////////
_radio_perifs[0].fp_gpio =
- gpio_atr_3000::make(_radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO);
+ gpio_atr_3000::make(_radio_perifs[0].ctrl,
+ gpio_atr_offsets::make_default(TOREG(SR_FP_GPIO), RB32_FP_GPIO));
for (const auto& attr : gpio_attr_map) {
switch (attr.first) {
case usrp::gpio_atr::GPIO_SRC:
@@ -883,7 +884,7 @@ void b200_impl::setup_radio(const size_t dspno)
////////////////////////////////////////////////////////////////////
// Set up peripherals
////////////////////////////////////////////////////////////////////
- perif.atr = gpio_atr_3000::make_write_only(perif.ctrl, TOREG(SR_ATR));
+ perif.atr = gpio_atr_3000::make(perif.ctrl, gpio_atr_offsets::make_write_only(TOREG(SR_ATR)));
perif.atr->set_atr_mode(MODE_ATR, 0xFFFFFFFF);
// create rx dsp control objects
perif.framer = rx_vita_core_3000::make(perif.ctrl, TOREG(SR_RX_CTRL));
diff --git a/host/lib/usrp/cores/gpio_atr_3000.cpp b/host/lib/usrp/cores/gpio_atr_3000.cpp
index 0c7eeebda..e4c8c5154 100644
--- a/host/lib/usrp/cores/gpio_atr_3000.cpp
+++ b/host/lib/usrp/cores/gpio_atr_3000.cpp
@@ -17,13 +17,6 @@ using namespace usrp;
// gpio_atr_3000
//-------------------------------------------------------------
-#define REG_ATR_IDLE_OFFSET (base + reg_offset * 0)
-#define REG_ATR_RX_OFFSET (base + reg_offset * 1)
-#define REG_ATR_TX_OFFSET (base + reg_offset * 2)
-#define REG_ATR_FDX_OFFSET (base + reg_offset * 3)
-#define REG_DDR_OFFSET (base + reg_offset * 4)
-#define REG_ATR_DISABLE_OFFSET (base + reg_offset * 5)
-
namespace {
// Special RB addr value to indicate no readback
// This value is invalid as a real address because it is not a multiple of 4
@@ -32,21 +25,48 @@ static constexpr wb_iface::wb_addr_type READBACK_DISABLED = 0xFFFFFFFF;
namespace uhd { namespace usrp { namespace gpio_atr {
+bool gpio_atr_offsets::is_writeonly() const
+{
+ return readback == READBACK_DISABLED;
+}
+
+gpio_atr_offsets gpio_atr_offsets::make_default(
+ const uhd::wb_iface::wb_addr_type base,
+ const uhd::wb_iface::wb_addr_type rb_addr,
+ const size_t stride)
+{
+ gpio_atr_offsets offsets {
+ base, // Idle
+ static_cast<uhd::wb_iface::wb_addr_type>(base + stride), // RX
+ static_cast<uhd::wb_iface::wb_addr_type>(base + stride * 2), // TX
+ static_cast<uhd::wb_iface::wb_addr_type>(base + stride * 3), // Full Duplex
+ static_cast<uhd::wb_iface::wb_addr_type>(base + stride * 4), // DDR
+ static_cast<uhd::wb_iface::wb_addr_type>(base + stride * 5), // Disabled
+ rb_addr, // Readback
+ };
+ return offsets;
+}
+
+gpio_atr_offsets gpio_atr_offsets::make_write_only(
+ const uhd::wb_iface::wb_addr_type base,
+ const size_t stride)
+{
+ return make_default(base, READBACK_DISABLED, stride);
+}
+
class gpio_atr_3000_impl : public gpio_atr_3000
{
public:
gpio_atr_3000_impl(wb_iface::sptr iface,
- const wb_iface::wb_addr_type base,
- const wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset)
+ const gpio_atr_offsets registers)
: _iface(iface)
- , _rb_addr(rb_addr)
- , _atr_idle_reg(REG_ATR_IDLE_OFFSET, _atr_disable_reg)
- , _atr_rx_reg(REG_ATR_RX_OFFSET)
- , _atr_tx_reg(REG_ATR_TX_OFFSET)
- , _atr_fdx_reg(REG_ATR_FDX_OFFSET)
- , _ddr_reg(REG_DDR_OFFSET)
- , _atr_disable_reg(REG_ATR_DISABLE_OFFSET)
+ , _rb_addr(registers.readback)
+ , _atr_idle_reg(registers.idle, _atr_disable_reg)
+ , _atr_rx_reg(registers.rx)
+ , _atr_tx_reg(registers.tx)
+ , _atr_fdx_reg(registers.duplex)
+ , _ddr_reg(registers.ddr)
+ , _atr_disable_reg(registers.disable)
{
_atr_idle_reg.initialize(*_iface, true);
_atr_rx_reg.initialize(*_iface, true);
@@ -311,19 +331,13 @@ protected:
}
};
-gpio_atr_3000::sptr gpio_atr_3000::make(wb_iface::sptr iface,
- const wb_iface::wb_addr_type base,
- const wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset)
+gpio_atr_3000::sptr gpio_atr_3000::make(wb_iface::sptr iface, gpio_atr_offsets registers)
{
- return sptr(new gpio_atr_3000_impl(iface, base, rb_addr, reg_offset));
-}
-
-gpio_atr_3000::sptr gpio_atr_3000::make_write_only(
- wb_iface::sptr iface, const wb_iface::wb_addr_type base, const size_t reg_offset)
-{
- gpio_atr_3000::sptr gpio_iface(
- new gpio_atr_3000_impl(iface, base, READBACK_DISABLED, reg_offset));
+ gpio_atr_3000::sptr gpio_iface = std::make_shared<gpio_atr_3000_impl>(
+ iface, registers);
+ if (registers.is_writeonly()) {
+ gpio_iface->set_gpio_ddr(DDR_OUTPUT, MASK_SET_ALL);
+ }
gpio_iface->set_gpio_ddr(DDR_OUTPUT, MASK_SET_ALL);
return gpio_iface;
}
@@ -335,11 +349,8 @@ gpio_atr_3000::sptr gpio_atr_3000::make_write_only(
class db_gpio_atr_3000_impl : public gpio_atr_3000_impl, public db_gpio_atr_3000
{
public:
- db_gpio_atr_3000_impl(wb_iface::sptr iface,
- const wb_iface::wb_addr_type base,
- const wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset)
- : gpio_atr_3000_impl(iface, base, rb_addr, reg_offset)
+ db_gpio_atr_3000_impl(wb_iface::sptr iface, const gpio_atr_offsets registers)
+ : gpio_atr_3000_impl(iface, registers)
{ /* NOP */
}
@@ -443,12 +454,9 @@ private:
}
};
-db_gpio_atr_3000::sptr db_gpio_atr_3000::make(wb_iface::sptr iface,
- const wb_iface::wb_addr_type base,
- const wb_iface::wb_addr_type rb_addr,
- const size_t reg_offset)
+db_gpio_atr_3000::sptr db_gpio_atr_3000::make(wb_iface::sptr iface, gpio_atr_offsets registers)
{
- return sptr(new db_gpio_atr_3000_impl(iface, base, rb_addr, reg_offset));
+ return std::make_shared<db_gpio_atr_3000_impl>(iface, registers);
}
}}} // namespace uhd::usrp::gpio_atr
diff --git a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp
index 995133442..95f6301f2 100644
--- a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp
+++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp
@@ -86,9 +86,10 @@ void e3xx_radio_control_impl::_init_peripherals()
// Note: The register offset is baked into the different _wb_iface
// objects!
_db_gpio.emplace_back(
- usrp::gpio_atr::gpio_atr_3000::make_write_only(_wb_ifaces.at(radio_idx),
- e3xx_regs::SR_DB_GPIO + (radio_idx * e3xx_regs::PERIPH_REG_CHAN_OFFSET),
- e3xx_regs::PERIPH_REG_OFFSET));
+ usrp::gpio_atr::gpio_atr_3000::make(_wb_ifaces.at(radio_idx),
+ usrp::gpio_atr::gpio_atr_offsets::make_write_only(
+ e3xx_regs::SR_DB_GPIO + (radio_idx * e3xx_regs::PERIPH_REG_CHAN_OFFSET),
+ e3xx_regs::PERIPH_REG_OFFSET)));
_db_gpio[radio_idx]->set_atr_mode(
usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
}
@@ -96,17 +97,19 @@ void e3xx_radio_control_impl::_init_peripherals()
for (size_t radio_idx = 0; radio_idx < E3XX_NUM_CHANS; radio_idx++) {
RFNOC_LOG_TRACE("Initializing LED GPIOs for channel " << radio_idx);
_leds_gpio.emplace_back(
- usrp::gpio_atr::gpio_atr_3000::make_write_only(_wb_ifaces.at(radio_idx),
- e3xx_regs::SR_LEDS + (radio_idx * e3xx_regs::PERIPH_REG_CHAN_OFFSET),
- e3xx_regs::PERIPH_REG_OFFSET));
+ usrp::gpio_atr::gpio_atr_3000::make(_wb_ifaces.at(radio_idx),
+ usrp::gpio_atr::gpio_atr_offsets::make_write_only(
+ e3xx_regs::SR_LEDS + (radio_idx * e3xx_regs::PERIPH_REG_CHAN_OFFSET),
+ e3xx_regs::PERIPH_REG_OFFSET)));
_leds_gpio[radio_idx]->set_atr_mode(
usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
}
RFNOC_LOG_TRACE("Initializing front-panel GPIO control...")
_fp_gpio = usrp::gpio_atr::gpio_atr_3000::make(_wb_ifaces.at(0),
- e3xx_regs::SR_FP_GPIO,
- e3xx_regs::RB_FP_GPIO,
- e3xx_regs::PERIPH_REG_OFFSET);
+ usrp::gpio_atr::gpio_atr_offsets::make_default(
+ e3xx_regs::SR_FP_GPIO,
+ e3xx_regs::RB_FP_GPIO,
+ e3xx_regs::PERIPH_REG_OFFSET));
auto block_args = get_block_args();
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp
index 98c370275..95c5dcc52 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp
@@ -120,9 +120,10 @@ void magnesium_radio_control_impl::_init_peripherals()
_wb_ifaces.push_back(RFNOC_MAKE_WB_IFACE(0, radio_idx));
RFNOC_LOG_TRACE("Initializing GPIOs for channel " << radio_idx);
_gpio.emplace_back(usrp::gpio_atr::gpio_atr_3000::make(_wb_ifaces.back(),
- n310_regs::SR_DB_GPIO + radio_idx * n310_regs::CHAN_REG_OFFSET,
- n310_regs::RB_DB_GPIO + radio_idx * n310_regs::CHAN_REG_OFFSET,
- n310_regs::PERIPH_REG_OFFSET));
+ usrp::gpio_atr::gpio_atr_offsets::make_default(
+ n310_regs::SR_DB_GPIO + radio_idx * n310_regs::CHAN_REG_OFFSET,
+ n310_regs::RB_DB_GPIO + radio_idx * n310_regs::CHAN_REG_OFFSET,
+ n310_regs::PERIPH_REG_OFFSET)));
// DSA and AD9371 gain bits do *not* toggle on ATR modes. If we ever
// connect anything else to this core, we might need to set_atr_mode()
// to MODE_ATR on those bits. For now, all bits simply do what they're
@@ -134,9 +135,10 @@ void magnesium_radio_control_impl::_init_peripherals()
}
RFNOC_LOG_TRACE("Initializing front-panel GPIO control...")
_fp_gpio = usrp::gpio_atr::gpio_atr_3000::make(_wb_ifaces.front(),
- n310_regs::SR_FP_GPIO,
- n310_regs::RB_FP_GPIO,
- n310_regs::PERIPH_REG_OFFSET);
+ usrp::gpio_atr::gpio_atr_offsets::make_default(
+ n310_regs::SR_FP_GPIO,
+ n310_regs::RB_FP_GPIO,
+ n310_regs::PERIPH_REG_OFFSET));
}
void magnesium_radio_control_impl::_init_frontend_subtree(
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp
index 844b0752b..06c1c533a 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp
@@ -196,9 +196,10 @@ void rhodium_radio_control_impl::_init_peripherals()
RFNOC_LOG_TRACE("Initializing GPIOs...");
// DB GPIOs
_gpio = usrp::gpio_atr::gpio_atr_3000::make(_wb_iface,
- n320_regs::SR_DB_GPIO,
- n320_regs::RB_DB_GPIO,
- n320_regs::PERIPH_REG_OFFSET);
+ gpio_atr::gpio_atr_offsets::make_default(
+ n320_regs::SR_DB_GPIO,
+ n320_regs::RB_DB_GPIO,
+ n320_regs::PERIPH_REG_OFFSET));
_gpio->set_atr_mode(usrp::gpio_atr::MODE_ATR, // Enable ATR mode for Rhodium bits
RHODIUM_GPIO_MASK);
_gpio->set_atr_mode(usrp::gpio_atr::MODE_GPIO, // Disable ATR mode for unused bits
@@ -206,9 +207,10 @@ void rhodium_radio_control_impl::_init_peripherals()
_gpio->set_gpio_ddr(usrp::gpio_atr::DDR_OUTPUT, // Make all GPIOs outputs
usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
_fp_gpio = gpio_atr::gpio_atr_3000::make(_wb_iface,
- n320_regs::SR_FP_GPIO,
- n320_regs::RB_FP_GPIO,
- n320_regs::PERIPH_REG_OFFSET);
+ gpio_atr::gpio_atr_offsets::make_default(
+ n320_regs::SR_FP_GPIO,
+ n320_regs::RB_FP_GPIO,
+ n320_regs::PERIPH_REG_OFFSET));
RFNOC_LOG_TRACE("Set initial ATR values...");
_update_atr(RHODIUM_DEFAULT_TX_ANTENNA, TX_DIRECTION);
diff --git a/host/lib/usrp/x300/x300_radio_control.cpp b/host/lib/usrp/x300/x300_radio_control.cpp
index 949650906..ab56adb07 100644
--- a/host/lib/usrp/x300/x300_radio_control.cpp
+++ b/host/lib/usrp/x300/x300_radio_control.cpp
@@ -151,9 +151,10 @@ public:
// FP-GPIO (the gpio_atr_3000 ctor will initialize default values)
RFNOC_LOG_TRACE("Creating FP-GPIO interface...");
_fp_gpio = gpio_atr::gpio_atr_3000::make(_wb_iface,
- x300_regs::SR_FP_GPIO,
- x300_regs::RB_FP_GPIO,
- x300_regs::PERIPH_REG_OFFSET);
+ gpio_atr::gpio_atr_offsets::make_default(
+ x300_regs::SR_FP_GPIO,
+ x300_regs::RB_FP_GPIO,
+ x300_regs::PERIPH_REG_OFFSET));
// Create the GPIO banks and attributes, and populate them with some default
// values
// TODO: Do we need this section? Since the _fp_gpio handles state now, we
@@ -173,8 +174,9 @@ public:
// LEDs are technically valid for both RX and TX, but let's put them
// here
- _leds = gpio_atr::gpio_atr_3000::make_write_only(
- _wb_iface, x300_regs::SR_LEDS, x300_regs::PERIPH_REG_OFFSET);
+ _leds = gpio_atr::gpio_atr_3000::make(_wb_iface,
+ gpio_atr::gpio_atr_offsets::make_write_only(
+ x300_regs::SR_LEDS, x300_regs::PERIPH_REG_OFFSET));
_leds->set_atr_mode(
usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
// We always want to initialize at least one frontend core for both TX and RX
@@ -1520,9 +1522,10 @@ private:
// create a new dboard interface
x300_dboard_iface_config_t db_config;
db_config.gpio = gpio_atr::db_gpio_atr_3000::make(_wb_iface,
- x300_regs::SR_DB_GPIO,
- x300_regs::RB_DB_GPIO,
- x300_regs::PERIPH_REG_OFFSET);
+ gpio_atr::gpio_atr_offsets::make_default(
+ x300_regs::SR_DB_GPIO,
+ x300_regs::RB_DB_GPIO,
+ x300_regs::PERIPH_REG_OFFSET));
db_config.spi = _spi;
db_config.rx_spi_slaveno = DB_RX_SEN;
db_config.tx_spi_slaveno = DB_TX_SEN;