1 /*
2  * Copyright (c) 2023 - 2024, 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 /** @brief Interrupt priority level. */
60 typedef enum
61 {
62     NRF_VPR_CLIC_PRIORITY_LEVEL0 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL0, /**< Priority level 0. */
63     NRF_VPR_CLIC_PRIORITY_LEVEL1 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL1, /**< Priority level 1. */
64     NRF_VPR_CLIC_PRIORITY_LEVEL2 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL2, /**< Priority level 2. */
65     NRF_VPR_CLIC_PRIORITY_LEVEL3 = CLIC_CLIC_CLICINT_PRIORITY_PRIOLEVEL3, /**< Priority level 3. */
66 } nrf_vpr_clic_priority_t;
67 
68 /** @brief Macro for converting integer priority level to @ref nrf_vpr_clic_priority_t. */
69 #define NRF_VPR_CLIC_INT_TO_PRIO(x) ((x) == 0 ? NRF_VPR_CLIC_PRIORITY_LEVEL0 : \
70                                     ((x) == 1 ? NRF_VPR_CLIC_PRIORITY_LEVEL1 : \
71                                     ((x) == 2 ? NRF_VPR_CLIC_PRIORITY_LEVEL2 : \
72                                     ((x) == 3 ? NRF_VPR_CLIC_PRIORITY_LEVEL3 : 0))))
73 
74 /** @brief VPR CLIC configuration structure. */
75 typedef struct
76 {
77     bool                hw_vectoring;   /**< Selective interrupt hardware vectoring. */
78     uint8_t             level_encoding; /**< Interrupt level encoding. */
79     nrf_vpr_clic_mode_t privilege_mode; /**< Interrupt privilege mode. */
80 } nrf_vpr_clic_config_t;
81 
82 /** @brief VPR CLIC information structure. */
83 typedef struct
84 {
85     uint16_t interrupt_count; /**< Maximum number of interrupts supported. */
86     uint8_t  version;         /**< Version of CLIC. */
87     uint8_t  trigger_count;   /**< Number of maximum interrupt triggers supported. */
88 } nrf_vpr_clic_info_t;
89 
90 /** @brief Interrupt trigger and polarity types. */
91 typedef enum
92 {
93     NRF_VPR_CLIC_TRIGGER_EDGE_POS  = CLIC_CLIC_CLICINT_TRIG_EdgeTriggered,  /**< Interrupts are positive edge-triggered. */
94 } nrf_vpr_clic_trigger_t;
95 
96 /** @brief Interrupt privilege. */
97 typedef enum
98 {
99     NRF_VPR_CLIC_PRIV_MACHINE    = CLIC_CLIC_CLICINT_MODE_MachineMode,    /**< Machine mode. */
100 } nrf_vpr_clic_priv_t;
101 
102 /** @brief Interrupt attributes structure. */
103 typedef struct
104 {
105     bool                   hw_vectoring; /**< Selective interrupt hardware vectoring. */
106     nrf_vpr_clic_trigger_t trigger;      /**< Trigger type and polarity for the interrupt. */
107     nrf_vpr_clic_priv_t    privilege;    /**< Privilege mode. */
108 } nrf_vpr_clic_attr_t;
109 
110 /**
111  * @brief Function for getting the CLIC configuration.
112  *
113  * @param[in]  p_reg    Pointer to the structure of registers of the peripheral.
114  * @param[out] p_config Pointer to the VPR CLIC configuration structure.
115  */
116 NRF_STATIC_INLINE void nrf_vpr_clic_config_get(NRF_CLIC_Type const *   p_reg,
117                                                nrf_vpr_clic_config_t * p_config);
118 
119 /**
120  * @brief Function for getting the CLIC information.
121  *
122  * @param[in]  p_reg  Pointer to the structure of registers of the peripheral.
123  * @param[out] p_info Pointer to the VPR CLIC information structure.
124  */
125 NRF_STATIC_INLINE void nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,
126                                              nrf_vpr_clic_info_t * p_info);
127 
128 /**
129  * @brief Function for setting the specified interrupt to be pending.
130  *
131  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
132  * @param[in] irq_num Number of interrupt to be triggered.
133  */
134 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg, uint32_t irq_num);
135 
136 /**
137  * @brief Function for clearing the pending status for the specified interrupt.
138  *
139  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
140  * @param[in] irq_num Number of interrupt to be cleared.
141  */
142 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg, uint32_t irq_num);
143 
144 /**
145  * @brief Function for checking if the specified interrupt is pending.
146  *
147  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
148  * @param[in] irq_num Number of interrupt to be checked.
149  *
150  * @retval true  Interrupt is pending.
151  * @retval false Interrupt is not pending.
152  */
153 NRF_STATIC_INLINE bool nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num);
154 
155 /**
156  * @brief Function for enabling or disabling the specified interrupt.
157  *
158  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
159  * @param[in] irq_num Number of interrupt to be enabled or disabled.
160  * @param[in] enable  True if interrupt is to be enabled, false otherwise.
161  */
162 NRF_STATIC_INLINE void nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,
163                                                    uint32_t        irq_num,
164                                                    bool            enable);
165 
166 /**
167  * @brief Function for checking if the specified interrupt is enabled.
168  *
169  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
170  * @param[in] irq_num Number of interrupt to be checked.
171  *
172  * @retval true  Interrupt is enabled.
173  * @retval false Interrupt is disabled.
174  */
175 NRF_STATIC_INLINE bool nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num);
176 
177 /**
178  * @brief Function for setting the priority of the specified interrupt.
179  *
180  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
181  * @param[in] irq_num  Number of interrupt.
182  * @param[in] priority Priority to be set.
183  */
184 NRF_STATIC_INLINE void nrf_vpr_clic_int_priority_set(NRF_CLIC_Type *         p_reg,
185                                                      uint32_t                irq_num,
186                                                      nrf_vpr_clic_priority_t priority);
187 
188 /**
189  * @brief Function for getting the priority of the specified interrupt.
190  *
191  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
192  * @param[in] irq_num Number of interrupt.
193  *
194  * @return Priority of the specified interrupt.
195  */
196 NRF_STATIC_INLINE
197 nrf_vpr_clic_priority_t nrf_vpr_clic_int_priority_get(NRF_CLIC_Type const * p_reg,
198                                                       uint32_t              irq_num);
199 
200 /**
201  * @brief Function for getting the CLIC attributes.
202  *
203  * @param[in]  p_reg   Pointer to the structure of registers of the peripheral.
204  * @param[in]  irq_num Number of interrupt.
205  * @param[out] p_attr  Pointer to the structure to be filled with VPR CLIC attributes.
206  */
207 NRF_STATIC_INLINE void nrf_vpr_clic_int_attr_get(NRF_CLIC_Type const *  p_reg,
208                                                  uint32_t               irq_num,
209                                                  nrf_vpr_clic_attr_t *  p_attr);
210 
211 #ifndef NRF_DECLARE_ONLY
212 
nrf_vpr_clic_config_get(NRF_CLIC_Type const * p_reg,nrf_vpr_clic_config_t * p_config)213 NRF_STATIC_INLINE void nrf_vpr_clic_config_get(NRF_CLIC_Type const *   p_reg,
214                                                nrf_vpr_clic_config_t * p_config)
215 {
216     NRFX_ASSERT(p_config);
217     uint32_t cfg = p_reg->CLIC.CLICCFG;
218 
219     p_config->hw_vectoring   = (cfg & CLIC_CLIC_CLICCFG_NVBITS_Msk) >> CLIC_CLIC_CLICCFG_NVBITS_Pos;
220     p_config->level_encoding = (cfg & CLIC_CLIC_CLICCFG_NLBITS_Msk) >> CLIC_CLIC_CLICCFG_NLBITS_Pos;
221     p_config->privilege_mode = (nrf_vpr_clic_mode_t)((cfg & CLIC_CLIC_CLICCFG_NMBITS_Msk)
222                                                      >> CLIC_CLIC_CLICCFG_NMBITS_Pos);
223 }
224 
nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,nrf_vpr_clic_info_t * p_info)225 NRF_STATIC_INLINE void nrf_vpr_clic_info_get(NRF_CLIC_Type const * p_reg,
226                                              nrf_vpr_clic_info_t * p_info)
227 {
228     NRFX_ASSERT(p_info);
229     uint32_t inf = p_reg->CLIC.CLICINFO;
230 
231     p_info->interrupt_count = (inf & CLIC_CLIC_CLICINFO_NUMINTERRUPTS_Msk)
232                               >> CLIC_CLIC_CLICINFO_NUMINTERRUPTS_Pos;
233     p_info->version         = (inf & CLIC_CLIC_CLICINFO_VERSION_Msk)
234                               >> CLIC_CLIC_CLICINFO_VERSION_Pos;
235     p_info->trigger_count   = (inf & CLIC_CLIC_CLICINFO_NUMTRIGGER_Msk)
236                               >> CLIC_CLIC_CLICINFO_NUMTRIGGER_Pos;
237 }
238 
nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg,uint32_t irq_num)239 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_set(NRF_CLIC_Type * p_reg, uint32_t irq_num)
240 {
241     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
242     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IP_Msk) |
243                                    (CLIC_CLIC_CLICINT_IP_Pending << CLIC_CLIC_CLICINT_IP_Pos);
244 }
245 
nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg,uint32_t irq_num)246 NRF_STATIC_INLINE void nrf_vpr_clic_int_pending_clear(NRF_CLIC_Type * p_reg, uint32_t irq_num)
247 {
248     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
249     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IP_Msk) |
250                                    (CLIC_CLIC_CLICINT_IP_NotPending << CLIC_CLIC_CLICINT_IP_Pos);
251 }
252 
nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg,uint32_t irq_num)253 NRF_STATIC_INLINE bool nrf_vpr_clic_int_pending_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num)
254 {
255     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
256 
257     return ((p_reg->CLIC.CLICINT[irq_num] & CLIC_CLIC_CLICINT_IP_Msk) >> CLIC_CLIC_CLICINT_IP_Pos)
258            ==
259            CLIC_CLIC_CLICINT_IP_Pending ? true : false;
260 }
261 
nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,uint32_t irq_num,bool enable)262 NRF_STATIC_INLINE void nrf_vpr_clic_int_enable_set(NRF_CLIC_Type * p_reg,
263                                                    uint32_t        irq_num,
264                                                    bool            enable)
265 {
266     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
267     p_reg->CLIC.CLICINT[irq_num] = (p_reg->CLIC.CLICINT[irq_num] & ~CLIC_CLIC_CLICINT_IE_Msk) |
268                                    ((enable ? CLIC_CLIC_CLICINT_IE_Enabled :
269                                               CLIC_CLIC_CLICINT_IE_Disabled)
270                                     << CLIC_CLIC_CLICINT_IE_Pos);
271 }
272 
nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg,uint32_t irq_num)273 NRF_STATIC_INLINE bool nrf_vpr_clic_int_enable_check(NRF_CLIC_Type const * p_reg, uint32_t irq_num)
274 {
275     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
276 
277     return ((p_reg->CLIC.CLICINT[irq_num] & CLIC_CLIC_CLICINT_IE_Msk) >> CLIC_CLIC_CLICINT_IE_Pos)
278            == CLIC_CLIC_CLICINT_IE_Enabled ? true : false;
279 }
280 
nrf_vpr_clic_int_priority_set(NRF_CLIC_Type * p_reg,uint32_t irq_num,nrf_vpr_clic_priority_t priority)281 NRF_STATIC_INLINE void nrf_vpr_clic_int_priority_set(NRF_CLIC_Type *         p_reg,
282                                                      uint32_t                irq_num,
283                                                      nrf_vpr_clic_priority_t priority)
284 {
285     NRFX_ASSERT(irq_num < NRF_VPR_CLIC_IRQ_COUNT);
286     NRFX_ASSERT(priority != 0);
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