dif_rram_ctrl.h

To use this DIF, include the following C header:

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

This header provides the following device interface functions:

Generated from dif_rram_ctrl.h
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RRAM_CTRL_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RRAM_CTRL_H_

/**
 * @file
 * @brief <a href="/book/hw/ip/rram_ctrl/doc/">RRAM
 * Controller</a> Device Interface Functions
 */

#include <stdbool.h>
#include <stdint.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 "sw/device/lib/dif/autogen/dif_rram_ctrl_autogen.h"

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

/**
 * Carries transaction state for a RRAM controller device.
 *
 * All members except `dev` should be considered private and should not be
 * accessed directly outside of the DIF implementation.
 */
typedef struct dif_rram_ctrl_state {
  /**
   * Contains autogenerated device information, like the base address for
   * registers in the RRAM controller device.
   */
  dif_rram_ctrl_t dev;

  /** Number of words remaining for the current transaction. */
  uint32_t words_remaining;
  /** Whether a transaction is pending completion. */
  bool transaction_pending;
} dif_rram_ctrl_state_t;

/**
 * Initialize the DIF state for the RRAM controller.
 *
 * @param handle The RRAM controller DIF state to initialize.
 * @param base_addr The base address for the RRAM controller.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_init_state(dif_rram_ctrl_state_t *handle,
                                      mmio_region_t base_addr);

/**
 * Initialize the DIF state for the RRAM controller from a device tree handle.
 *
 * @param handle The RRAM controller DIF state to initialize.
 * @param dt The RRAM controller device tree handle.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_init_state_from_dt(dif_rram_ctrl_state_t *handle,
                                              dt_rram_ctrl_t dt);

typedef struct dif_rram_ctrl_device_info {
  /** Number of bytes per RRAM word. */
  uint32_t bytes_per_word;
  /** Number of bytes per RRAM page. */
  uint32_t bytes_per_page;
  /** Number of pages in the data partition. */
  uint32_t data_pages;
  /** Number of pages in the info partition. */
  uint32_t info_pages;
} dif_rram_ctrl_device_info_t;

/**
 * Get information on the RRAM controller sizes.
 *
 * @return A `dif_rram_ctrl_device_info_t` representing the feature sizes for
 * various components of the RRAM.
 */
OT_WARN_UNUSED_RESULT
dif_rram_ctrl_device_info_t dif_rram_ctrl_get_device_info(void);

/**
 * Set whether the RRAM is enabled.
 *
 * Generally, this is used to disable RRAM functionality in case of an
 * emergency. RRAM functionality is ordinarily enabled.
 *
 * @param handle The RRAM controller DIF state.
 * @param enable Enable/disable RRAM functionality.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` on success.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_rram_enablement(dif_rram_ctrl_state_t *handle,
                                               dif_toggle_t enable);

/**
 * Get whether RRAM functionality is enabled.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] enabled_out Out parameter, where to store whether RRAM is
 * enabled.
 * @return `kDifBadArg` if `handle` or `enabled_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_rram_enablement(
    const dif_rram_ctrl_state_t *handle, dif_toggle_t *enabled_out);

/**
 * Set whether execution / fetch access is enabled.
 *
 * @param handle The RRAM controller DIF state.
 * @param enable Enable/disable execution / fetch access.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_exec_enablement(dif_rram_ctrl_state_t *handle,
                                               dif_toggle_t enable);

/**
 * Get whether execution / fetch access is enabled.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] enabled_out Out parameter, whether execution / fetch access is
 * allowed.
 * @return `kDifBadArg` if `handle` or `enabled_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_exec_enablement(
    const dif_rram_ctrl_state_t *handle, dif_toggle_t *enabled_out);

/**
 * Begins the RRAM controller's initialization sequence. The RRAM controller
 * will read out the root seeds before allowing other usage of the controller.
 * This operation will only be performed once, and controller initialization
 * cannot be requested again until after a reset.
 *
 * @param handle The RRAM controller DIF state.
 * @return `kDifError` if initialization has already been started, and
 * `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_start_controller_init(dif_rram_ctrl_state_t *handle);

/**
 * Status bits that can be queried.
 */
