blob: a7759115d7d03785793fb15ced48fdb7ab42a9fc [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_pinmux.h"
#include "sw/device/lib/dif/dif_pwrmgr.h"
#include "sw/device/lib/dif/dif_rstmgr.h"
#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/pwrmgr_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"
OTTF_DEFINE_TEST_CONFIG();
static dif_pwrmgr_t pwrmgr;
static dif_rstmgr_t rstmgr;
static dif_sysrst_ctrl_t sysrst_ctrl;
enum {
kTestPhaseCheckComboReset = 0,
kTestPhaseCheckDeepSleepWakeup = 1,
kTestPhaseCheckDeepSleepReset = 2,
kTestPhaseFinalCheck = 3,
};
// Threshold/Duration values are not specific to a real-world debounce
// scenario so are kept short to avoid excessive simulation time.
// Assuming a 5us aon clock period.
enum {
kDetectionTimeThreshold = 1024, // ~5ms
kEcResetDuration = 512, // ~2.5ms
kDebounceTimeThreshold = 128, // ~0.6ms
};
static volatile const uint8_t kTestPhase = 0;
static void check_combo_reset(void) {
CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
&sysrst_ctrl, kDifSysrstCtrlKeyCombo0,
(dif_sysrst_ctrl_key_combo_config_t){
.actions = kDifSysrstCtrlKeyComboActionEcReset |
kDifSysrstCtrlKeyComboActionSelfReset,
.detection_time_threshold = kDetectionTimeThreshold,
.embedded_controller_reset_duration = kEcResetDuration,
.keys = kDifSysrstCtrlKey0 | kDifSysrstCtrlKey1}));
CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
&sysrst_ctrl, (dif_sysrst_ctrl_input_change_config_t){
.debounce_time_threshold = kDebounceTimeThreshold,
.input_changes = kDifSysrstCtrlInputKey0H2L |
kDifSysrstCtrlInputKey1H2L}));
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_configure(
&sysrst_ctrl, kDifSysrstCtrlPinFlashWriteProtectInOut,
(dif_sysrst_ctrl_pin_config_t){.allow_one = true,
.allow_zero = true,
.enabled = kDifToggleEnabled,
.override_value = true}));
// Prepare rstmgr for a reset with sysrst_ctrl (source one).
rstmgr_testutils_pre_reset(&rstmgr);
CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset,
kDifPwrmgrResetRequestSourceOne,
kDifToggleEnabled));
// Issue WFI and wait for reset condition.
test_status_set(kTestStatusInWfi);
wait_for_interrupt();
}
static void check_deep_sleep_wakeup(void) {
CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_configure(
&sysrst_ctrl, (dif_sysrst_ctrl_ulp_wakeup_config_t){
.ac_power_debounce_time_threshold = 0,
.lid_open_debounce_time_threshold = 0,
.power_button_debounce_time_threshold = 0,
.enabled = kDifToggleEnabled}));
// Setup low power.
// Wakeup source is from sysrst_ctrl (source one).
rstmgr_testutils_pre_reset(&rstmgr);
pwrmgr_testutils_enable_low_power(&pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
0);
// Issue WFI and wait for reset condition.
test_status_set(kTestStatusInWfi);
wait_for_interrupt();
}
static void check_deep_sleep_reset(void) {
CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
&sysrst_ctrl, kDifSysrstCtrlKeyCombo1,
(dif_sysrst_ctrl_key_combo_config_t){
.actions = kDifSysrstCtrlKeyComboActionEcReset |
kDifSysrstCtrlKeyComboActionSelfReset,
.detection_time_threshold = kDetectionTimeThreshold,
.embedded_controller_reset_duration = kEcResetDuration,
.keys = kDifSysrstCtrlKey2 | kDifSysrstCtrlKeyPowerButton}));
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_configure(
&sysrst_ctrl, kDifSysrstCtrlPinFlashWriteProtectInOut,
(dif_sysrst_ctrl_pin_config_t){.allow_one = true,
.allow_zero = true,
.enabled = kDifToggleEnabled,
.override_value = true}));
CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
&sysrst_ctrl, (dif_sysrst_ctrl_input_change_config_t){
.debounce_time_threshold = kDebounceTimeThreshold,
.input_changes = kDifSysrstCtrlInputKey2H2L |
kDifSysrstCtrlInputPowerButtonH2L}));
// Setup low power.
// Reset source is from sysrst_ctrl (source one).
rstmgr_testutils_pre_reset(&rstmgr);
CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset,
kDifPwrmgrResetRequestSourceOne,
kDifToggleEnabled));
// Enable low power with wakeup source other than
// sysrst_ctrl (e.g. source two) as we don't want
// a wakeup request but instead a reset.
pwrmgr_testutils_enable_low_power(&pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
0);
// Issue WFI and wait for reset condition.
test_status_set(kTestStatusInWfi);
wait_for_interrupt();
}
bool test_main(void) {
CHECK_DIF_OK(dif_pwrmgr_init(
mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
CHECK_DIF_OK(dif_rstmgr_init(
mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
CHECK_DIF_OK(dif_sysrst_ctrl_init(
mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
&sysrst_ctrl));
dif_rstmgr_reset_info_bitfield_t rstmgr_reset_info;
rstmgr_reset_info = rstmgr_testutils_reason_get();
dif_pinmux_t pinmux;
CHECK_DIF_OK(dif_pinmux_init(
mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
kTopMatchaPinmuxInselIob3));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In,
kTopMatchaPinmuxInselIob6));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In,
kTopMatchaPinmuxInselIob8));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn,
kTopMatchaPinmuxInselIob9));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonAcPresent,
kTopMatchaPinmuxInselIoc7));
CHECK_DIF_OK(dif_pinmux_input_select(
&pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonLidOpen,
kTopMatchaPinmuxInselIoc9));
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled(
&sysrst_ctrl, kDifSysrstCtrlPinEcResetInOut, kDifToggleDisabled));
switch (kTestPhase) {
case kTestPhaseCheckComboReset:
CHECK(rstmgr_reset_info == kDifRstmgrResetInfoPor);
check_combo_reset();
break;
case kTestPhaseCheckDeepSleepWakeup:
CHECK(rstmgr_reset_info == kDifRstmgrResetInfoSysRstCtrl);
check_deep_sleep_wakeup();
break;
case kTestPhaseCheckDeepSleepReset:
CHECK(rstmgr_reset_info == kDifRstmgrResetInfoLowPowerExit);
check_deep_sleep_reset();
break;
case kTestPhaseFinalCheck:
CHECK(rstmgr_reset_info ==
(kDifRstmgrResetInfoSysRstCtrl | kDifRstmgrResetInfoLowPowerExit));
return true;
break;
default:
LOG_ERROR("Unexpected test phase : %d", kTestPhase);
break;
}
return false;
}