// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/dif/dif_i2c.h"

#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"

#include "i2c_regs.h"  // Generated

/**
 * Performs a 32-bit integer unsigned division, rounding up. The bottom
 * 16 bits of the result are then returned.
 *
 * As usual, a divisor of 0 is still Undefined Behavior.
 */
static uint16_t round_up_divide(uint32_t a, uint32_t b) {
  return ((a - 1) / b) + 1;
}

/**
 * Reads i2c status bits from registers
 */
dif_result_t dif_i2c_get_status(const dif_i2c_t *i2c,
                                dif_i2c_status_t *status) {
  if (i2c == NULL || status == NULL) {
    return kDifBadArg;
  }

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
  status->enable_host = bitfield_bit32_read(reg, I2C_CTRL_ENABLEHOST_BIT);
  status->enable_target = bitfield_bit32_read(reg, I2C_CTRL_ENABLETARGET_BIT);
  status->line_loopback = bitfield_bit32_read(reg, I2C_CTRL_LLPBK_BIT);
  reg = mmio_region_read32(i2c->base_addr, I2C_STATUS_REG_OFFSET);
  status->fmt_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_FMTFULL_BIT);
  status->rx_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_RXFULL_BIT);
  status->fmt_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_FMTEMPTY_BIT);
  status->rx_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_RXEMPTY_BIT);
  status->host_idle = bitfield_bit32_read(reg, I2C_STATUS_HOSTIDLE_BIT);
  status->target_idle = bitfield_bit32_read(reg, I2C_STATUS_TARGETIDLE_BIT);
  status->tx_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_TXFULL_BIT);
  status->acq_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_ACQFULL_BIT);
  status->tx_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_TXEMPTY_BIT);
  status->acq_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_ACQEMPTY_BIT);

  return kDifOk;
}

/**
 * Computes default timing parameters for a particular I2C speed, given the
 * clock period, in nanoseconds.
 *
 * Returns an unspecified value for an invalid speed.
 */
static dif_i2c_config_t default_timing_for_speed(dif_i2c_speed_t speed,
                                                 uint32_t clock_period_nanos) {
  // NOTE: All constants below are lifted from Table 10 of the I2C spec.
  // All literal values are given in nanoseconds; we don't bother putting
  // these into constants since they are not used anywhere else.
  switch (speed) {
    case kDifI2cSpeedStandard:
      return (dif_i2c_config_t){
          .scl_time_high_cycles = round_up_divide(4000, clock_period_nanos),
          .scl_time_low_cycles = round_up_divide(4700, clock_period_nanos),
          .start_signal_setup_cycles =
              round_up_divide(4700, clock_period_nanos),
          .start_signal_hold_cycles = round_up_divide(4000, clock_period_nanos),
          .data_signal_setup_cycles = round_up_divide(250, clock_period_nanos),
          .data_signal_hold_cycles = 1,
          .stop_signal_setup_cycles = round_up_divide(4000, clock_period_nanos),
          .stop_signal_hold_cycles = round_up_divide(4700, clock_period_nanos),
      };
    case kDifI2cSpeedFast:
      return (dif_i2c_config_t){
          .scl_time_high_cycles = round_up_divide(600, clock_period_nanos),
          .scl_time_low_cycles = round_up_divide(1300, clock_period_nanos),
          .start_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
          .start_signal_hold_cycles = round_up_divide(600, clock_period_nanos),
          .data_signal_setup_cycles = round_up_divide(100, clock_period_nanos),
          .data_signal_hold_cycles = 1,
          .stop_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
          .stop_signal_hold_cycles = round_up_divide(1300, clock_period_nanos),
      };
    case kDifI2cSpeedFastPlus:
      return (dif_i2c_config_t){
          .scl_time_high_cycles = round_up_divide(260, clock_period_nanos),
          .scl_time_low_cycles = round_up_divide(500, clock_period_nanos),
          .start_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
          .start_signal_hold_cycles = round_up_divide(260, clock_period_nanos),
          .data_signal_setup_cycles = round_up_divide(50, clock_period_nanos),
          .data_signal_hold_cycles = 1,
          .stop_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
          .stop_signal_hold_cycles = round_up_divide(500, clock_period_nanos),
      };
    default:
      return (dif_i2c_config_t){0};
  }
}

static const uint32_t kNanosPerKBaud = 1000000;  // One million.

