[dif/adc_ctrl] Implement filter get/set-enabled DIFs
This implements the filter get/set-enabled DIFs, and corresponding unit
tests for the ADC Controller.
Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/sw/device/lib/dif/dif_adc_ctrl.c b/sw/device/lib/dif/dif_adc_ctrl.c
index 0ea3c89..85a724f 100644
--- a/sw/device/lib/dif/dif_adc_ctrl.c
+++ b/sw/device/lib/dif/dif_adc_ctrl.c
@@ -204,3 +204,133 @@
return kDifOk;
}
+
+static bool get_filter_offset(dif_adc_ctrl_channel_t channel,
+ dif_adc_ctrl_filter_t filter,
+ ptrdiff_t *filter_ctrl_reg_offset) {
+#define DIF_ADC_CTRL_CHANNEL0_FILTER_CTRL_REG_CASE_(filter_) \
+ case kDifAdcCtrlFilter##filter_: \
+ *filter_ctrl_reg_offset = \
+ ADC_CTRL_ADC_CHN0_FILTER_CTL_##filter_##_REG_OFFSET; \
+ break;
+
+#define DIF_ADC_CTRL_CHANNEL1_FILTER_CTRL_REG_CASE_(filter_) \
+ case kDifAdcCtrlFilter##filter_: \
+ *filter_ctrl_reg_offset = \
+ ADC_CTRL_ADC_CHN1_FILTER_CTL_##filter_##_REG_OFFSET; \
+ break;
+
+ switch (channel) {
+ case kDifAdcCtrlChannel0:
+ switch (filter) {
+ DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_CHANNEL0_FILTER_CTRL_REG_CASE_)
+ default:
+ return false;
+ }
+ break;
+ case kDifAdcCtrlChannel1:
+ switch (filter) {
+ DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_CHANNEL1_FILTER_CTRL_REG_CASE_)
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+#undef DIF_ADC_CTRL_CHANNEL0_FILTER_CTRL_REG_CASE_
+#undef DIF_ADC_CTRL_CHANNEL1_FILTER_CTRL_REG_CASE_
+
+ return true;
+}
+
+static bool get_filter_enable_bit(dif_adc_ctrl_channel_t channel,
+ dif_adc_ctrl_filter_t filter,
+ bitfield_bit32_index_t *enable_bit) {
+#define DIF_ADC_CTRL_CHANNEL0_FILTER_ENABLE_CASE_(filter_) \
+ case kDifAdcCtrlFilter##filter_: \
+ *enable_bit = ADC_CTRL_ADC_CHN0_FILTER_CTL_##filter_##_EN_##filter_##_BIT; \
+ break;
+
+#define DIF_ADC_CTRL_CHANNEL1_FILTER_ENABLE_CASE_(filter_) \
+ case kDifAdcCtrlFilter##filter_: \
+ *enable_bit = ADC_CTRL_ADC_CHN1_FILTER_CTL_##filter_##_EN_##filter_##_BIT; \
+ break;
+
+ switch (channel) {
+ case kDifAdcCtrlChannel0:
+ switch (filter) {
+ DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_CHANNEL0_FILTER_ENABLE_CASE_)
+ default:
+ return false;
+ }
+ break;
+ case kDifAdcCtrlChannel1:
+ switch (filter) {
+ DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_CHANNEL1_FILTER_ENABLE_CASE_)
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+#undef DIF_ADC_CTRL_CHANNEL0_FILTER_ENABLE_CASE_
+#undef DIF_ADC_CTRL_CHANNEL1_FILTER_ENABLE_CASE_
+
+ return true;
+}
+
+dif_result_t dif_adc_ctrl_filter_set_enabled(const dif_adc_ctrl_t *adc_ctrl,
+ dif_adc_ctrl_channel_t channel,
+ dif_adc_ctrl_filter_t filter,
+ dif_toggle_t enabled) {
+ if (adc_ctrl == NULL || !dif_is_valid_toggle(enabled)) {
+ return kDifBadArg;
+ }
+
+ ptrdiff_t filter_ctrl_reg_offset;
+ bitfield_bit32_index_t enable_bit;
+ if (!get_filter_offset(channel, filter, &filter_ctrl_reg_offset)) {
+ return kDifBadArg;
+ }
+ if (!get_filter_enable_bit(channel, filter, &enable_bit)) {
+ return kDifBadArg;
+ }
+
+ uint32_t filter_ctrl_reg =
+ mmio_region_read32(adc_ctrl->base_addr, filter_ctrl_reg_offset);
+ filter_ctrl_reg = bitfield_bit32_write(filter_ctrl_reg, enable_bit,
+ dif_toggle_to_bool(enabled));
+ mmio_region_write32(adc_ctrl->base_addr, filter_ctrl_reg_offset,
+ filter_ctrl_reg);
+
+ return kDifOk;
+}
+
+dif_result_t dif_adc_ctrl_filter_get_enabled(const dif_adc_ctrl_t *adc_ctrl,
+ dif_adc_ctrl_channel_t channel,
+ dif_adc_ctrl_filter_t filter,
+ dif_toggle_t *is_enabled) {
+ if (adc_ctrl == NULL || is_enabled == NULL) {
+ return kDifBadArg;
+ }
+
+ ptrdiff_t filter_ctrl_reg_offset;
+ bitfield_bit32_index_t enable_bit;
+ if (!get_filter_offset(channel, filter, &filter_ctrl_reg_offset)) {
+ return kDifBadArg;
+ }
+ if (!get_filter_enable_bit(channel, filter, &enable_bit)) {
+ return kDifBadArg;
+ }
+
+ uint32_t filter_ctrl_reg =
+ mmio_region_read32(adc_ctrl->base_addr, filter_ctrl_reg_offset);
+ *is_enabled =
+ dif_bool_to_toggle(bitfield_bit32_read(filter_ctrl_reg, enable_bit));
+
+ return kDifOk;
+}
diff --git a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
index e7b10fd..f0671d0 100644
--- a/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
+++ b/sw/device/lib/dif/dif_adc_ctrl_unittest.cc
@@ -216,5 +216,115 @@
EXPECT_EQ(is_enabled, kDifToggleDisabled);
}
+class SetFilterEnabledTest : public AdcCtrlTest {};
+
+TEST_F(SetFilterEnabledTest, NullHandle) {
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_set_enabled(
+ nullptr, kDifAdcCtrlChannel0, kDifAdcCtrlFilter3, kDifToggleEnabled));
+}
+
+TEST_F(SetFilterEnabledTest, BadChannel) {
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, static_cast<dif_adc_ctrl_channel_t>(2), kDifAdcCtrlFilter3,
+ kDifToggleEnabled));
+}
+
+TEST_F(SetFilterEnabledTest, BadFilter) {
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0,
+ static_cast<dif_adc_ctrl_filter_t>(ADC_CTRL_PARAM_NUM_ADC_FILTER),
+ kDifToggleEnabled));
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel1,
+ static_cast<dif_adc_ctrl_filter_t>(ADC_CTRL_PARAM_NUM_ADC_FILTER),
+ kDifToggleEnabled));
+}
+
+TEST_F(SetFilterEnabledTest, BadEnabled) {
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0, kDifAdcCtrlFilter3,
+ static_cast<dif_toggle_t>(2)));
+}
+
+TEST_F(SetFilterEnabledTest, Success) {
+ EXPECT_READ32(ADC_CTRL_ADC_CHN1_FILTER_CTL_2_REG_OFFSET,
+ {{ADC_CTRL_ADC_CHN1_FILTER_CTL_2_MIN_V_2_OFFSET,
+ filter_config_.min_voltage},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_MAX_V_2_OFFSET,
+ filter_config_.max_voltage},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_COND_2_BIT, true},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_EN_2_BIT, false}});
+ EXPECT_WRITE32(ADC_CTRL_ADC_CHN1_FILTER_CTL_2_REG_OFFSET,
+ {{ADC_CTRL_ADC_CHN1_FILTER_CTL_2_MIN_V_2_OFFSET,
+ filter_config_.min_voltage},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_MAX_V_2_OFFSET,
+ filter_config_.max_voltage},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_COND_2_BIT, true},
+ {ADC_CTRL_ADC_CHN1_FILTER_CTL_2_EN_2_BIT, true}});
+ EXPECT_DIF_OK(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel1, kDifAdcCtrlFilter2, kDifToggleEnabled));
+
+ EXPECT_READ32(ADC_CTRL_ADC_CHN0_FILTER_CTL_7_REG_OFFSET,
+ {{ADC_CTRL_ADC_CHN0_FILTER_CTL_7_MIN_V_7_OFFSET,
+ filter_config_.min_voltage},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_MAX_V_7_OFFSET,
+ filter_config_.max_voltage},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_COND_7_BIT, true},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_EN_7_BIT, true}});
+ EXPECT_WRITE32(ADC_CTRL_ADC_CHN0_FILTER_CTL_7_REG_OFFSET,
+ {{ADC_CTRL_ADC_CHN0_FILTER_CTL_7_MIN_V_7_OFFSET,
+ filter_config_.min_voltage},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_MAX_V_7_OFFSET,
+ filter_config_.max_voltage},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_COND_7_BIT, true},
+ {ADC_CTRL_ADC_CHN0_FILTER_CTL_7_EN_7_BIT, false}});
+ EXPECT_DIF_OK(dif_adc_ctrl_filter_set_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0, kDifAdcCtrlFilter7, kDifToggleDisabled));
+}
+
+class GetFilterEnabledTest : public AdcCtrlTest {};
+
+TEST_F(GetFilterEnabledTest, NullArgs) {
+ dif_toggle_t is_enabled;
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_get_enabled(
+ nullptr, kDifAdcCtrlChannel0, kDifAdcCtrlFilter3, &is_enabled));
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0, kDifAdcCtrlFilter3, nullptr));
+}
+
+TEST_F(GetFilterEnabledTest, BadChannel) {
+ dif_toggle_t is_enabled;
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, static_cast<dif_adc_ctrl_channel_t>(2), kDifAdcCtrlFilter3,
+ &is_enabled));
+}
+
+TEST_F(GetFilterEnabledTest, BadFilter) {
+ dif_toggle_t is_enabled;
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0,
+ static_cast<dif_adc_ctrl_filter_t>(ADC_CTRL_PARAM_NUM_ADC_FILTER),
+ &is_enabled));
+ EXPECT_DIF_BADARG(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel1,
+ static_cast<dif_adc_ctrl_filter_t>(ADC_CTRL_PARAM_NUM_ADC_FILTER),
+ &is_enabled));
+}
+
+TEST_F(GetFilterEnabledTest, Success) {
+ dif_toggle_t is_enabled;
+
+ EXPECT_READ32(ADC_CTRL_ADC_CHN0_FILTER_CTL_7_REG_OFFSET,
+ {{ADC_CTRL_ADC_CHN0_FILTER_CTL_7_EN_7_BIT, true}});
+ EXPECT_DIF_OK(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel0, kDifAdcCtrlFilter7, &is_enabled));
+ EXPECT_EQ(is_enabled, kDifToggleEnabled);
+
+ EXPECT_READ32(ADC_CTRL_ADC_CHN1_FILTER_CTL_4_REG_OFFSET, 0);
+ EXPECT_DIF_OK(dif_adc_ctrl_filter_get_enabled(
+ &adc_ctrl_, kDifAdcCtrlChannel1, kDifAdcCtrlFilter4, &is_enabled));
+ EXPECT_EQ(is_enabled, kDifToggleDisabled);
+}
+
} // namespace
} // namespace dif_adc_ctrl_unittest