typedef struct dif_rram_ctrl_status {
  /**
   * RRAM read FIFO full, software must consume data.
   */
  bool read_fifo_full;
  /**
   * RRAM read FIFO empty.
   */
  bool read_fifo_empty;
  /**
   * RRAM write FIFO full.
   */
  bool write_fifo_full;
  /**
   * RRAM write FIFO empty, software must provide data.
   */
  bool write_fifo_empty;
  /**
   * RRAM controller init complete.
   */
  bool controller_init_done;
  /**
   * RRAM controller keys valid.
   */
  bool controller_keys_valid;
} dif_rram_ctrl_status_t;

/**
 * Query the status registers on the RRAM controller.
 *
 * This function checks the various status bits as described in
 * `dif_rram_ctrl_status_t`.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] status_out Out parameter. The current status of the RRAM
 * controller.
 * @return `kDifBadArg` if `handle` or `status_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_status(const dif_rram_ctrl_state_t *handle,
                                      dif_rram_ctrl_status_t *status_out);

/**
 * Enum to represent the RRAM partition type (data or info).
 */
typedef enum dif_rram_ctrl_partition_type {
  kDifRramCtrlPartitionTypeData = 0,
  kDifRramCtrlPartitionTypeInfo = 1
} dif_rram_ctrl_partition_type_t;

typedef enum dif_rram_ctrl_operation {
  /** Read the specified number of words. */
  kDifRramCtrlOpRead = 0,
  /** Write the specified number of words. */
  kDifRramCtrlOpWrite = 1,
  /** Rewrite a specific word to repair it. */
  kDifRramCtrlOpRewrite = 2,
} dif_rram_ctrl_operation_t;

typedef struct dif_rram_ctrl_transaction {
  dif_rram_ctrl_operation_t op;
  /**
   * The partition type for the transaction.
   *
   */
  dif_rram_ctrl_partition_type_t partition_type;
  /**
   * Byte address (in the RRAM address space) to start the operation.
   *
   * For operations at a granularity of words, the RRAM controller will
   * truncate to the closest, lower word aligned address. For example, if 0x13
   * is supplied for a read, the controller will perform a read at address 0x10.
   *
   * For write operations, the granularity is 4 words or 16 bytes. The RRAM
   * controller and `dif_rram_ctrl_start_unsafe()` will truncate the address
   * to the closest, lower aligned 16 byte address; `dif_rram_ctrl_start()`
   * instead rejects a misaligned write address with `kDifBadArg`.
   */
  uint32_t byte_address;
  /**
   * Number of 32-bit words in the operation. Must be in the range [1,1024]
   * (inclusive) for write or read operations.
   * For write operations the number of 32-bit words must be a multiple of 4.
   */
  uint32_t word_count;
} dif_rram_ctrl_transaction_t;

