blob: 9d75be2a5184a3db82946fb2129aa884d17db365 [file] [log] [blame]
Timothy Chen877ec922022-04-19 14:47:50 -07001// Copyright lowRISC contributors.
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/lib/base/abs_mmio.h"
6#include "sw/device/lib/base/mmio.h"
7#include "sw/device/lib/dif/dif_alert_handler.h"
8#include "sw/device/lib/dif/dif_flash_ctrl.h"
9#include "sw/device/lib/dif/dif_rstmgr.h"
10#include "sw/device/lib/dif/dif_rv_plic.h"
11#include "sw/device/lib/dif/dif_sensor_ctrl.h"
12#include "sw/device/lib/irq.h"
13#include "sw/device/lib/runtime/ibex.h"
14#include "sw/device/lib/runtime/log.h"
Timothy Chen877ec922022-04-19 14:47:50 -070015#include "sw/device/lib/testing/flash_ctrl_testutils.h"
16#include "sw/device/lib/testing/pwrmgr_testutils.h"
Miguel Young de la Sota09d4d012022-04-19 11:05:36 -040017#include "sw/device/lib/testing/test_framework/check.h"
Miguel Young de la Sota4d46eb92022-04-19 13:11:15 -040018#include "sw/device/lib/testing/test_framework/ottf_main.h"
Timothy Chen877ec922022-04-19 14:47:50 -070019
20#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
21#include "sensor_ctrl_regs.h" // Generated.
22
23/**
24 * This test checks that incoming ast events can be
25 * configured as both recoverable and fatal.
26 * Further, this test checks that recoverable and fatal
27 * events are able to reach their proper alert_handler
28 * destination.
29 *
30 * Since fatal events do not stop firing once asserted,
31 * this test performs a self reset after every fatal
32 * event. In order to keep track of how far the test
33 * has advanced, a non-volatile counter in flash is
34 * used to track current progress.
35 */
36static dif_rstmgr_t rstmgr;
37static dif_flash_ctrl_state_t flash_ctrl;
38static dif_sensor_ctrl_t sensor_ctrl;
39static dif_alert_handler_t alert_handler;
40
41/**
42 * The events_vector stores the tested events in bit strike fashion.
43 * This means at first the flash word is 0xFFFF_FFFF.
44 * As events are tested, they are marked as 0 in the vector,
45 * so we go from 0xFFFF_FFFF -> 0xFFFF_FFFE -> 0xFFFF_FFFC
46 */
47__attribute__((section(".non_volatile_scratch")))
48const volatile uint32_t events_vector = -1;
49
50/**
51 * Extracts current event id from the bit-strike counter.
52 */
Alexander Williams8e192a22022-05-03 20:09:34 -070053static uint32_t event_to_test(void) {
Timothy Chen877ec922022-04-19 14:47:50 -070054 uint32_t addr = (uint32_t)(&events_vector);
55 uint32_t val = abs_mmio_read32(addr);
56
57 for (size_t i = 0; i < 32; ++i) {
58 if (val >> i & 0x1) {
59 return i;
60 }
61 }
62 return -1;
63};
64
65/**
66 * Increment flash bit-strike counter.
67 */
68static bool incr_flash_cnt(uint32_t tested_idx) {
69 uint32_t addr = (uint32_t)(&events_vector);
70
71 // set the tested bit to 0
72 uint32_t val = abs_mmio_read32(addr) & ~(1 << tested_idx);
73
74 // program the word into flash
75 return flash_ctrl_testutils_write(&flash_ctrl, addr, 0, &val,
76
77 kDifFlashCtrlPartitionTypeData, 1);
78};
79
80/**
81 * Clear event trigger and recoverble status.
82 */
83static void clear_event(uint32_t idx, dif_toggle_t fatal) {
84 CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
85 kDifToggleDisabled));
86
87 if (!dif_toggle_to_bool(fatal)) {
88 CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, idx));
89 }
90}
91
92static uint32_t get_events(dif_toggle_t fatal) {
93 dif_sensor_ctrl_events_t events = 0;
94 if (dif_toggle_to_bool(fatal)) {
95 CHECK_DIF_OK(dif_sensor_ctrl_get_fatal_events(&sensor_ctrl, &events));
96 } else {
97 CHECK_DIF_OK(dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &events));
98 }
99 return events;
100}
101
102/**
103 * Check alert cause registers are correctly set
104 */
105static void check_alert_state(dif_toggle_t fatal) {
106 bool fatal_cause = false;
107 bool recov_cause = false;
108
109 CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
110 &alert_handler, kTopEarlgreyAlertIdSensorCtrlFatalAlert, &fatal_cause));
111
112 CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
113 &alert_handler, kTopEarlgreyAlertIdSensorCtrlRecovAlert, &recov_cause));
114
115 if (dif_toggle_to_bool(fatal)) {
116 CHECK(fatal_cause & !recov_cause,
117 "Fatal alert not correctly observed in alert handler");
118 } else {
119 CHECK(recov_cause & !fatal_cause,
120 "Recov alert not correctly observed in alert handler");
121 }
122
123 CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
124 &alert_handler, kTopEarlgreyAlertIdSensorCtrlRecovAlert));
125 CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
126 &alert_handler, kTopEarlgreyAlertIdSensorCtrlFatalAlert));
127};
128
129/**
130 * First configure fatality of the desired event.
131 * Then trigger the event from sensor_ctrl to ast.
132 * Next poll for setting of correct events inside sensor_ctrl status.
133 * When a recoverable event is triggerd, make sure only recoverable
134 * status is seen, likewise for fatal events.
135 * Finally, check for correct capture of cause in alert handler.
136 */
137static void test_event(uint32_t idx, dif_toggle_t fatal) {
138 // Configure event fatality
139 CHECK_DIF_OK(dif_sensor_ctrl_set_alert_fatal(&sensor_ctrl, idx, fatal));
140
141 // Trigger event
142 CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
143 kDifToggleEnabled));
144
145 // wait for events to set
146 IBEX_SPIN_FOR(get_events(fatal) > 0, 1);
147
148 // Check for the event in ast sensor_ctrl
149 // if the event is not set, error
150 CHECK(((get_events(fatal) >> idx) & 0x1) == 1, "Event %d not observed in AST",
151 idx);
152
153 // check the opposite fatality setting, should not be set
154 CHECK(((get_events(!fatal) >> idx) & 0x1) == 0,
155 "Event %d observed in AST when it should not be", idx);
156
157 // clear event trigger
158 clear_event(idx, fatal);
159
160 // check whether alert handler captured the event
161 check_alert_state(fatal);
162};
163
164bool test_main(void) {
165 // Initialize flash_ctrl
166 CHECK_DIF_OK(dif_flash_ctrl_init_state(
167 &flash_ctrl,
168 mmio_region_from_addr(TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR)));
169
170 // Initialize sensor_ctrl
171 CHECK_DIF_OK(dif_sensor_ctrl_init(
172 mmio_region_from_addr(TOP_EARLGREY_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl));
173
174 // Initialize alert_handler
175 CHECK_DIF_OK(dif_alert_handler_init(
176 mmio_region_from_addr(TOP_EARLGREY_ALERT_HANDLER_BASE_ADDR),
177 &alert_handler));
178
179 CHECK_DIF_OK(dif_rstmgr_init(
180 mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
181
182 // Enable both recoverable and fatal alerts
183 CHECK_DIF_OK(dif_alert_handler_configure_alert(
184 &alert_handler, kTopEarlgreyAlertIdSensorCtrlRecovAlert,
185 kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
186 CHECK_DIF_OK(dif_alert_handler_configure_alert(
187 &alert_handler, kTopEarlgreyAlertIdSensorCtrlFatalAlert,
188 kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
189
190 // First check the flash stored value
191 uint32_t event_idx = event_to_test();
192
193 // Capture the number of events to test
194 uint32_t sensor_ctrl_events = SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS;
195
196 if (event_idx == sensor_ctrl_events) {
197 LOG_INFO("Tested all events");
198 return true;
199 } else {
200 LOG_INFO("Testing event %d", event_idx);
201 }
202
203 // Enable flash access
204 flash_ctrl_testutils_default_region_access(&flash_ctrl,
205 /*rd_en*/ true,
206 /*prog_en*/ true,
207 /*erase_en*/ true,
208 /*scramble_en*/ false,
209 /*ecc_en*/ false,
210 /*he_en*/ false);
211
212 // test recoverable event
213 test_event(event_idx, /*fatal*/ kDifToggleDisabled);
214
215 // test fatal event
216 test_event(event_idx, /*fatal*/ kDifToggleEnabled);
217
218 // increment flash counter to know where we are
219 if (incr_flash_cnt(event_idx)) {
220 LOG_ERROR("Error when incrementing flash counter");
221 }
222
223 // Now request system to reset and test again
224 LOG_INFO("Rebooting system");
225 CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
226 wait_for_interrupt();
227
228 return true;
229}