1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * CRACEN - Cryptographic accelerator engine
9  *
10  * This file contains the wrapping logic, for the underlying crypto IPs
11  *
12  * That includes the events and interrupt logic and registers
13  *
14  * Note:
15  *  * Only the RNG IP is modeled at this point, so:
16  *    * SEED is unused at this point and SEEDVALIND & SEEDLOCK ignored
17  *    * PROTECTEDRAMLOCK is ignored
18  */
19 
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include "NHW_common_types.h"
24 #include "NHW_config.h"
25 #include "NHW_peri_types.h"
26 #include "NHW_templates.h"
27 #include "NHW_xPPI.h"
28 #include "NHW_CRACEN_RNG.h"
29 #include "NHW_CRACEN_CM.h"
30 #include "irq_ctrl.h"
31 #include "nsi_tasks.h"
32 #include "nsi_hws_models_if.h"
33 #include "bs_utils.h"
34 
35 NRF_CRACEN_Type NRF_CRACEN_regs;
36 NRF_CRACENCORE_Type NRF_CRACENCORE_regs;
37 
38 static bs_time_t Timer_CRACEN = TIME_NEVER;
39 
40 static struct cracen_wrap_status {
41   bool CRYPTOMASTER_int_line;
42   bool RNG_int_line;
43   bool PKEIKG_int_line;
44 } cracen_w_st;
45 
46 /**
47  * Initialize the RNG model
48  */
nhw_CRACEN_init(void)49 static void nhw_CRACEN_init(void) {
50   memset(&NRF_CRACEN_regs, 0, sizeof(NRF_CRACEN_regs));
51   memset(&NRF_CRACENCORE_regs, 0, sizeof(NRF_CRACENCORE_regs));
52   memset(&cracen_w_st, 0, sizeof(cracen_w_st));
53 
54   nhw_CRACEN_RNG_init();
55   nhw_CRACEN_CM_init();
56 }
57 
58 NSI_TASK(nhw_CRACEN_init, HW_INIT, 100);
59 
nhw_CRACEN_eval_interrupt(uint inst)60 static void nhw_CRACEN_eval_interrupt(uint inst) {
61   static bool CRACEN_int_line[NHW_CRACEN_TOTAL_INST]; /* Is the CRACEN currently driving its interrupt line high */
62   /* Mapping of peripheral instance to {int controller instance, int number} */
63   static struct nhw_irq_mapping nhw_cracen_irq_map[NHW_CRACEN_TOTAL_INST] = NHW_CRACEN_INT_MAP;
64   bool new_int_line = false;
65 
66   NHW_CHECK_INTERRUPT_si(CRACEN, CRYPTOMASTER, NRF_CRACEN_regs.INTEN)
67   NHW_CHECK_INTERRUPT_si(CRACEN, RNG, NRF_CRACEN_regs.INTEN)
68   NHW_CHECK_INTERRUPT_si(CRACEN, PKEIKG, NRF_CRACEN_regs.INTEN)
69 
70   hw_irq_ctrl_toggle_level_irq_line_if(&CRACEN_int_line[inst],
71                                        new_int_line,
72                                        &nhw_cracen_irq_map[inst]);
73 }
74 
75 #define NHW_CRACEN_SIGNAL_EVENT(event) \
76   void nhw_CRACEN_signal_EVENTS_##event(void) \
77   { \
78     NRF_CRACEN_regs.EVENTS_##event = 1; \
79     nhw_CRACEN_eval_interrupt(0); \
80   }
81 
82 #define NHW_CRACEN_TOGGLE_INTLINE(event) \
83   void nhw_CRACEN_toggle_##event##_intline(bool level) { \
84     if (level == cracen_w_st. event##_int_line){ \
85       return; \
86     } \
87     cracen_w_st. event##_int_line = level; \
88     if (level) { \
89       nhw_CRACEN_signal_EVENTS_##event(); \
90     } \
91   }
92 
93 #define NHW_CRACEN_REGW_SIDEEFFECTS_EVENT(event) \
94   void nhw_CRACEN_regw_sideeffects_EVENTS_##event(void) { \
95     if (cracen_w_st. event##_int_line) { \
96       NRF_CRACEN_regs.EVENTS_##event = 1; \
97     } \
98     nhw_CRACEN_eval_interrupt(0); \
99   }
100 
101 #define NHW_CRACEN_EVENT_LOGIC(event) \
102   NHW_CRACEN_SIGNAL_EVENT(event) \
103   NHW_CRACEN_TOGGLE_INTLINE(event) \
104   NHW_CRACEN_REGW_SIDEEFFECTS_EVENT(event) \
105 
106 NHW_CRACEN_EVENT_LOGIC(CRYPTOMASTER)
107 NHW_CRACEN_EVENT_LOGIC(RNG)
108 NHW_CRACEN_EVENT_LOGIC(PKEIKG)
109 
110 NHW_SIDEEFFECTS_INTEN(CRACEN, NRF_CRACEN_regs., NRF_CRACEN_regs.INTEN)
111 NHW_SIDEEFFECTS_INTSET(CRACEN, NRF_CRACEN_regs., NRF_CRACEN_regs.INTEN)
112 NHW_SIDEEFFECTS_INTCLR(CRACEN, NRF_CRACEN_regs., NRF_CRACEN_regs.INTEN)
113 
114 extern bs_time_t Timer_CRACEN_NDRNG;
115 extern bs_time_t Timer_CRACEN_CM;
116 
nhw_CRACEN_update_timer(void)117 void nhw_CRACEN_update_timer(void) {
118 
119   bs_time_t new_t = BS_MIN(Timer_CRACEN_NDRNG, Timer_CRACEN_CM);
120   if (Timer_CRACEN != new_t) {
121     Timer_CRACEN = new_t;
122     nsi_hws_find_next_event();
123   }
124 }
125 
nhw_CRACEN_timer_triggered(void)126 static void nhw_CRACEN_timer_triggered(void) {
127   bs_time_t timer = Timer_CRACEN;
128   if (timer == Timer_CRACEN_NDRNG) {
129     nhw_CRACEN_RNG_timer_triggered();
130   }
131   if (timer == Timer_CRACEN_CM) {
132     nhw_CRACEN_CM_timer_triggered();
133   }
134 }
135 
136 NSI_HW_EVENT(Timer_CRACEN, nhw_CRACEN_timer_triggered, 50);
137