Software APIs
ibex.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "sw/device/silicon_creator/lib/drivers/ibex.h"
6
7#include "dt/dt_rv_core_ibex.h"
12
13#include "rv_core_ibex_regs.h"
14
15static const dt_rv_core_ibex_t kRvCoreIbexDt = kDtRvCoreIbex;
16
17/**
18 * Base address of the rv_core_ibex registers.
19 *
20 */
21static inline uint32_t rv_core_ibex_base(void) {
22 return dt_rv_core_ibex_reg_block(kRvCoreIbexDt, kDtRvCoreIbexRegBlockCfg);
23}
24
25uint32_t ibex_fpga_version(void) {
26 const uint32_t kBase = rv_core_ibex_base();
27 return abs_mmio_read32(kBase + RV_CORE_IBEX_FPGA_INFO_REG_OFFSET);
28}
29
30void ibex_addr_remap_0_set(uint32_t matching_addr, uint32_t remap_addr,
31 size_t size) {
32 const uint32_t kBase = rv_core_ibex_base();
33 // Work-around for opentitan#22884: Mask off bits below the alignment size
34 // prior to programming the REMAP_ADDR register.
35 size = size - 1;
36 uint32_t match = (matching_addr & ~size) | size >> 1;
37 remap_addr &= ~size;
38
39 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_MATCHING_0_REG_OFFSET, match);
40 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_MATCHING_0_REG_OFFSET, match);
41
42 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET,
43 remap_addr);
44 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_REMAP_ADDR_0_REG_OFFSET,
45 remap_addr);
46
47 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET, 1);
48 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_EN_0_REG_OFFSET, 1);
49 icache_invalidate();
50}
51
52void ibex_addr_remap_1_set(uint32_t matching_addr, uint32_t remap_addr,
53 size_t size) {
54 const uint32_t kBase = rv_core_ibex_base();
55 // Work-around for opentitan#22884: Mask off bits below the alignment size
56 // prior to programming the REMAP_ADDR register.
57 size = size - 1;
58 uint32_t match = (matching_addr & ~size) | size >> 1;
59 remap_addr &= ~size;
60
61 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_MATCHING_1_REG_OFFSET, match);
62 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_MATCHING_1_REG_OFFSET, match);
63
64 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_REMAP_ADDR_1_REG_OFFSET,
65 remap_addr);
66 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_REMAP_ADDR_1_REG_OFFSET,
67 remap_addr);
68
69 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_ADDR_EN_1_REG_OFFSET, 1);
70 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_ADDR_EN_1_REG_OFFSET, 1);
71 icache_invalidate();
72}
73
74uint32_t ibex_addr_remap_get(uint32_t index) {
75 const uint32_t kBase = rv_core_ibex_base();
76 HARDENED_CHECK_LT(index, 2);
77 index *= sizeof(uint32_t);
78 if (abs_mmio_read32(kBase + RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET + index)) {
79 return abs_mmio_read32(kBase + RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET +
80 index);
81 } else {
82 return 0;
83 }
84}
85
86void ibex_addr_remap_lockdown(uint32_t index) {
87 const uint32_t kBase = rv_core_ibex_base();
88 HARDENED_CHECK_LT(index, 2);
89 index *= sizeof(uint32_t);
90 sec_mmio_write32(kBase + RV_CORE_IBEX_IBUS_REGWEN_0_REG_OFFSET + index, 0);
91 sec_mmio_write32(kBase + RV_CORE_IBEX_DBUS_REGWEN_0_REG_OFFSET + index, 0);
92}
93
94// `extern` declarations to give the inline functions in the corresponding
95// header a link location.
96extern void ibex_mcycle_zero(void);
97extern uint32_t ibex_mcycle32(void);
98extern uint64_t ibex_mcycle(void);
99extern uint64_t ibex_time_to_cycles(uint64_t time_us);