Merge "Add chip_sw_ast_clk_outputs and chip_sw_clkmgr_external_clk_src_for_lc to edacloud"
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index fcf5414..cb83396 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1737,7 +1737,7 @@
     {
       name: chip_sw_clkmgr_external_clk_src_for_lc
       uvm_test_seq: chip_sw_lc_ctrl_transition_vseq
-      sw_images: ["//sw/device/tests/sim_dv:clkmgr_external_clk_src_for_lc_test:1"]
+      sw_images: ["//sw/device/tests/sim_dv:clkmgr_external_clk_src_for_lc_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+chip_clock_source=ChipClockSourceExternal48Mhz", "+calibrate_usb_clk=1"]
     }
@@ -1791,7 +1791,7 @@
     {
       name: chip_sw_ast_clk_outputs
       uvm_test_seq: chip_sw_ast_clk_outputs_vseq
-      sw_images: ["//sw/device/tests:ast_clk_outs_test:1"]
+      sw_images: ["//sw/device/tests:ast_clk_outs_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+calibrate_usb_clk=1"]
     }
@@ -2112,9 +2112,11 @@
         "chip_sw_aon_timer_sleep_wdog_sleep_pause",
         "chip_sw_aon_timer_smoketest",
         "chip_sw_aon_timer_wdog_bite_reset",
+        "chip_sw_ast_clk_outputs",
         "chip_sw_ast_clk_rst_inputs",
         "chip_sw_atomics_test",
         "chip_sw_cam_ctrl_test",
+        "chip_sw_clkmgr_external_clk_src_for_lc",
         "chip_sw_clkmgr_external_clk_src_for_sw_fast",
         "chip_sw_clkmgr_external_clk_src_for_sw_slow",
         "chip_sw_clkmgr_off_audio_trans",
@@ -2222,9 +2224,11 @@
         "chip_sw_aon_timer_sleep_wdog_sleep_pause",
         "chip_sw_aon_timer_smoketest",
         "chip_sw_aon_timer_wdog_bite_reset",
+        "chip_sw_ast_clk_outputs",
         "chip_sw_ast_clk_rst_inputs",
         "chip_sw_atomics_test",
         "chip_sw_cam_ctrl_test",
+        "chip_sw_clkmgr_external_clk_src_for_lc",
         "chip_sw_clkmgr_external_clk_src_for_sw_fast",
         "chip_sw_clkmgr_external_clk_src_for_sw_slow",
         "chip_sw_clkmgr_off_audio_trans",
diff --git a/sw/device/lib/dif/dif_clkmgr.h b/sw/device/lib/dif/dif_clkmgr.h
index a8afa83..2ed2186 100644
--- a/sw/device/lib/dif/dif_clkmgr.h
+++ b/sw/device/lib/dif/dif_clkmgr.h
@@ -86,45 +86,77 @@
    */
   kDifClkmgrRecovErrTypeShadowUpdate = 1u << 0,
   /**
+   * A recoverable measurement error for AUDIO clock.
+   */
+  kDifClkmgrRecovErrTypeAudioMeas = 1u << 1,
+  /**
    * A recoverable measurement error for IO clock.
    */
-  kDifClkmgrRecovErrTypeIoMeas = 1u << 1,
+  kDifClkmgrRecovErrTypeIoMeas = 1u << 2,
   /**
    * A recoverable measurement error for IO_DIV2 clock.
    */
-  kDifClkmgrRecovErrTypeIoDiv2Meas = 1u << 2,
+  kDifClkmgrRecovErrTypeIoDiv2Meas = 1u << 3,
   /**
    * A recoverable measurement error for IO_DIV4 clock.
    */
-  kDifClkmgrRecovErrTypeIoDiv4Meas = 1u << 3,
+  kDifClkmgrRecovErrTypeIoDiv4Meas = 1u << 4,
   /**
    * A recoverable measurement error for MAIN clock.
    */
-  kDifClkmgrRecovErrTypeMainMeas = 1u << 4,
+  kDifClkmgrRecovErrTypeMainMeas = 1u << 5,
+  /**
+   * A recoverable measurement error for ML clock.
+   */
+  kDifClkmgrRecovErrTypeMlMeas = 1u << 6,
+  /**
+   * A recoverable measurement error for SMC clock.
+   */
+  kDifClkmgrRecovErrTypeSmcMeas = 1u << 7,
   /**
    * A recoverable measurement error for USB clock.
    */
-  kDifClkmgrRecovErrTypeUsbMeas = 1u << 5,
+  kDifClkmgrRecovErrTypeUsbMeas = 1u << 8,
+  /**
+   * A recoverable measurement error for VIDEO clock.
+   */
+  kDifClkmgrRecovErrTypeVideoMeas = 1u << 9,
+  /**
+   * A recoverable timeout error for AUDIO clock.
+   */
+  kDifClkmgrRecovErrTypeAudioTimeout = 1u << 10,
   /**
    * A recoverable timeout error for IO clock.
    */
