Software APIs
i2c_host_override_test.c
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 
5 #include <assert.h>
6 
15 #include "sw/device/lib/testing/i2c_testutils.h"
16 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
20 
22 #include "i2c_regs.h" // Generated.
23 
24 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
25  "This test assumes the target platform is little endian.");
26 
27 OTTF_DEFINE_TEST_CONFIG();
28 
29 enum {
30  kDefaultTimeoutMicros = 50000,
31 };
32 
33 // Test harness will backdoor write to this variable.
34 static volatile uint8_t backdoor_start = false;
35 
36 static dif_rv_core_ibex_t rv_core_ibex;
37 static dif_pinmux_t pinmux;
38 static dif_i2c_t i2c;
39 
40 const static volatile uint8_t kBitbangData = 0x56;
41 
42 static status_t test_override(void) {
43  // Start bit
44  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/1, /*sda=*/1));
45  busy_spin_micros(15);
46  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/1, /*sda=*/0));
47  busy_spin_micros(15);
48  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/0, /*sda=*/0));
49 
50  const uint8_t bits = sizeof(kBitbangData) * 8;
51  uint16_t sda = 0;
52  uint16_t data = (uint8_t)(kBitbangData << 1); // Add ack.
53  for (int i = 0; i <= bits; ++i) {
54  busy_spin_micros(15);
55  sda = (data >> (bits - i)) & 0x01;
56  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/0, sda));
57  busy_spin_micros(15);
58  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/1, sda));
59  busy_spin_micros(30);
60  if (i < bits) {
61  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/0, sda));
62  }
63  }
64 
65  // Stop bit
66  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/1, /*sda=*/0));
67  busy_spin_micros(15);
68  TRY(dif_i2c_override_drive_pins(&i2c, /*scl=*/1, /*sda=*/1));
69  busy_spin_micros(15);
70 
71  return OK_STATUS();
72 }
73 
74 static status_t test_init(void) {
75  mmio_region_t base_addr =
77  TRY(dif_rv_core_ibex_init(base_addr, &rv_core_ibex));
78 
80  TRY(dif_pinmux_init(base_addr, &pinmux));
81 
82  return OK_STATUS();
83 }
84 
85 static status_t i2c_detach_instance(uint8_t i2c_instance) {
87  return i2c_testutils_detach_pinmux(&pinmux, i2c_instance);
88 }
89 
90 static status_t i2c_configure_instance(uint8_t i2c_instance) {
91  const uintptr_t kI2cBaseAddrTable[] = {TOP_EARLGREY_I2C0_BASE_ADDR,
94  LOG_INFO("%d", i2c_instance);
95  TRY_CHECK(i2c_instance < ARRAYSIZE(kI2cBaseAddrTable));
96 
97  mmio_region_t base_addr =
98  mmio_region_from_addr(kI2cBaseAddrTable[i2c_instance]);
99  TRY(dif_i2c_init(base_addr, &i2c));
100 
101  TRY(i2c_testutils_select_pinmux(&pinmux, i2c_instance,
102  I2cPinmuxPlatformIdHyper310));
103 
106  return OK_STATUS();
107 }
108 
109 bool test_main(void) {
110  status_t test_result;
111  CHECK_STATUS_OK(test_init());
112 
113  test_result = OK_STATUS();
114  for (uint8_t instance = 0; instance < 3; instance++) {
115  CHECK_STATUS_OK(i2c_configure_instance(instance));
116  OTTF_WAIT_FOR(backdoor_start, kDefaultTimeoutMicros);
117  // Wait 1ms for the host start sampling before we start transmission.
118  busy_spin_micros(50000);
119  EXECUTE_TEST(test_result, test_override);
120  backdoor_start = false;
121  CHECK_STATUS_OK(i2c_detach_instance(instance));
122  }
123 
124  return status_ok(test_result);
125 }