Software APIs
dif_gpio_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 
7 #include <limits>
8 
9 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/mock_mmio.h"
13 
14 #include "gpio_regs.h" // Generated
15 
16 namespace dif_gpio_unittest {
17 namespace {
18 
19 // Convenience constants and functions
20 constexpr uint32_t kAllOnes = std::numeric_limits<uint32_t>::max();
21 
22 uint32_t AllZerosExcept(uint32_t index) { return 1 << index; }
23 
24 uint32_t AllOnesExcept(uint32_t index) { return ~AllZerosExcept(index); }
25 
26 // Base class for the test fixtures in this file.
27 class GpioTest : public testing::Test, public mock_mmio::MmioTest {};
28 
29 // Base class for the rest of the tests in this file, provides a
30 // `dif_gpio_t` instance.
31 class GpioTestInitialized : public GpioTest {
32  protected:
33  const dif_gpio_t gpio_ = {.base_addr = dev().region()};
34 };
35 
36 // Reset tests
37 class ResetTest : public GpioTestInitialized {};
38 
39 TEST_F(ResetTest, BadArgs) { EXPECT_DIF_BADARG(dif_gpio_reset(nullptr)); }
40 
41 TEST_F(ResetTest, Reset) {
42  EXPECT_WRITE32(GPIO_INTR_ENABLE_REG_OFFSET, 0);
43  EXPECT_WRITE32(GPIO_DIRECT_OE_REG_OFFSET, 0);
44  EXPECT_WRITE32(GPIO_DIRECT_OUT_REG_OFFSET, 0);
45  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, 0);
46  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, 0);
47  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, 0);
48  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, 0);
49  EXPECT_WRITE32(GPIO_CTRL_EN_INPUT_FILTER_REG_OFFSET, 0);
50  EXPECT_WRITE32(GPIO_INTR_STATE_REG_OFFSET, kAllOnes);
51 
53 }
54 
55 // Read tests
56 class ReadTest : public GpioTestInitialized {};
57 
58 TEST_F(ReadTest, BadArgs) {
59  dif_gpio_state_t out_arg_uint32_t;
60  bool out_arg_bool;
61 
62  EXPECT_DIF_BADARG(dif_gpio_read_all(nullptr, &out_arg_uint32_t));
63  EXPECT_DIF_BADARG(dif_gpio_read_all(&gpio_, nullptr));
64  EXPECT_DIF_BADARG(dif_gpio_read_all(nullptr, nullptr));
65 
66  EXPECT_DIF_BADARG(dif_gpio_read(nullptr, 0, &out_arg_bool));
67  EXPECT_DIF_BADARG(dif_gpio_read(&gpio_, 0, nullptr));
68  EXPECT_DIF_BADARG(dif_gpio_read(nullptr, 0, nullptr));
69  EXPECT_DIF_BADARG(dif_gpio_read(&gpio_, kDifGpioNumPins, &out_arg_bool));
70 }
71 
72 TEST_F(ReadTest, AllPins) {
73  constexpr uint32_t kVal = 0xA5A5A5A5;
74  EXPECT_READ32(GPIO_DATA_IN_REG_OFFSET, kVal);
75 
76  dif_gpio_state_t pin_values = 0;
77  EXPECT_DIF_OK(dif_gpio_read_all(&gpio_, &pin_values));
78  EXPECT_EQ(pin_values, kVal);
79 }
80 
81 TEST_F(ReadTest, SinglePin) {
82  for (uint32_t pin = 0; pin < 32; ++pin) {
83  for (const bool exp_pin_val : {true, false}) {
84  const uint32_t reg_val =
85  exp_pin_val ? AllZerosExcept(pin) : AllOnesExcept(pin);
86  EXPECT_READ32(GPIO_DATA_IN_REG_OFFSET, reg_val);
87 
88  bool pin_val = !exp_pin_val;
89  EXPECT_DIF_OK(dif_gpio_read(&gpio_, pin, &pin_val));
90  EXPECT_EQ(pin_val, exp_pin_val);
91  }
92  }
93 }
94 
95 // Write tests
96 class WriteTest : public GpioTestInitialized {};
97 
98 TEST_F(WriteTest, BadArgs) {
99  EXPECT_DIF_BADARG(dif_gpio_write_all(nullptr, kAllOnes));
100  EXPECT_DIF_BADARG(dif_gpio_write(nullptr, 0, true));
101  EXPECT_DIF_BADARG(dif_gpio_write_masked(nullptr, kAllOnes, kAllOnes));
103 }
104 
105 TEST_F(WriteTest, AllPins) {
106  constexpr uint32_t kVal = 0xA5A5A5A5;
107  EXPECT_WRITE32(GPIO_DIRECT_OUT_REG_OFFSET, kVal);
108 
109  EXPECT_DIF_OK(dif_gpio_write_all(&gpio_, kVal));
110 }
111 
112 // The GPIO device provides masked bit-level atomic writes to its DIRECT_OUT
113 // and DIRECT_OE registers. A 32-bit mask and a 32-bit value
114 //
115 // mask = [mask_upper, mask_lower],
116 // bits: 31......16 15.......0
117 //
118 // val = [val_upper, val_lower]
119 // bits: 31.....16 15......0
120 //
121 // are written to the registers such that
122 //
123 // MASKED_*_UPPER = [mask_upper, val_upper]
124 // bits: 31......16 15......0
125 //
126 // MASKED_*_LOWER = [mask_lower, val_lower]
127 // bits: 31......16 15......0
128 //
129 // Functions that operate on individual pins basically work in the same way
130 // after creating the equivalent mask and value.
131 
132 TEST_F(WriteTest, SinglePin) {
133  EXPECT_WRITE32(GPIO_MASKED_OUT_LOWER_REG_OFFSET, {{16, 1}, {0, 1}});
134  EXPECT_DIF_OK(dif_gpio_write(&gpio_, 0, true));
135 
136  EXPECT_WRITE32(GPIO_MASKED_OUT_LOWER_REG_OFFSET, {{31, 1}, {15, 0}});
137  EXPECT_DIF_OK(dif_gpio_write(&gpio_, 15, false));
138 
139  EXPECT_WRITE32(GPIO_MASKED_OUT_UPPER_REG_OFFSET, {{16, 1}, {0, 1}});
140  EXPECT_DIF_OK(dif_gpio_write(&gpio_, 16, true));
141 
142  EXPECT_WRITE32(GPIO_MASKED_OUT_UPPER_REG_OFFSET, {{31, 1}, {15, 0}});
143  EXPECT_DIF_OK(dif_gpio_write(&gpio_, 31, false));
144 }
145 
146 TEST_F(WriteTest, Masked) {
147  EXPECT_WRITE32(GPIO_MASKED_OUT_LOWER_REG_OFFSET, 0xCDCD3322);
148  EXPECT_WRITE32(GPIO_MASKED_OUT_UPPER_REG_OFFSET, 0xABAB5544);
149  EXPECT_DIF_OK(dif_gpio_write_masked(&gpio_, 0xABABCDCD, 0x55443322));
150 
151  EXPECT_WRITE32(GPIO_MASKED_OUT_UPPER_REG_OFFSET, 0xABAB5544);
152  EXPECT_DIF_OK(dif_gpio_write_masked(&gpio_, 0xABAB0000, 0x55443322));
153 
154  EXPECT_WRITE32(GPIO_MASKED_OUT_LOWER_REG_OFFSET, 0xCDCD3322);
155  EXPECT_DIF_OK(dif_gpio_write_masked(&gpio_, 0x0000CDCD, 0x55443322));
156 }
157 
158 // Output mode tests
160 
161 TEST_F(OutputModeTest, BadArgs) {
167  dif_gpio_output_set_enabled_masked(nullptr, kAllOnes, kAllOnes));
168 }
169 
170 TEST_F(OutputModeTest, AllPins) {
171  constexpr uint32_t kVal = 0xA5A5A5A5;
172  EXPECT_WRITE32(GPIO_DIRECT_OE_REG_OFFSET, kVal);
173 
175 }
176 
177 TEST_F(OutputModeTest, SinglePin) {
178  EXPECT_WRITE32(GPIO_MASKED_OE_LOWER_REG_OFFSET, {{16, 1}, {0, 1}});
180 
181  EXPECT_WRITE32(GPIO_MASKED_OE_LOWER_REG_OFFSET, {{31, 1}, {15, 0}});
183 
184  EXPECT_WRITE32(GPIO_MASKED_OE_UPPER_REG_OFFSET, {{16, 1}, {0, 1}});
186 
187  EXPECT_WRITE32(GPIO_MASKED_OE_UPPER_REG_OFFSET, {{31, 1}, {15, 0}});
189 }
190 
191 TEST_F(OutputModeTest, Masked) {
192  EXPECT_WRITE32(GPIO_MASKED_OE_LOWER_REG_OFFSET, 0xCDCD3322);
193  EXPECT_WRITE32(GPIO_MASKED_OE_UPPER_REG_OFFSET, 0xABAB5544);
195  dif_gpio_output_set_enabled_masked(&gpio_, 0xABABCDCD, 0x55443322));
196 
197  EXPECT_WRITE32(GPIO_MASKED_OE_LOWER_REG_OFFSET, 0xCDCD3322);
199  dif_gpio_output_set_enabled_masked(&gpio_, 0x0000CDCD, 0x55443322));
200 
201  EXPECT_WRITE32(GPIO_MASKED_OE_UPPER_REG_OFFSET, 0xABAB5544);
203  dif_gpio_output_set_enabled_masked(&gpio_, 0xABAB0000, 0x55443322));
204 }
205 
206 // Input noise filter tests
208 
209 TEST_F(InputFilterTest, BadArgs) {
213  nullptr, kAllOnes, kDifToggleDisabled));
214 }
215 
216 TEST_F(InputFilterTest, MaskedEnable) {
217  constexpr uint32_t kVal = 0xABABABAB;
218  EXPECT_READ32(GPIO_CTRL_EN_INPUT_FILTER_REG_OFFSET, 0x0);
219  EXPECT_WRITE32(GPIO_CTRL_EN_INPUT_FILTER_REG_OFFSET, kVal);
220 
223 }
224 
225 TEST_F(InputFilterTest, MaskedDisable) {
226  constexpr uint32_t kVal = 0xABABABAB;
227  EXPECT_READ32(GPIO_CTRL_EN_INPUT_FILTER_REG_OFFSET, kAllOnes);
228  EXPECT_WRITE32(GPIO_CTRL_EN_INPUT_FILTER_REG_OFFSET, ~kVal);
229 
232 }
233 
234 class IrqTest : public GpioTestInitialized {
235  protected:
236  // Expectations for disabling the interrupt triggers of the pins given by
237  // `pins`.
238  void ExpectIrqTriggerMaskedDisable(uint32_t pins) {
239  EXPECT_READ32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, kAllOnes);
240  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, ~pins);
241  EXPECT_READ32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, kAllOnes);
242  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, ~pins);
243  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, kAllOnes);
244  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, ~pins);
245  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, kAllOnes);
246  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, ~pins);
247  }
248 };
249 
250 TEST_F(IrqTest, MaskedConfigTriggerEdgeRising) {
251  SCOPED_TRACE("IrqTest.MaskedConfigTriggerEdgeRising");
252  constexpr uint32_t kVal = 0xABABABAB;
253  ExpectIrqTriggerMaskedDisable(kVal);
254  EXPECT_READ32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, 0);
255  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, kVal);
256 
259 }
260 
261 TEST_F(IrqTest, MaskedConfigTriggerEdgeFalling) {
262  SCOPED_TRACE("IrqTest.MaskedConfigTriggerEdgeFalling");
263  constexpr uint32_t kVal = 0xABABABAB;
264  ExpectIrqTriggerMaskedDisable(kVal);
265  EXPECT_READ32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, 0);
266  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, kVal);
267 
270 }
271 
272 TEST_F(IrqTest, MaskedConfigTriggerLevelLow) {
273  SCOPED_TRACE("IrqTest.MaskedConfigTriggerLevelLow");
274  constexpr uint32_t kVal = 0xABABABAB;
275  ExpectIrqTriggerMaskedDisable(kVal);
276  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, 0);
277  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, kVal);
278 
281 }
282 
283 TEST_F(IrqTest, MaskedConfigTriggerLevelHigh) {
284  SCOPED_TRACE("IrqTest.MaskedConfigTriggerLevelHigh");
285  constexpr uint32_t kVal = 0xABABABAB;
286  ExpectIrqTriggerMaskedDisable(kVal);
287  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, 0);
288  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, kVal);
289 
292 }
293 
294 TEST_F(IrqTest, MaskedConfigTriggerEdgeRisingFalling) {
295  SCOPED_TRACE("IrqTest.MaskedConfigTriggerEdgeRisingFalling");
296  constexpr uint32_t kVal = 0xABABABAB;
297  ExpectIrqTriggerMaskedDisable(kVal);
298  EXPECT_READ32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, 0);
299  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, kVal);
300  EXPECT_READ32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, 0);
301  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, kVal);
302 
305 }
306 
307 TEST_F(IrqTest, MaskedConfigTriggerEdgeRisingLevelLow) {
308  SCOPED_TRACE("IrqTest.MaskedConfigTriggerEdgeRisingLevelLow");
309  constexpr uint32_t kVal = 0xABABABAB;
310  ExpectIrqTriggerMaskedDisable(kVal);
311  EXPECT_READ32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, 0);
312  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, kVal);
313  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, 0);
314  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, kVal);
315 
318 }
319 
320 TEST_F(IrqTest, MaskedConfigTriggerEdgeFallingLevelHigh) {
321  SCOPED_TRACE("IrqTest.MaskedConfigTriggerEdgeFallingLevelHigh");
322  constexpr uint32_t kVal = 0xABABABAB;
323  ExpectIrqTriggerMaskedDisable(kVal);
324  EXPECT_READ32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, 0);
325  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, kVal);
326  EXPECT_READ32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, 0);
327  EXPECT_WRITE32(GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, kVal);
328 
331 }
332 
333 TEST_F(IrqTest, MaskedConfigTriggerGeneralError) {
334  SCOPED_TRACE("IrqTest.MaskedConfigTriggerGeneralError");
335  constexpr uint32_t kVal = 0xABABABAB;
336  ExpectIrqTriggerMaskedDisable(kVal);
337 
338  EXPECT_EQ(dif_gpio_irq_set_trigger(
339  &gpio_, kVal, static_cast<dif_gpio_irq_trigger_t>(kAllOnes)),
340  kDifError);
341 }
342 
343 } // namespace
344 } // namespace dif_gpio_unittest