// 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_rstmgr.h"

#include <assert.h>
#include <stdint.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/base/multibits.h"
#include "sw/device/lib/dif/dif_base.h"

#include "rstmgr_regs.h"  // Generated.

// These assertions are only defined for the Earl Grey chip.
#if !OT_IS_ENGLISH_BREAKFAST
// This macro simplifies the `static_assert` check to make sure that the
// public reset info register bitfield matches register bits.
#define RSTMGR_RESET_INFO_CHECK(pub_name, priv_name)         \
  static_assert(kDifRstmgrResetInfo##pub_name ==             \
                    (0x1 << RSTMGR_RESET_##priv_name##_BIT), \
                "kDifRstmgrResetInfo" #pub_name              \
                " must match the register definition!")

RSTMGR_RESET_INFO_CHECK(Por, INFO_POR);
RSTMGR_RESET_INFO_CHECK(LowPowerExit, INFO_LOW_POWER_EXIT);

static_assert(kDifRstmgrResetInfoHwReq == (RSTMGR_RESET_INFO_HW_REQ_MASK
                                           << RSTMGR_RESET_INFO_HW_REQ_OFFSET),
              "kDifRstmgrResetInfoHwReq must match the register definition!");

// Turn off the static_assert to enable non-earlgrey top run
// static_assert(
//     RSTMGR_PARAM_NUM_SW_RESETS == 8,
//     "Number of software resets has changed, please update this file!");

// The Reset Manager implementation will have to be updated if the number
// of software resets grows, as it would span across multiple registers, so
// there will be multiple of Reset Enable and Reset Control registers. The
// appropriate offset from the peripheral base would then have to be
// calculated.
static_assert(
    RSTMGR_PARAM_NUM_SW_RESETS <= 32,
    "Reset Enable and Control registers span across multiple registers!");

// Make sure that the public alert info crash dump size matches the HW.
// Note that `RSTMGR_ALERT_INFO_CTRL_INDEX_MASK` implies 16 indexes ( 0 - 15
// inclusive). However, in reality it only supports 15, as
// `RSTMGR_ALERT_INFO_ATTR_CNT_AVAIL_MASK` is of the same size, but value of
// 0 indicates that there is no alert info crash dump.
static_assert(
    DIF_RSTMGR_ALERT_INFO_MAX_SIZE == RSTMGR_ALERT_INFO_CTRL_INDEX_MASK,
    "Alert info dump max size has grown, please update the public define!");
#endif  // !OT_IS_ENGLISH_BREAKFAST

/**
 * Checks whether alert_info capture is disabled.
 */
static bool alert_capture_is_locked(mmio_region_t base_addr) {
  uint32_t bitfield =
      mmio_region_read32(base_addr, RSTMGR_ALERT_REGWEN_REG_OFFSET);

  // When bit is cleared, alert capture is disabled.
  return !bitfield_bit32_read(bitfield, RSTMGR_ALERT_REGWEN_EN_BIT);
}

/**
 * Checks whether CPU info capture is disabled.
 */
static bool cpu_capture_is_locked(mmio_region_t base_addr) {
  uint32_t bitfield =
      mmio_region_read32(base_addr, RSTMGR_CPU_REGWEN_REG_OFFSET);

  // When bit is cleared, APU capture is disabled.
  return !bitfield_bit32_read(bitfield, RSTMGR_CPU_REGWEN_EN_BIT);
}

/**
 * Checks whether the software reset is disabled for a `peripheral`.
 */
static bool rstmgr_software_reset_is_locked(
    mmio_region_t base_addr, dif_rstmgr_peripheral_t peripheral) {
  return !mmio_region_read32(
      base_addr, RSTMGR_SW_RST_REGWEN_0_REG_OFFSET + 4 * peripheral);
}

/**
 * Holds or releases a `peripheral` in/from the reset state.
 */
static void rstmgr_software_reset_hold(mmio_region_t base_addr,
                                       dif_rstmgr_peripheral_t peripheral,
                                       bool hold) {
  bool value = hold ? false : true;
  mmio_region_write32(
      base_addr, RSTMGR_SW_RST_CTRL_N_0_REG_OFFSET + 4 * peripheral, value);
}

/**
 * Clears entire reset info register.
 *
 * Normal "Power On Reset" cause is also cleared. Set bit to clear.
 */
static void rstmgr_reset_info_clear(mmio_region_t base_addr) {
  mmio_region_write32(base_addr, RSTMGR_RESET_INFO_REG_OFFSET, UINT32_MAX);
}

dif_result_t dif_rstmgr_reset(const dif_rstmgr_t *handle) {
  if (handle == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  rstmgr_reset_info_clear(base_addr);

  // Set bits to stop holding all peripherals in the reset state.
  for (uint32_t i = 0; i < RSTMGR_PARAM_NUM_SW_RESETS; i++) {
    mmio_region_write32(base_addr, RSTMGR_SW_RST_CTRL_N_0_REG_OFFSET + i * 4,
                        UINT32_MAX);
  }

  return kDifOk;
}

dif_result_t dif_rstmgr_reset_lock(const dif_rstmgr_t *handle,
                                   dif_rstmgr_peripheral_t peripheral) {
  if (handle == NULL || peripheral >= RSTMGR_PARAM_NUM_SW_RESETS) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  mmio_region_write32(base_addr,
                      RSTMGR_SW_RST_REGWEN_0_REG_OFFSET + 4 * peripheral, 0);

  return kDifOk;
}

dif_result_t dif_rstmgr_reset_is_locked(const dif_rstmgr_t *handle,
                                        dif_rstmgr_peripheral_t peripheral,
                                        bool *is_locked) {
  if (handle == NULL || is_locked == NULL ||
      peripheral >= RSTMGR_PARAM_NUM_SW_RESETS) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;
  *is_locked = rstmgr_software_reset_is_locked(base_addr, peripheral);

  return kDifOk;
}

dif_result_t dif_rstmgr_reset_info_get(const dif_rstmgr_t *handle,
                                       dif_rstmgr_reset_info_bitfield_t *info) {
  if (handle == NULL || info == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;
  *info = mmio_region_read32(base_addr, RSTMGR_RESET_INFO_REG_OFFSET);

  return kDifOk;
}

dif_result_t dif_rstmgr_reset_info_clear(const dif_rstmgr_t *handle) {
  if (handle == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  rstmgr_reset_info_clear(base_addr);

  return kDifOk;
}

dif_result_t dif_rstmgr_alert_info_set_enabled(const dif_rstmgr_t *handle,
                                               dif_toggle_t state) {
  if (handle == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  if (alert_capture_is_locked(base_addr)) {
    return kDifLocked;
  }

  uint32_t enabled = (state == kDifToggleEnabled) ? 0x1 : 0x0;

  // This will clobber the `ALERT_INFO_CTRL.INDEX` field. However, the index
  // field is only relevant during the crash dump read operation, and is
  // set by the caller and not the hardware, so it is safe to clobber it.
  mmio_region_write32(base_addr, RSTMGR_ALERT_INFO_CTRL_REG_OFFSET, enabled);

  return kDifOk;
}

dif_result_t dif_rstmgr_alert_info_get_enabled(const dif_rstmgr_t *handle,
                                               dif_toggle_t *state) {
  if (handle == NULL || state == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  uint32_t reg =
      mmio_region_read32(base_addr, RSTMGR_ALERT_INFO_CTRL_REG_OFFSET);
  bool enabled = bitfield_bit32_read(reg, RSTMGR_ALERT_INFO_CTRL_EN_BIT);

  *state = enabled ? kDifToggleEnabled : kDifToggleDisabled;

  return kDifOk;
}

dif_result_t dif_rstmgr_alert_info_get_size(const dif_rstmgr_t *handle,
                                            size_t *size) {
  if (handle == NULL || size == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;
  *size = mmio_region_read32(base_addr, RSTMGR_ALERT_INFO_ATTR_REG_OFFSET);
  return kDifOk;
}

dif_result_t dif_rstmgr_alert_info_dump_read(
    const dif_rstmgr_t *handle, dif_rstmgr_alert_info_dump_segment_t *dump,
    size_t dump_size, size_t *segments_read) {
  if (handle == NULL || dump == NULL || segments_read == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  // The actual crash dump size (can be smaller than `dump_size`).
  size_t dump_size_actual =
      mmio_region_read32(base_addr, RSTMGR_ALERT_INFO_ATTR_REG_OFFSET);

  // Partial crash dump read is not allowed.
  if (dump_size < dump_size_actual) {
    return kDifError;
  }

  uint32_t control_reg =
      mmio_region_read32(base_addr, RSTMGR_ALERT_INFO_CTRL_REG_OFFSET);

  // Read the entire alert info crash dump, one 32bit data segment at the time.
  for (int i = 0; i < dump_size_actual; ++i) {
    control_reg = bitfield_field32_write(control_reg,
                                         RSTMGR_ALERT_INFO_CTRL_INDEX_FIELD, i);

    // Set the index of the 32bit data segment to be read at `i`.
    mmio_region_write32(base_addr, RSTMGR_ALERT_INFO_CTRL_REG_OFFSET,
                        control_reg);

    // Read the alert info crash dump 32bit data segment.
    dump[i] = mmio_region_read32(base_addr, RSTMGR_ALERT_INFO_REG_OFFSET);
  }

  *segments_read = dump_size_actual;

  return kDifOk;
}

dif_result_t dif_rstmgr_cpu_info_set_enabled(const dif_rstmgr_t *handle,
                                             dif_toggle_t state) {
  if (handle == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  if (cpu_capture_is_locked(base_addr)) {
    return kDifLocked;
  }

  uint32_t enabled = (state == kDifToggleEnabled) ? 0x1 : 0x0;

  // This will clobber the `CPU_INFO_CTRL.INDEX` field. However, the index
  // field is only relevant during the crash dump read operation, and is
  // set by the caller and not the hardware, so it is safe to clobber it.
  mmio_region_write32(base_addr, RSTMGR_CPU_INFO_CTRL_REG_OFFSET, enabled);

  return kDifOk;
}

dif_result_t dif_rstmgr_cpu_info_get_enabled(const dif_rstmgr_t *handle,
                                             dif_toggle_t *state) {
  if (handle == NULL || state == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  uint32_t reg = mmio_region_read32(base_addr, RSTMGR_CPU_INFO_CTRL_REG_OFFSET);
  bool enabled = bitfield_bit32_read(reg, RSTMGR_CPU_INFO_CTRL_EN_BIT);

  *state = enabled ? kDifToggleEnabled : kDifToggleDisabled;

  return kDifOk;
}

dif_result_t dif_rstmgr_cpu_info_get_size(const dif_rstmgr_t *handle,
                                          size_t *size) {
  if (handle == NULL || size == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;
  *size = mmio_region_read32(base_addr, RSTMGR_CPU_INFO_ATTR_REG_OFFSET);
  return kDifOk;
}

dif_result_t dif_rstmgr_cpu_info_dump_read(
    const dif_rstmgr_t *handle, dif_rstmgr_cpu_info_dump_segment_t *dump,
    size_t dump_size, size_t *segments_read) {
  if (handle == NULL || dump == NULL || segments_read == NULL) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;

  // The actual crash dump size (can be smaller than `dump_size`).
  size_t dump_size_actual =
      mmio_region_read32(base_addr, RSTMGR_CPU_INFO_ATTR_REG_OFFSET);

  // Partial crash dump read is not allowed.
  if (dump_size < dump_size_actual) {
    return kDifError;
  }

  uint32_t control_reg =
      mmio_region_read32(base_addr, RSTMGR_CPU_INFO_CTRL_REG_OFFSET);

  // Read the entire cpu info crash dump, one 32bit data segment at the time.
  for (int i = 0; i < dump_size_actual; ++i) {
    control_reg = bitfield_field32_write(control_reg,
                                         RSTMGR_CPU_INFO_CTRL_INDEX_FIELD, i);

    // Set the index of the 32bit data segment to be read at `i`.
    mmio_region_write32(base_addr, RSTMGR_CPU_INFO_CTRL_REG_OFFSET,
                        control_reg);

    // Read the cpu info crash dump 32bit data segment.
    dump[i] = mmio_region_read32(base_addr, RSTMGR_CPU_INFO_REG_OFFSET);
  }

  *segments_read = dump_size_actual;

  return kDifOk;
}

dif_result_t dif_rstmgr_software_reset(const dif_rstmgr_t *handle,
                                       dif_rstmgr_peripheral_t peripheral,
                                       dif_rstmgr_software_reset_t reset) {
  if (handle == NULL || peripheral >= RSTMGR_PARAM_NUM_SW_RESETS) {
    return kDifBadArg;
  }

  mmio_region_t base_addr = handle->base_addr;
  if (rstmgr_software_reset_is_locked(base_addr, peripheral)) {
    return kDifLocked;
  }

  switch (reset) {
    case kDifRstmgrSoftwareReset:
      rstmgr_software_reset_hold(base_addr, peripheral, true);
      rstmgr_software_reset_hold(base_addr, peripheral, false);
      break;
    case kDifRstmgrSoftwareResetHold:
      rstmgr_software_reset_hold(base_addr, peripheral, true);
      break;
    case kDifRstmgrSoftwareResetRelease:
      rstmgr_software_reset_hold(base_addr, peripheral, false);
      break;
    default:
      return kDifError;
  }

  return kDifOk;
}

dif_result_t dif_rstmgr_software_reset_is_held(
    const dif_rstmgr_t *handle, dif_rstmgr_peripheral_t peripheral,
    bool *asserted) {
  if (handle == NULL || asserted == NULL ||
      peripheral >= RSTMGR_PARAM_NUM_SW_RESETS) {
    return kDifBadArg;
  }

  // When the bit is cleared - peripheral is held in reset.
  *asserted = !mmio_region_read32(
      handle->base_addr, RSTMGR_SW_RST_CTRL_N_0_REG_OFFSET + 4 * peripheral);

  return kDifOk;
}

dif_result_t dif_rstmgr_software_device_reset(const dif_rstmgr_t *handle) {
  if (handle == NULL) {
    return kDifBadArg;
  }

  mmio_region_write32(handle->base_addr, RSTMGR_RESET_REQ_REG_OFFSET,
                      kMultiBitBool4True);

  return kDifOk;
}

dif_result_t dif_rstmgr_fatal_err_code_get_codes(
    const dif_rstmgr_t *rstmgr, dif_rstmgr_fatal_err_codes_t *codes) {
  if (rstmgr == NULL || codes == NULL) {
    return kDifBadArg;
  }
  *codes = mmio_region_read32(rstmgr->base_addr, RSTMGR_ERR_CODE_REG_OFFSET);
  return kDifOk;
}
