Software APIs
watchdog.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/watchdog.h"
6 
9 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
10 #include "sw/device/silicon_creator/lib/drivers/otp.h"
11 #include "sw/device/silicon_creator/lib/drivers/pwrmgr.h"
12 
13 #include "aon_timer_regs.h"
15 #include "otp_ctrl_regs.h"
16 #include "pwrmgr_regs.h"
17 
18 enum {
21 
22  kCtrlEnable = 1 << AON_TIMER_WDOG_CTRL_ENABLE_BIT,
23  kCtrlDisable = 0 << AON_TIMER_WDOG_CTRL_ENABLE_BIT,
24 };
25 
26 void watchdog_init(lifecycle_state_t lc_state) {
27  SEC_MMIO_ASSERT_WRITE_INCREMENT(kWatchdogSecMmioInit,
28  kWatchdogSecMmioConfigure);
29  // Disable the watchdog bite when in test and RMA lifecycle states.
31  switch (launder32(lc_state)) {
32  case kLcStateTest:
33  HARDENED_CHECK_EQ(lc_state, kLcStateTest);
34  enable = kHardenedBoolFalse;
35  break;
36  case kLcStateDev:
37  HARDENED_CHECK_EQ(lc_state, kLcStateDev);
38  enable = kHardenedBoolTrue;
39  break;
40  case kLcStateProd:
41  HARDENED_CHECK_EQ(lc_state, kLcStateProd);
42  enable = kHardenedBoolTrue;
43  break;
44  case kLcStateProdEnd:
45  HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
46  enable = kHardenedBoolTrue;
47  break;
48  case kLcStateRma:
49  HARDENED_CHECK_EQ(lc_state, kLcStateRma);
50  enable = kHardenedBoolFalse;
51  break;
52  default:
53  HARDENED_TRAP();
54  }
55 
56  uint32_t threshold = otp_read32(
57  OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_WATCHDOG_BITE_THRESHOLD_CYCLES_OFFSET);
58 
59  // Disable watchdog if `threshold` is less than minimum.
60  if (launder32(threshold) < kWatchdogMinThreshold) {
61  HARDENED_CHECK_LT(threshold, kWatchdogMinThreshold);
62  enable = kHardenedBoolFalse;
63  }
64 
65  watchdog_configure((watchdog_config_t){
66  // 1.125 x bite_threshold
67  .bark_threshold = (9 * threshold) / 8,
68  .bite_threshold = threshold,
69  .enable = enable,
70  });
71 }
72 
73 void watchdog_configure(watchdog_config_t config) {
74  SEC_MMIO_ASSERT_WRITE_INCREMENT(kWatchdogSecMmioConfigure, 4);
75  // Tell pwrmgr we want watchdog reset events to reset the chip.
77  kPwrMgrBase + PWRMGR_RESET_EN_REG_OFFSET,
79  0, kTopEarlgreyPowerManagerResetRequestsAonTimerAonAonTimerRstReq,
80  true));
81  pwrmgr_cdc_sync(1);
82 
83  // Set the watchdog bite and bark thresholds.
84  sec_mmio_write32(kBase + AON_TIMER_WDOG_CTRL_REG_OFFSET, kCtrlDisable);
85  abs_mmio_write32(kBase + AON_TIMER_WDOG_COUNT_REG_OFFSET, 0);
86  abs_mmio_write32(kBase + AON_TIMER_WDOG_BARK_THOLD_REG_OFFSET,
87  config.bark_threshold);
88  sec_mmio_write32(kBase + AON_TIMER_WDOG_BITE_THOLD_REG_OFFSET,
89  config.bite_threshold);
90 
91  // Enable or disable the watchdog as requested.
92  uint32_t ctrl = kCtrlEnable;
93  switch (launder32(config.enable)) {
94  case kHardenedBoolTrue:
96  ctrl = kCtrlEnable;
97  break;
98  case kHardenedBoolFalse:
100  ctrl = kCtrlDisable;
101  break;
102  default:
103  HARDENED_TRAP();
104  }
105  sec_mmio_write32(kBase + AON_TIMER_WDOG_CTRL_REG_OFFSET, ctrl);
106 
107  // Redundantly re-request the pwrmgr configuration sync since it isn't
108  // possible to use sec_mmio for it.
109  pwrmgr_cdc_sync(1);
110 }
111 
112 void watchdog_disable(void) {
113  SEC_MMIO_ASSERT_WRITE_INCREMENT(kWatchdogSecMmioDisable, 1);
114  sec_mmio_write32(kBase + AON_TIMER_WDOG_CTRL_REG_OFFSET, kCtrlDisable);
115 }
116 
117 void watchdog_pet(void) {
118  abs_mmio_write32(kBase + AON_TIMER_WDOG_COUNT_REG_OFFSET, 0);
119 }
120 
121 uint32_t watchdog_get(void) {
122  return abs_mmio_read32(kBase + AON_TIMER_WDOG_COUNT_REG_OFFSET);
123 }