blob: 5868e8d961bed13ee49c03ee64e744e3d05b3843 [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_OTBN_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_OTBN_H_
/**
* @file
* @brief <a href="/hw/ip/otbn/doc/">OTBN</a> Device Interface Functions
*/
#include <stddef.h>
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Configuration for initializing an OTBN device.
*/
typedef struct dif_otbn_config {
/** Base address of the OTBN device in the system. */
mmio_region_t base_addr;
} dif_otbn_config_t;
/**
* Internal state of a OTBN device.
*
* Instances of this struct must be initialized by `dif_otbn_init()` before
* being passed to other functions.
*/
typedef struct dif_otbn {
/** Base address of the OTBN device in the system. */
mmio_region_t base_addr;
} dif_otbn_t;
/**
* Generic return codes for the functions in the OTBN DIF library.
*/
typedef enum dif_otbn_result {
/**
* The function succeeded.
*/
kDifOtbnOk,
/**
* The function failed a non-specific assertion.
*
* This error is not recoverable.
*/
kDifOtbnError,
/**
* There is a problem with the argument(s) to the function.
*
* This return code is only returned before the function has any side effects.
*
* This error is recoverable and the operation can be retried after correcting
* the problem with the argument(s).
*/
kDifOtbnBadArg
} dif_otbn_result_t;
/**
* OTBN commands
*/
typedef enum dif_otbn_cmd {
kDifOtbnCmdExecute = 0x01,
kDifOtbnCmdSecWipeDmem = 0x02,
kDifOtbnCmdSecWipeImem = 0x03,
} dif_otbn_cmd_t;
/**
* OTBN status
*/
typedef enum dif_otbn_status {
kDifOtbnStatusIdle = 0x00,
kDifOtbnStatusBusyExecute = 0x01,
kDifOtbnStatusBusySecWipeDmem = 0x02,
kDifOtbnStatusBusySecWipeImem = 0x03,
} dif_otbn_status_t;
/**
* OTBN Errors
*
* OTBN uses a bitfield to indicate which errors have been seen. Multiple errors
* can be seen at the same time. This enum gives the individual bits that may be
* set for different errors.
*/
typedef enum dif_otbn_err_bits {
kDifOtbnErrBitsNoError = 0,
/** Load or store to invalid address. */
kDifOtbnErrBitsBadDataAddr = (1 << 0),
/** Instruction fetch from invalid address. */
kDifOtbnErrBitsBadInsnAddr = (1 << 1),
/** Call stack underflow or overflow. */
kDifOtbnErrBitsCallStack = (1 << 2),
/** Illegal instruction execution attempted */
kDifOtbnErrBitsIllegalInsn = (1 << 3),
/** LOOP[I] related error */
kDifOtbnErrBitsLoop = (1 << 4),
/** Error seen in Imem read */
kDifOtbnErrBitsFatalImem = (1 << 5),
/** Error seen in Dmem read */
kDifOtbnErrBitsFatalDmem = (1 << 6),
/** Error seen in RF read */
kDifOtbnErrBitsFatalReg = (1 << 7),
/**
* A bus-accessible register or memory was read or written while when it was
* not allowed.
*/
kDifOtbnErrBitsFatalIllegalBusAccess = (1 << 8),
/** OTBN received a life cycle escalation request from the system */
kDifOtbnErrBitsFatalLifecycleEscalation = (1 << 9),
} dif_otbn_err_bits_t;
/**
* OTBN interrupt configuration.
*
* Enumeration used to enable, disable, test and query the OTBN interrupts.
* Please see the comportability specification for more information:
* https://docs.opentitan.org/doc/rm/comportability_specification/
*/
typedef enum dif_otbn_interrupt {
/**
* OTBN is done, it has run the application to completion.
*
* Associated with the `otbn.INTR_STATE.done` hardware interrupt.
*/
kDifOtbnInterruptDone = 0,
} dif_otbn_interrupt_t;
/**
* Generic enable/disable enumeration.
*
* Enumeration used to enable/disable bits, flags, ...
*/
typedef enum dif_otbn_enable {
/** Enable functionality. */
kDifOtbnEnable = 0,
/** Disable functionality. */
kDifOtbnDisable,
} dif_otbn_enable_t;
/**
* Initialize a OTBN device using `config` and return its internal state.
*
* A particular OTBN device must first be initialized by this function
* before calling other functions of this library.
*
* @param config Configuration for initializing an OTBN device.
* @param[out] otbn OTBN instance that will store the internal state of the
* initialized OTBN device.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_init(const dif_otbn_config_t *config,
dif_otbn_t *otbn);
/**
* Reset OTBN device.
*
* Resets the given OTBN device by setting its configuration registers to
* reset values. Disables interrupts, output, and input filter.
*
* @param otbn OTBN instance
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_reset(const dif_otbn_t *otbn);
/**
* OTBN get requested IRQ state.
*
* Get the state of the requested IRQ in `irq_type`.
*
* @param otbn OTBN state data.
* @param irq_type IRQ to get the state of.
* @param[out] state IRQ state.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_irq_state_get(const dif_otbn_t *otbn,
dif_otbn_interrupt_t irq_type,
dif_otbn_enable_t *state);
/**
* OTBN clear requested IRQ state.
*
* Clear the state of the requested IRQ in `irq_type`. Primary use of this
* function is to de-assert the interrupt after it has been serviced.
*
* @param otbn OTBN state data.
* @param irq_type IRQ to be de-asserted.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_irq_state_clear(const dif_otbn_t *otbn,
dif_otbn_interrupt_t irq_type);
/**
* OTBN disable interrupts.
*
* Disable generation of all OTBN interrupts, and pass previous interrupt state
* in `state` back to the caller. Parameter `state` is ignored if NULL.
*
* @param otbn OTBN state data.
* @param[out] state IRQ state for use with `dif_otbn_irqs_restore`.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_irqs_disable(const dif_otbn_t *otbn,
uint32_t *state);
/**
* OTBN restore IRQ state.
*
* Restore previous OTBN IRQ state. This function is used to restore the
* OTBN interrupt state prior to `dif_otbn_irqs_disable` function call.
*
* @param otbn OTBN instance
* @param state IRQ state to restore.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_irqs_restore(const dif_otbn_t *otbn, uint32_t state);
/**
* OTBN interrupt control.
*
* Enable/disable an OTBN interrupt specified in `irq_type`.
*
* @param otbn OTBN instance
* @param irq_type OTBN interrupt type.
* @param enable enable or disable the interrupt.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_irq_control(const dif_otbn_t *otbn,
dif_otbn_interrupt_t irq_type,
dif_otbn_enable_t enable);
/**
* OTBN interrupt force.
*
* Force interrupt specified in `irq_type`.
*
* @param otbn OTBN instance
* @param irq_type OTBN interrupt type to be forced.
* @return `dif_otbn_result_t`.
*/
dif_otbn_result_t dif_otbn_irq_force(const dif_otbn_t *otbn,
dif_otbn_interrupt_t irq_type);
/**
* Set the start address of the execution.
*
* @param otbn OTBN instance.
* @param start_addr The IMEM byte address to start the execution at.
* @return `kDifOtbnBadArg` if `otbn` is `NULL` or `start_addr` is invalid,
* `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_set_start_addr(const dif_otbn_t *otbn,
unsigned int start_addr);
/**
* Start an operation by issuing a command.
*
* @param otbn OTBN instance.
* @param cmd The command.
* @return `kDifOtbnBadArg` if `otbn` is `NULL`, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_write_cmd(const dif_otbn_t *otbn,
dif_otbn_cmd_t cmd);
/**
* Gets the current status of OTBN.
*
* @param otbn OTBN instance
* @param[out] status OTBN status
* @return `kDifOtbnBadArg` if `otbn` or `status` is `NULL`,
* `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_get_status(const dif_otbn_t *otbn,
dif_otbn_status_t *status);
/**
* Get the error bits set by the device if the operation failed.
*
* @param otbn OTBN instance
* @param[out] err_bits The error bits returned by the hardware.
* @return `kDifOtbnBadArg` if `otbn` or `err_code` is `NULL`,
* `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_get_err_bits(const dif_otbn_t *otbn,
dif_otbn_err_bits_t *err_bits);
/**
* Gets the number of executed OTBN instructions.
*
* Gets the number of instructions executed so far in the current OTBN run if
* there is one. Otherwise, gets the number executed in total in the previous
* OTBN run.
*
* @param otbn OTBN instance
* @param[out] insn_cnt The number of instructions executed by OTBN.
* @return `kDifOtbnBadArg` if `otbn` or `insn_cnt` is `NULL`,
* `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_get_insn_cnt(const dif_otbn_t *otbn,
uint32_t *insn_cnt);
/**
* Write an OTBN application into its instruction memory (IMEM)
*
* Only 32b-aligned 32b word accesses are allowed.
*
* @param otbn OTBN instance
* @param offset_bytes the byte offset in IMEM the first word is written to
* @param src the main memory location to start reading from.
* @param len_bytes number of bytes to copy.
* @return `kDifOtbnBadArg` if `otbn` is `NULL` or len_bytes or size are
* invalid, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_imem_write(const dif_otbn_t *otbn,
uint32_t offset_bytes, const void *src,
size_t len_bytes);
/**
* Read from OTBN's instruction memory (IMEM)
*
* Only 32b-aligned 32b word accesses are allowed.
*
* @param otbn OTBN instance
* @param offset_bytes the byte offset in IMEM the first word is read from
* @param[out] dest the main memory location to copy the data to (preallocated)
* @param len_bytes number of bytes to copy.
* @return `kDifOtbnBadArg` if `otbn` is `NULL` or len_bytes or size are
* invalid, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_imem_read(const dif_otbn_t *otbn,
uint32_t offset_bytes, void *dest,
size_t len_bytes);
/**
* Write to OTBN's data memory (DMEM)
*
* Only 32b-aligned 32b word accesses are allowed.
*
* @param otbn OTBN instance
* @param offset_bytes the byte offset in DMEM the first word is written to
* @param src the main memory location to start reading from.
* @param len_bytes number of bytes to copy.
* @return `kDifOtbnBadArg` if `otbn` is `NULL` or len_bytes or size are
* invalid, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_dmem_write(const dif_otbn_t *otbn,
uint32_t offset_bytes, const void *src,
size_t len_bytes);
/**
* Read from OTBN's data memory (DMEM)
*
* Only 32b-aligned 32b word accesses are allowed.
*
* @param otbn OTBN instance
* @param offset_bytes the byte offset in DMEM the first word is read from
* @param[out] dest the main memory location to copy the data to (preallocated)
* @param len_bytes number of bytes to copy.
* @return `kDifOtbnBadArg` if `otbn` is `NULL` or len_bytes or size are
* invalid, `kDifOtbnOk` otherwise.
*/
dif_otbn_result_t dif_otbn_dmem_read(const dif_otbn_t *otbn,
uint32_t offset_bytes, void *dest,
size_t len_bytes);
/**
* Get the size of OTBN's data memory in bytes.
*
* @param otbn OTBN instance
* @return data memory size in bytes
*/
size_t dif_otbn_get_dmem_size_bytes(const dif_otbn_t *otbn);
/**
* Get the size of OTBN's instruction memory in bytes.
*
* @param otbn OTBN instance
* @return instruction memory size in bytes
*/
size_t dif_otbn_get_imem_size_bytes(const dif_otbn_t *otbn);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_OTBN_H_