-  kDifClkmgrRecovErrTypeIoTimeout = 1u << 6,
+  kDifClkmgrRecovErrTypeIoTimeout = 1u << 11,
   /**
    * A recoverable timeout error for IO_DIV2 clock.
    */
-  kDifClkmgrRecovErrTypeIoDiv2Timeout = 1u << 7,
+  kDifClkmgrRecovErrTypeIoDiv2Timeout = 1u << 12,
   /**
    * A recoverable timeout error for IO_DIV4 clock.
    */
-  kDifClkmgrRecovErrTypeIoDiv4Timeout = 1u << 8,
+  kDifClkmgrRecovErrTypeIoDiv4Timeout = 1u << 13,
   /**
    * A recoverable timeout error for MAIN clock.
    */
-  kDifClkmgrRecovErrTypeMainTimeout = 1u << 9,
+  kDifClkmgrRecovErrTypeMainTimeout = 1u << 14,
+  /**
+   * A recoverable timeout error for ML clock.
+   */
+  kDifClkmgrRecovErrTypeMlTimeout = 1u << 15,
+  /**
+   * A recoverable timeout error for SMC clock.
+   */
+  kDifClkmgrRecovErrTypeSmcTimeout = 1u << 16,
   /**
    * A recoverable timeout error for USB clock.
    */
-  kDifClkmgrRecovErrTypeUsbTimeout = 1u << 10,
+  kDifClkmgrRecovErrTypeUsbTimeout = 1u << 17,
+  /**
+   * A recoverable timeout error for VIDEO clock.
+   */
+  kDifClkmgrRecovErrTypeVideoTimeout = 1u << 18
 } dif_clkmgr_recov_err_type_t;
 
 /**
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index c766536..63262f8 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -1185,6 +1185,19 @@
     ],
 )
 
+matcha_dv_test(
+    name = "ast_clk_outs_test",
+    srcs = ["ast_clk_outs_test.c"],
+    deps = [
+        ":test_dv_lib",
+        "//sw/device/lib/testing:clkmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:sensor_ctrl_testutils",
+    ],
+)
+
 # Smoke tests
 matcha_dv_test(
     name = "aes_smoketest",
diff --git a/sw/device/tests/ast_clk_outs_test.c b/sw/device/tests/ast_clk_outs_test.c
new file mode 100644
index 0000000..5094956
--- /dev/null
+++ b/sw/device/tests/ast_clk_outs_test.c
@@ -0,0 +1,140 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#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.
+    dif_clkmgr_recov_err_codes_t err_codes;
+    CHECK_DIF_OK(dif_clkmgr_recov_err_code_get_codes(&clkmgr, &err_codes));
+    CHECK(err_codes & kDifClkmgrRecovErrTypeMainMeas,
+          "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;
+}
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index 43cfc58..0ea6912 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -522,3 +522,23 @@
         "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
     ],
 )
+
+cc_library(
+    name = "lc_ctrl_transition_impl",
+    srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:lc_ctrl_transition_impl.c"],
+    hdrs = ["lc_ctrl_transition_impl.h"],
+    deps = [
+        "//sw/device/tests:test_dv_lib_opentitan",
+        "@lowrisc_opentitan//sw/device/lib/base:bitfield",
+        "@lowrisc_opentitan//sw/device/lib/dif:lc_ctrl",
+        "@lowrisc_opentitan//sw/device/lib/testing:lc_ctrl_testutils",
+    ],
+)
+
+matcha_dv_test(
+    name = "clkmgr_external_clk_src_for_lc_test",
+    srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:clkmgr_external_clk_src_for_lc_test.c"],
+    deps = [
+        ":lc_ctrl_transition_impl",
+    ],
+)
diff --git a/sw/device/tests/sim_dv/lc_ctrl_transition_impl.h b/sw/device/tests/sim_dv/lc_ctrl_transition_impl.h
new file mode 100644
index 0000000..671bbee
--- /dev/null
+++ b/sw/device/tests/sim_dv/lc_ctrl_transition_impl.h
@@ -0,0 +1,13 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef SW_DEVICE_TESTS_SIM_DV_LC_CTRL_TRANSITION_IMPL_H_
+#define SW_DEVICE_TESTS_SIM_DV_LC_CTRL_TRANSITION_IMPL_H_
+
+#include <stdbool.h>
+
+bool execute_lc_ctrl_transition_test(bool use_ext_clk);
+
+#endif  // SW_DEVICE_TESTS_SIM_DV_LC_CTRL_TRANSITION_IMPL_H_