Software APIs
boot_svc_wakeup_test.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 
6 #include "sw/device/lib/base/status.h"
10 #include "sw/device/lib/testing/pwrmgr_testutils.h"
11 #include "sw/device/lib/testing/test_framework/check.h"
13 #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_empty.h"
14 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
15 #include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
16 #include "sw/device/silicon_creator/rom_ext/e2e/boot_svc/boot_svc_test_lib.h"
17 
18 static const dt_pwrmgr_t kPwrmgrDt = 0;
19 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
20 static const dt_aon_timer_t kAonTimerDt = 0;
21 static_assert(kDtAonTimerCount >= 1,
22  "this test expects at least one aon_timer");
23 
24 OTTF_DEFINE_TEST_CONFIG();
25 
26 static dif_pwrmgr_t pwrmgr;
27 static dif_aon_timer_t aon_timer;
28 static dif_pwrmgr_request_sources_t wakeup_sources;
29 
30 static status_t test_init(void) {
31  // Initialize aon timer to use the wdog.
32  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
33  TRY(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
35  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
36  kDtAonTimerWakeupWkupReq, &wakeup_sources));
37  return OK_STATUS();
38 }
39 
40 static status_t deep_sleep_enter(uint32_t wakeup_ticks) {
41  dif_pwrmgr_domain_config_t pwrmgr_domain_cfg = 0;
42  TRY(pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources,
43  pwrmgr_domain_cfg));
44  TRY(dif_aon_timer_wakeup_start(&aon_timer, wakeup_ticks, 0));
45  LOG_INFO("Going to sleep.");
47  LOG_INFO("Unexpected wakeup from deep sleep.");
48  return UNKNOWN();
49 }
50 
51 static status_t deep_sleep_check(void) {
52  bool wkup = TRY(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, wakeup_sources));
53  return OK_STATUS(wkup);
54 }
55 
56 static status_t initialize(retention_sram_t *retram, boot_svc_retram_t *state) {
57  boot_svc_msg_t msg = {0};
58  boot_svc_empty_req_init(&msg.empty);
59  retram->creator.boot_svc_msg = msg;
60  state->state = kBootSvcTestStateCheckEmpty;
61  TRY(deep_sleep_enter((uint32_t)kClockFreqAonHz));
62  return INTERNAL();
63 }
64 
65 static status_t check_empty(retention_sram_t *retram,
66  boot_svc_retram_t *state) {
67  if (!TRY(deep_sleep_check())) {
68  LOG_ERROR("Expected wakup from deep sleep");
69  return INTERNAL();
70  }
71  boot_svc_msg_t msg = retram->creator.boot_svc_msg;
72  TRY(boot_svc_header_check(&msg.header));
73  // We expect the `EmptyReqType` here because the ROM_EXT should not process
74  // boot_svc requests when waking from deep sleep.
75  TRY_CHECK(msg.header.type == kBootSvcEmptyReqType);
76  state->state = kBootSvcTestStateFinal;
77  return OK_STATUS();
78 }
79 
80 static status_t empty_message_test(void) {
81  TRY(test_init());
82  retention_sram_t *retram = retention_sram_get();
83  TRY(boot_svc_test_init(retram, kBootSvcTestWakeup));
84  boot_svc_retram_t *state = (boot_svc_retram_t *)&retram->owner;
85 
86  for (;;) {
87  LOG_INFO("Test state = %d", state->state);
88  switch (state->state) {
89  case kBootSvcTestStateInit:
90  TRY(initialize(retram, state));
91  break;
92  case kBootSvcTestStateCheckEmpty:
93  TRY(check_empty(retram, state));
94  break;
95  case kBootSvcTestStateFinal:
96  return OK_STATUS();
97  default:
98  return UNKNOWN();
99  }
100  }
101 }
102 
103 bool test_main(void) {
104  status_t sts = empty_message_test();
105  if (status_err(sts)) {
106  LOG_ERROR("boot_svc_wakeup_test: %r", sts);
107  }
108  return status_ok(sts);
109 }