dif_result_t dif_i2c_compute_timing(dif_i2c_timing_config_t timing_config,
                                    dif_i2c_config_t *config) {
  if (config == NULL) {
    return kDifBadArg;
  }
  uint32_t lowest_target_device_speed_khz;
  switch (timing_config.lowest_target_device_speed) {
    case kDifI2cSpeedStandard:
      lowest_target_device_speed_khz = 100;
      break;
    case kDifI2cSpeedFast:
      lowest_target_device_speed_khz = 400;
      break;
    case kDifI2cSpeedFastPlus:
      lowest_target_device_speed_khz = 1000;
      break;
    default:
      return kDifBadArg;
  }

  // This code follows the algorithm given in
  // https://docs.opentitan.org/hw/ip/i2c/doc/index.html#initialization

  *config = default_timing_for_speed(timing_config.lowest_target_device_speed,
                                     timing_config.clock_period_nanos);

  config->rise_cycles = round_up_divide(timing_config.sda_rise_nanos,
                                        timing_config.clock_period_nanos);
  config->fall_cycles = round_up_divide(timing_config.sda_fall_nanos,
                                        timing_config.clock_period_nanos);

  uint32_t scl_period_nanos = timing_config.scl_period_nanos;
  uint32_t slowest_scl_period_nanos =
      kNanosPerKBaud / lowest_target_device_speed_khz;
  if (scl_period_nanos < slowest_scl_period_nanos) {
    scl_period_nanos = slowest_scl_period_nanos;
  }
  uint16_t scl_period_cycles =
      round_up_divide(scl_period_nanos, timing_config.clock_period_nanos);

  // Lengthen the SCL high period to accommodate the desired SCL period.
  uint16_t lengthened_high_cycles = scl_period_cycles -
                                    config->scl_time_low_cycles -
                                    config->rise_cycles - config->fall_cycles;
  if (lengthened_high_cycles > config->scl_time_high_cycles) {
    config->scl_time_high_cycles = lengthened_high_cycles;
  }

  return kDifOk;
}

dif_result_t dif_i2c_configure(const dif_i2c_t *i2c, dif_i2c_config_t config) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t timing0 = 0;
  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_THIGH_FIELD,
                                   config.scl_time_high_cycles);
  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_TLOW_FIELD,
                                   config.scl_time_low_cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMING0_REG_OFFSET, timing0);

  uint32_t timing1 = 0;
  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_R_FIELD,
                                   config.rise_cycles);
  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_F_FIELD,
                                   config.fall_cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMING1_REG_OFFSET, timing1);

  uint32_t timing2 = 0;
  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_TSU_STA_FIELD,
                                   config.start_signal_setup_cycles);
  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_THD_STA_FIELD,
                                   config.start_signal_hold_cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMING2_REG_OFFSET, timing2);

  uint32_t timing3 = 0;
  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_TSU_DAT_FIELD,
                                   config.data_signal_setup_cycles);
  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_THD_DAT_FIELD,
                                   config.data_signal_hold_cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMING3_REG_OFFSET, timing3);

  uint32_t timing4 = 0;
  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_TSU_STO_FIELD,
                                   config.stop_signal_setup_cycles);
  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_T_BUF_FIELD,
                                   config.stop_signal_hold_cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMING4_REG_OFFSET, timing4);

  return kDifOk;
}

dif_result_t dif_i2c_reset_rx_fifo(const dif_i2c_t *i2c) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_RXRST_BIT, true);
  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_reset_fmt_fifo(const dif_i2c_t *i2c) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_FMTRST_BIT, true);
  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_reset_tx_fifo(const dif_i2c_t *i2c) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_TXRST_BIT, true);
  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_reset_acq_fifo(const dif_i2c_t *i2c) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_ACQRST_BIT, true);
  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_set_watermarks(const dif_i2c_t *i2c,
                                    dif_i2c_level_t rx_level,
                                    dif_i2c_level_t fmt_level) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  ptrdiff_t rx_level_value;
  switch (rx_level) {
    case kDifI2cLevel1Byte:
      rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL1;
      break;
    case kDifI2cLevel4Byte:
      rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL4;
      break;
    case kDifI2cLevel8Byte:
      rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL8;
      break;
    case kDifI2cLevel16Byte:
      rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL16;
      break;
    case kDifI2cLevel30Byte:
      rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL30;
      break;
    default:
      return kDifBadArg;
  }

  ptrdiff_t fmt_level_value;
  switch (fmt_level) {
    case kDifI2cLevel1Byte:
      fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL1;
      break;
    case kDifI2cLevel4Byte:
      fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL4;
      break;
    case kDifI2cLevel8Byte:
      fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL8;
      break;
    case kDifI2cLevel16Byte:
      fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL16;
      break;
    default:
      return kDifBadArg;
  }

  uint32_t ctrl_value =
      mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
  ctrl_value = bitfield_field32_write(ctrl_value, I2C_FIFO_CTRL_RXILVL_FIELD,
                                      rx_level_value);
  ctrl_value = bitfield_field32_write(ctrl_value, I2C_FIFO_CTRL_FMTILVL_FIELD,
                                      fmt_level_value);
  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, ctrl_value);

  return kDifOk;
}

