5#include "sw/device/silicon_creator/lib/drivers/rram_ctrl.h"
14#include "sw/device/lib/base/multibits.h"
16#include "sw/device/silicon_creator/lib/drivers/otp.h"
17#include "sw/device/silicon_creator/lib/error.h"
19#include "hw/top/otp_ctrl_regs.h"
30static inline uint32_t rram_ctrl_core_base(
void) {
56} transaction_params_t;
63static void transaction_start(transaction_params_t params) {
64 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_ADDR_REG_OFFSET,
66 uint32_t reg = bitfield_bit32_write(0, RRAM_CTRL_CONTROL_START_BIT,
true);
67 reg = bitfield_field32_write(reg, RRAM_CTRL_CONTROL_OP_FIELD, params.
op_type);
68 reg = bitfield_bit32_write(reg, RRAM_CTRL_CONTROL_PARTITION_BIT,
70 reg = bitfield_field32_write(reg, RRAM_CTRL_CONTROL_NUM_FIELD,
72 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_CONTROL_REG_OFFSET, reg);
81static void fifo_read(
size_t word_count,
void *data) {
82 size_t i = 0, r = word_count - 1;
83 for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
85 abs_mmio_read32(rram_ctrl_core_base() + RRAM_CTRL_RD_FIFO_REG_OFFSET),
87 data = (
char *)data +
sizeof(uint32_t);
99static void fifo_write(
size_t word_count,
const void *data) {
100 size_t i = 0, r = word_count - 1;
101 for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
102 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_WR_FIFO_REG_OFFSET,
104 data = (
const char *)data +
sizeof(uint32_t);
117static rom_error_t wait_for_done(rom_error_t error) {
121 abs_mmio_read32(rram_ctrl_core_base() + RRAM_CTRL_OP_STATUS_REG_OFFSET);
122 }
while (!bitfield_bit32_read(op_status, RRAM_CTRL_OP_STATUS_DONE_BIT));
123 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_OP_STATUS_REG_OFFSET, 0u);
125 if (bitfield_bit32_read(op_status, RRAM_CTRL_OP_STATUS_ERR_BIT)) {
139 kRramWriteGranuleWords = 4,
140 kRramWriteGranuleBytes = kRramWriteGranuleWords * (uint32_t)
sizeof(uint32_t),
142static_assert((kRramWriteGranuleBytes & (kRramWriteGranuleBytes - 1)) == 0,
143 "RRAM write granule must be a power of two.");
157static rom_error_t read(uint32_t addr,
bool is_info, uint32_t word_count,
158 void *data, rom_error_t error) {
159 transaction_start((transaction_params_t){
161 .op_type = RRAM_CTRL_CONTROL_OP_VALUE_READ,
163 .word_count = word_count,
165 fifo_read(word_count, data);
166 return wait_for_done(error);
187static rom_error_t write_aligned(uint32_t addr,
bool is_info,
188 uint32_t word_count,
const void *data,
191 kMaxWordCount = RRAM_CTRL_CONTROL_NUM_MASK + 1,
193 if (word_count % kRramWriteGranuleWords != 0) {
197 while (word_count > 0) {
198 uint32_t chunk_word_count =
199 word_count < kMaxWordCount ? word_count : kMaxWordCount;
201 transaction_start((transaction_params_t){
203 .op_type = RRAM_CTRL_CONTROL_OP_VALUE_WRITE,
205 .word_count = chunk_word_count,
208 fifo_write(chunk_word_count, data);
209 RETURN_IF_ERROR(wait_for_done(error));
211 addr += chunk_word_count *
sizeof(uint32_t);
212 data = (
const char *)data + chunk_word_count *
sizeof(uint32_t);
213 word_count -= chunk_word_count;
227static rom_error_t granule_rmw(uint32_t aligned_addr,
bool is_info,
size_t lead,
228 const void *data,
size_t len,
229 rom_error_t write_error,
230 rom_error_t read_error) {
231 uint8_t buf[kRramWriteGranuleBytes];
233 read(aligned_addr, is_info, kRramWriteGranuleWords, buf, read_error));
234 memcpy(buf + lead, data, len);
235 return write_aligned(aligned_addr, is_info, kRramWriteGranuleWords, buf,
261static rom_error_t write(uint32_t addr,
bool is_info, uint32_t word_count,
262 const void *data, rom_error_t write_error,
263 rom_error_t read_error) {
264 if (word_count == 0) {
268 size_t byte_count = (size_t)word_count *
sizeof(uint32_t);
269 uint32_t aligned_addr = addr & ~(uint32_t)(kRramWriteGranuleBytes - 1);
270 size_t lead = addr - aligned_addr;
272 if (lead == 0 && byte_count % kRramWriteGranuleBytes == 0) {
274 return write_aligned(addr, is_info, word_count, data, write_error);
278 size_t first_chunk_len = kRramWriteGranuleBytes - lead;
279 if (first_chunk_len > byte_count) {
280 first_chunk_len = byte_count;
282 RETURN_IF_ERROR(granule_rmw(aligned_addr, is_info, lead, data,
283 first_chunk_len, write_error, read_error));
284 data = (
const char *)data + first_chunk_len;
285 byte_count -= first_chunk_len;
286 aligned_addr += kRramWriteGranuleBytes;
289 size_t middle_words =
290 (byte_count / kRramWriteGranuleBytes) * kRramWriteGranuleWords;
291 if (middle_words > 0) {
292 RETURN_IF_ERROR(write_aligned(aligned_addr, is_info, (uint32_t)middle_words,
294 size_t middle_bytes = middle_words *
sizeof(uint32_t);
295 data = (
const char *)data + middle_bytes;
296 byte_count -= middle_bytes;
297 aligned_addr += middle_bytes;
301 if (byte_count > 0) {
302 RETURN_IF_ERROR(granule_rmw(aligned_addr, is_info, 0, data, byte_count,
303 write_error, read_error));
308void rram_ctrl_init(
void) {
313 extern char _nvm_slot_reserved_bytes[];
315 (uint32_t)_nvm_slot_reserved_bytes,
316 kRramCtrlReservedPageCount * RRAM_CTRL_PARAM_BYTES_PER_PAGE);
319 kRramCtrlSecMmioDataDefaultCfgSet);
324 uint32_t reg_val = RRAM_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL;
326 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_NVM_HW_INFO_CFG_OVERRIDE_OFFSET);
327 multi_bit_bool_t scramble_dis = bitfield_field32_read(
328 otp_val, RRAM_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS);
329 if (scramble_dis == kMultiBitBool4True) {
330 reg_val = bitfield_field32_write(
331 reg_val, RRAM_CTRL_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS_FIELD,
334 multi_bit_bool_t ecc_dis = bitfield_field32_read(
335 otp_val, RRAM_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_ECC_DIS);
336 if (ecc_dis == kMultiBitBool4True) {
337 reg_val = bitfield_field32_write(
338 reg_val, RRAM_CTRL_HW_INFO_CFG_OVERRIDE_ECC_DIS_FIELD, ecc_dis);
340 if (reg_val != RRAM_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL) {
342 rram_ctrl_core_base() + RRAM_CTRL_HW_INFO_CFG_OVERRIDE_REG_OFFSET,
351 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_INIT_REG_OFFSET,
352 bitfield_bit32_write(0, RRAM_CTRL_INIT_VAL_BIT,
true));
353 rram_ctrl_status_t
status;
355 rram_ctrl_status_get(&
status);
356 }
while (!
status.init_done);
362 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_NVM_DATA_DEFAULT_CFG_OFFSET);
363 rram_ctrl_cfg_t data_default_cfg = {
365 bitfield_field32_read(otp_val, RRAM_CTRL_OTP_FIELD_SCRAMBLING),
366 .ecc = bitfield_field32_read(otp_val, RRAM_CTRL_OTP_FIELD_ECC),
368 rram_ctrl_data_default_cfg_set(data_default_cfg);
371void rram_ctrl_disable(
void) {
372 abs_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_DIS_REG_OFFSET, 0);
375void rram_ctrl_status_get(rram_ctrl_status_t *
status) {
377 abs_mmio_read32(rram_ctrl_core_base() + RRAM_CTRL_STATUS_REG_OFFSET);
378 status->rd_full = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_RD_FULL_BIT);
379 status->rd_empty = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_RD_EMPTY_BIT);
380 status->wr_full = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_WR_FULL_BIT);
381 status->wr_empty = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_WR_EMPTY_BIT);
382 status->init_done = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_INIT_DONE_BIT);
385void rram_ctrl_error_code_get(rram_ctrl_error_code_t *error_code) {
387 abs_mmio_read32(rram_ctrl_core_base() + RRAM_CTRL_ERR_CODE_REG_OFFSET);
388 error_code->
op_err = bitfield_bit32_read(code, RRAM_CTRL_ERR_CODE_OP_ERR_BIT);
389 error_code->
mp_err = bitfield_bit32_read(code, RRAM_CTRL_ERR_CODE_MP_ERR_BIT);
390 error_code->
rd_err = bitfield_bit32_read(code, RRAM_CTRL_ERR_CODE_RD_ERR_BIT);
391 error_code->
wr_err = bitfield_bit32_read(code, RRAM_CTRL_ERR_CODE_WR_ERR_BIT);
394rom_error_t rram_ctrl_data_read(uint32_t addr, uint32_t word_count,
396 return read(addr,
false, word_count, data,
397 kErrorRramCtrlDataRead);
400static uint32_t info_page_addr(
const rram_ctrl_info_page_t *info_page,
403 return info_page->
page_id * RRAM_CTRL_PARAM_BYTES_PER_PAGE + offset;
406rom_error_t rram_ctrl_info_read(
const rram_ctrl_info_page_t *info_page,
407 uint32_t offset, uint32_t word_count,
409 return read(info_page_addr(info_page, offset),
true, word_count,
410 data, kErrorRramCtrlInfoRead);
413rom_error_t rram_ctrl_info_read_zeros_on_read_error(
414 const rram_ctrl_info_page_t *info_page, uint32_t offset,
415 uint32_t word_count,
void *data) {
416 rom_error_t err = rram_ctrl_info_read(info_page, offset, word_count, data);
417 if (err != kErrorOk) {
418 rram_ctrl_error_code_t rram_ctrl_err_code;
419 rram_ctrl_error_code_get(&rram_ctrl_err_code);
420 if (rram_ctrl_err_code.
rd_err) {
422 memset(data, 0, word_count *
sizeof(uint32_t));
429rom_error_t rram_ctrl_data_write(uint32_t addr, uint32_t word_count,
431 return write(addr,
false, word_count, data,
432 kErrorRramCtrlDataWrite, kErrorRramCtrlDataRead);
435rom_error_t rram_ctrl_info_write(
const rram_ctrl_info_page_t *info_page,
436 uint32_t offset, uint32_t word_count,
438 return write(info_page_addr(info_page, offset),
true, word_count,
439 data, kErrorRramCtrlInfoWrite, kErrorRramCtrlInfoRead);
442void rram_ctrl_exec_set(uint32_t exec_val) {
444 sec_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_EXEC_REG_OFFSET, exec_val);
447void rram_ctrl_data_default_perms_set(rram_ctrl_perms_t perms) {
452 RRAM_CTRL_DEFAULT_REGION_REG_OFFSET);
453 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_RD_EN_FIELD,
455 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_WR_EN_FIELD,
457 sec_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_DEFAULT_REGION_REG_OFFSET,
461void rram_ctrl_info_perms_set(
const rram_ctrl_info_page_t *info_page,
462 rram_ctrl_perms_t perms) {
466 uint32_t cfg_offset = RRAM_CTRL_INFO_PAGE_CFG_0_REG_OFFSET +
467 info_page->
page_id *
sizeof(uint32_t);
470 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_EN_0_FIELD,
472 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_RD_EN_0_FIELD,
474 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_WR_EN_0_FIELD,
479void rram_ctrl_data_default_cfg_set(rram_ctrl_cfg_t cfg) {
484 RRAM_CTRL_DEFAULT_REGION_REG_OFFSET);
485 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
487 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_ECC_EN_FIELD,
489 sec_mmio_write32(rram_ctrl_core_base() + RRAM_CTRL_DEFAULT_REGION_REG_OFFSET,
493rram_ctrl_cfg_t rram_ctrl_data_default_cfg_get(
void) {
495 rram_ctrl_core_base() + RRAM_CTRL_DEFAULT_REGION_REG_OFFSET);
496 return (rram_ctrl_cfg_t){
497 .scrambling = bitfield_field32_read(
498 default_region, RRAM_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
499 .ecc = bitfield_field32_read(default_region,
500 RRAM_CTRL_DEFAULT_REGION_ECC_EN_FIELD),
504rram_ctrl_cfg_t rram_ctrl_boot_data_cfg_get(
void) {
506 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_NVM_INFO_BOOT_DATA_CFG_OFFSET);
507 return (rram_ctrl_cfg_t){
509 bitfield_field32_read(otp_val, RRAM_CTRL_OTP_FIELD_SCRAMBLING),
510 .ecc = bitfield_field32_read(otp_val, RRAM_CTRL_OTP_FIELD_ECC),
514void rram_ctrl_data_region_protect(rram_ctrl_region_index_t region,
515 uint32_t page_offset, uint32_t num_pages,
516 rram_ctrl_perms_t perms, rram_ctrl_cfg_t cfg,
518 const uint32_t kBase = rram_ctrl_core_base();
519 HARDENED_CHECK_GE(region, 0);
520 HARDENED_CHECK_LT(region, RRAM_CTRL_PARAM_NUM_REGIONS);
524 HARDENED_CHECK_GE(num_pages, 1);
525 region *=
sizeof(uint32_t);
533 abs_mmio_write32(kBase + RRAM_CTRL_MP_REGION_CFG_0_REG_OFFSET + region,
534 RRAM_CTRL_MP_REGION_CFG_0_REG_RESVAL);
543 uint32_t mp_region = RRAM_CTRL_MP_REGION_0_REG_RESVAL;
544 mp_region = bitfield_field32_write(
545 mp_region, RRAM_CTRL_MP_REGION_0_BASE_0_FIELD, page_offset);
546 mp_region = bitfield_field32_write(
547 mp_region, RRAM_CTRL_MP_REGION_0_SIZE_0_FIELD, num_pages - 1);
552 uint32_t mp_region_cfg = RRAM_CTRL_MP_REGION_CFG_0_REG_RESVAL;
553 mp_region_cfg = bitfield_field32_write(
554 mp_region_cfg, RRAM_CTRL_MP_REGION_CFG_0_ECC_EN_0_FIELD, cfg.
ecc);
555 mp_region_cfg = bitfield_field32_write(
556 mp_region_cfg, RRAM_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD,
558 mp_region_cfg = bitfield_field32_write(
559 mp_region_cfg, RRAM_CTRL_MP_REGION_CFG_0_WR_EN_0_FIELD, perms.
write);
560 mp_region_cfg = bitfield_field32_write(
561 mp_region_cfg, RRAM_CTRL_MP_REGION_CFG_0_RD_EN_0_FIELD, perms.
read);
562 mp_region_cfg = bitfield_field32_write(
563 mp_region_cfg, RRAM_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4True);
575void rram_ctrl_info_cfg_set(
const rram_ctrl_info_page_t *info_page,
576 rram_ctrl_cfg_t cfg) {
580 uint32_t cfg_offset = RRAM_CTRL_INFO_PAGE_CFG_0_REG_OFFSET +
581 info_page->
page_id *
sizeof(uint32_t);
584 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_EN_0_FIELD,
586 reg = bitfield_field32_write(
587 reg, RRAM_CTRL_INFO_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD, cfg.
scrambling);
588 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_ECC_EN_0_FIELD,
593void rram_ctrl_info_cfg_lock(
const rram_ctrl_info_page_t *info_page) {
595 uint32_t regwen_offset = RRAM_CTRL_INFO_REGWEN_0_REG_OFFSET +
596 info_page->
page_id *
sizeof(uint32_t);
600void rram_ctrl_info_page_lockdown(
const rram_ctrl_info_page_t *info_page) {
602 uint32_t cfg_offset = RRAM_CTRL_INFO_PAGE_CFG_0_REG_OFFSET +
603 info_page->
page_id *
sizeof(uint32_t);
604 uint32_t regwen_offset = RRAM_CTRL_INFO_REGWEN_0_REG_OFFSET +
605 info_page->
page_id *
sizeof(uint32_t);