// 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/check.h"
#include "sw/device/lib/testing/test_framework/ottf.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"

const test_config_t kTestConfig;

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