/*
 * 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/memory.h"
#include "sw/device/lib/dif/dif_sensor_ctrl.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/aon_timer_testutils.h"
#include "sw/device/lib/testing/clkmgr_testutils.h"
#include "sw/device/lib/testing/pwrmgr_testutils.h"
#include "sw/device/lib/testing/sensor_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();

/**
 * AST CLK OUTPUTS TEST
 *
 * This test measure clock counts with clkmgr frequency measurements, performing
 * 100 measurements per round. Measurement errors (fast or slow clocks) are
 * recorded as recoverable error in clkmgr.
 *
 * After 100 measurements, test kicks in low-power mode, where
 * 3 clocks are off and measurement should not report spurious errors.
 *
 * When the dut wakes up, another 100 measurements are done before the
 * test finishes.
 *
 * Notice the test overrides the hardware behavior so it comes out with
 * calibrated USB clock, otherwise the USB clock frequency will be incorrect.
 * USB calibration should be a separate test, and may be vendor-specific.
 */
enum {
  kWaitForCSRPollingUs = 1,  // 1us
  kMeasurementsPerRound = 100,
};

static dif_clkmgr_t clkmgr;
static dif_pwrmgr_t pwrmgr;

bool test_main(void) {
  dif_sensor_ctrl_t sensor_ctrl;
  dif_aon_timer_t aon_timer;

  const uint32_t kMeasurementDelayMicros =
      aon_timer_testutils_get_us_from_aon_cycles(kMeasurementsPerRound);

  CHECK_DIF_OK(dif_clkmgr_init(
      mmio_region_from_addr(TOP_MATCHA_CLKMGR_AON_BASE_ADDR), &clkmgr));
  CHECK_DIF_OK(dif_sensor_ctrl_init(
      mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl));
  CHECK_DIF_OK(dif_pwrmgr_init(
      mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
  CHECK_DIF_OK(dif_aon_timer_init(
      mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));

  LOG_INFO("TEST: wait for ast init");
  IBEX_SPIN_FOR(sensor_ctrl_ast_init_done(&sensor_ctrl), 1000);
  LOG_INFO("TEST: done ast init");

  if (pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) {
    // At POR.
    LOG_INFO("Run clock measurements right after POR");
    clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
        &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
        /*low_speed=*/false);
    busy_spin_micros(kMeasurementDelayMicros);

    // check results
    CHECK(clkmgr_testutils_check_measurement_counts(&clkmgr));
    clkmgr_testutils_disable_clock_counts(&clkmgr);

    // Set wakeup timer to 100 us to have enough down time, and also wait before
    // entering deep sleep to have a chance to measure before sleeping.
    // As a side-effect of deep sleep the clock measurements are disabled, but
    // recoverable errors are not cleared.
    //
    // Set the counters so we should get an error unless they are cleared.
    uint32_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 1000 : 100;
    aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold);

    LOG_INFO("Start clock measurements to cause an error for main clk.");
    clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
        &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/true,
        /*low_speed=*/false);
    // Disable writes to measure ctrl registers.
    CHECK_DIF_OK(dif_clkmgr_measure_ctrl_disable(&clkmgr));

    busy_spin_micros(kMeasurementDelayMicros);

    pwrmgr_testutils_enable_low_power(
        &pwrmgr, kDifPwrmgrWakeupRequestSourceFive,
        kDifPwrmgrDomainOptionUsbClockInActivePower);

    LOG_INFO("TEST: Issue WFI to enter deep sleep");
    wait_for_interrupt();

  } else if (pwrmgr_testutils_is_wakeup_reason(
                 &pwrmgr, kDifPwrmgrWakeupRequestSourceFive)) {
    // Fail if some measurements are enabled.
    CHECK(clkmgr_testutils_check_measurement_enables(&clkmgr,
                                                     kDifToggleDisabled));
    // Check measurement control regwen is enabled.
    dif_toggle_t state;
    CHECK_DIF_OK(dif_clkmgr_measure_ctrl_get_enable(&clkmgr, &state));
    CHECK(state == kDifToggleEnabled);
    LOG_INFO("Check for all clock measurements disabled done");

    // Check we have a measurement error for the main clock.
    // Opentitan checks io clock error recov but matcha checks audio clock error
    // recov.
    dif_clkmgr_recov_err_codes_t expected_err_codes =
        kDifClkmgrRecovErrTypeMainMeas | kDifClkmgrRecovErrTypeAudioMeas;
    dif_clkmgr_recov_err_codes_t err_codes;
    CHECK_DIF_OK(dif_clkmgr_recov_err_code_get_codes(&clkmgr, &err_codes));
    CHECK(err_codes & expected_err_codes,
          "expected main clk measurement error, but got 0x%x", err_codes);

    // Clear measurement errors.
    CHECK_DIF_OK(dif_clkmgr_recov_err_code_clear_codes(&clkmgr, UINT32_MAX));

    LOG_INFO("TEST: one more measurement");
    clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
        &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
        /*low_speed=*/false);
    busy_spin_micros(kMeasurementDelayMicros);
    CHECK(clkmgr_testutils_check_measurement_counts(&clkmgr));
    clkmgr_testutils_disable_clock_counts(&clkmgr);

    LOG_INFO("TEST: done");
    return true;
  } else {  // error
    dif_pwrmgr_wakeup_reason_t wakeup_reason;
    CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
    LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d",
              wakeup_reason.types, wakeup_reason.request_sources);
    return false;
  }

  return false;
}