/**
 * Start a RRAM controller operation.
 *
 * @param handle The RRAM controller DIF state.
 * @param transaction The parameters that constitute the operation to start.
 * @return `kDifBadArg` if `handle` is null, if `transaction` contains an
 * invalid or unsupported operation, if `word_count` is zero or out of range,
 * if `word_count` is not a multiple of 4 for write operations, or if
 * `byte_address` is not 16-byte aligned for write operations;
 * `kDifUnavailable` if a RRAM transaction is in progress at the controller,
 * `kDifIpFifoFull` if the FIFOs are not empty, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_start(dif_rram_ctrl_state_t *handle,
                                 dif_rram_ctrl_transaction_t transaction);

/**
 * Start a RRAM controller operation, with fewer safeguards. (unsafe version)
 *
 * Unlike `dif_rram_ctrl_start()`, this variant does not check whether the
 * word count is valid, whether the write address is 16-byte aligned, or
 * whether the FIFOs have been emptied. This function is intended to be used
 * to trigger errors on purpose, for testing the hardware responses.
 *
 * @param handle The RRAM controller DIF state.
 * @param transaction The parameters that constitute the operation to start.
 * @return `kDifBadArg` if `handle` is null, `kDifUnavailable` if a RRAM
 * transaction is in progress, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_start_unsafe(
    dif_rram_ctrl_state_t *handle, dif_rram_ctrl_transaction_t transaction);

/**
 * Push data to the write FIFO. (unsafe version)
 *
 * This function is primarily for testing hardware error responses. If you are
 * not specifically trying to force an error, consider
 * `dif_rram_ctrl_wr_fifo_push()` instead. This function does not check if a
 * write transaction has begun, nor if the number of words would exceed the
 * size of the current transaction.
 *
 * Attempts to write the contents of `data` to the write FIFO without
 * consideration for the current controller state.
 *
 * It is up to the caller to call `dif_rram_ctrl_end()` to ensure the
 * RRAM controller completed this transaction successfully.
 *
 * @param handle The RRAM controller DIF state.
 * @param word_count The number of words to write.
 * @param data The data to write.
 * @return `kDifBadArg` if `handle` or `data` are null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_wr_fifo_push_unsafe(dif_rram_ctrl_state_t *handle,
                                               uint32_t word_count,
                                               const uint32_t *data);

/**
 * Push data to the write FIFO.
 *
 * Attempts to write the contents of `data` to the write FIFO. It is required
 * that a write transaction be started prior to calling this function, else
 * the call will fail with `kDifError`.
 *
 * The following conditions are also required:
 *   - `data` must reference a contiguous, allocated, readable region of at
 *     least `word_count` words, violation of this will produce undefined
 *     behavior.
 *   - The first call to this function after starting the write transaction
 *     the same `word_count` must not exceed what was supplied at the start of
 *     the write transaction.
 *   - Each subsequent call the new `word_count` must not exceed `word_count -
 *     words_sent_out` from the previous call.
 * All deviations on the above will produce a `kDifBadArg` error
 * unless otherwise specified.
 *
 * If the FIFO fills up, this function will cause the CPU to block until the
 * RRAM controller frees up more space.
 *
 * It is up to the caller to call `dif_rram_ctrl_end()` to ensure the
 * RRAM controller completed this transaction successfully.
 *
 * @param handle The RRAM controller DIF state.
 * @param word_count The number of words to write.
 * @param data The data to write.
 * @return `kDifBadArg` if `handle` or `data` are null or if the value of
 * `word_count` is illegal. `kDifError` if a write transaction was not
 * started. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_wr_fifo_push(dif_rram_ctrl_state_t *handle,
                                        uint32_t word_count,
                                        const uint32_t *data);

/**
 * Read data from the read FIFO. (unsafe version)
 *
 * This function is primarily for testing hardware error responses. If you are
 * not specifically trying to force an error, consider
 * `dif_rram_ctrl_read_fifo_pop()` instead. This function does not check if a
 * transaction is currently in progress, nor if this would cause a read beyond
 * the number of words for the current operation.
 *
 * Attempts to read `word_count` words from the read FIFO without consideration
 * for the current controller state.
 *
 * It is up to the caller to call `dif_rram_ctrl_end()` to ensure the
 * RRAM controller completed this transaction successfully.
 *
 * @param handle The RRAM controller DIF state.
 * @param word_count The number of words to read.
 * @param[out] data_out The region in memory to store the data read off the
 * FIFO.
 * @return `kDifBadArg` if `handle` or `data_out` are null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_read_fifo_pop_unsafe(dif_rram_ctrl_state_t *handle,
                                                uint32_t word_count,
                                                uint32_t *data_out);

/**
 * Read data from the read FIFO.
 *
 * Attempts to read `word_count` words from the read FIFO.
 *
 * The following conditions are required:
 *   - `data_out` must reference a contiguous, allocated, writable region of at
 *     least `word_count` words, violation of this will produce undefined
 *     behavior.
 *   - The first call to this function after starting the write transaction
 *     the same `word_count` must not exceed what was supplied at the start of
 * the read transaction.
 *   - Each subsequent call the new `word_count` must not exceed `word_count -
 *     words_received` from the previous call.
 * All deviations on the above will produce a `kDifBadArg` error unless
 * otherwise specified.
 *
 * If the FIFO empties this function will cause the CPU to block until the RRAM
 * controller fills the FIFO with more data.
 *
 * It is up to the caller to call `dif_rram_ctrl_end()` to ensure the
 * RRAM controller completed this transaction successfully.
 *
 * @param handle The RRAM controller DIF state.
 * @param word_count The number of words to read.
 * @param[out] data_out The region in memory to store the data read off the
 * FIFO.
 * @return `kDifBadArg` if `handle` or `data_out` are null, or if the value of
 * `word_count` is illegal. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_read_fifo_pop(dif_rram_ctrl_state_t *handle,
                                         uint32_t word_count,
                                         uint32_t *data_out);

typedef struct dif_rram_ctrl_error_codes {
  /**
   * Controller operation error.
   */
  bool operation_error;
  /**
   * Access permission error.
   */
  bool memory_protection_error;
  /**
   * Uncorrectable RRAM read data error.
   */
  bool read_error;
  /**
   * RRAM write error.
   */
  bool write_error;
} dif_rram_ctrl_error_codes_t;

