Software APIs
soc_proxy_smoketest.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 
8 #include "sw/device/lib/dif/dif_soc_proxy.h"
10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/rstmgr_testutils.h"
14 
15 #include "hw/top_darjeeling/sw/autogen/top_darjeeling.h"
16 #include "soc_proxy_regs.h"
17 
18 OTTF_DEFINE_TEST_CONFIG();
19 
20 /**
21  * @brief To be executed after power-on reset (POR).
22  *
23  * @param pwrmgr Pointer to an initialized `dif_pwrmgr_t`.
24  *
25  * @return Does not return (spinwaits for a timeout and fails a check if the
26  * timeout is reached).
27  */
28 void after_por(dif_pwrmgr_t *pwrmgr) {
29  LOG_INFO("Reset after POR.");
30 
31  // Enable external reset request in pwrmgr.
33  kDifPwrmgrResetRequestSourceTwo,
35  LOG_INFO("External resets enabled.");
36 
37  // Give DV environment time for triggering external reset.
38  busy_spin_micros(1000);
39 
40  // This should never be reached.
41  CHECK(false, "Did not get reset in time!");
42 }
43 
44 /**
45  * @brief To be executed after external reset request.
46  */
47 void after_ext_rst_req(const dif_rv_plic_t *rv_plic,
48  const dif_soc_proxy_t *soc_proxy) {
49  LOG_INFO("Reset on external request.");
50 
51  // At this point, we are expecting interrupt requests from DV env.
52 
53  // Enable external IRQs in Ibex.
54  irq_external_ctrl(true);
55 
56  for (unsigned i = 0; i < SOC_PROXY_PARAM_NUM_EXTERNAL_IRQS; i++) {
57  const dif_rv_plic_irq_id_t rv_plic_irq =
58  (dif_rv_plic_irq_id_t)(kTopDarjeelingPlicIrqIdSocProxyExternal0 + i);
59  const dif_rv_plic_target_t rv_plic_target = kTopDarjeelingPlicTargetIbex0;
60  const dif_soc_proxy_irq_t soc_proxy_irq = (dif_soc_proxy_irq_t)i;
61 
62  // Enable IRQ in SoC Proxy and PLIC.
63  CHECK_DIF_OK(dif_soc_proxy_irq_set_enabled(soc_proxy, soc_proxy_irq,
65  CHECK_DIF_OK(dif_rv_plic_irq_set_priority(rv_plic, rv_plic_irq, 1));
66  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
67  rv_plic, rv_plic_irq, rv_plic_target, kDifToggleEnabled));
68  LOG_INFO("IRQ %0d enabled.", i);
69 
70  for (unsigned num_try = 0; num_try < 10; num_try++) {
71  // Wait for interrupt, then check that the expected IRQ is pending in both
72  // SoC Proxy and PLIC.
74  bool soc_proxy_irq_pending;
75  CHECK_DIF_OK(dif_soc_proxy_irq_is_pending(soc_proxy, soc_proxy_irq,
76  &soc_proxy_irq_pending));
77  if (soc_proxy_irq_pending) {
78  LOG_INFO("IRQ %0d pending in soc_proxy.", i);
79  } else {
80  // Not the IRQ we're expecting, wait for another one.
81  continue;
82  }
83  bool rv_plic_irq_pending;
84  CHECK_DIF_OK(dif_rv_plic_irq_is_pending(rv_plic, rv_plic_irq,
85  &rv_plic_irq_pending));
86  if (rv_plic_irq_pending) {
87  // IRQ pending in PLIC and SoC Proxy, stop trying.
88  LOG_INFO("IRQ %0d pending in rv_plic.", i);
89  break;
90  } else {
91  // IRQ pending in SoC Proxy but not PLIC -> error and abort.
92  CHECK(false, "Expected IRQ to be pending in soc_proxy AND rv_plic!");
93  }
94  }
95 
96  // Acknowledge and complete IRQ.
97  CHECK_DIF_OK(dif_soc_proxy_irq_acknowledge(soc_proxy, soc_proxy_irq));
98  CHECK_DIF_OK(
99  dif_rv_plic_irq_complete(rv_plic, rv_plic_target, rv_plic_irq));
100 
101  // Disable IRQ in PLIC and SoC Proxy.
102  CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
103  rv_plic, rv_plic_irq, rv_plic_target, kDifToggleDisabled));
104  CHECK_DIF_OK(dif_soc_proxy_irq_set_enabled(soc_proxy, soc_proxy_irq,
106  }
107 
108  // Disable external IRQs in Ibex.
109  irq_external_ctrl(false);
110 }
111 
112 bool test_main(void) {
113  dif_pwrmgr_t pwrmgr;
114  dif_rstmgr_t rstmgr;
115  dif_rv_plic_t rv_plic;
116  dif_soc_proxy_t soc_proxy;
117 
118  CHECK_DIF_OK(dif_pwrmgr_init(
119  mmio_region_from_addr(TOP_DARJEELING_PWRMGR_AON_BASE_ADDR), &pwrmgr));
120  CHECK_DIF_OK(dif_rstmgr_init(
121  mmio_region_from_addr(TOP_DARJEELING_RSTMGR_AON_BASE_ADDR), &rstmgr));
122  CHECK_DIF_OK(dif_rv_plic_init(
123  mmio_region_from_addr(TOP_DARJEELING_RV_PLIC_BASE_ADDR), &rv_plic));
124  CHECK_DIF_OK(dif_soc_proxy_init(
125  mmio_region_from_addr(TOP_DARJEELING_SOC_PROXY_CORE_BASE_ADDR),
126  &soc_proxy));
127 
128  // Behave based on reset reason.
129  if (UNWRAP(
130  rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoPor))) {
131  after_por(&pwrmgr);
132  } else if (UNWRAP(rstmgr_testutils_reset_info_any(
133  &rstmgr, kDifRstmgrResetInfoExternalRst))) {
134  after_ext_rst_req(&rv_plic, &soc_proxy);
135  } else {
136  // Unexpected reset reason -> fail test.
137  return false;
138  }
139 
140  return true;
141 }