1 /*
2  * Copyright 2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_itrc.h"
9 
10 /*******************************************************************************
11  * Definitions
12  *******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.itrc"
17 #endif
18 
19 #define b11 0x3UL
20 #define b10 0x2u
21 #define b01 0x1u
22 
23 #define OUT_SEL_0_COUNT (16u)
24 #define OUT_SEL_1_COUNT (32u)
25 #define OUT_SEL_2_COUNT (48u)
26 
27 /* Value used to trigger SW Events */
28 #define SW_EVENT_VAL 0x5AA55AA5u
29 
30 /*******************************************************************************
31  * Prototypes
32  ******************************************************************************/
33 
34 /*******************************************************************************
35  * Code
36  ******************************************************************************/
37 
38 /*!
39  * Weak implementation of ITRC IRQ, should be re-defined by user when using ITRC IRQ
40  */
ITRC0_DriverIRQHandler(void)41 __WEAK void ITRC0_DriverIRQHandler(void)
42 {
43     /* ITRC generates IRQ until corresponding bit in STATUS is cleared by calling
44      * ITRC_ClearStatus(ITRC,((uint32_t)kITRC_Irq)
45      */
46 }
47 
48 /*!
49  * brief Clear ITRC status
50  *
51  * This function clears corresponding ITRC event or action in STATUS register.
52  *
53  * param base ITRC peripheral base address
54  * param word 32bit word represent corresponding event/action in STATUS register to be cleared (see
55  * ITRC_STATUS_INx/OUTx_STATUS)
56  * return kStatus_Success if success, kStatus_InvalidArgument otherwise
57  */
ITRC_ClearStatus(ITRC_Type * base,uint32_t word)58 status_t ITRC_ClearStatus(ITRC_Type *base, uint32_t word)
59 {
60     /* If reserved/unused bits in STATUS register are set in 'word' parameter, return kStatus_InvalidArgument */
61     if ((word & ~(IN_0_15_EVENTS_MASK | OUT_ACTIONS_MASK)) != 0u)
62     {
63         return kStatus_InvalidArgument;
64     }
65 
66     base->STATUS |= word;
67 
68     return kStatus_Success;
69 }
70 
71 /*!
72  * brief Get ITRC Status
73  *
74  * This function returns ITRC STATUS1 register value.
75  *
76  * param base ITRC peripheral base address
77  * return Value of ITRC STATUS register
78  */
ITRC_GetStatus(ITRC_Type * base)79 uint32_t ITRC_GetStatus(ITRC_Type *base)
80 {
81     return base->STATUS;
82 }
83 
84 #if defined(ITRC_STATUS1_IN16_STATUS_MASK)
85 /*!
86  * brief Clear ITRC status 1
87  *
88  * This function clears corresponding ITRC event or action in STATUS1 register.
89  *
90  * param base ITRC peripheral base address
91  * param word 32bit word represent corresponding event/action in STATUS1 register to be cleared (see
92  * ITRC_STATUS_INx/OUTx_STATUS)
93  * return kStatus_Success if success, kStatus_InvalidArgument otherwise
94  */
ITRC_ClearStatus1(ITRC_Type * base,uint32_t word)95 status_t ITRC_ClearStatus1(ITRC_Type *base, uint32_t word)
96 {
97     /* If reserved/unused bits in STATUS register are set in 'word' parameter, return kStatus_InvalidArgument */
98     if ((word & ~(IN_16_47_EVENTS_MASK)) != 0u)
99     {
100         return kStatus_InvalidArgument;
101     }
102 
103     base->STATUS1 |= word;
104 
105     return kStatus_Success;
106 }
107 
108 /*!
109  * brief Get ITRC Status 1
110  *
111  * This function returns ITRC STATUS1 register value.
112  *
113  * param base ITRC peripheral base address
114  * return Value of ITRC STATUS1 register
115  */
ITRC_GetStatus1(ITRC_Type * base)116 uint32_t ITRC_GetStatus1(ITRC_Type *base)
117 {
118     return base->STATUS1;
119 }
120 
121 #endif /* defined(ITRC_STATUS1_IN16_STATUS_MASK) */
122 
123 /*!
124  * brief Clear all ITRC status
125  *
126  * This clears all event and action in STATUS and STATUS1 registers.
127  *
128  * param base ITRC peripheral base address
129  * return kStatus_Success
130  */
ITRC_ClearAllStatus(ITRC_Type * base)131 status_t ITRC_ClearAllStatus(ITRC_Type *base)
132 {
133     base->STATUS |= (IN_0_15_EVENTS_MASK | OUT_ACTIONS_MASK);
134 #if defined(ITRC_STATUS1_IN16_STATUS_MASK)
135     base->STATUS1 |= (IN_16_47_EVENTS_MASK);
136 #endif /* defined(ITRC_STATUS1_IN16_STATUS_MASK) */
137 
138     return kStatus_Success;
139 }
140 
141 /*!
142  * brief Trigger ITRC SW Event 0
143  *
144  * This funciton set SW_EVENT0 register with value !=0 which triggers ITRC SW Event 0.
145  *
146  * param base ITRC peripheral base address
147  */
ITRC_SetSWEvent0(ITRC_Type * base)148 void ITRC_SetSWEvent0(ITRC_Type *base)
149 {
150     base->SW_EVENT0 = SW_EVENT_VAL;
151 }
152 
153 /*!
154  * brief Trigger ITRC SW Event 1
155  *
156  * This funciton set SW_EVENT1 register with value !=0 which triggers ITRC SW Event 1.
157  *
158  * param base ITRC peripheral base address
159  */
ITRC_SetSWEvent1(ITRC_Type * base)160 void ITRC_SetSWEvent1(ITRC_Type *base)
161 {
162     base->SW_EVENT1 = SW_EVENT_VAL;
163 }
164 
165 /*!
166  * brief Set ITRC Action to Event
167  *
168  * This function sets input Event signal to corresponding output Action response signal.
169  *
170  * param base ITRC peripheral base address
171  * param out ITRC OUT signal action
172  * param in ITRC IN signal event
173  * param lock if set locks INx_SEL configuration. This can be cleared only by PMC Core reset.
174  * param enable if set input Event will be selected for output Action, otherwise disable (if not already locked).
175  * return kStatus_Success if success, kStatus_InvalidArgument otherwise
176  */
ITRC_SetActionToEvent(ITRC_Type * base,itrc_out_signals_t out,itrc_input_signals_t in,itrc_lock_t lock,itrc_enable_t enable)177 status_t ITRC_SetActionToEvent(
178     ITRC_Type *base, itrc_out_signals_t out, itrc_input_signals_t in, itrc_lock_t lock, itrc_enable_t enable)
179 {
180     uint32_t sel0, sel1, index, select_AND_mask;
181 
182     /*   prepare values for INx_SEL0/1 bit-field according to secure techniques and register behavior
183      *    +------------+------------+------------------+---------------------------+
184      *    |  INx_SEL0  |  INx_SEL1  | Signal selected? |      Writable field?      |
185      *    +------------+------------+------------------+---------------------------+
186      *    | 10         | 10         | No               | Yes (default after reset) |
187      *    | 01         | 10         | Yes              | Yes                       |
188      *    | don't care | !="10"     | Yes              | No                        |
189      *    | 00 or 11   | don't care | Yes              | No                        |
190      *    +------------+------------+------------------+---------------------------+
191      */
192     if ((lock == kITRC_Unlock) && (enable == kITRC_Disable))
193     {
194         sel0 = b10;
195         sel1 = b10;
196     }
197     else if ((lock == kITRC_Unlock) && (enable == kITRC_Enable))
198     {
199         sel0 = b01;
200         sel1 = b10;
201     }
202     else
203     {
204         sel0 = b11;
205         sel1 = b11;
206     }
207 
208     /* Compute index for INx_SEL0/1 bit-field within OUTy_SEL0/1 registers */
209     if ((uint32_t)in < OUT_SEL_0_COUNT)
210     {
211         index = 2u * (uint32_t)in;
212     }
213     else if (OUT_SEL_0_COUNT <= (uint32_t)in && (uint32_t)in < OUT_SEL_1_COUNT)
214     {
215         index = 2u * ((uint32_t)in - OUT_SEL_0_COUNT);
216     }
217     else if (OUT_SEL_1_COUNT <= (uint32_t)in && (uint32_t)in < OUT_SEL_2_COUNT)
218     {
219         index = 2u * ((uint32_t)in - OUT_SEL_1_COUNT);
220     }
221     else
222     {
223         return kStatus_InvalidArgument;
224     }
225 
226     /* Prepare AND mask to set INx_SEL0 accordingly */
227     select_AND_mask = ~(uint32_t)(b11 << index);
228 
229     /* Configure OUT action for IN event */
230     for (uint8_t i = (uint8_t)kITRC_Irq; i < ITRC_OUT_COUNT; i++)
231     {
232         /* Loop over all OUT actions, set only requested one */
233         if (i == (uint8_t)out)
234         {
235             if ((uint32_t)in < OUT_SEL_0_COUNT)
236             {
237                 base->OUT_SEL[i][0] = (base->OUT_SEL[i][0] & select_AND_mask) | (sel0 << index);
238                 base->OUT_SEL[i][1] |= sel1 << index;
239                 break;
240             }
241 #if defined(ITRC_OUTX_SEL_1_OUTX_SELY_OUT_SEL_1_COUNT)
242             else if (OUT_SEL_0_COUNT <= (uint32_t)in && (uint32_t)in < OUT_SEL_1_COUNT)
243             {
244                 base->OUT_SEL_1[i][0] = (base->OUT_SEL[i][0] & select_AND_mask) | (sel0 << index);
245                 base->OUT_SEL_1[i][1] |= sel1 << index;
246                 break;
247             }
248 #endif /* defined(OUT_SEL_1) */
249 #if defined(ITRC_OUTX_SEL_2_OUTX_SELY_OUT_SEL_2_COUNT)
250             else if (OUT_SEL_1_COUNT <= (uint32_t)in && (uint32_t)in < OUT_SEL_2_COUNT)
251             {
252                 base->OUT_SEL_2[i][0] = (base->OUT_SEL[i][0] & select_AND_mask) | (sel0 << index);
253                 base->OUT_SEL_2[i][1] |= sel1 << index;
254                 break;
255             }
256             else
257             {
258                 /* All the cases have been listed above, this branch should not be reached. */
259                 return kStatus_InvalidArgument;
260             }
261 #endif /* defined(OUT_SEL_2) */
262         }
263     }
264 
265     return kStatus_Success;
266 }
267 
268 /*!
269  * brief Initialize ITRC
270  *
271  * This function initializes ITRC by enabling IRQ.
272  *
273  * param base ITRC peripheral base address
274  * return Status of the init operation
275  */
ITRC_Init(ITRC_Type * base)276 status_t ITRC_Init(ITRC_Type *base)
277 {
278     NVIC_EnableIRQ(ITRC0_IRQn);
279 
280     return kStatus_Success;
281 }
282 
283 /*!
284  * brief Deinitialize ITRC
285  *
286  * This function just disable ITRC IRQ.
287  *
288  * param base ITRC peripheral base address
289  */
ITRC_Deinit(ITRC_Type * base)290 void ITRC_Deinit(ITRC_Type *base)
291 {
292     NVIC_DisableIRQ(ITRC0_IRQn);
293 }
294