blob: 9e6ef138503c6b41bad26fe94d16f1988b381ba4 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/dif/dif_aon_timer.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_clkmgr.h"
#include "sw/device/lib/dif/dif_pwrmgr.h"
#include "sw/device/lib/dif/dif_rstmgr.h"
#include "sw/device/lib/dif/dif_uart.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/aon_timer_testutils.h"
#include "sw/device/lib/testing/rstmgr_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
/**
* The peripherals used to test when the peri clocks are disabled are
* bit 0: clk_io_div4_peri: uart0
* bit 1: clk_io_div2_peri: spi_host1
* bit 2: clk_usb_peri: usbdev
* bit 3: clk_io_peri: spi_host0
*/
OTTF_DEFINE_TEST_CONFIG();
static dif_aon_timer_t aon_timer;
static dif_uart_t uart0;
static const uint32_t bite_us = 200;
/**
* Send CSR access to uart0, expecting to timeout.
*/
static void uart0_csr_access(void) {
CHECK_DIF_OK(dif_uart_watermark_rx_set(&uart0, kDifUartWatermarkByte1));
}
/**
* Test that disabling a 'gateable' unit's clock causes the unit to become
* unresponsive to CSR accesses. Configure a watchdog reset, and if it triggers
* the test is successful.
*/
static void test_gateable_clocks_off(const dif_clkmgr_t *clkmgr,
dif_clkmgr_gateable_clock_t clock) {
// Make sure the clock for the unit is on.
CHECK_DIF_OK(
dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleEnabled));
// The unit is enabled. Set the aon timer to bite, disable it, and issue a
// CSR read.
uint32_t bite_cycles = aon_timer_testutils_get_aon_cycles_from_us(bite_us);
LOG_INFO("Setting bite reset for %u us (%u cycles)", bite_us, bite_cycles);
aon_timer_testutils_watchdog_config(&aon_timer, UINT32_MAX, bite_cycles,
false);
CHECK_DIF_OK(
dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleDisabled));
uart0_csr_access();
}
bool test_main(void) {
dif_clkmgr_t clkmgr;
dif_pwrmgr_t pwrmgr;
dif_rstmgr_t rstmgr;
CHECK_DIF_OK(dif_rstmgr_init(
mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
CHECK_DIF_OK(dif_clkmgr_init(
mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr));
CHECK_DIF_OK(dif_pwrmgr_init(
mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR), &pwrmgr));
// Initialize aon timer.
CHECK_DIF_OK(dif_aon_timer_init(
mmio_region_from_addr(TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR), &aon_timer));
// Initialize uart0.
CHECK_DIF_OK(dif_uart_init(
mmio_region_from_addr(TOP_EARLGREY_UART0_BASE_ADDR), &uart0));
if (rstmgr_testutils_is_reset_info(&rstmgr, kDifRstmgrResetInfoPor)) {
// Enable watchdog bite reset.
CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset,
kDifPwrmgrResetRequestSourceTwo,
true));
rstmgr_testutils_pre_reset(&rstmgr);
test_gateable_clocks_off(&clkmgr, 0);
// This should never be reached.
LOG_ERROR("This is unreachable since a reset should have been triggered");
return false;
} else if (rstmgr_testutils_is_reset_info(&rstmgr,
kDifRstmgrResetInfoWatchdog)) {
return true;
} else {
dif_rstmgr_reset_info_bitfield_t reset_info;
CHECK_DIF_OK(dif_rstmgr_reset_info_get(&rstmgr, &reset_info));
LOG_ERROR("Unexpected reset_info 0x%x", reset_info);
}
return false;
}