blob: 327f2c47a47a22500522712072e078d32087c999 [file] [log] [blame]
// Copyright lowRISC contributors.
// 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_EDN_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_EDN_H_
/**
* @file
* @brief <a href="/hw/ip/edn/doc/">Entropy Distribution Network</a> Device
* Interface Functions
*
* This API implements the interface for the Entropy Distribution Network (EDN)
* hardware.
*
* There are two main modes of operation:
*
* - boot-time: EDN configures the associated CSRNG instance to fetch pre-FIPS
* entropy immediately at boot-time or after reset.
* - auto refresh: EDN sends reseed and generate commands to the associated
* CSRNG instance. The API allows the user to set the CSRNG instantiate,
* reseed and generate para meters, as well as the reseed frequency.
*
* Common set of operations for both boot-time and auto refresh modes:
*
* - `dif_edn_init()`
* - `dif_edn_configure()`
*
* Order of operations in boot-time request mode:
*
* - `did_edn_boot_mode_start()`
* - `dif_edn_stop()`
*
* Order of operations in auto refresh mode:
*
* - `dif_edn_auto_mode_start()`
* - `dif_edn_stop()`
*
* Remaining work:
*
* - Add error status interface.
*/
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_warn_unused_result.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
enum {
/**
* Maximum seed material number of uint32_t words supported in CSRNG
* instantiate and seed commands.
*/
kDifEntropySeedMaterialMaxWordLen = 12,
};
/**
* A toggle state: enabled, or disabled.
*
* This enum may be used instead of a `bool` when describing an enabled/disabled
* state.
*/
typedef enum dif_edn_toggle {
/*
* The "enabled" state.
*/
kDifEdnToggleEnabled,
/**
* The "disabled" state.
*/
kDifEdnToggleDisabled,
} dif_edn_toggle_t;
/**
* Hardware instantiation parameters for Entropy Distribution Network.
*
* This struct describes information about the underlying hardware that is
* not determined until the hardware design is used as part of a top-level
* design.
*/
typedef struct dif_edn_params {
/**
* The base address for the Entropy Distribution Network hardware registers.
*/
mmio_region_t base_addr;
} dif_edn_params_t;
/**
* A handle to Entropy Distribution Network.
*
* This type should be treated as opaque by users.
*/
typedef struct dif_edn {
dif_edn_params_t params;
} dif_edn_t;
/**
* The result of a Entropy Distribution Network operation.
*/
typedef enum dif_edn_result {
/**
* Indicates that the operation succeeded.
*/
kDifEdnOk = 0,
/**
* Indicates some unspecified failure.
*/
kDifEdnError = 1,
/**
* Indicates that some parameter passed into a function failed a
* precondition.
*
* When this value is returned, no hardware operations occurred.
*/
kDifEdnBadArg = 2,
/**
* Indicates that this operation has been locked out, and can never
* succeed until hardware reset.
*/
kDifEdnLocked = 3,
/**
* Indicates that the device is busy and cannot perform the requested
* operation.
*/
kDifEdnBusy = 4,
} dif_edn_result_t;
/**
* CSRNG additional parameters for instantiate and generate commands.
*/
typedef struct dif_edn_seed_material {
/**
* Number of uint32_t words in `data`. Up to
* `kDifEntropySeedMaterialMaxWordLen` words can be set to initialize or
* reseed the CSRNG. CSRNG will extend the `data` to zeros if the provided
* value is less than kDifEntropySeedMaterialMaxWordLen.
*/
uint32_t len;
/**
* Seed material used in CSRNG instantiate or generate call.
*/
uint32_t data[kDifEntropySeedMaterialMaxWordLen];
} dif_edn_seed_material_t;
/**
* Auto-generate EDN module configuration parameters.
*/
typedef struct dif_edn_auto_params {
/**
* CSRNG instantiate command parameters.
*/
dif_edn_seed_material_t instantiate_params;
/**
* CSRNG reseed command parameters.
*/
dif_edn_seed_material_t reseed_params;
/**
* Number of uint32_t words to request the CSRNG on each generate call rounded
* to the nearest 128bit block.
*/
uint32_t generate_len;
/**
* Number of generate calls that can be made before a reseed request is made.
*/
uint32_t reseed_interval;
} dif_edn_auto_params_t;
/**
* A Entropy Distribution Network interrupt request type.
*/
typedef enum dif_edn_irq {
/**
* Asserted when a CSRNG request has completed.
*/
kDifEdnCmdReqDone,
/**
* Asserted when a FIFO error occurs.
*/
kDifEdnFatalError,
} dif_edn_irq_t;
/**
* A snapshot of the enablement state of the interrupts the device.
*
* This is an opaque type, to be used with the `dif_edn_irq_disable_all()` and
* `dif_edn_irq_restore_all()` functions.
*/
typedef uint32_t dif_edn_irq_snapshot_t;
/**
* Creates a new handle for Entropy Distribution Network.
*
* This function does not actuate the hardware.
*
* @param params Hardware instantiation parameters.
* @param[out] edn Out param for the initialized handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_init(dif_edn_params_t params, dif_edn_t *edn);
/**
* Configures Entropy Distribution Network with runtime information.
*
* This function should need to be called once for the lifetime of `handle`.
*
* @param edn An Entropy Distribution Network handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_configure(const dif_edn_t *edn);
/**
* Enables the Entropy Distribution Network in boot-time mode.
*
* Each call to this function should be sequenced with a call to
* `dif_edn_stop()`.
*
* @param edn An Entropy Distribution Network handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_boot_mode_start(const dif_edn_t *edn);
/**
* Enables the Entropy Distribution Network in auto refresh mode.
*
* Each call to this function should be sequenced with a call to
* `dif_edn_stop()`.
*
* @param edn An Entropy Distribution Network handle.
* @param config Auto request configuration parameters.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_auto_mode_start(const dif_edn_t *edn,
dif_edn_auto_params_t *config);
/**
* EDN Status flags.
*/
typedef enum dif_edn_status {
/**
* Device is actively processing a command in either auto or boot-time mode of
* operation.
*/
kDifEdnStatusCmdRunning,
/**
* Device has started the boot-time initialization process.
*/
kDifEdnStatusCmdBootInitAck,
} dif_edn_status_t;
/**
* Queries the Entropy Distribution Network status flags.
*
* @param edn An Entropy Distribution Network handle.
* @param flag Status flag to query.
* @param set Flag state (set/unset).
* @return The result of the operation.
*/
dif_edn_result_t dif_edn_get_status(const dif_edn_t *edn, dif_edn_status_t flag,
bool *set);
/**
* Stops the current mode of operation and disables the entropy module.
*
* @param edn An Entropy Distribution Network handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_stop(const dif_edn_t *edn);
/**
* Locks out Entropy Distribution Network functionality.
*
* This function is reentrant: calling it while functionality is locked will
* have no effect and return `kDifEdnOk`.
*
* @param edn An Entropy Distribution Network handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_lock(const dif_edn_t *edn);
/**
* Checks whether this Entropy Distribution Network is locked.
*
* @param edn An Entropy Distribution Network handle.
* @param[out] is_locked Out-param for the locked state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_is_locked(const dif_edn_t *edn, bool *is_locked);
/**
* Returns whether a particular interrupt is currently pending.
*
* @param edn An Entropy Distribution Network handle.
* @param irq An interrupt type.
* @param[out] is_pending Out-param for whether the interrupt is pending.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_is_pending(const dif_edn_t *edn, dif_edn_irq_t irq,
bool *is_pending);
/**
* Acknowledges a particular interrupt, indicating to the hardware that it has
* been successfully serviced.
*
* @param edn An Entropy Distribution Network handle.
* @param irq An interrupt type.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_acknowledge(const dif_edn_t *edn,
dif_edn_irq_t irq);
/**
* Checks whether a particular interrupt is currently enabled or disabled.
*
* @param edn An Entropy Distribution Network handle.
* @param irq An interrupt type.
* @param[out] state Out-param toggle state of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_get_enabled(const dif_edn_t *edn,
dif_edn_irq_t irq,
dif_edn_toggle_t *state);
/**
* Sets whether a particular interrupt is currently enabled or disabled.
*
* @param edn An Entropy Distribution Network handle.
* @param irq An interrupt type.
* @param state The new toggle state for the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_set_enabled(const dif_edn_t *edn,
dif_edn_irq_t irq,
dif_edn_toggle_t state);
/**
* Forces a particular interrupt, causing it to be serviced as if hardware had
* asserted it.
*
* @param edn An Entropy Distribution Network handle.
* @param irq An interrupt type.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_force(const dif_edn_t *edn, dif_edn_irq_t irq);
/**
* Disables all interrupts, optionally snapshotting all toggle state for later
* restoration.
*
* @param edn An Entropy Distribution Network handle.
* @param[out] snapshot Out-param for the snapshot; may be `NULL`.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_disable_all(const dif_edn_t *edn,
dif_edn_irq_snapshot_t *snapshot);
/**
* Restores interrupts from the given snapshot.
*
* This function can be used with `dif_edn_irq_disable_all()` to temporary
* interrupt save-and-restore.
*
* @param edn An Entropy Distribution Network handle.
* @param snapshot A snapshot to restore from.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_edn_result_t dif_edn_irq_restore_all(
const dif_edn_t *edn, const dif_edn_irq_snapshot_t *snapshot);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_EDN_H_