1 /*
2  * Copyright (c) 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifndef NRF_VPR_CLIC_H_
35 #define NRF_VPR_CLIC_H_
36 
37 #include <nrfx.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrf_vpr_clic_hal VPR CLIC HAL
45  * @{
46  * @ingroup nrf_vpr
47  * @brief   Hardware access layer for managing the VPR RISC-V CPU Interrupt Controller (VPR CLIC).
48  */
49 
50 /** @brief Interrupts count. */
51 #define NRF_VPR_CLIC_IRQ_COUNT CLIC_CLIC_CLICINT_MaxCount
52 
53 /** @brief Interrupt privilege modes available. */
54 typedef enum
55 {
56     NRF_VPR_CLIC_MODE_M   = CLIC_CLIC_CLICCFG_NMBITS_ModeM, /**< All interrupts are M-mode only. */
57 } nrf_vpr_clic_mode_t;
58 
59 #if defined(NRF54H20_ENGA_XXAA) || defined(__NRFX_DOXYGEN__)
60 /** @brief Interrupt priority level. */
61 typedef enum
62 {
63     NRF_VPR_CLIC_PRIORITY_LEVEL0 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL0, /**< Priority level 0. */
64     NRF_VPR_CLIC_PRIORITY_LEVEL1 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL1, /**< Priority level 1. */
65     NRF_VPR_CLIC_PRIORITY_LEVEL2 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL2, /**< Priority level 2. */
66     NRF_VPR_CLIC_PRIORITY_LEVEL3 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL3, /**< Priority level 3. */
67 } nrf_vpr_clic_priority_t;
68 #else
69 typedef uint8_t nrf_vpr_clic_priority_t;
70 #endif
71 
72 /** @brief VPR CLIC configuration structure. */
73 typedef struct
74 {
75     bool                hw_vectoring;   /**< Selective interrupt hardware vectoring. */
76     uint8_t             level_encoding; /**< Interrupt level encoding. */
77     nrf_vpr_clic_mode_t privilege_mode; /**< Interrupt privilege mode. */
78 } nrf_vpr_clic_config_t;
79 
80 /** @brief VPR CLIC information structure. */
81 typedef struct
82 {
83     uint16_t interrupt_count; /**< Maximum number of interrupts supported. */
84     uint8_t  version;         /**< Version of CLIC. */
85     uint8_t  trigger_count;   /**< Number of maximum interrupt triggers supported. */
86 } nrf_vpr_clic_info_t;
87 
88 /** @brief Interrupt trigger and polarity types. */
89 typedef enum
90 {
91     NRF_VPR_CLIC_TRIGGER_EDGE_POS  = CLIC_CLIC_CLICINT_TRIG_EdgeTriggered,  /**< Interrupts are positive edge-triggered. */
92 } nrf_vpr_clic_trigger_t;
93 
94 /** @brief Interrupt privilege. */
95 typedef enum
96 {
97     NRF_VPR_CLIC_PRIV_MACHINE    = CLIC_CLIC_CLICINT_MODE_MachineMode,    /**< Machine mode. */
98 } nrf_vpr_clic_priv_t;
99 
100 /** @brief Interrupt attributes structure. */
101 typedef struct
102 {
103     bool                   hw_vectoring; /**< Selective interrupt hardware vectoring. */
104     nrf_vpr_clic_trigger_t trigger;      /**< Trigger type and polarity for the interrupt. */
105     nrf_vpr_clic_priv_t    privilege;    /**< Privilege mode. */
106 } nrf_vpr_clic_attr_t;
107 
108 /**
109  * @brief Function for getting the CLIC configuration.
110  *
111  * @param[in]  p_reg    Pointer to the structure of registers of the peripheral.
112  * @param[out] p_config Pointer to the VPR CLIC configuration structure.
113  */
114 NRF_STATIC_INLINE void nrf_vpr_clic_config_get(NRF_CLIC_Type const *   p_reg,
115                                                nrf_vpr_clic_config_t * p_config);
116 
117 /**
118  * @brief Function for getting the CLIC information.
119  *
120  * @param[in]  p_reg  Pointer to the structure of registers of the peripheral.
121  * @param[out] p_info Pointer to the VPR CLIC information structure.
122  */
123 NRF_STATIC_INLINE void nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,
124                                              nrf_vpr_clic_info_t * p_info);
125 
126 /**
127  * @brief Function for setting the specified interrupt to be pending.
128  *
129  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
130  * @param[in] irq_num Number of interrupt to be triggered.
131  */
132 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg, uint32_t irq_num);
133 
134 /**
135  * @brief Function for clearing the pending status for the specified interrupt.
136  *
137  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
138  * @param[in] irq_num Number of interrupt to be cleared.
139  */
140 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg, uint32_t irq_num);
141 
142 /**
143  * @brief Function for checking if the specified interrupt is pending.
144  *
145  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
146  * @param[in] irq_num Number of interrupt to be checked.
147  *
148  * @retval true  Interrupt is pending.
149  * @retval false Interrupt is not pending.
150  */
151 NRF_STATIC_INLINE bool nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num);
152 
153 /**
154  * @brief Function for enabling or disabling the specified interrupt.
155  *
156  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
157  * @param[in] irq_num Number of interrupt to be enabled or disabled.
158  * @param[in] enable  True if interrupt is to be enabled, false otherwise.
159  */
160 NRF_STATIC_INLINE void nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,
161                                                    uint32_t        irq_num,
162                                                    bool            enable);
163 
164 /**
165  * @brief Function for checking if the specified interrupt is enabled.
166  *
167  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
168  * @param[in] irq_num Number of interrupt to be checked.
169  *
170  * @retval true  Interrupt is enabled.
171  * @retval false Interrupt is disabled.
172  */
173 NRF_STATIC_INLINE bool nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num);
174 
175 /**
176  * @brief Function for setting the priority of the specified interrupt.
177  *
178  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
179  * @param[in] irq_num  Number of interrupt.
180  * @param[in] priority Priority to be set.
181  */
182 NRF_STATIC_INLINE void nrf_vpr_clic_int_priority_set(NRF_CLIC_Type *         p_reg,
183                                                      uint32_t                irq_num,
184                                                      nrf_vpr_clic_priority_t priority);
185 
186 /**
187  * @brief Function for getting the priority of the specified interrupt.
188  *
189  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
190  * @param[in] irq_num Number of interrupt.
191  *
192  * @return Priority of the specified interrupt.
193  */
194 NRF_STATIC_INLINE
195 nrf_vpr_clic_priority_t nrf_vpr_clic_int_priority_get(NRF_CLIC_Type const * p_reg,
196                                                       uint32_t              irq_num);
197 
198 /**
199  * @brief Function for getting the CLIC attributes.
200  *
201  * @param[in]  p_reg   Pointer to the structure of registers of the peripheral.
202  * @param[in]  irq_num Number of interrupt.
203  * @param[out] p_attr  Pointer to the structure to be filled with VPR CLIC attributes.
204  */
205 NRF_STATIC_INLINE void nrf_vpr_clic_int_attr_get(NRF_CLIC_Type const *  p_reg,
206                                                  uint32_t               irq_num,
207                                                  nrf_vpr_clic_attr_t *  p_attr);
208 
209 #ifndef NRF_DECLARE_ONLY
210 
nrf_vpr_clic_config_get(NRF_CLIC_Type const * p_reg,nrf_vpr_clic_config_t * p_config)211 NRF_STATIC_INLINE void nrf_vpr_clic_config_get(NRF_CLIC_Type const *   p_reg,
212                                                nrf_vpr_clic_config_t * p_config)
213 {
214     NRFX_ASSERT(p_config);
215     uint32_t cfg = p_reg->CLIC.CLICCFG;
216 
217     p_config->hw_vectoring   = (cfg & CLIC_CLIC_CLICCFG_NVBITS_Msk) >> CLIC_CLIC_CLICCFG_NVBITS_Pos;
218     p_config->level_encoding = (cfg & CLIC_CLIC_CLICCFG_NLBITS_Msk) >> CLIC_CLIC_CLICCFG_NLBITS_Pos;
219     p_config->privilege_mode = (nrf_vpr_clic_mode_t)((cfg & CLIC_CLIC_CLICCFG_NMBITS_Msk)
220                                                      >> CLIC_CLIC_CLICCFG_NMBITS_Pos);
221 }
222 
nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,nrf_vpr_clic_info_t * p_info)223 NRF_STATIC_INLINE void nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,
224                                              nrf_vpr_clic_info_t * p_info)
225 {
226     NRFX_ASSERT(p_info);
227     uint32_t inf = p_reg->CLIC.CLICINFO;
228 
229     p_info->interrupt_count = (inf & CLIC_CLIC_CLICINFO_NUMINTERRUPTS_Msk)
230                               >> CLIC_CLIC_CLICINFO_NUMINTERRUPTS_Pos;
231     p_info->version         = (inf & CLIC_CLIC_CLICINFO_VERSION_Msk)
232                               >> CLIC_CLIC_CLICINFO_VERSION_Pos;
233     p_info->trigger_count   = (inf & CLIC_CLIC_CLICINFO_NUMTRIGGER_Msk)
234                               >> CLIC_CLIC_CLICINFO_NUMTRIGGER_Pos;
235 }
236 
nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg,uint32_t irq_num)237 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg, uint32_t irq_num)
238 {
239     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
240     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IP_Msk) |
241                                    (CLIC_CLIC_CLICINT_IP_Pending << CLIC_CLIC_CLICINT_IP_Pos);
242 }
243 
nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg,uint32_t irq_num)244 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg, uint32_t irq_num)
245 {
246     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
247     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IP_Msk) |
248                                    (CLIC_CLIC_CLICINT_IP_NotPending << CLIC_CLIC_CLICINT_IP_Pos);
249 }
250 
nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg,uint32_t irq_num)251 NRF_STATIC_INLINE bool nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num)
252 {
253     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
254 
255     return ((p_reg->CLIC.CLICINT[irq_num] & CLIC_CLIC_CLICINT_IP_Msk) >> CLIC_CLIC_CLICINT_IP_Pos)
256            ==
257            CLIC_CLIC_CLICINT_IP_Pending ? true : false;
258 }
259 
nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,uint32_t irq_num,bool enable)260 NRF_STATIC_INLINE void nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,
261                                                    uint32_t        irq_num,
262                                                    bool            enable)
263 {
264     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
265     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IE_Msk) |
266                                    ((enable ? CLIC_CLIC_CLICINT_IE_Enabled :
267                                               CLIC_CLIC_CLICINT_IE_Disabled)
268                                     << CLIC_CLIC_CLICINT_IE_Pos);
269 }
270 
nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg,uint32_t irq_num)271 NRF_STATIC_INLINE bool nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num)
272 {
273     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
274 
275     return ((p_reg->CLIC.CLICINT[irq_num] & CLIC_CLIC_CLICINT_IE_Msk) >> CLIC_CLIC_CLICINT_IE_Pos)
276            == CLIC_CLIC_CLICINT_IE_Enabled ? true : false;
277 }
278 
nrf_vpr_clic_int_priority_set(NRF_CLIC_Type * p_reg,uint32_t irq_num,nrf_vpr_clic_priority_t priority)279 NRF_STATIC_INLINE void nrf_vpr_clic_int_priority_set(NRF_CLIC_Type *         p_reg,
280                                                      uint32_t                irq_num,
281                                                      nrf_vpr_clic_priority_t priority)
282 {
283     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
284 #if !defined(NRF54H20_ENGA_XXAA)
285     NRFX_ASSERT(priority < VPR_CLIC_PRIO_COUNT);
286 #endif
287 
288     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_PRIORITY_Msk)
289                                    | (priority << CLIC_CLIC_CLICINT_PRIORITY_Pos);
290 }
291 
292 NRF_STATIC_INLINE
nrf_vpr_clic_int_priority_get(NRF_CLIC_Type const * p_reg,uint32_t irq_num)293 nrf_vpr_clic_priority_t nrf_vpr_clic_int_priority_get(NRF_CLIC_Type const * p_reg,
294                                                       uint32_t              irq_num)
295 {
296     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
297 
298     return (nrf_vpr_clic_priority_t)((p_reg->CLIC.CLICINT[irq_num] & CLIC_CLIC_CLICINT_PRIORITY_Msk)
299            >> CLIC_CLIC_CLICINT_PRIORITY_Pos);
300 }
301 
nrf_vpr_clic_int_attr_get(NRF_CLIC_Type const * p_reg,uint32_t irq_num,nrf_vpr_clic_attr_t * p_attr)302 NRF_STATIC_INLINE void nrf_vpr_clic_int_attr_get(NRF_CLIC_Type const *  p_reg,
303                                                  uint32_t               irq_num,
304                                                  nrf_vpr_clic_attr_t *  p_attr)
305 {
306     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
307     NRFX_ASSERT(p_attr);
308     uint32_t att = p_reg->CLIC.CLICINT[irq_num];
309 
310     p_attr->hw_vectoring = (att & CLIC_CLIC_CLICINT_SHV_Msk) >> CLIC_CLIC_CLICINT_SHV_Pos;
311     p_attr->trigger      = (nrf_vpr_clic_trigger_t)((att & CLIC_CLIC_CLICINT_TRIG_Msk)
312                                                     >> CLIC_CLIC_CLICINT_TRIG_Pos);
313     p_attr->privilege    = (nrf_vpr_clic_priv_t)((att & CLIC_CLIC_CLICINT_MODE_Msk)
314                                                     >> CLIC_CLIC_CLICINT_MODE_Pos);
315 }
316 
317 #endif // NRF_DECLARE_ONLY
318 
319 /** @} */
320 
321 #ifdef __cplusplus
322 }
323 #endif
324 
325 #endif /* NRF_VPR_CLIC_H_ */
326