5#include "sw/device/lib/testing/i2c_testutils.h"
11#include "hw/top/dt/i2c.h"
12#include "hw/top/dt/pinmux.h"
19#include "sw/device/lib/testing/pinmux_testutils.h"
20#include "sw/device/lib/testing/test_framework/check.h"
22#include "hw/top/i2c_regs.h"
24#define MODULE_ID MAKE_MODULE_ID('i', 'i', 't')
36 .suppress_nak_irq =
false};
44static dt_i2c_t get_i2c_instance(uint8_t i2c_idx) {
62static status_t get_i2c_pads_for_platform(
dt_i2c_t i2c_dt,
63 i2c_pinmux_platform_id_t platform,
66#if defined(OPENTITAN_IS_DARJEELING)
69 return INVALID_ARGUMENT();
73#elif defined(OPENTITAN_IS_EARLGREY) || defined(OPENTITAN_IS_ENGLISHBREAKFAST)
76 case I2cPinmuxPlatformIdSilicon:
77 case I2cPinmuxPlatformIdCw340:
78 case I2cPinmuxPlatformIdHyper310:
82 case I2cPinmuxPlatformIdDvsim:
99 return INVALID_ARGUMENT();
102 case I2cPinmuxPlatformIdCw310Pmod:
107 return INVALID_ARGUMENT();
110 return UNIMPLEMENTED();
116status_t i2c_testutils_write(
const dif_i2c_t *i2c, uint8_t addr,
117 size_t byte_count,
const uint8_t *data,
122 TRY_CHECK(byte_count > 0);
126 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cWrite;
127 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
130 flags = kDefaultFlags;
131 if (byte_count > 1) {
132 TRY(dif_i2c_write_bytes_raw(i2c, byte_count - 1, data, flags));
135 flags.
stop = !skip_stop;
136 TRY(dif_i2c_write_byte_raw(i2c, data[byte_count - 1], flags));
142status_t i2c_testutils_issue_read(
const dif_i2c_t *i2c, uint8_t addr,
143 uint8_t byte_count) {
150 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cRead;
151 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
153 TRY(i2c_testutils_wait_transaction_finish(i2c));
154 dif_i2c_controller_halt_events_t halt_events = {0};
155 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
158 flags = kDefaultFlags;
162 TRY(dif_i2c_write_byte_raw(i2c, byte_count, flags));
165 TRY(dif_i2c_reset_fmt_fifo(i2c));
166 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
174status_t i2c_testutils_read(
const dif_i2c_t *i2c, uint8_t addr,
175 size_t byte_count, uint8_t *data,
size_t timeout) {
176 uint32_t nak_count = 0;
180 dif_i2c_controller_halt_events_t halt_events = {0};
181 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
182 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
183 TRY(dif_i2c_reset_rx_fifo(i2c));
189 I2C_PARAM_FIFO_DEPTH < UINT8_MAX ? I2C_PARAM_FIFO_DEPTH : UINT8_MAX;
190 uint8_t chunk = (uint8_t)(byte_count < max_chunk ? byte_count : max_chunk);
193 while (TRY(i2c_testutils_issue_read(i2c, addr, chunk))) {
195 if (ibex_timeout_check(&timer)) {
196 return DEADLINE_EXCEEDED();
201 TRY(dif_i2c_read_bytes(i2c, chunk, data));
205 }
while (byte_count > 0);
207 TRY(i2c_testutils_wait_transaction_finish(i2c));
208 return OK_STATUS((int32_t)nak_count);
211status_t i2c_testutils_target_check_start(
const dif_i2c_t *i2c, uint8_t *addr) {
213 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
214 TRY_CHECK(acq_fifo_lvl > 1);
218 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
223 return OK_STATUS(
byte & kI2cRead);
226status_t i2c_testutils_target_check_end(
const dif_i2c_t *i2c,
227 uint8_t *cont_byte) {
229 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
230 TRY_CHECK(acq_fifo_lvl >= 1);
234 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
238 return OK_STATUS(
false);
240 TRY_CHECK(cont_byte != NULL);
244 return OK_STATUS(
true);
247status_t i2c_testutils_target_read(
const dif_i2c_t *i2c, uint16_t byte_count,
248 const uint8_t *data) {
250 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, &tx_fifo_lvl, &acq_fifo_lvl));
252 TRY_CHECK(tx_fifo_lvl + byte_count <= I2C_PARAM_FIFO_DEPTH);
253 TRY_CHECK(acq_fifo_lvl + 2 <= I2C_PARAM_FIFO_DEPTH);
255 for (uint16_t i = 0; i < byte_count; ++i) {
256 TRY(dif_i2c_transmit_byte(i2c, data[i]));
262status_t i2c_testutils_target_check_read(
const dif_i2c_t *i2c, uint8_t *addr,
263 uint8_t *cont_byte) {
264 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
265 TRY_CHECK(dir == kI2cRead);
267 return i2c_testutils_target_check_end(i2c, cont_byte);
270status_t i2c_testutils_target_write(
const dif_i2c_t *i2c, uint16_t byte_count) {
272 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
273 TRY_CHECK(acq_fifo_lvl + 2 + byte_count <= I2C_PARAM_FIFO_DEPTH);
279status_t i2c_testutils_target_check_write(
const dif_i2c_t *i2c,
280 uint16_t byte_count, uint8_t *addr,
281 uint8_t *bytes, uint8_t *cont_byte) {
283 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
284 TRY_CHECK(acq_fifo_lvl >= 2 + byte_count);
286 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
287 TRY_CHECK(dir == kI2cWrite);
289 for (uint16_t i = 0; i < byte_count; ++i) {
291 TRY(dif_i2c_acquire_byte(i2c, bytes + i, &signal));
297 return i2c_testutils_target_check_end(i2c, cont_byte);
300status_t i2c_testutils_select_pinmux(
const dif_pinmux_t *pinmux, uint8_t i2c_id,
301 i2c_pinmux_platform_id_t platform) {
302 TRY_CHECK(platform < I2cPinmuxPlatformIdCount,
"Platform out of bounds");
304 dt_i2c_t i2c_dt = get_i2c_instance(i2c_id);
305 TRY_CHECK(i2c_dt <
kDtI2cCount,
"I2C index out of bounds");
313 TRY(get_i2c_pads_for_platform(i2c_dt, platform, &sda_pad, &scl_pad));
324status_t i2c_testutils_detach_pinmux(
const dif_pinmux_t *pinmux,
326 dt_i2c_t i2c_dt = get_i2c_instance(i2c_id);
327 TRY_CHECK(i2c_dt <
kDtI2cCount,
"I2C index out of bounds");
343 uint32_t sda_rise_nanos,
344 uint32_t sda_fall_nanos) {
345 uint32_t speed_khz = 0;
348 LOG_INFO(
"Setting i2c to %s mode.",
"Standard (100kHz)");
352 LOG_INFO(
"Setting i2c to %s mode.",
"Fast (400kHz)");
356 LOG_INFO(
"Setting i2c to %s mode.",
"FastPlus (1000kHz)");
364 .lowest_target_device_speed = speed,
365 .clock_period_nanos =
367 .sda_rise_nanos = sda_rise_nanos,
368 .sda_fall_nanos = sda_fall_nanos,
369 .scl_period_nanos = 1000000 / speed_khz};
372 TRY(dif_i2c_get_status(i2c, &
status));
377 TRY(dif_i2c_compute_timing(timing_config, &config));
379 LOG_INFO(
"period:%d nanos, cycles={fall=%d, rise=%d, hi=%d, lo=%d}",
381 config.rise_cycles, config.scl_time_high_cycles,
382 config.scl_time_low_cycles);
384 TRY(dif_i2c_configure(i2c, config));
393status_t i2c_testutils_wait_host_idle(
const dif_i2c_t *i2c) {
396 TRY(dif_i2c_get_status(i2c, &
status));
397 }
while (!
status.host_idle);
401status_t i2c_testutils_wait_transaction_finish(
const dif_i2c_t *i2c) {
403 bool controller_halted =
false;
406 &controller_halted));
407 if (controller_halted) {
410 TRY(dif_i2c_get_status(i2c, &
status));
411 }
while (!
status.fmt_fifo_empty);