/**
 * Represents recoverable errors and synchronous errors caused by software.
 */
typedef struct dif_rram_ctrl_error {
  /**
   * For errors associated with an address, the address where the error
   * occurred.
   */
  uint32_t address;

  /**
   * A set of error codes.
   */
  dif_rram_ctrl_error_codes_t codes;
} dif_rram_ctrl_error_t;

/**
 * Get the error codes and address of the last associated error.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] error_code_out Output parameter. The location where the current
 * status is to be stored.
 * @return `kDifBadArg` if `handle` or `error_code_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_error_codes(
    const dif_rram_ctrl_state_t *handle, dif_rram_ctrl_error_t *error_code_out);

/**
 * Clear the error codes.
 *
 * @param handle The RRAM controller DIF state.
 * @param codes The error codes to clear.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_clear_error_codes(dif_rram_ctrl_state_t *handle,
                                             dif_rram_ctrl_error_codes_t codes);

typedef struct dif_rram_ctrl_output {
  /**
   * The error code associated with an `operation_error`. This field is only
   * valid if `operation_error` is true.
   */
  dif_rram_ctrl_error_t error_code;
  /**
   * RRAM operation done.
   */
  bool operation_done;
  /**
   * RRAM operation error.
   */
  bool operation_error;

} dif_rram_ctrl_output_t;

/**
 * Check that the transaction has completed and return any resulting error
 * codes. Does not clear the error codes, but does clear the operation status if
 * the operation has terminated.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] out Out parameter. Contains the transaction status and error
 * codes.
 * @return `kDifBadArg` if `handle` or `out` are null, `kDifError` if no
 * transaction was pending, `kDifUnavailable` if the controller is still
 * processing the transaction, `kDifIpFifoFull` if there are still words
 * remaining for the FIFOs, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_end(dif_rram_ctrl_state_t *handle,
                               dif_rram_ctrl_output_t *out);

/**
 * Memory protection configuration options.
 */
typedef struct dif_rram_ctrl_region_properties {
  /** Read enable flag. */
  multi_bit_bool_t rd_en;
  /** Write enable flag. */
  multi_bit_bool_t wr_en;
  /** Scramble enable flag*/
  multi_bit_bool_t scramble_en;
  /** ECC enable flag. */
  multi_bit_bool_t ecc_en;
} dif_rram_ctrl_region_properties_t;

/**
 * A composite of a data region and its memory properties.
 */
typedef struct dif_rram_ctrl_data_region_properties {
  /** Region base page index. */
  uint32_t base;
  /** Region config size (in number of pages). */
  uint32_t size;
  /** Memory properties of the region. */
  dif_rram_ctrl_region_properties_t properties;
} dif_rram_ctrl_data_region_properties_t;

/**
 * Representation of the memory protection regions for the info pages.
 */
typedef struct dif_rram_ctrl_info_region {
  /** Region page index. */
  uint32_t page;
} dif_rram_ctrl_info_region_t;

