// 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_clkmgr.h"
#include "sw/device/lib/testing/check.h"
#include "sw/device/lib/testing/test_framework/test_main.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) {
  const dif_clkmgr_gateable_clock_t clocks[] = {
      kTopEarlgreyGateableClocksIoDiv4Peri,
      kTopEarlgreyGateableClocksUsbPeri,
  };

  for (int i = 0; i < ARRAYSIZE(clocks); ++i) {
    dif_clkmgr_gateable_clock_t clock = clocks[i];

    // 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.
    bool enabled;
    CHECK(dif_clkmgr_gateable_clock_get_enabled(clkmgr, clock, &enabled) ==
          kDifClkmgrOk);

    // Toggle the enable twice so that it ends up in its original state.
    for (int j = 0; j < 2; ++j) {
      bool expected = !enabled;
      CHECK(dif_clkmgr_gateable_clock_set_enabled(
                clkmgr, clock,
                expected ? kDifClkmgrToggleEnabled
                         : kDifClkmgrToggleDisabled) == kDifClkmgrOk);
      CHECK(dif_clkmgr_gateable_clock_get_enabled(clkmgr, clock, &enabled) ==
            kDifClkmgrOk);
      CHECK(enabled == expected);
    }
  }
}

/**
 * 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) {
  const dif_clkmgr_hintable_clock_t clocks[] = {
      kTopEarlgreyHintableClocksMainAes,
      kTopEarlgreyHintableClocksMainHmac,
      kTopEarlgreyHintableClocksMainKmac,
      kTopEarlgreyHintableClocksMainOtbn,
  };

  for (int i = 0; i < ARRAYSIZE(clocks); ++i) {
    dif_clkmgr_hintable_clock_t clock = clocks[i];

    // 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.
    bool enabled;
    CHECK(dif_clkmgr_hintable_clock_get_hint(clkmgr, clock, &enabled) ==
          kDifClkmgrOk);

    // Toggle the hint twice so that it ends up in its original state.
    for (int j = 0; j < 2; ++j) {
      bool expected = !enabled;
      CHECK(dif_clkmgr_hintable_clock_set_hint(
                clkmgr, clock,
                expected ? kDifClkmgrToggleEnabled
                         : kDifClkmgrToggleDisabled) == kDifClkmgrOk);
      CHECK(dif_clkmgr_hintable_clock_get_hint(clkmgr, clock, &enabled) ==
            kDifClkmgrOk);
      CHECK(enabled == expected);

      // If the clock hint is enabled then the clock should always be enabled.
      if (enabled) {
        bool status = false;
        CHECK(dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &status) ==
              kDifClkmgrOk);
        CHECK(status, "clock %u hint is enabled but status is disabled", clock);
      }
    }
  }
}

bool test_main() {
  const dif_clkmgr_params_t params = {
      .base_addr = mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR),
      .last_gateable_clock = kTopEarlgreyGateableClocksLast,
      .last_hintable_clock = kTopEarlgreyHintableClocksLast,
  };

  dif_clkmgr_t clkmgr;
  CHECK(dif_clkmgr_init(params, &clkmgr) == kDifClkmgrOk);
  test_gateable_clocks(&clkmgr);
  test_hintable_clocks(&clkmgr);

  return true;
}
