5#include "sw/device/lib/dif/dif_rv_core_ibex.h"
16#include "rv_core_ibex_regs.h"
22static_assert(kDifRvCoreIbexErrorStatusRegisterTransmissionIntegrity ==
23 1 << RV_CORE_IBEX_ERR_STATUS_REG_INTG_ERR_BIT,
24 "Layout of RV_CORE_IBEX_ERR_STATUS_REG register changed.");
25static_assert(kDifRvCoreIbexErrorStatusFatalResponseIntegrity ==
26 1 << RV_CORE_IBEX_ERR_STATUS_FATAL_INTG_ERR_BIT,
27 "Layout of RV_CORE_IBEX_ERR_STATUS_REG register changed.");
28static_assert(kDifRvCoreIbexErrorStatusFatalInternalError ==
29 1 << RV_CORE_IBEX_ERR_STATUS_FATAL_CORE_ERR_BIT,
30 "Layout of RV_CORE_IBEX_ERR_STATUS_REG register changed.");
31static_assert(kDifRvCoreIbexErrorStatusRecoverableInternal ==
32 1 << RV_CORE_IBEX_ERR_STATUS_RECOV_CORE_ERR_BIT,
33 "Layout of RV_CORE_IBEX_ERR_STATUS_REG register changed.");
40} ibex_addr_translation_regs_t;
42static const ibex_addr_translation_regs_t kRegsMap
43 [kDifRvCoreIbexAddrTranslationSlotCount]
44 [kDifRvCoreIbexAddrTranslationSlotCount] = {
45 [kDifRvCoreIbexAddrTranslationSlot_0]
46 [kDifRvCoreIbexAddrTranslationDBus] =
48 .matching = RV_CORE_IBEX_DBUS_ADDR_MATCHING_0_REG_OFFSET,
49 .remap = RV_CORE_IBEX_DBUS_REMAP_ADDR_0_REG_OFFSET,
50 .en = RV_CORE_IBEX_DBUS_ADDR_EN_0_REG_OFFSET,
51 .lock = RV_CORE_IBEX_DBUS_REGWEN_0_REG_OFFSET,
53 [kDifRvCoreIbexAddrTranslationSlot_0]
54 [kDifRvCoreIbexAddrTranslationIBus] =
56 .matching = RV_CORE_IBEX_IBUS_ADDR_MATCHING_0_REG_OFFSET,
57 .remap = RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET,
58 .en = RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET,
59 .lock = RV_CORE_IBEX_IBUS_REGWEN_0_REG_OFFSET,
61 [kDifRvCoreIbexAddrTranslationSlot_1]
62 [kDifRvCoreIbexAddrTranslationDBus] =
64 .matching = RV_CORE_IBEX_DBUS_ADDR_MATCHING_1_REG_OFFSET,
65 .remap = RV_CORE_IBEX_DBUS_REMAP_ADDR_1_REG_OFFSET,
66 .en = RV_CORE_IBEX_DBUS_ADDR_EN_1_REG_OFFSET,
67 .lock = RV_CORE_IBEX_DBUS_REGWEN_1_REG_OFFSET,
69 [kDifRvCoreIbexAddrTranslationSlot_1]
70 [kDifRvCoreIbexAddrTranslationIBus] =
72 .matching = RV_CORE_IBEX_IBUS_ADDR_MATCHING_1_REG_OFFSET,
73 .remap = RV_CORE_IBEX_IBUS_REMAP_ADDR_1_REG_OFFSET,
74 .en = RV_CORE_IBEX_IBUS_ADDR_EN_1_REG_OFFSET,
75 .lock = RV_CORE_IBEX_IBUS_REGWEN_1_REG_OFFSET,
86static uint32_t to_napot(uint32_t addr,
size_t size) {
87 return addr | (size - 1) >> 1;
97static uint32_t from_napot(uint32_t napot,
size_t *size) {
98 for (
size_t i = 1; i <
sizeof(uint32_t) * 8; ++i) {
99 uint32_t ref = (1u << i) - 1;
100 if ((napot & ref) == ref >> 1) {
105 return napot & ~((*size - 1) >> 1);
108dif_result_t dif_rv_core_ibex_configure_addr_translation(
110 dif_rv_core_ibex_addr_translation_slot_t slot,
111 dif_rv_core_ibex_addr_translation_bus_t bus,
112 dif_rv_core_ibex_addr_translation_mapping_t addr_map) {
113 if (rv_core_ibex == NULL || slot >= kDifRvCoreIbexAddrTranslationSlotCount ||
114 bus >= kDifRvCoreIbexAddrTranslationBusCount ||
115 !bitfield_is_power_of_two32(addr_map.
size)) {
119 const ibex_addr_translation_regs_t regs = kRegsMap[slot][bus];
121 if (mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.lock) == 0) {
126 mmio_region_write32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.matching, mask);
127 mmio_region_write32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.remap,
135 dif_rv_core_ibex_addr_translation_slot_t slot,
136 dif_rv_core_ibex_addr_translation_bus_t bus) {
137 if (rv_core_ibex == NULL || slot >= kDifRvCoreIbexAddrTranslationSlotCount ||
138 bus >= kDifRvCoreIbexAddrTranslationBusCount) {
141 const ibex_addr_translation_regs_t regs = kRegsMap[slot][bus];
142 if (mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.lock) == 0) {
145 mmio_region_write32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.en, 1);
152 dif_rv_core_ibex_addr_translation_slot_t slot,
153 dif_rv_core_ibex_addr_translation_bus_t bus) {
154 if (rv_core_ibex == NULL || slot >= kDifRvCoreIbexAddrTranslationSlotCount ||
155 bus >= kDifRvCoreIbexAddrTranslationBusCount) {
158 const ibex_addr_translation_regs_t regs = kRegsMap[slot][bus];
159 if (mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.lock) == 0) {
162 mmio_region_write32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.en, 0);
169 dif_rv_core_ibex_addr_translation_slot_t slot,
170 dif_rv_core_ibex_addr_translation_bus_t bus,
171 dif_rv_core_ibex_addr_translation_mapping_t *addr_map) {
172 if (rv_core_ibex == NULL || addr_map == NULL ||
173 slot >= kDifRvCoreIbexAddrTranslationSlotCount ||
174 bus >= kDifRvCoreIbexAddrTranslationBusCount) {
178 const ibex_addr_translation_regs_t regs = kRegsMap[slot][bus];
181 mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.matching);
185 mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.remap);
192 dif_rv_core_ibex_addr_translation_slot_t slot,
193 dif_rv_core_ibex_addr_translation_bus_t bus) {
194 if (rv_core_ibex == NULL || slot >= kDifRvCoreIbexAddrTranslationSlotCount ||
195 bus >= kDifRvCoreIbexAddrTranslationBusCount) {
198 const ibex_addr_translation_regs_t regs = kRegsMap[slot][bus];
201 if (mmio_region_read32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.lock) == 1) {
202 mmio_region_write32(rv_core_ibex->
base_addr, (ptrdiff_t)regs.lock, 0);
210 dif_rv_core_ibex_error_status_t *error_status) {
211 if (rv_core_ibex == NULL || error_status == NULL) {
215 *error_status = mmio_region_read32(rv_core_ibex->
base_addr,
216 RV_CORE_IBEX_ERR_STATUS_REG_OFFSET);
223 dif_rv_core_ibex_error_status_t error_status) {
224 if (rv_core_ibex == NULL ||
225 (error_status & ~(uint32_t)kDifRvCoreIbexErrorStatusAll) != 0) {
229 mmio_region_write32(rv_core_ibex->
base_addr,
230 RV_CORE_IBEX_ERR_STATUS_REG_OFFSET, error_status);
236 dif_rv_core_ibex_nmi_source_t nmi) {
237 if (rv_core_ibex == NULL || nmi & ~(uint32_t)kDifRvCoreIbexNmiSourceAll) {
242 reg = bitfield_bit32_write(
243 reg, RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT,
244 (nmi & kDifRvCoreIbexNmiSourceAlert) == kDifRvCoreIbexNmiSourceAlert);
245 reg = bitfield_bit32_write(
246 reg, RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT,
247 (nmi & kDifRvCoreIbexNmiSourceWdog) == kDifRvCoreIbexNmiSourceWdog);
249 mmio_region_write32(rv_core_ibex->
base_addr,
250 RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET, reg);
257 dif_rv_core_ibex_nmi_state_t *nmi_state) {
258 if (rv_core_ibex == NULL || nmi_state == NULL) {
262 *nmi_state = (dif_rv_core_ibex_nmi_state_t){0};
264 uint32_t reg = mmio_region_read32(rv_core_ibex->
base_addr,
265 RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET);
267 bitfield_bit32_read(reg, RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT);
269 bitfield_bit32_read(reg, RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT);
271 reg = mmio_region_read32(rv_core_ibex->
base_addr,
272 RV_CORE_IBEX_NMI_STATE_REG_OFFSET);
274 bitfield_bit32_read(reg, RV_CORE_IBEX_NMI_STATE_ALERT_BIT);
276 bitfield_bit32_read(reg, RV_CORE_IBEX_NMI_STATE_WDOG_BIT);
283 if (rv_core_ibex == NULL || nmi & ~(uint32_t)kDifRvCoreIbexNmiSourceAll) {
288 reg = bitfield_bit32_write(
289 reg, RV_CORE_IBEX_NMI_STATE_ALERT_BIT,
290 (nmi & kDifRvCoreIbexNmiSourceAlert) == kDifRvCoreIbexNmiSourceAlert);
291 reg = bitfield_bit32_write(
292 reg, RV_CORE_IBEX_NMI_STATE_WDOG_BIT,
293 (nmi & kDifRvCoreIbexNmiSourceWdog) == kDifRvCoreIbexNmiSourceWdog);
295 mmio_region_write32(rv_core_ibex->
base_addr,
296 RV_CORE_IBEX_NMI_STATE_REG_OFFSET, reg);
302 dif_rv_core_ibex_rnd_status_t *
status) {
303 if (rv_core_ibex == NULL ||
status == NULL) {
308 RV_CORE_IBEX_RND_STATUS_REG_OFFSET);
314 if (rv_core_ibex == NULL || data == NULL) {
318 *data = mmio_region_read32(rv_core_ibex->
base_addr,
319 RV_CORE_IBEX_RND_DATA_REG_OFFSET);
325 dif_rv_core_ibex_fpga_info_t *info) {
326 if (rv_core_ibex == NULL || info == NULL) {
330 *info = mmio_region_read32(rv_core_ibex->
base_addr,
331 RV_CORE_IBEX_FPGA_INFO_REG_OFFSET);
337 if (rv_core_ibex == NULL || enabled == NULL) {
340 uint32_t reg = mmio_region_read32(rv_core_ibex->
base_addr,
341 RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET);
342 *enabled = reg != kMultiBitBool4False;
346dif_result_t dif_rv_core_ibex_trigger_sw_recov_err_alert(
348 if (rv_core_ibex == NULL) {
353 reg = bitfield_field32_write(reg, RV_CORE_IBEX_SW_RECOV_ERR_VAL_FIELD,
356 mmio_region_write32(rv_core_ibex->
base_addr,
357 RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET, reg);
363 if (rv_core_ibex == NULL || enabled == NULL) {
366 uint32_t reg = mmio_region_read32(rv_core_ibex->
base_addr,
367 RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET);
368 *enabled = reg != kMultiBitBool4False;
372dif_result_t dif_rv_core_ibex_trigger_sw_fatal_err_alert(
374 if (rv_core_ibex == NULL) {
379 reg = bitfield_field32_write(reg, RV_CORE_IBEX_SW_FATAL_ERR_VAL_FIELD,
382 mmio_region_write32(rv_core_ibex->
base_addr,
383 RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET, reg);
388 kIbexCrashDumpBytesCount =
sizeof(dif_rv_core_ibex_crash_dump_info_t),
389 kIbexCrashDumpWordsCount = kIbexCrashDumpBytesCount /
sizeof(uint32_t),
390 kIbexCrashDumpStateBytesCount =
sizeof(dif_rv_core_ibex_crash_dump_state_t),
391 kIbexCrashDumpStateWordsCount =
392 kIbexCrashDumpStateBytesCount /
sizeof(uint32_t),
393 kIbexCrashDumpPreviousStateBytesCount =
394 sizeof(dif_rv_core_ibex_previous_crash_dump_state_t),
395 kIbexCrashDumpPreviousStateWordsCount =
396 kIbexCrashDumpPreviousStateBytesCount /
sizeof(uint32_t),
401 uint32_t cpu_info_len,
402 dif_rv_core_ibex_crash_dump_info_t *crash_dump_info) {
403 if (rv_core_ibex == NULL || cpu_info == NULL || crash_dump_info == NULL ||
404 cpu_info_len < kIbexCrashDumpWordsCount) {
408 memcpy(crash_dump_info, cpu_info, kIbexCrashDumpBytesCount - 1);
410 dif_bool_to_toggle(cpu_info[kIbexCrashDumpWordsCount - 1] == 1);