| /* |
| * 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; |
| } |