Software APIs
extclk_sca_fi.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/tests/penetrationtests/firmware/lib/extclk_sca_fi.h"
6 
7 #include "sw/device/lib/base/multibits.h"
8 #include "sw/device/lib/base/status.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
14 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
15 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
16 #include "sw/device/lib/ujson/ujson.h"
17 #include "sw/device/tests/penetrationtests/json/extclk_sca_fi_commands.h"
18 
20 
21 // Switching to external clocks causes the clocks to be unstable for some time.
22 // This is used to delay further action when the switch happens.
23 static const int kSettleDelayMicros = 200;
24 
25 static dif_clkmgr_t clkmgr;
26 
27 // For passing into `IBEX_SPIN_FOR`.
28 static bool did_extclk_settle(const dif_clkmgr_t *clkmgr) {
29  bool status;
30  CHECK_DIF_OK(dif_clkmgr_external_clock_is_settled(clkmgr, &status));
31  return status;
32 }
33 
34 status_t handle_extclk_sca_fi_configure(ujson_t *uj) {
35  penetrationtest_extclk_sca_fi_cfg_t uj_data;
36  TRY(ujson_deserialize_penetrationtest_extclk_sca_fi_cfg_t(uj, &uj_data));
37 
39  &clkmgr));
40  LOG_INFO("Configuring Extclk...");
41 
42  if (uj_data.sel) {
43  if (!uj_data.hi_speed_sel) {
44  LOG_INFO("Switching to low speed Extclk...");
45  } else {
46  LOG_INFO("Switching to high speed Extclk...");
47  }
48  // Enable external clock.
49  TRY(dif_clkmgr_external_clock_set_enabled(&clkmgr, !uj_data.hi_speed_sel));
50  // Wait for the external clock to become active.
51  IBEX_SPIN_FOR(did_extclk_settle(&clkmgr), kSettleDelayMicros);
52  LOG_INFO("External clock enabled.");
53  } else {
54  // Disable external clock.
55  LOG_INFO("Manually reset the device to switch back to internal clock.");
56  }
57 
58  return OK_STATUS();
59 }
60 
61 status_t handle_extclk_sca_fi(ujson_t *uj) {
62  extclk_sca_fi_subcommand_t cmd;
63  TRY(ujson_deserialize_extclk_sca_fi_subcommand_t(uj, &cmd));
64  switch (cmd) {
65  case kExtClkScaFiSubcommandConfigure:
66  return handle_extclk_sca_fi_configure(uj);
67  default:
68  LOG_ERROR("Unrecognized EXTCLK SCA FI subcommand: %d", cmd);
69  return INVALID_ARGUMENT();
70  }
71  return OK_STATUS();
72 }