/**
 * Enable/disable the data region of RRAM indexed by `region`.
 *
 * This may only be done if region configuration has not been locked.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to operate on.
 * @param enable Enable or disable this `region`.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid, `kDifLocked`
 * if region configuration has been locked, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_data_region_enablement(
    dif_rram_ctrl_state_t *handle, uint32_t region, dif_toggle_t enable);

/**
 * Get the enabled/disabled state for the indicated data `region`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region in question.
 * @param[out] enabled_out Out-parameter, the enabled/disabled state of this
 * region.
 * @return `kDifBadArg` if `handle` or `enabled_out` is null, or if `region` is
 * invalid, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_data_region_enablement(
    const dif_rram_ctrl_state_t *handle, uint32_t region,
    dif_toggle_t *enabled_out);

/**
 * Enable/disable the info region of RRAM identified by `region`.
 *
 * This may only be done if region configuration has not been locked.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to operate on.
 * @param enable Enable or disable this `region`.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid, `kDifLocked`
 * if region configuration has been locked, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_info_region_enablement(
    dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region,
    dif_toggle_t enable);

/**
 * Get the enabled/disabled state for the indicated info `region`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region in question.
 * @param[out] enabled_out Out-parameter, the enabled/disabled state of this
 * region.
 * @return `kDifBadArg` if `handle` or `enabled_out` is null, or if `region` is
 * invalid, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_info_region_enablement(
    const dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region,
    dif_toggle_t *enabled_out);

/**
 * Set the default memory properties for data regions, when not overridden by a
 * specific entry in the data region memory properties table.
 *
 * @param handle The RRAM controller DIF state.
 * @param properties The memory properties to control.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_default_region_properties(
    dif_rram_ctrl_state_t *handle,
    dif_rram_ctrl_region_properties_t properties);

/**
 * Get the default memory properties for data regions, when they are not
 * overridden by a specific entry in the data region memory properties table.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] properties_out Out-parameter, a pointer to a
 * `dif_rram_ctrl_region_properties_t` struct for writing the memory
 * properties.
 * @return `kDifBadArg` if `handle` or `properties_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_default_region_properties(
    const dif_rram_ctrl_state_t *handle,
    dif_rram_ctrl_region_properties_t *properties_out);

/**
 * Set memory properties for the data region of RRAM indexed by `region`.
 *
 * This may only be done if region configuration has not been locked.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to operate on.
 * @param config The memory properties to control for this `region`.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid, `kDifLocked`
 * if region configuration has been locked, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_data_region_properties(
    dif_rram_ctrl_state_t *handle, uint32_t region,
    dif_rram_ctrl_data_region_properties_t config);

/**
 * Get the memory properties for the data region of RRAM indexed by `region`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The index of the region entry in question.
 * @param[out] config_out Out-parameter, a pointer to a
 * `dif_rram_ctrl_data_region_properties_t` struct for writing the full entry
 * showing the region configuration and its memory properties.
 * @return `kDifBadArg` if `handle` or `config_out` is null or if `region`
 * is invalid. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_data_region_properties(
    const dif_rram_ctrl_state_t *handle, uint32_t region,
    dif_rram_ctrl_data_region_properties_t *config_out);

/**
 * Set memory properties for the info region of RRAM identified by `region`.
 *
 * This may only be done if region configuration has not been locked.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to operate on.
 * @param properties The memory properties to control for this `region`.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid, `kDifLocked`
 * if region configuration has been locked, and `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_info_region_properties(
    dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region,
    dif_rram_ctrl_region_properties_t properties);

/**
 * Get the memory properties for the info region of RRAM identified by
 * `region`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The index of the region entry in question.
 * @param[out] properties_out Out-parameter, a pointer to a
 * `dif_rram_ctrl_region_properties_t` struct for writing memory properties
 * associated with the indicated `region`.
 * @return `kDifBadArg` if `handle` or `properties_out` is null or if `region`
 * is invalid. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_info_region_properties(
    const dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region,
    dif_rram_ctrl_region_properties_t *properties_out);

/**
 * Lock data region memory properties configuration until the device is reset.
 *
 * This will prevent any further configuration of region properties until device
 * reset. Future calls to functions that set data region memory properties will
 * return `kDifLocked`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to lock.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid,
 * `kDifLocked` if configuration is already locked, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_lock_data_region_properties(
    dif_rram_ctrl_state_t *handle, uint32_t region);

/**
 * Lock info region memory properties configuration until the device is reset.
 *
 * This will prevent any further configuration of region properties until device
 * reset. Future calls to functions that set info region memory properties will
 * return `kDifLocked`.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region to lock.
 * @return `kDifBadArg` if `handle` is null or `region` is invalid,
 * `kDifLocked` if configuration is already locked, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_lock_info_region_properties(
    dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region);

/**
 * Query the state of the region configuration lock for the given data `region`
 * entry's index.
 *
 * This function checks if memory region configuration is still enabled or if it
 * has been locked. Once locked, region configuration cannot be enabled again,
 * and all calls to region configuration functions will return `kDifLocked`
 * until the device is restarted.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region in question.
 * @param[out] locked_out Out-parameter, the current state of the region's
 * configuration lock.
 * @return `kDifBadArg` if `handle` or `locked_out` is null, or if `region` is
 * invalid, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_data_region_is_locked(
    const dif_rram_ctrl_state_t *handle, uint32_t region, bool *locked_out);

/**
 * Query the state of the region configuration lock for the given info `region`.
 *
 * This function checks if memory region configuration is still enabled or if it
 * has been locked. Once locked, region configuration cannot be enabled again,
 * and all calls to region configuration functions will return `kDifLocked`
 * until the device is restarted.
 *
 * @param handle The RRAM controller DIF state.
 * @param region The region in question.
 * @param[out] locked_out Out-parameter, the current state of the region's
 * configuration lock.
 * @return `kDifBadArg` if `handle` or `locked_out` is null, or if `region` is
 * invalid, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_info_region_is_locked(
    const dif_rram_ctrl_state_t *handle, dif_rram_ctrl_info_region_t region,
    bool *locked_out);

/**
 * Set the interrupt watermarks for the write FIFO.
 *
 * The value of `level` defines the level the write FIFO must drain to before
 * triggering a `wr_lvl` interrupt.
 *
 * This interrupts will only trigger if enabled through the interrupt API.
 *
 * @param handle The RRAM controller DIF state.
 * @param level Trigger an interrupt when the write FIFO drains to this level.
 * @return `kDifBadArg` if `handle` is null or the value `level` is out of
 * range, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_wr_fifo_watermark(dif_rram_ctrl_state_t *handle,
                                                 uint32_t level);

/**
 * Set the interrupt watermarks for the read FIFO.
 *
 * The value of `level` defines the level the read FIFO must fill to before
 * triggering a `rd_lvl` interrupt.
 *
 * This interrupt will only trigger if enabled through the interrupt API.
 *
 * @param handle The RRAM controller DIF state.
 * @param level Trigger an interrupt when the read FIFO fills to this level.
 * @return `kDifBadArg` if `handle` is null or the value of `level` is out of
 * range, `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_read_fifo_watermark(
    dif_rram_ctrl_state_t *handle, uint32_t level);

/**
 * Get the interrupt watermarks for the write and read FIFOs.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] write_out Out-parameter, the write FIFO watermark level. If the
 * write FIFO empties to this level, a corresponding status bit and possibly
 * an interrupt may be generated. May be null.
 * @param[out] read_out Out-parameter, the read FIFO watermark level. If the
 * read FIFO fills to this level, a corresponding status bit and possibly an
 * interrupt may be generated. May be null.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_fifo_watermarks(
    const dif_rram_ctrl_state_t *handle, uint32_t *write_out,
    uint32_t *read_out);

/**
 * Clears the write FIFO.
 *
 * This is useful in the event of an unexpected error as a means of reseting
 * state.
 *
 * Note that this does not reset the handle's internal `words_remaining` or
 * `transaction_pending` tracking. After an aborted transaction, the handle
 * must be reinitialized with `dif_rram_ctrl_init_state()` (which has no MMIO
 * side effects) before starting a new one; otherwise `dif_rram_ctrl_start()`
 * returns `kDifUnavailable` and `dif_rram_ctrl_end()` returns
 * `kDifIpFifoFull`. See #30909 for adding a proper way to abort an ongoing
 * transaction.
 *
 * @param handle The RRAM controller DIF state.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_clear_wr_fifo(dif_rram_ctrl_state_t *handle);

/**
 * Clears the read FIFO.
 *
 * This is useful in the event of an unexpected error as a means of reseting
 * state.
 *
 * Note that this does not reset the handle's internal `words_remaining` or
 * `transaction_pending` tracking. After an aborted transaction, the handle
 * must be reinitialized with `dif_rram_ctrl_init_state()` (which has no MMIO
 * side effects) before starting a new one; otherwise `dif_rram_ctrl_start()`
 * returns `kDifUnavailable` and `dif_rram_ctrl_end()` returns
 * `kDifIpFifoFull`. See #30909 for adding a proper way to abort an ongoing
 * transaction.
 *
 * @param handle The RRAM controller DIF state.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_clear_rd_fifo(dif_rram_ctrl_state_t *handle);

// TODO(#30908): This only covers FAULT_STATUS bits 0-7. It is missing
// `seed_err`, `phy_relbl_err`, `phy_rd_intg_err`, `phy_rd_ctrl_err`,
// `spurious_done`, and `host_gnt_err`. `phy_relbl_err` in particular has no
// accessor to read or clear it (it is `rw0c` and firmware needs to clear it
// during firmware selection), nor is there a way to set the companion
// `DIS.RELBL_ERR_FATAL`. `STD_FAULT_STATUS`, `HW_INFO_CFG_OVERRIDE`, and
// `CURR_FIFO_LVL` also have no accessors.
typedef struct dif_rram_ctrl_faults {
  /** The lcmgr hardware interface encountered an invalid operation. */
  bool lcmgr_operation_error;
  /** The lcmgr hardware interface encountered a memory permission error. */
  bool lcmgr_memory_protection_error;
  /** The lcmgr hardware interface encountered a read data error. */
  bool lcmgr_read_error;
  /** The lcmgr hardware interface encountered a write data error. */
  bool lcmgr_write_error;
  /** The otp hardware interface encountered an invalid operation. */
  bool otp_operation_error;
  /** The otp hardware interface encountered a memory permission error. */
  bool otp_memory_protection_error;
  /** The otp hardware interface encountered a read data error. */
  bool otp_read_error;
  /** The otp hardware interface encountered a write data error. */
  bool otp_write_error;
} dif_rram_ctrl_faults_t;