dif_result_t dif_i2c_host_set_enabled(const dif_i2c_t *i2c,
                                      dif_toggle_t state) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  if (!dif_is_valid_toggle(state)) {
    return kDifBadArg;
  }
  bool flag = dif_toggle_to_bool(state);

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_CTRL_ENABLEHOST_BIT, flag);
  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_device_set_enabled(const dif_i2c_t *i2c,
                                        dif_toggle_t state) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  if (!dif_is_valid_toggle(state)) {
    return kDifBadArg;
  }
  bool flag = dif_toggle_to_bool(state);

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_CTRL_ENABLETARGET_BIT, flag);
  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_line_loopback_set_enabled(const dif_i2c_t *i2c,
                                               dif_toggle_t state) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  if (!dif_is_valid_toggle(state)) {
    return kDifBadArg;
  }
  bool flag = dif_toggle_to_bool(state);

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_CTRL_LLPBK_BIT, flag);
  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);

  return kDifOk;
}
dif_result_t dif_i2c_override_set_enabled(const dif_i2c_t *i2c,
                                          dif_toggle_t state) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  if (!dif_is_valid_toggle(state)) {
    return kDifBadArg;
  }
  bool flag = dif_toggle_to_bool(state);

  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
  reg = bitfield_bit32_write(reg, I2C_OVRD_TXOVRDEN_BIT, flag);
  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, reg);

  return kDifOk;
}

dif_result_t dif_i2c_override_drive_pins(const dif_i2c_t *i2c, bool scl,
                                         bool sda) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t override_val =
      mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SCLVAL_BIT, scl);
  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SDAVAL_BIT, sda);
  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, override_val);

  return kDifOk;
}

dif_result_t dif_i2c_override_sample_pins(const dif_i2c_t *i2c,
                                          uint16_t *scl_samples,
                                          uint16_t *sda_samples) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t samples = mmio_region_read32(i2c->base_addr, I2C_VAL_REG_OFFSET);
  if (scl_samples != NULL) {
    *scl_samples = bitfield_field32_read(samples, I2C_VAL_SCL_RX_FIELD);
  }

  if (sda_samples != NULL) {
    *sda_samples = bitfield_field32_read(samples, I2C_VAL_SDA_RX_FIELD);
  }

  return kDifOk;
}

dif_result_t dif_i2c_get_fifo_levels(const dif_i2c_t *i2c,
                                     uint8_t *fmt_fifo_level,
                                     uint8_t *rx_fifo_level,
                                     uint8_t *tx_fifo_level,
                                     uint8_t *acq_fifo_level) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t values =
      mmio_region_read32(i2c->base_addr, I2C_FIFO_STATUS_REG_OFFSET);
  if (fmt_fifo_level != NULL) {
    *fmt_fifo_level =
        bitfield_field32_read(values, I2C_FIFO_STATUS_FMTLVL_FIELD);
  }
  if (rx_fifo_level != NULL) {
    *rx_fifo_level = bitfield_field32_read(values, I2C_FIFO_STATUS_RXLVL_FIELD);
  }
  if (tx_fifo_level != NULL) {
    *tx_fifo_level = bitfield_field32_read(values, I2C_FIFO_STATUS_TXLVL_FIELD);
  }
  if (acq_fifo_level != NULL) {
    *acq_fifo_level =
        bitfield_field32_read(values, I2C_FIFO_STATUS_ACQLVL_FIELD);
  }

  return kDifOk;
}

dif_result_t dif_i2c_read_byte(const dif_i2c_t *i2c, uint8_t *byte) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t values = mmio_region_read32(i2c->base_addr, I2C_RDATA_REG_OFFSET);
  if (byte != NULL) {
    *byte = bitfield_field32_read(values, I2C_RDATA_RDATA_FIELD);
  }

  return kDifOk;
}

dif_result_t dif_i2c_write_byte_raw(const dif_i2c_t *i2c, uint8_t byte,
                                    dif_i2c_fmt_flags_t flags) {
  if (i2c == NULL) {
    return kDifBadArg;
  }
  // Validate that "write only" flags and "read only" flags are not set
  // simultaneously.
  bool has_write_flags = flags.start || flags.suppress_nak_irq;
  bool has_read_flags = flags.read || flags.read_cont;
  if (has_write_flags && has_read_flags) {
    return kDifBadArg;
  }
  // Also, read_cont requires read.
  if (flags.read_cont && !flags.read) {
    return kDifBadArg;
  }

  uint32_t fmt_byte = 0;
  fmt_byte = bitfield_field32_write(fmt_byte, I2C_FDATA_FBYTE_FIELD, byte);
  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_START_BIT, flags.start);
  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_STOP_BIT, flags.stop);
  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_READ_BIT, flags.read);
  fmt_byte =
      bitfield_bit32_write(fmt_byte, I2C_FDATA_RCONT_BIT, flags.read_cont);
  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_NAKOK_BIT,
                                  flags.suppress_nak_irq);
  mmio_region_write32(i2c->base_addr, I2C_FDATA_REG_OFFSET, fmt_byte);

  return kDifOk;
}

