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 
15 static const dt_rv_core_ibex_t kRvCoreIbexDt = kDtRvCoreIbex;
16 
17 /**
18  * Base address of the rv_core_ibex registers.
19  *
20  */
21 static inline uint32_t rv_core_ibex_base(void) {
22  return dt_rv_core_ibex_reg_block(kRvCoreIbexDt, kDtRvCoreIbexRegBlockCfg);
23 }
24 
25 uint32_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 
30 void 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);
50 }
51 
52 void 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);
72 }
73 
74 uint32_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 
86 void 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.
96 extern void ibex_mcycle_zero(void);
97 extern uint32_t ibex_mcycle32(void);
98 extern uint64_t ibex_mcycle(void);
99 extern uint64_t ibex_time_to_cycles(uint64_t time_us);