|  | // 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_base.h" | 
|  | #include "sw/device/lib/dif/dif_clkmgr.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" | 
|  |  | 
|  | OTTF_DEFINE_TEST_CONFIG(); | 
|  |  | 
|  | /** | 
|  | * Test that all 'gateable' clocks, directly controlled by software, | 
|  | * can be enabled and disabled. | 
|  | */ | 
|  | static void test_gateable_clocks(const dif_clkmgr_t *clkmgr) { | 
|  | for (dif_clkmgr_gateable_clock_t clock = 0; | 
|  | clock <= kTopEarlgreyGateableClocksLast; ++clock) { | 
|  | // Get the initial state of the clock. The clock might be enabled or | 
|  | // disabled depending on reset behavior - either is fine for the purposes of | 
|  | // this test. | 
|  | dif_toggle_t state; | 
|  | CHECK_DIF_OK(dif_clkmgr_gateable_clock_get_enabled(clkmgr, clock, &state)); | 
|  |  | 
|  | // Toggle the enable twice so that it ends up in its original state. | 
|  | for (int j = 0; j < 2; ++j) { | 
|  | dif_toggle_t expected_state = | 
|  | state == kDifToggleEnabled ? kDifToggleDisabled : kDifToggleEnabled; | 
|  | dif_toggle_t actual_state = state; | 
|  | CHECK_DIF_OK( | 
|  | dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, expected_state)); | 
|  | CHECK_DIF_OK( | 
|  | dif_clkmgr_gateable_clock_get_enabled(clkmgr, clock, &actual_state)); | 
|  | CHECK(actual_state == expected_state); | 
|  |  | 
|  | state = actual_state; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Test that all 'hintable' clocks, indirectly controlled by software, | 
|  | * can have their hint toggled and status checked. | 
|  | */ | 
|  | void test_hintable_clocks(const dif_clkmgr_t *clkmgr) { | 
|  | for (dif_clkmgr_hintable_clock_t clock = 0; | 
|  | clock <= kTopEarlgreyHintableClocksLast; ++clock) { | 
|  | // Get the initial state of the hint for the clock The clock hint might be | 
|  | // enabled or disabled depending on reset behavior - either is fine for the | 
|  | // purposes of this test. | 
|  | dif_toggle_t state; | 
|  | CHECK_DIF_OK(dif_clkmgr_hintable_clock_get_hint(clkmgr, clock, &state)); | 
|  |  | 
|  | // Toggle the hint twice so that it ends up in its original state. | 
|  | for (int j = 0; j < 2; ++j) { | 
|  | dif_toggle_t expected_state = | 
|  | state == kDifToggleEnabled ? kDifToggleDisabled : kDifToggleEnabled; | 
|  | dif_toggle_t actual_state = state; | 
|  | CHECK_DIF_OK( | 
|  | dif_clkmgr_hintable_clock_set_hint(clkmgr, clock, expected_state)); | 
|  | CHECK_DIF_OK( | 
|  | dif_clkmgr_hintable_clock_get_hint(clkmgr, clock, &actual_state)); | 
|  | CHECK(actual_state == expected_state); | 
|  |  | 
|  | // If the clock hint is enabled then the clock should always be enabled. | 
|  | if (actual_state == kDifToggleEnabled) { | 
|  | dif_toggle_t state = kDifToggleDisabled; | 
|  | CHECK_DIF_OK( | 
|  | dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &state)); | 
|  | CHECK(state == kDifToggleEnabled, | 
|  | "clock %u hint is enabled but status is disabled", clock); | 
|  | } | 
|  |  | 
|  | state = actual_state; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | bool test_main(void) { | 
|  | dif_clkmgr_t clkmgr; | 
|  | CHECK_DIF_OK(dif_clkmgr_init( | 
|  | mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr)); | 
|  | test_gateable_clocks(&clkmgr); | 
|  | test_hintable_clocks(&clkmgr); | 
|  |  | 
|  | return true; | 
|  | } |