Software APIs
pwrmgr_usb_clk_disabled_when_active_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 
5 // Tests the pwrmgr setting to disable the USB clock in active mode. The check
6 // is to issue a USB CSR access when the clock is disabled, expecting the USB to
7 // hung, and causing a watchdog reset.
8 
15 #include "sw/device/lib/testing/aon_timer_testutils.h"
16 #include "sw/device/lib/testing/pwrmgr_testutils.h"
17 #include "sw/device/lib/testing/rstmgr_testutils.h"
18 #include "sw/device/lib/testing/test_framework/check.h"
20 
22 #include "usbdev_regs.h"
23 
24 OTTF_DEFINE_TEST_CONFIG();
25 
26 static dif_aon_timer_t aon_timer;
27 static dif_usbdev_t usbdev;
28 
29 static const uint32_t kExpectedHunkAddress =
30  TOP_EARLGREY_USBDEV_BASE_ADDR + USBDEV_INTR_ENABLE_REG_OFFSET;
31 
32 static void usbdev_csr_access(void) {
33  CHECK_DIF_OK(dif_usbdev_irq_set_enabled(&usbdev, kDifUsbdevIrqPowered,
35  dif_toggle_t state;
36  CHECK_DIF_OK(
37  dif_usbdev_irq_get_enabled(&usbdev, kDifUsbdevIrqPowered, &state));
38  CHECK(state == kDifToggleEnabled);
39 }
40 
41 bool test_main(void) {
42  dif_pwrmgr_t pwrmgr;
43  dif_rstmgr_t rstmgr;
44 
45  CHECK_DIF_OK(dif_rstmgr_init(
47  CHECK_DIF_OK(dif_pwrmgr_init(
49  CHECK_DIF_OK(dif_aon_timer_init(
51  CHECK_DIF_OK(dif_usbdev_init(
53 
54  // Enable cpu dump capture.
55  CHECK_DIF_OK(dif_rstmgr_cpu_info_set_enabled(&rstmgr, kDifToggleEnabled));
56 
57  if (UNWRAP(rstmgr_testutils_is_reset_info(&rstmgr, kDifRstmgrResetInfoPor))) {
58  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
59 
60  // Make sure the USB CSR access is okay before turning off the USB clock.
61  usbdev_csr_access();
62 
63  // Bite after enough time has elapsed past the hung csr access.
64  uint32_t bite_us = (kDeviceType == kDeviceSimDV) ? 400 : 800;
65  uint32_t bite_cycles = 0;
66  CHECK_STATUS_OK(
67  aon_timer_testutils_get_aon_cycles_32_from_us(bite_us, &bite_cycles));
68  LOG_INFO("Setting bite reset for %u us (%u cycles)", bite_us, bite_cycles);
69 
70  // Set bite timer.
71  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(&aon_timer, UINT32_MAX,
72  bite_cycles, false));
73 
74  // Enable watchdog bite reset.
76  kDifPwrmgrResetRequestSourceTwo,
78 
79  // Disable the USB in active mode, and wait some microseconds for the
80  // register update to propagate to the AST.
81  CHECK_DIF_OK(dif_pwrmgr_set_domain_config(&pwrmgr, 0, kDifToggleEnabled));
82  busy_spin_micros(50);
83 
84  // This should cause the CPU to hung.
85  usbdev_csr_access();
86 
87  // This should never be reached.
88  LOG_ERROR("This is unreachable since a reset should have been triggered");
89  return false;
90  } else if (UNWRAP(rstmgr_testutils_is_reset_info(
91  &rstmgr, kDifRstmgrResetInfoWatchdog))) {
92  LOG_INFO("Got an expected watchdog reset when accessing USB");
93 
94  size_t actual_size;
95  CHECK_DIF_OK(dif_rstmgr_cpu_info_get_size(&rstmgr, &actual_size));
96  // Verify the cpu crash dump.
98  size_t size_read;
99  CHECK_DIF_OK(dif_rstmgr_cpu_info_dump_read(
100  &rstmgr, cpu_dump, DIF_RSTMGR_CPU_INFO_MAX_SIZE, &size_read));
101  CHECK(size_read <= DIF_RSTMGR_CPU_INFO_MAX_SIZE);
102  CHECK(size_read == actual_size);
103  LOG_INFO("EXC_ADDR = 0x%x", cpu_dump[0]);
104  LOG_INFO("EXC_PC = 0x%x", cpu_dump[1]);
105  LOG_INFO("LAST_DATA ADDR = 0x%x", cpu_dump[2]);
106  LOG_INFO("NEXT_PC = 0x%x", cpu_dump[3]);
107  LOG_INFO("CURRENT_PC = 0x%x", cpu_dump[4]);
108  LOG_INFO("PREV_EXC_ADDR = 0x%x", cpu_dump[5]);
109  LOG_INFO("PREV_EXC_PC = 0x%x", cpu_dump[6]);
110  LOG_INFO("PREV_VALID = 0x%x", cpu_dump[7]);
111  // The cpu dump has the address that was last accessed at index 2.
112  CHECK(cpu_dump[2] == kExpectedHunkAddress, "Unexpected hung address");
113  return true;
114  } else {
116  reset_info = rstmgr_testutils_reason_get();
117  LOG_ERROR("Unexpected reset_info 0x%x", reset_info);
118  }
119  return false;
120 }