aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x400/x400_gpio_control.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x400/x400_gpio_control.cpp')
-rw-r--r--host/lib/usrp/x400/x400_gpio_control.cpp80
1 files changed, 69 insertions, 11 deletions
diff --git a/host/lib/usrp/x400/x400_gpio_control.cpp b/host/lib/usrp/x400/x400_gpio_control.cpp
index b0eb4f27e..94b61f8c1 100644
--- a/host/lib/usrp/x400/x400_gpio_control.cpp
+++ b/host/lib/usrp/x400/x400_gpio_control.cpp
@@ -32,7 +32,7 @@ constexpr uint32_t DIO_DIRECTION_REG = 0x4;
} // namespace gpio_regmap
// There are two ports, each with 12 pins
-constexpr size_t NUM_PORTS = 2;
+constexpr size_t NUM_PORTS = 2;
constexpr size_t NUM_PINS_PER_PORT = 12;
// Start of Port B pin numbers relative to Port A:
@@ -45,22 +45,24 @@ constexpr uint32_t PORTB_MAPPING[12] = {10, 11, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0};
const char* uhd::rfnoc::x400::GPIO_BANK_NAME = "GPIO";
-gpio_control::gpio_control(
- uhd::usrp::x400_rpc_iface::sptr rpcc, uhd::wb_iface::sptr iface)
- : _rpcc(rpcc), _regs(iface)
+gpio_control::gpio_control(uhd::usrp::x400_rpc_iface::sptr rpcc,
+ uhd::rfnoc::mpmd_mb_controller::sptr mb_control,
+ uhd::wb_iface::sptr iface)
+ : _rpcc(rpcc), _mb_control(mb_control), _regs(iface)
{
_rpcc->dio_set_port_mapping("DIO");
_rpcc->dio_set_voltage_level("PORTA", "3V3");
_rpcc->dio_set_voltage_level("PORTB", "3V3");
- // Hardcode classic ATR (channels operate independently)
- _regs->poke32(gpio_regmap::CLASSIC_MODE_OFFSET, 0x1);
+ // Hardcode new ATR (channel ATRs are combined into 4-bit index)
+ // Note that we emulate classic ATR
+ _regs->poke32(gpio_regmap::CLASSIC_MODE_OFFSET, 0x0);
// Initialize everything as inputs
_rpcc->dio_set_pin_directions("PORTA", 0x0);
_rpcc->dio_set_pin_directions("PORTB", 0x0);
- for (size_t bank = 0; bank < 2; bank++) {
+ for (size_t bank = 0; bank < 4; bank++) {
const wb_iface::wb_addr_type atr_base = bank * gpio_regmap::ATR_STRIDE;
usrp::gpio_atr::gpio_atr_offsets regmap{
atr_base + gpio_regmap::ATR_IDLE_OFFSET,
@@ -85,13 +87,58 @@ void gpio_control::set_gpio_attr(
_rpcc->dio_set_pin_directions("PORTB", value >> 12);
}
- const uint32_t internal_value = map_dio(value);
- _gpios[0]->set_gpio_attr(attr, internal_value);
if (is_atr_attr(attr)) {
- _gpios[1]->set_gpio_attr(attr, internal_value);
+ const uint32_t rf1_mask = build_rf1_mask();
+
+ for (size_t i = 0; i < 4; i++) {
+ const uint32_t previous_value = unmap_dio(_gpios[i]->get_attr_reg(attr));
+ const uint32_t new_value = (previous_value & rf1_mask) | (value & ~rf1_mask);
+ _gpios[i]->set_gpio_attr(attr, map_dio(new_value));
+ }
+
+ // Set the RF1 settings
+ for (const auto subattr : {uhd::usrp::gpio_atr::GPIO_ATR_0X,
+ uhd::usrp::gpio_atr::GPIO_ATR_RX,
+ uhd::usrp::gpio_atr::GPIO_ATR_TX,
+ uhd::usrp::gpio_atr::GPIO_ATR_XX}) {
+ const uint32_t previous_value =
+ unmap_dio(_gpios[atr_attr_index(attr)]->get_attr_reg(subattr));
+ const uint32_t new_value = (previous_value & ~rf1_mask) | (value & rf1_mask);
+ _gpios[atr_attr_index(attr)]->set_gpio_attr(subattr, map_dio(new_value));
+ }
+ } else {
+ const uint32_t internal_value = map_dio(value);
+ _gpios[0]->set_gpio_attr(attr, internal_value);
}
}
+uint32_t gpio_control::build_rf1_mask()
+{
+ auto porta_sources = _mb_control->get_gpio_src("GPIO0");
+ auto portb_sources = _mb_control->get_gpio_src("GPIO1");
+
+ uint32_t rf1_mask = 0;
+ for (size_t i = 0; i < 12; i++) {
+ if (porta_sources[i].find("RF1") != std::string::npos) {
+ rf1_mask |= 1 << i;
+ }
+ if (portb_sources[i].find("RF1") != std::string::npos) {
+ rf1_mask |= 1 << (i + 12);
+ }
+ }
+
+ return rf1_mask;
+}
+
+size_t gpio_control::atr_attr_index(const uhd::usrp::gpio_atr::gpio_attr_t attr)
+{
+ return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X ? 0
+ : attr == uhd::usrp::gpio_atr::GPIO_ATR_RX ? 1
+ : attr == uhd::usrp::gpio_atr::GPIO_ATR_TX ? 2
+ : attr == uhd::usrp::gpio_atr::GPIO_ATR_XX ? 3
+ : 0;
+}
+
bool gpio_control::is_atr_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr)
{
return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X
@@ -136,6 +183,16 @@ uint32_t gpio_control::get_gpio_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr
return unmap_dio(raw_value);
}
+ if (is_atr_attr(attr)) {
+ const uint32_t rf1_mask = build_rf1_mask();
+
+ // Grab the values for each channel
+ const uint32_t rf0_atr = unmap_dio(_gpios[0]->get_attr_reg(attr));
+ const uint32_t rf1_atr = unmap_dio(
+ _gpios[atr_attr_index(attr)]->get_attr_reg(uhd::usrp::gpio_atr::GPIO_ATR_0X));
+ return (rf0_atr & ~rf1_mask) | (rf1_atr & rf1_mask);
+ }
+
const uint32_t raw_value = _gpios[0]->get_attr_reg(attr);
return unmap_dio(raw_value);
}
@@ -151,7 +208,8 @@ uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::map_value(const uint32_t& val
}
}
throw uhd::lookup_error(
- std::string("Could not find corresponding GPIO pin number for given SPI pin ") + std::to_string(value));
+ std::string("Could not find corresponding GPIO pin number for given SPI pin ")
+ + std::to_string(value));
}
uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::unmap_value(const uint32_t& value)