blob: b7040a13926f23cc4955ab52bf0af2a4d25630d8 [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_sysrst_ctrl.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/flash_ctrl_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_pinmux_t pinmux;
static dif_sysrst_ctrl_t sysrst_ctrl;
static dif_flash_ctrl_state_t flash;
const uint32_t kTestPhaseTimeoutUsec = 100;
enum {
kTestPhaseSetup = 0,
kTestPhaseLoopback = 1,
kTestPhaseOverrideSetup = 2,
kTestPhaseOverrideZeros = 3,
kTestPhaseOverrideOnes = 4,
kTestPhaseOverrideRelease = 5,
kTestPhaseOverrideAndLoopback = 6,
kTestPhaseDone = 7,
};
enum {
kAllZero = 0x0,
kAllOne = 0xff,
kLoopbackPartial = 0x5,
kNumMioInputs = 0x4,
kNumMioOutputs = 0x6,
kOutputNumPads = 0x8,
};
static const dif_pinmux_index_t kPeripheralInputs[] = {
kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In,
kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In,
kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn,
};
static const dif_pinmux_index_t kInputPads[] = {
kTopMatchaPinmuxInselIob3,
kTopMatchaPinmuxInselIob6,
kTopMatchaPinmuxInselIob8,
kTopMatchaPinmuxInselIor13,
};
static const dif_pinmux_index_t kPeripheralOutputs[] = {
kTopMatchaPinmuxOutselSysrstCtrlAonKey0Out,
kTopMatchaPinmuxOutselSysrstCtrlAonKey1Out,
kTopMatchaPinmuxOutselSysrstCtrlAonKey2Out,
kTopMatchaPinmuxOutselSysrstCtrlAonPwrbOut,
kTopMatchaPinmuxOutselSysrstCtrlAonBatDisable,
kTopMatchaPinmuxOutselSysrstCtrlAonZ3Wakeup,
};
static const dif_pinmux_index_t kOutputPads[] = {
kTopMatchaPinmuxMioOutIob9, kTopMatchaPinmuxMioOutIor5,
kTopMatchaPinmuxMioOutIor6, kTopMatchaPinmuxMioOutIoc7,
kTopMatchaPinmuxMioOutIoc9, kTopMatchaPinmuxMioOutIod4,
};
static const dif_sysrst_ctrl_pin_t kSysrstCtrlOutputs[] = {
kDifSysrstCtrlPinKey0Out, kDifSysrstCtrlPinKey1Out,
kDifSysrstCtrlPinKey2Out, kDifSysrstCtrlPinPowerButtonOut,
kDifSysrstCtrlPinBatteryDisableOut, kDifSysrstCtrlPinZ3WakeupOut,
kDifSysrstCtrlPinEcResetInOut, kDifSysrstCtrlPinFlashWriteProtectInOut,
};
// Test phase written by testbench.
static volatile const uint8_t kTestPhase = 0;
// Sets up the pinmux to assign input and output pads
// to the sysrst_ctrl peripheral as required.
static void pinmux_setup(void) {
for (int i = 0; i < kNumMioInputs; ++i) {
CHECK_DIF_OK(
dif_pinmux_input_select(&pinmux, kPeripheralInputs[i], kInputPads[i]));
}
for (int i = 0; i < kNumMioOutputs; ++i) {
CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, kOutputPads[i],
kPeripheralOutputs[i]));
}
}
// Waits for the kTestPhase variable to be changed by a backdoor overwrite
// from the testbench in `chip_sw_sysrst_ctrl_ec_rst_l_vseq.sv`. This will
// indicate that the testbench is ready to proceed with the next phase of the
// test. The function `flash_ctrl_testutils_backdoor_wait_update` it's used to
// deal with possible caching that can prevent the software to read the new
// value of `kTestPhase`.
static void sync_with_testbench(void) {
// Set WFI status for testbench synchronization,
// no actual WFI instruction is issued.
test_status_set(kTestStatusInWfi);
test_status_set(kTestStatusInTest);
flash_ctrl_testutils_backdoor_wait_update(&flash, (uintptr_t)&kTestPhase,
kTestPhaseTimeoutUsec);
}
// Enables the sysrst_ctrl overrides for the output pins. Allows
// both low and high override values.
static void override_setup(uint8_t pins_to_override) {
for (int i = 0; i < kOutputNumPads; ++i) {
if ((pins_to_override >> i) & 0x1) {
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled(
&sysrst_ctrl, kSysrstCtrlOutputs[i], kDifToggleEnabled));
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_allowed(
&sysrst_ctrl, kSysrstCtrlOutputs[i], true, true));
}
}
}
// Disables the overrides. Allows the outputs to pass-through the
// values from the relevant input pins.
static void override_disable(void) {
for (int i = 0; i < kOutputNumPads; ++i) {
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled(
&sysrst_ctrl, kSysrstCtrlOutputs[i], kDifToggleDisabled));
}
}
// Sets the values of the output overrides as required.
static void set_output_overrides(uint8_t override_value) {
for (int i = 0; i < kOutputNumPads; ++i) {
CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_set_override(
&sysrst_ctrl, kSysrstCtrlOutputs[i], (override_value >> i) & 0x1));
}
}
bool test_main(void) {
CHECK_DIF_OK(dif_pinmux_init(
mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
CHECK_DIF_OK(dif_sysrst_ctrl_init(
mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
&sysrst_ctrl));
flash_ctrl_testutils_backdoor_init(&flash);
while (kTestPhase < kTestPhaseDone) {
switch (kTestPhase) {
case kTestPhaseSetup:
pinmux_setup();
break;
case kTestPhaseLoopback:
break;
case kTestPhaseOverrideSetup:
override_setup(kAllOne);
break;
case kTestPhaseOverrideZeros:
set_output_overrides(kAllZero);
break;
case kTestPhaseOverrideOnes:
set_output_overrides(kAllOne);
break;
case kTestPhaseOverrideRelease:
override_disable();
break;
case kTestPhaseOverrideAndLoopback:
override_setup(kLoopbackPartial);
set_output_overrides(kLoopbackPartial);
break;
default:
LOG_ERROR("Unexpected test phase : %d", kTestPhase);
break;
}
sync_with_testbench();
}
return true;
}