blob: 70fc5e7f6bb5bb798df15e239fbffac1219a5b46 [file] [log] [blame]
Guillermo Maturana597283e2022-02-22 19:02:29 -08001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
Guillermo Maturana761a1392022-06-09 08:11:27 -07005#include "sw/device/lib/base/abs_mmio.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -08006#include "sw/device/lib/base/memory.h"
7#include "sw/device/lib/dif/dif_aon_timer.h"
8#include "sw/device/lib/dif/dif_base.h"
9#include "sw/device/lib/dif/dif_clkmgr.h"
Guillermo Maturana761a1392022-06-09 08:11:27 -070010#include "sw/device/lib/dif/dif_flash_ctrl.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080011#include "sw/device/lib/dif/dif_pwrmgr.h"
12#include "sw/device/lib/dif/dif_rstmgr.h"
Guillermo Maturana761a1392022-06-09 08:11:27 -070013#include "sw/device/lib/dif/dif_spi_host.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080014#include "sw/device/lib/dif/dif_uart.h"
Guillermo Maturana761a1392022-06-09 08:11:27 -070015#include "sw/device/lib/dif/dif_usbdev.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080016#include "sw/device/lib/runtime/log.h"
17#include "sw/device/lib/testing/aon_timer_testutils.h"
Guillermo Maturana761a1392022-06-09 08:11:27 -070018#include "sw/device/lib/testing/flash_ctrl_testutils.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080019#include "sw/device/lib/testing/rstmgr_testutils.h"
Miguel Young de la Sota09d4d012022-04-19 11:05:36 -040020#include "sw/device/lib/testing/test_framework/check.h"
Miguel Young de la Sota4d46eb92022-04-19 13:11:15 -040021#include "sw/device/lib/testing/test_framework/ottf_main.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080022
23#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
Guillermo Maturana761a1392022-06-09 08:11:27 -070024#include "spi_host_regs.h"
25#include "uart_regs.h"
26#include "usbdev_regs.h"
Guillermo Maturana597283e2022-02-22 19:02:29 -080027
28/**
29 * The peripherals used to test when the peri clocks are disabled are
30 * bit 0: clk_io_div4_peri: uart0
31 * bit 1: clk_io_div2_peri: spi_host1
Guillermo Maturana761a1392022-06-09 08:11:27 -070032 * bit 2: clk_io_peri: spi_host0
33 * bit 3: clk_usb_peri: usbdev
Guillermo Maturana597283e2022-02-22 19:02:29 -080034 */
35
Alphan Ulusoy9f4fc672022-06-17 21:39:16 -040036OTTF_DEFINE_TEST_CONFIG();
Guillermo Maturana597283e2022-02-22 19:02:29 -080037
Guillermo Maturana761a1392022-06-09 08:11:27 -070038typedef struct peri_context {
39 void (*csr_access)(); // The function causing a timeout.
40 uint32_t address; // The address causing a timeout.
41} peri_context_t;
42
Guillermo Maturana597283e2022-02-22 19:02:29 -080043static dif_aon_timer_t aon_timer;
Guillermo Maturana761a1392022-06-09 08:11:27 -070044static dif_flash_ctrl_state_t flash_ctrl;
45static dif_spi_host_t spi_host0;
46static dif_spi_host_t spi_host1;
47static dif_usbdev_t usbdev;
Guillermo Maturana597283e2022-02-22 19:02:29 -080048static dif_uart_t uart0;
49
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -040050OT_SECTION(".non_volatile_scratch") uint64_t hung_data_addr[4];
Guillermo Maturana597283e2022-02-22 19:02:29 -080051
Guillermo Maturana761a1392022-06-09 08:11:27 -070052static void set_hung_address(dif_clkmgr_gateable_clock_t clock,
53 uint32_t value) {
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -040054 uint32_t addr =
55 (uintptr_t)&hung_data_addr[clock] - TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR;
56 uint32_t flash_word[2] = {value, 0};
57 CHECK(flash_ctrl_testutils_write(&flash_ctrl, addr, 0, flash_word,
58 kDifFlashCtrlPartitionTypeData, 2));
59 CHECK(hung_data_addr[clock] == value, "Unexpected mismatch on read back");
Guillermo Maturana761a1392022-06-09 08:11:27 -070060 LOG_INFO("The expected hung address for clock %d is 0x%x at 0x%x", clock,
61 value, addr);
62}
63
64static void uart0_csr_access() {
65 dif_toggle_t state;
66 CHECK_DIF_OK(dif_uart_irq_set_enabled(&uart0, kDifUartIrqTxWatermark,
67 kDifToggleEnabled));
68 CHECK_DIF_OK(
69 dif_uart_irq_get_enabled(&uart0, kDifUartIrqTxWatermark, &state));
70 CHECK(state == kDifToggleEnabled);
71}
72
73static void spi_host0_csr_access() {
74 dif_toggle_t state;
75 CHECK_DIF_OK(dif_spi_host_irq_set_enabled(&spi_host0, kDifSpiHostIrqSpiEvent,
76 kDifToggleEnabled));
77 CHECK_DIF_OK(
78 dif_spi_host_irq_get_enabled(&spi_host0, kDifSpiHostIrqSpiEvent, &state));
79 CHECK(state == kDifToggleEnabled);
80}
81
82static void spi_host1_csr_access() {
83 dif_toggle_t state;
84 CHECK_DIF_OK(dif_spi_host_irq_set_enabled(&spi_host1, kDifSpiHostIrqSpiEvent,
85 kDifToggleEnabled));
86 CHECK_DIF_OK(
87 dif_spi_host_irq_get_enabled(&spi_host1, kDifSpiHostIrqSpiEvent, &state));
88 CHECK(state == kDifToggleEnabled);
89}
90
91static void usbdev_csr_access() {
92 CHECK_DIF_OK(dif_usbdev_irq_set_enabled(&usbdev, kDifUsbdevIrqPowered,
93 kDifToggleEnabled));
94 dif_toggle_t state;
95 CHECK_DIF_OK(
96 dif_usbdev_irq_get_enabled(&usbdev, kDifUsbdevIrqPowered, &state));
97 CHECK(state == kDifToggleEnabled);
98}
99
100peri_context_t peri_context[kTopEarlgreyGateableClocksLast + 1] = {
101 {uart0_csr_access,
102 TOP_EARLGREY_UART0_BASE_ADDR + UART_INTR_ENABLE_REG_OFFSET},
103 {spi_host1_csr_access,
104 TOP_EARLGREY_SPI_HOST1_BASE_ADDR + SPI_HOST_INTR_ENABLE_REG_OFFSET},
105 {spi_host0_csr_access,
106 TOP_EARLGREY_SPI_HOST0_BASE_ADDR + SPI_HOST_INTR_ENABLE_REG_OFFSET},
107 {usbdev_csr_access,
108 TOP_EARLGREY_USBDEV_BASE_ADDR + USBDEV_INTR_ENABLE_REG_OFFSET}};
109
Guillermo Maturana597283e2022-02-22 19:02:29 -0800110/**
111 * Test that disabling a 'gateable' unit's clock causes the unit to become
112 * unresponsive to CSR accesses. Configure a watchdog reset, and if it triggers
113 * the test is successful.
114 */
115static void test_gateable_clocks_off(const dif_clkmgr_t *clkmgr,
Guillermo Maturana761a1392022-06-09 08:11:27 -0700116 const dif_pwrmgr_t *pwrmgr,
Guillermo Maturana597283e2022-02-22 19:02:29 -0800117 dif_clkmgr_gateable_clock_t clock) {
118 // Make sure the clock for the unit is on.
119 CHECK_DIF_OK(
120 dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleEnabled));
Guillermo Maturana761a1392022-06-09 08:11:27 -0700121 // Enable watchdog bite reset.
122 CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
123 kDifPwrmgrResetRequestSourceTwo,
124 kDifToggleEnabled));
125 LOG_INFO("Testing peripheral clock %d", clock);
Guillermo Maturana597283e2022-02-22 19:02:29 -0800126
Guillermo Maturana761a1392022-06-09 08:11:27 -0700127 // Bite after enough time has elapsed past the hung csr access.
128 uint32_t bite_us = (kDeviceType == kDeviceSimDV) ? 400 : 800;
Guillermo Maturana597283e2022-02-22 19:02:29 -0800129 uint32_t bite_cycles = aon_timer_testutils_get_aon_cycles_from_us(bite_us);
130 LOG_INFO("Setting bite reset for %u us (%u cycles)", bite_us, bite_cycles);
131
Guillermo Maturana761a1392022-06-09 08:11:27 -0700132 // Make sure the CSR is accessible before turning the clock off.
133 (*peri_context[clock].csr_access)();
134 LOG_INFO("CSR access was okay before disabling the clock");
135
136 // Save the expected hung address to check against cpu_info's LAST_DATA_ADDR.
137 set_hung_address(clock, peri_context[clock].address);
138 // Set bite timer.
Guillermo Maturana597283e2022-02-22 19:02:29 -0800139 aon_timer_testutils_watchdog_config(&aon_timer, UINT32_MAX, bite_cycles,
140 false);
Guillermo Maturana761a1392022-06-09 08:11:27 -0700141 // Disable the peripheral's clock.
Guillermo Maturana597283e2022-02-22 19:02:29 -0800142 CHECK_DIF_OK(
143 dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleDisabled));
Guillermo Maturana761a1392022-06-09 08:11:27 -0700144 // Wait for the clock to really turn off.
145 busy_spin_micros(100);
146 // And issue the CSR access that will freeze and cause a reset.
147 (*peri_context[clock].csr_access)();
Guillermo Maturana597283e2022-02-22 19:02:29 -0800148}
149
Luís Marquesec88d272022-04-19 12:00:37 +0200150bool test_main(void) {
Guillermo Maturana597283e2022-02-22 19:02:29 -0800151 dif_clkmgr_t clkmgr;
152 dif_pwrmgr_t pwrmgr;
153 dif_rstmgr_t rstmgr;
154
155 CHECK_DIF_OK(dif_rstmgr_init(
156 mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
157
158 CHECK_DIF_OK(dif_clkmgr_init(
159 mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr));
160
161 CHECK_DIF_OK(dif_pwrmgr_init(
162 mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR), &pwrmgr));
163
Guillermo Maturana761a1392022-06-09 08:11:27 -0700164 CHECK_DIF_OK(dif_flash_ctrl_init_state(
165 &flash_ctrl,
166 mmio_region_from_addr(TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR)));
167
Guillermo Maturana597283e2022-02-22 19:02:29 -0800168 // Initialize aon timer.
169 CHECK_DIF_OK(dif_aon_timer_init(
170 mmio_region_from_addr(TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR), &aon_timer));
171
Guillermo Maturana761a1392022-06-09 08:11:27 -0700172 // Initialize peripherals.
Guillermo Maturana597283e2022-02-22 19:02:29 -0800173 CHECK_DIF_OK(dif_uart_init(
174 mmio_region_from_addr(TOP_EARLGREY_UART0_BASE_ADDR), &uart0));
Guillermo Maturana761a1392022-06-09 08:11:27 -0700175 CHECK_DIF_OK(dif_spi_host_init(
176 mmio_region_from_addr(TOP_EARLGREY_SPI_HOST0_BASE_ADDR), &spi_host0));
177 CHECK_DIF_OK(dif_spi_host_init(
178 mmio_region_from_addr(TOP_EARLGREY_SPI_HOST1_BASE_ADDR), &spi_host1));
179 CHECK_DIF_OK(dif_usbdev_init(
180 mmio_region_from_addr(TOP_EARLGREY_USBDEV_BASE_ADDR), &usbdev));
181
182 // Enable cpu dump capture.
183 CHECK_DIF_OK(dif_rstmgr_cpu_info_set_enabled(&rstmgr, kDifToggleEnabled));
184
185 // Enable raw flash access.
186 flash_ctrl_testutils_default_region_access(&flash_ctrl,
187 /*rd_en*/ true,
188 /*prog_en*/ true,
189 /*erase_en*/ true,
190 /*scramble_en*/ false,
191 /*ecc_en*/ false,
192 /*he_en*/ false);
Guillermo Maturana597283e2022-02-22 19:02:29 -0800193
194 if (rstmgr_testutils_is_reset_info(&rstmgr, kDifRstmgrResetInfoPor)) {
Guillermo Maturana597283e2022-02-22 19:02:29 -0800195 rstmgr_testutils_pre_reset(&rstmgr);
Guillermo Maturana761a1392022-06-09 08:11:27 -0700196
197 // Starting clock.
198 dif_clkmgr_gateable_clock_t clock = kTopEarlgreyGateableClocksIoDiv4Peri;
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -0400199 LOG_INFO("Next clock to test %d", flash_ctrl_testutils_counter_get(0));
Guillermo Maturana761a1392022-06-09 08:11:27 -0700200
201 test_gateable_clocks_off(&clkmgr, &pwrmgr, clock);
Guillermo Maturana597283e2022-02-22 19:02:29 -0800202
203 // This should never be reached.
204 LOG_ERROR("This is unreachable since a reset should have been triggered");
205 return false;
206 } else if (rstmgr_testutils_is_reset_info(&rstmgr,
207 kDifRstmgrResetInfoWatchdog)) {
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -0400208 dif_clkmgr_gateable_clock_t clock = flash_ctrl_testutils_counter_get(0);
Guillermo Maturana761a1392022-06-09 08:11:27 -0700209 LOG_INFO("Got an expected watchdog reset when reading for clock %d", clock);
210
211 size_t actual_size;
212 CHECK_DIF_OK(dif_rstmgr_cpu_info_get_size(&rstmgr, &actual_size));
213 // Verify the cpu crash dump.
214 dif_rstmgr_cpu_info_dump_segment_t cpu_dump[DIF_RSTMGR_CPU_INFO_MAX_SIZE];
215 size_t size_read;
216 CHECK_DIF_OK(dif_rstmgr_cpu_info_dump_read(
217 &rstmgr, cpu_dump, DIF_RSTMGR_CPU_INFO_MAX_SIZE, &size_read));
218 CHECK(size_read <= DIF_RSTMGR_CPU_INFO_MAX_SIZE);
219 CHECK(size_read == actual_size);
220 LOG_INFO("EXC_ADDR = 0x%x", cpu_dump[0]);
221 LOG_INFO("EXC_PC = 0x%x", cpu_dump[1]);
222 LOG_INFO("LAST_DATA ADDR = 0x%x", cpu_dump[2]);
223 LOG_INFO("NEXT_PC = 0x%x", cpu_dump[3]);
224 LOG_INFO("CURRENT_PC = 0x%x", cpu_dump[4]);
225 LOG_INFO("PREV_EXC_ADDR = 0x%x", cpu_dump[5]);
226 LOG_INFO("PREV_EXC_PC = 0x%x", cpu_dump[6]);
227 LOG_INFO("PREV_VALID = 0x%x", cpu_dump[7]);
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -0400228 uint32_t expected_hung_address = hung_data_addr[clock];
Guillermo Maturana761a1392022-06-09 08:11:27 -0700229 LOG_INFO("The expected hung address = 0x%x", expected_hung_address);
230 CHECK(cpu_dump[2] == expected_hung_address, "Unexpected hung address");
231 // Mark this clock as tested.
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -0400232 flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
Guillermo Maturana761a1392022-06-09 08:11:27 -0700233
234 if (clock < kTopEarlgreyGateableClocksLast) {
Alphan Ulusoy9ffc2572022-09-13 14:46:23 -0400235 clock = flash_ctrl_testutils_counter_get(0);
Guillermo Maturana761a1392022-06-09 08:11:27 -0700236 LOG_INFO("Next clock to test %d", clock);
237
238 rstmgr_testutils_pre_reset(&rstmgr);
239
240 test_gateable_clocks_off(&clkmgr, &pwrmgr, clock);
241
242 // This should never be reached.
243 LOG_ERROR("This is unreachable since a reset should have been triggered");
244 return false;
245 } else {
246 return true;
247 }
Guillermo Maturana597283e2022-02-22 19:02:29 -0800248 } else {
249 dif_rstmgr_reset_info_bitfield_t reset_info;
Drew Macrae89903962022-07-08 15:17:50 -0400250 reset_info = rstmgr_testutils_reason_get();
Guillermo Maturana597283e2022-02-22 19:02:29 -0800251 LOG_ERROR("Unexpected reset_info 0x%x", reset_info);
252 }
253 return false;
254}