Skip to content

Commit

Permalink
[edn/dif] Align dif with new sw_cmd_sts register
Browse files Browse the repository at this point in the history
This commit aligns the EDN difs with the HW changes in prior commits.
Some of the difs are shared between the EDN and CSRNG. The main difference
is that now the difs can see when a command is done by looking at the
ack bit in the sw_cmd_sts register.

Signed-off-by: Hakim Filali <[email protected]>
  • Loading branch information
Hakim Filali committed Jan 19, 2024
1 parent 401c186 commit c6abdc3
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 19 deletions.
1 change: 1 addition & 0 deletions sw/device/lib/dif/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ cc_library(
deps = [
":base",
"//hw/ip/csrng/data:csrng_regs",
"//hw/ip/edn/data:edn_regs",
"//sw/device/lib/base:bitfield",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
Expand Down
10 changes: 5 additions & 5 deletions sw/device/lib/dif/dif_csrng.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ dif_result_t dif_csrng_instantiate(
if (csrng == NULL || seed_material == NULL) {
return kDifBadArg;
}
return csrng_send_app_cmd(csrng->base_addr, CSRNG_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
(csrng_app_cmd_t){
.id = kCsrngAppCmdInstantiate,
.entropy_src_enable = entropy_src_enable,
Expand All @@ -77,7 +77,7 @@ dif_result_t dif_csrng_reseed(const dif_csrng_t *csrng,
if (csrng == NULL || seed_material == NULL) {
return kDifBadArg;
}
return csrng_send_app_cmd(csrng->base_addr, CSRNG_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
(csrng_app_cmd_t){
.id = kCsrngAppCmdReseed,
.seed_material = seed_material,
Expand All @@ -89,7 +89,7 @@ dif_result_t dif_csrng_update(const dif_csrng_t *csrng,
if (csrng == NULL || seed_material == NULL) {
return kDifBadArg;
}
return csrng_send_app_cmd(csrng->base_addr, CSRNG_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
(csrng_app_cmd_t){
.id = kCsrngAppCmdUpdate,
.seed_material = seed_material,
Expand All @@ -104,7 +104,7 @@ dif_result_t dif_csrng_generate_start(const dif_csrng_t *csrng, size_t len) {
// Round up the number of 128bit blocks. Aligning with respect to uint32_t.
// TODO(#6112): Consider using a canonical reference for alignment operations.
const uint32_t num_128bit_blocks = (len + 3) / 4;
return csrng_send_app_cmd(csrng->base_addr, CSRNG_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
(csrng_app_cmd_t){
.id = kCsrngAppCmdGenerate,
.generate_len = num_128bit_blocks,
Expand All @@ -131,7 +131,7 @@ dif_result_t dif_csrng_uninstantiate(const dif_csrng_t *csrng) {
if (csrng == NULL) {
return kDifBadArg;
}
return csrng_send_app_cmd(csrng->base_addr, CSRNG_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
(csrng_app_cmd_t){
.id = kCsrngAppCmdUninstantiate,
});
Expand Down
43 changes: 42 additions & 1 deletion sw/device/lib/dif/dif_csrng_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

#include "sw/device/lib/base/multibits.h"

#include "csrng_regs.h" // Generated
#include "edn_regs.h" // Generated

// The application command header is not specified as a register in the
// hardware specification, so the fields are mapped here by hand. The
// command register also accepts arbitrary 32bit data.
Expand All @@ -29,8 +32,30 @@ uint32_t csrng_cmd_header_build(
return reg;
}

dif_result_t csrng_send_app_cmd(mmio_region_t base_addr, ptrdiff_t offset,
dif_result_t csrng_send_app_cmd(mmio_region_t base_addr,
csrng_app_cmd_type_t cmd_type,
csrng_app_cmd_t cmd) {
bool ready;
ptrdiff_t offset;
uint32_t reg;

switch (cmd_type) {
case kCsrngAppCmdTypeCsrng:
offset = CSRNG_CMD_REQ_REG_OFFSET;
break;
case kCsrngAppCmdTypeEdnSw:
offset = EDN_SW_CMD_REQ_REG_OFFSET;
break;
case kCsrngAppCmdTypeEdnGen:
offset = EDN_GENERATE_CMD_REG_OFFSET;
break;
case kCsrngAppCmdTypeEdnRes:
offset = EDN_RESEED_CMD_REG_OFFSET;
break;
default:
return kDifBadArg;
}

// Ensure the `seed_material` array is word-aligned, so it can be loaded to a
// CPU register with natively aligned loads.
if (cmd.seed_material != NULL &&
Expand All @@ -54,10 +79,26 @@ dif_result_t csrng_send_app_cmd(mmio_region_t base_addr, ptrdiff_t offset,
return kDifOutOfRange;
}

if (cmd_type == kCsrngAppCmdTypeEdnSw) {
// Wait for the status register to be ready to accept the next command.
do {
reg = mmio_region_read32(base_addr, EDN_SW_CMD_STS_REG_OFFSET);
ready = bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_RDY_BIT);
} while (!ready);
}

mmio_region_write32(base_addr, offset,
csrng_cmd_header_build(cmd.id, cmd.entropy_src_enable,
cmd_len, cmd.generate_len));
for (size_t i = 0; i < cmd_len; ++i) {
// If the command is issued to the SW register of the EDN, the reg ready
// bit needs to be polled before writing each word of additional data.
if (cmd_type == kCsrngAppCmdTypeEdnSw) {
do {
reg = mmio_region_read32(base_addr, EDN_SW_CMD_STS_REG_OFFSET);
ready = bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_REG_RDY_BIT);
} while (!ready);
}
mmio_region_write32(base_addr, offset, cmd.seed_material->seed_material[i]);
}
return kDifOk;
Expand Down
28 changes: 27 additions & 1 deletion sw/device/lib/dif/dif_csrng_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,31 @@ typedef struct csrng_app_cmd {
uint32_t generate_len;
} csrng_app_cmd_t;

/**
* This enum type contains all the different command types for
* csrng_send_cmd().
*/
typedef enum csrng_app_cmd_type {
/**
* Command issued directly to CSRNG.
*/
kCsrngAppCmdTypeCsrng,
/**
* Command issued to CSRNG via the SW_CMD_REQ register of the EDN.
*/
kCsrngAppCmdTypeEdnSw,
/**
* Command issued to CSRNG via the GENERATE_CMD register of the EDN.
* This type of command will be used in the auto mode of the EDN.
*/
kCsrngAppCmdTypeEdnGen,
/**
* Command issued to CSRNG via the RESEED_CMD register of the EDN.
* This type of command will be used in the auto mode of the EDN.
*/
kCsrngAppCmdTypeEdnRes,
} csrng_app_cmd_type_t;

/**
* Builds a CSRNG command header.
*
Expand All @@ -87,7 +112,8 @@ uint32_t csrng_cmd_header_build(
* Returns the result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t csrng_send_app_cmd(mmio_region_t base_addr, ptrdiff_t offset,
dif_result_t csrng_send_app_cmd(mmio_region_t base_addr,
csrng_app_cmd_type_t cmd_type,
csrng_app_cmd_t cmd);

#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_CSRNG_SHARED_H_
23 changes: 15 additions & 8 deletions sw/device/lib/dif/dif_edn.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,13 @@ dif_result_t dif_edn_set_auto_mode(const dif_edn_t *edn,
// Wait until CSRNG acknowledges command.
ready = false;
while (!ready) {
DIF_RETURN_IF_ERROR(dif_edn_get_status(edn, kDifEdnStatusReady, &ready));
DIF_RETURN_IF_ERROR(dif_edn_get_status(edn, kDifEdnStatusCsrngAck, &ready));
}

// Read request acknowledge error and return accordingly.
bool ack_err;
DIF_RETURN_IF_ERROR(dif_edn_get_status(edn, kDifEdnStatusCsrngAck, &ack_err));
DIF_RETURN_IF_ERROR(
dif_edn_get_status(edn, kDifEdnStatusCsrngStatus, &ack_err));
return ack_err ? kDifError : kDifOk;
}

Expand All @@ -158,12 +159,18 @@ dif_result_t dif_edn_get_status(const dif_edn_t *edn, dif_edn_status_t flag,

uint32_t bit;
switch (flag) {
case kDifEdnStatusRegReady:
bit = EDN_SW_CMD_STS_CMD_REG_RDY_BIT;
break;
case kDifEdnStatusReady:
bit = EDN_SW_CMD_STS_CMD_RDY_BIT;
break;
case kDifEdnStatusCsrngAck:
case kDifEdnStatusCsrngStatus:
bit = EDN_SW_CMD_STS_CMD_STS_BIT;
break;
case kDifEdnStatusCsrngAck:
bit = EDN_SW_CMD_STS_CMD_ACK_BIT;
break;
default:
return kDifBadArg;
}
Expand Down Expand Up @@ -280,7 +287,7 @@ dif_result_t dif_edn_instantiate(
return kDifBadArg;
}
return csrng_send_app_cmd(
edn->base_addr, EDN_SW_CMD_REQ_REG_OFFSET,
edn->base_addr, kCsrngAppCmdTypeEdnSw,
(csrng_app_cmd_t){
.id = kCsrngAppCmdInstantiate,
.entropy_src_enable =
Expand All @@ -296,7 +303,7 @@ dif_result_t dif_edn_reseed(const dif_edn_t *edn,
}
dif_csrng_seed_material_t seed_material2;
memcpy(&seed_material2, seed_material, sizeof(seed_material2));
return csrng_send_app_cmd(edn->base_addr, EDN_SW_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(edn->base_addr, kCsrngAppCmdTypeEdnSw,
(csrng_app_cmd_t){
.id = kCsrngAppCmdReseed,
.seed_material = &seed_material2,
Expand All @@ -310,7 +317,7 @@ dif_result_t dif_edn_update(const dif_edn_t *edn,
}
dif_csrng_seed_material_t seed_material2;
memcpy(&seed_material2, seed_material, sizeof(seed_material2));
return csrng_send_app_cmd(edn->base_addr, EDN_SW_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(edn->base_addr, kCsrngAppCmdTypeEdnSw,
(csrng_app_cmd_t){
.id = kCsrngAppCmdUpdate,
.seed_material = &seed_material2,
Expand All @@ -325,7 +332,7 @@ dif_result_t dif_edn_generate_start(const dif_edn_t *edn, size_t len) {
// Round up the number of 128bit blocks. Aligning with respect to uint32_t.
// TODO(#6112): Consider using a canonical reference for alignment operations.
const uint32_t num_128bit_blocks = (len + 3) / 4;
return csrng_send_app_cmd(edn->base_addr, EDN_SW_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(edn->base_addr, kCsrngAppCmdTypeEdnSw,
(csrng_app_cmd_t){
.id = kCsrngAppCmdGenerate,
.generate_len = num_128bit_blocks,
Expand All @@ -336,7 +343,7 @@ dif_result_t dif_edn_uninstantiate(const dif_edn_t *edn) {
if (edn == NULL) {
return kDifBadArg;
}
return csrng_send_app_cmd(edn->base_addr, EDN_SW_CMD_REQ_REG_OFFSET,
return csrng_send_app_cmd(edn->base_addr, kCsrngAppCmdTypeEdnSw,
(csrng_app_cmd_t){
.id = kCsrngAppCmdUninstantiate,
});
Expand Down
8 changes: 8 additions & 0 deletions sw/device/lib/dif/dif_edn.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,18 @@ typedef struct dif_edn_auto_params {
* EDN Status flags.
*/
typedef enum dif_edn_status {
/**
* SW command register is ready to receive the next word of a command.
*/
kDifEdnStatusRegReady,
/**
* Device is ready to receive a command.
*/
kDifEdnStatusReady,
/**
* Device has received an error from the CSRNG block.
*/
kDifEdnStatusCsrngStatus,
/**
* Device has recieved an ACK from the CSRNG block.
*/
Expand Down
Loading

0 comments on commit c6abdc3

Please sign in to comment.