dif_result_t dif_i2c_write_byte(const dif_i2c_t *i2c, uint8_t byte,
                                dif_i2c_fmt_t code, bool suppress_nak_irq) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  // Validate that `suppress_nak_irq` has not been mixed with an Rx code.
  if (suppress_nak_irq) {
    switch (code) {
      case kDifI2cFmtRx:
      case kDifI2cFmtRxContinue:
      case kDifI2cFmtRxStop:
        return kDifBadArg;
      default:
        break;
    }
  }

  // Convert the format code into flags.
  dif_i2c_fmt_flags_t flags = {.suppress_nak_irq = suppress_nak_irq};
  switch (code) {
    case kDifI2cFmtStart:
      flags.start = true;
      break;
    case kDifI2cFmtTx:
      break;
    case kDifI2cFmtTxStop:
      flags.stop = true;
      break;
    case kDifI2cFmtRx:
      flags.read = true;
      break;
    case kDifI2cFmtRxContinue:
      flags.read = true;
      flags.read_cont = true;
      break;
    case kDifI2cFmtRxStop:
      flags.read = true;
      flags.stop = true;
      break;
    default:
      return kDifBadArg;
  }

  return dif_i2c_write_byte_raw(i2c, byte, flags);
}

dif_result_t dif_i2c_transmit_byte(const dif_i2c_t *i2c, uint8_t byte) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t tx_byte = 0;
  tx_byte = bitfield_field32_write(tx_byte, I2C_TXDATA_TXDATA_FIELD, byte);
  mmio_region_write32(i2c->base_addr, I2C_TXDATA_REG_OFFSET, tx_byte);

  return kDifOk;
}

dif_result_t dif_i2c_acquire_byte(const dif_i2c_t *i2c, uint8_t *byte,
                                  dif_i2c_signal_t *signal) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t acq_byte =
      mmio_region_read32(i2c->base_addr, I2C_ACQDATA_REG_OFFSET);
  if (byte != NULL) {
    *byte = bitfield_field32_read(acq_byte, I2C_ACQDATA_ABYTE_FIELD);
  }
  if (signal != NULL) {
    *signal = bitfield_field32_read(acq_byte, I2C_ACQDATA_SIGNAL_FIELD);
  }
  return kDifOk;
}

dif_result_t dif_i2c_enable_clock_stretching_timeout(const dif_i2c_t *i2c,
                                                     dif_toggle_t enable,
                                                     uint32_t cycles) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  if (!dif_is_valid_toggle(enable)) {
    return kDifBadArg;
  }
  bool flag = dif_toggle_to_bool(enable);

  uint32_t config = 0;
  config = bitfield_bit32_write(config, I2C_TIMEOUT_CTRL_EN_BIT, flag);
  config = bitfield_field32_write(config, I2C_TIMEOUT_CTRL_VAL_FIELD, cycles);
  mmio_region_write32(i2c->base_addr, I2C_TIMEOUT_CTRL_REG_OFFSET, config);
  return kDifOk;
}

dif_result_t dif_i2c_set_device_id(const dif_i2c_t *i2c, dif_i2c_id_t *id0,
                                   dif_i2c_id_t *id1) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  uint32_t config = 0;
  if (id0 != NULL) {
    config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS0_FIELD,
                                    id0->address);
    config =
        bitfield_field32_write(config, I2C_TARGET_ID_MASK0_FIELD, id0->mask);
  } else {
    // Don't listen by default
    config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS0_FIELD, 0x7f);
  }

  if (id1 != NULL) {
    config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS1_FIELD,
                                    id1->address);
    config =
        bitfield_field32_write(config, I2C_TARGET_ID_MASK1_FIELD, id1->mask);
  } else {
    // Don't listen by default
    config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS1_FIELD, 0x7f);
  }

  mmio_region_write32(i2c->base_addr, I2C_TARGET_ID_REG_OFFSET, config);
  return kDifOk;
}

dif_result_t dif_i2c_set_host_timeout(const dif_i2c_t *i2c, uint32_t cycles) {
  if (i2c == NULL) {
    return kDifBadArg;
  }

  mmio_region_write32(i2c->base_addr, I2C_HOST_TIMEOUT_CTRL_REG_OFFSET, cycles);
  return kDifOk;
}
