5#include "sw/device/lib/testing/i2c_testutils.h"
11#include "hw/top/dt/dt_i2c.h"
12#include "hw/top/dt/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) {
45 if (i2c_idx >= kDtI2cCount) {
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 I2cPinmuxPlatformIdHyper310:
80 case I2cPinmuxPlatformIdDvsim:
97 return INVALID_ARGUMENT();
100 case I2cPinmuxPlatformIdCw310Pmod:
105 return INVALID_ARGUMENT();
108 return UNIMPLEMENTED();
114status_t i2c_testutils_write(
const dif_i2c_t *i2c, uint8_t addr,
115 size_t byte_count,
const uint8_t *data,
120 TRY_CHECK(byte_count > 0);
124 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cWrite;
125 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
128 flags = kDefaultFlags;
129 if (byte_count > 1) {
130 TRY(dif_i2c_write_bytes_raw(i2c, byte_count - 1, data, flags));
133 flags.
stop = !skip_stop;
134 TRY(dif_i2c_write_byte_raw(i2c, data[byte_count - 1], flags));
140status_t i2c_testutils_issue_read(
const dif_i2c_t *i2c, uint8_t addr,
141 uint8_t byte_count) {
148 data_frame = (uint8_t)(addr << 1) | (uint8_t)kI2cRead;
149 TRY(dif_i2c_write_byte_raw(i2c, data_frame, flags));
151 TRY(i2c_testutils_wait_transaction_finish(i2c));
152 dif_i2c_controller_halt_events_t halt_events = {0};
153 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
156 flags = kDefaultFlags;
160 TRY(dif_i2c_write_byte_raw(i2c, byte_count, flags));
163 TRY(dif_i2c_reset_fmt_fifo(i2c));
164 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
172status_t i2c_testutils_read(
const dif_i2c_t *i2c, uint8_t addr,
173 size_t byte_count, uint8_t *data,
size_t timeout) {
174 uint32_t nak_count = 0;
178 dif_i2c_controller_halt_events_t halt_events = {0};
179 TRY(dif_i2c_get_controller_halt_events(i2c, &halt_events));
180 TRY(dif_i2c_clear_controller_halt_events(i2c, halt_events));
181 TRY(dif_i2c_reset_rx_fifo(i2c));
187 I2C_PARAM_FIFO_DEPTH < UINT8_MAX ? I2C_PARAM_FIFO_DEPTH : UINT8_MAX;
188 uint8_t chunk = (uint8_t)(byte_count < max_chunk ? byte_count : max_chunk);
191 while (TRY(i2c_testutils_issue_read(i2c, addr, chunk))) {
193 if (ibex_timeout_check(&timer)) {
194 return DEADLINE_EXCEEDED();
199 TRY(dif_i2c_read_bytes(i2c, chunk, data));
203 }
while (byte_count > 0);
205 TRY(i2c_testutils_wait_transaction_finish(i2c));
206 return OK_STATUS((int32_t)nak_count);
209status_t i2c_testutils_target_check_start(
const dif_i2c_t *i2c, uint8_t *addr) {
211 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
212 TRY_CHECK(acq_fifo_lvl > 1);
216 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
221 return OK_STATUS(
byte & kI2cRead);
224status_t i2c_testutils_target_check_end(
const dif_i2c_t *i2c,
225 uint8_t *cont_byte) {
227 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
228 TRY_CHECK(acq_fifo_lvl >= 1);
232 TRY(dif_i2c_acquire_byte(i2c, &
byte, &signal));
236 return OK_STATUS(
false);
238 TRY_CHECK(cont_byte != NULL);
242 return OK_STATUS(
true);
245status_t i2c_testutils_target_read(
const dif_i2c_t *i2c, uint16_t byte_count,
246 const uint8_t *data) {
248 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, &tx_fifo_lvl, &acq_fifo_lvl));
250 TRY_CHECK(tx_fifo_lvl + byte_count <= I2C_PARAM_FIFO_DEPTH);
251 TRY_CHECK(acq_fifo_lvl + 2 <= I2C_PARAM_FIFO_DEPTH);
253 for (uint16_t i = 0; i < byte_count; ++i) {
254 TRY(dif_i2c_transmit_byte(i2c, data[i]));
260status_t i2c_testutils_target_check_read(
const dif_i2c_t *i2c, uint8_t *addr,
261 uint8_t *cont_byte) {
262 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
263 TRY_CHECK(dir == kI2cRead);
265 return i2c_testutils_target_check_end(i2c, cont_byte);
268status_t i2c_testutils_target_write(
const dif_i2c_t *i2c, uint16_t byte_count) {
270 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
271 TRY_CHECK(acq_fifo_lvl + 2 + byte_count <= I2C_PARAM_FIFO_DEPTH);
277status_t i2c_testutils_target_check_write(
const dif_i2c_t *i2c,
278 uint16_t byte_count, uint8_t *addr,
279 uint8_t *bytes, uint8_t *cont_byte) {
281 TRY(dif_i2c_get_fifo_levels(i2c, NULL, NULL, NULL, &acq_fifo_lvl));
282 TRY_CHECK(acq_fifo_lvl >= 2 + byte_count);
284 int32_t dir = TRY(i2c_testutils_target_check_start(i2c, addr));
285 TRY_CHECK(dir == kI2cWrite);
287 for (uint16_t i = 0; i < byte_count; ++i) {
289 TRY(dif_i2c_acquire_byte(i2c, bytes + i, &signal));
295 return i2c_testutils_target_check_end(i2c, cont_byte);
298status_t i2c_testutils_select_pinmux(
const dif_pinmux_t *pinmux, uint8_t i2c_id,
299 i2c_pinmux_platform_id_t platform) {
300 TRY_CHECK(platform < I2cPinmuxPlatformIdCount,
"Platform out of bounds");
302 dt_i2c_t i2c_dt = get_i2c_instance(i2c_id);
303 TRY_CHECK(i2c_dt < kDtI2cCount,
"I2C index out of bounds");
311 TRY(get_i2c_pads_for_platform(i2c_dt, platform, &sda_pad, &scl_pad));
322status_t i2c_testutils_detach_pinmux(
const dif_pinmux_t *pinmux,
324 dt_i2c_t i2c_dt = get_i2c_instance(i2c_id);
325 TRY_CHECK(i2c_dt < kDtI2cCount,
"I2C index out of bounds");
341 uint32_t sda_rise_nanos,
342 uint32_t sda_fall_nanos) {
343 uint32_t speed_khz = 0;
346 LOG_INFO(
"Setting i2c to %s mode.",
"Standard (100kHz)");
350 LOG_INFO(
"Setting i2c to %s mode.",
"Fast (400kHz)");
354 LOG_INFO(
"Setting i2c to %s mode.",
"FastPlus (1000kHz)");
362 .lowest_target_device_speed = speed,
363 .clock_period_nanos =
365 .sda_rise_nanos = sda_rise_nanos,
366 .sda_fall_nanos = sda_fall_nanos,
367 .scl_period_nanos = 1000000 / speed_khz};
370 TRY(dif_i2c_get_status(i2c, &
status));
375 TRY(dif_i2c_compute_timing(timing_config, &config));
377 LOG_INFO(
"period:%d nanos, cycles={fall=%d, rise=%d, hi=%d, lo=%d}",
379 config.rise_cycles, config.scl_time_high_cycles,
380 config.scl_time_low_cycles);
382 TRY(dif_i2c_configure(i2c, config));
391status_t i2c_testutils_wait_host_idle(
const dif_i2c_t *i2c) {
394 TRY(dif_i2c_get_status(i2c, &
status));
395 }
while (!
status.host_idle);
399status_t i2c_testutils_wait_transaction_finish(
const dif_i2c_t *i2c) {
401 bool controller_halted =
false;
404 &controller_halted));
405 if (controller_halted) {
408 TRY(dif_i2c_get_status(i2c, &
status));
409 }
while (!
status.fmt_fifo_empty);