/**
 * Gets the unrecoverable or hardware faults.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] faults_out Out parameter, a pointer to the location to write
 * the fault values.
 * @return `kDifBadArg` if `handle` or `faults_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_faults(const dif_rram_ctrl_state_t *handle,
                                      dif_rram_ctrl_faults_t *faults_out);

typedef struct dif_rram_ctrl_ecc_errors {
  /** Count of the number of correctable ECC errors. */
  uint32_t corr_error_count;
  /** The last address that produced a correctable ECC error. */
  uint32_t last_error_address;
  /** The last partition that produced a correctable ECC error. */
  dif_rram_ctrl_partition_type_t last_error_partition;
} dif_rram_ctrl_ecc_errors_t;

/**
 * Get the ECC error information of the RRAM.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] errors_out Out parameter, the ECC error information.
 * @return `kDifBadArg` if `handle` or `errors_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_ecc_errors(
    const dif_rram_ctrl_state_t *handle,
    dif_rram_ctrl_ecc_errors_t *errors_out);

typedef struct dif_rram_ctrl_phy_status {
  /** RRAM phy controller initialization complete. */
  bool phy_init_done;
  /** RRAM phy write operation in progress. */
  bool phy_wr_busy;
} dif_rram_ctrl_phy_status_t;

/**
 * Query the status registers on the RRAM controller.
 *
 * This function checks the various status bits as described in
 * `dif_rram_ctrl_phy_status_t`.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] status_out Out-parameter, the current status of the RRAM phy.
 * @return `kDifBadArg` if `handle` or `status_out` is null. `kDifOk`
 * otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_phy_status(
    const dif_rram_ctrl_state_t *handle,
    dif_rram_ctrl_phy_status_t *status_out);

/**
 * Set the value of the scratch register.
 *
 * @param handle The RRAM controller DIF state.
 * @param value The value to set the scratch register to.
 * @return `kDifBadArg` if `handle` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_set_scratch(dif_rram_ctrl_state_t *handle,
                                       uint32_t value);

/**
 * Get the value of the scratch register.
 *
 * @param handle The RRAM controller DIF state.
 * @param[out] value_out Out parameter. The location to write the scratch
 * register's value to.
 * @return `kDifBadArg` if `handle` or `value_out` is null. `kDifOk` otherwise.
 */
OT_WARN_UNUSED_RESULT
dif_result_t dif_rram_ctrl_get_scratch(const dif_rram_ctrl_state_t *handle,
                                       uint32_t *value_out);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif  // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RRAM_CTRL_H_