Software APIs
rstmgr.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/rstmgr.h"
6 
7 #include <assert.h>
8 
13 #include "sw/device/lib/base/multibits.h"
14 #include "sw/device/silicon_creator/lib/drivers/otp.h"
15 
16 #ifdef OT_PLATFORM_RV32
18 #endif
19 
21 #include "otp_ctrl_regs.h"
22 #include "rstmgr_regs.h"
23 
24 enum {
26 };
27 
28 void rstmgr_alert_info_collect(rstmgr_info_t *info) {
30  abs_mmio_read32(kBase + RSTMGR_ALERT_INFO_ATTR_REG_OFFSET),
31  RSTMGR_ALERT_INFO_ATTR_CNT_AVAIL_FIELD);
32  for (uint32_t i = 0; i < info->length; ++i) {
33  abs_mmio_write32(
34  kBase + RSTMGR_ALERT_INFO_CTRL_REG_OFFSET,
35  bitfield_field32_write(0, RSTMGR_ALERT_INFO_CTRL_INDEX_FIELD, i));
36  info->info[i] = abs_mmio_read32(kBase + RSTMGR_ALERT_INFO_REG_OFFSET);
37  }
38 }
39 
40 void rstmgr_cpu_info_collect(rstmgr_info_t *info) {
42  abs_mmio_read32(kBase + RSTMGR_CPU_INFO_ATTR_REG_OFFSET),
43  RSTMGR_CPU_INFO_ATTR_CNT_AVAIL_FIELD);
44  for (uint32_t i = 0; i < info->length; ++i) {
45  abs_mmio_write32(
46  kBase + RSTMGR_CPU_INFO_CTRL_REG_OFFSET,
47  bitfield_field32_write(0, RSTMGR_CPU_INFO_CTRL_INDEX_FIELD, i));
48  info->info[i] = abs_mmio_read32(kBase + RSTMGR_CPU_INFO_REG_OFFSET);
49  }
50 }
51 
52 uint32_t rstmgr_reason_get(void) {
53  // Static assertions for bitfield indices.
54 #define REASON_ASSERT(index, expect) \
55  static_assert((index) == (expect), #index " value incorrect.");
56 
57  REASON_ASSERT(kRstmgrReasonPowerOn, RSTMGR_RESET_INFO_POR_BIT);
58  REASON_ASSERT(kRstmgrReasonLowPowerExit,
59  RSTMGR_RESET_INFO_LOW_POWER_EXIT_BIT);
60  REASON_ASSERT(kRstmgrReasonSysrstCtrl,
61  RSTMGR_RESET_INFO_HW_REQ_OFFSET +
62  kTopEarlgreyPowerManagerResetRequestsSysrstCtrlAonRstReq);
63  REASON_ASSERT(
64  kRstmgrReasonWatchdog,
65  RSTMGR_RESET_INFO_HW_REQ_OFFSET +
66  kTopEarlgreyPowerManagerResetRequestsAonTimerAonAonTimerRstReq);
67 
68  // Alert escalation is one bit after the reset request index for the last
69  // peripheral.
70  REASON_ASSERT(kRstmgrReasonEscalation,
71  RSTMGR_RESET_INFO_HW_REQ_OFFSET +
72  kTopEarlgreyPowerManagerResetRequestsLast + 2)
73 
74  // Check that the last index corresponds to the last bit in HW_REQ.
75  static_assert(
76  ((1 << (kRstmgrReasonLast - RSTMGR_RESET_INFO_HW_REQ_OFFSET + 1)) - 1) ==
77  RSTMGR_RESET_INFO_HW_REQ_MASK,
78  "kRstmgrReasonLast value incorrect.");
79 
80 #undef REASON_ASSERT
81 
82  return abs_mmio_read32(kBase + RSTMGR_RESET_INFO_REG_OFFSET);
83 }
84 
85 void rstmgr_reason_clear(uint32_t reasons) {
86  abs_mmio_write32(kBase + RSTMGR_RESET_INFO_REG_OFFSET, reasons);
87 }
88 
89 void rstmgr_alert_info_enable(void) {
90  abs_mmio_write32(kBase + RSTMGR_ALERT_INFO_CTRL_REG_OFFSET, 1);
91 }
92 
93 void rstmgr_cpu_info_enable(void) {
94  abs_mmio_write32(kBase + RSTMGR_CPU_INFO_CTRL_REG_OFFSET, 1);
95 }
96 
97 rom_error_t rstmgr_info_en_check(uint32_t reset_reasons) {
98  enum {
99  kByteTrueXorFalse = kHardenedByteBoolTrue ^ kHardenedByteBoolFalse,
100  kOkXorError = kErrorOk ^ kErrorRstmgrBadInit,
101  };
102  // Read the OTP item. Set OTP item's fields that are not enabled to
103  // `kHardenedByteFalse`.
104  uint32_t otp =
105  otp_read32(OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_RSTMGR_INFO_EN_OFFSET);
106  if (bitfield_field32_read(otp, RSTMGR_OTP_FIELD_ALERT_INFO_EN) !=
108  otp = bitfield_field32_write(otp, RSTMGR_OTP_FIELD_ALERT_INFO_EN,
110  }
111  if (bitfield_field32_read(otp, RSTMGR_OTP_FIELD_CPU_INFO_EN) !=
113  otp = bitfield_field32_write(otp, RSTMGR_OTP_FIELD_CPU_INFO_EN,
115  }
116  barrier32(otp);
117  // Prepare the expected OTP value from rstmgr.
118  uint32_t alert_info = launder32(kHardenedByteBoolFalse);
120  abs_mmio_read32(kBase + RSTMGR_ALERT_INFO_CTRL_REG_OFFSET),
121  RSTMGR_ALERT_INFO_CTRL_EN_BIT)) {
122  alert_info ^= launder32(kByteTrueXorFalse);
123  }
124  uint32_t cpu_info = launder32(kHardenedByteBoolFalse);
126  abs_mmio_read32(kBase + RSTMGR_CPU_INFO_CTRL_REG_OFFSET),
127  RSTMGR_CPU_INFO_CTRL_EN_BIT)) {
128  cpu_info ^= launder32(kByteTrueXorFalse);
129  }
130  // Compare.
131  uint32_t expected =
132  bitfield_field32_write(0, RSTMGR_OTP_FIELD_ALERT_INFO_EN, alert_info);
133  expected =
134  bitfield_field32_write(expected, RSTMGR_OTP_FIELD_CPU_INFO_EN, cpu_info);
135  expected ^= launder32(kOkXorError);
136  barrier32(expected);
137  uint32_t res = launder32(kErrorRstmgrBadInit);
138  bool low_power_exit =
139  bitfield_bit32_read(reset_reasons, kRstmgrReasonLowPowerExit);
140  if (launder32(low_power_exit)) {
141  HARDENED_CHECK_EQ(low_power_exit, 1);
142  res ^= kOkXorError;
143  } else {
144  HARDENED_CHECK_EQ(low_power_exit, 0);
145  res ^= otp ^ expected;
146  }
147  if (launder32(res) == kErrorOk) {
148  HARDENED_CHECK_EQ(res, kErrorOk);
149  return res;
150  }
151  return kErrorRstmgrBadInit;
152 }
153 
154 void rstmgr_reset(void) {
155  abs_mmio_write32(kBase + RSTMGR_RESET_REQ_REG_OFFSET, kMultiBitBool4True);
156 #ifdef OT_PLATFORM_RV32
157  // Wait until the chip resets.
158  while (true) {
160  }
161 #endif
162 }