1 /*
2  * Copyright 2017-2020, 2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_rdc_sema42.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.rdc_sema42"
17 #endif
18 
19 /* The first number write to RSTGDP when reset RDC_SEMA42 gate. */
20 #define RDC_SEMA42_GATE_RESET_PATTERN_1 (0xE2U)
21 /* The second number write to RSTGDP when reset RDC_SEMA42 gate. */
22 #define RDC_SEMA42_GATE_RESET_PATTERN_2 (0x1DU)
23 
24 #if !defined(RDC_SEMAPHORE_GATE_COUNT)
25 /* Compatible remap. */
26 #define RDC_SEMAPHORE_GATE_LDOM(x)    RDC_SEMAPHORE_GATE0_LDOM(x)
27 #define RDC_SEMAPHORE_GATE_GTFSM(x)   RDC_SEMAPHORE_GATE0_GTFSM(x)
28 #define RDC_SEMAPHORE_GATE_LDOM_MASK  RDC_SEMAPHORE_GATE0_LDOM_MASK
29 #define RDC_SEMAPHORE_GATE_LDOM_SHIFT RDC_SEMAPHORE_GATE0_LDOM_SHIFT
30 #endif
31 
32 /*******************************************************************************
33  * Prototypes
34  ******************************************************************************/
35 
36 /*!
37  * @brief Get instance number for RDC_SEMA42 module.
38  *
39  * @param base RDC_SEMA42 peripheral base address.
40  */
41 uint32_t RDC_SEMA42_GetInstance(RDC_SEMAPHORE_Type *base);
42 
43 /*******************************************************************************
44  * Variables
45  ******************************************************************************/
46 
47 /*! @brief Pointers to sema42 bases for each instance. */
48 static RDC_SEMAPHORE_Type *const s_sema42Bases[] = RDC_SEMAPHORE_BASE_PTRS;
49 
50 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
51 #if defined(RDC_SEMA42_CLOCKS)
52 /*! @brief Pointers to sema42 clocks for each instance. */
53 static const clock_ip_name_t s_sema42Clocks[] = RDC_SEMA42_CLOCKS;
54 #endif
55 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
56 
57 /******************************************************************************
58  * CODE
59  *****************************************************************************/
60 
RDC_SEMA42_GetInstance(RDC_SEMAPHORE_Type * base)61 uint32_t RDC_SEMA42_GetInstance(RDC_SEMAPHORE_Type *base)
62 {
63     uint32_t instance;
64 
65     /* Find the instance index from base address mappings. */
66     for (instance = 0; instance < ARRAY_SIZE(s_sema42Bases); instance++)
67     {
68         if (s_sema42Bases[instance] == base)
69         {
70             break;
71         }
72     }
73 
74     assert(instance < ARRAY_SIZE(s_sema42Bases));
75 
76     return instance;
77 }
78 
79 /*!
80  * brief Initializes the RDC_SEMA42 module.
81  *
82  * This function initializes the RDC_SEMA42 module. It only enables the clock but does
83  * not reset the gates because the module might be used by other processors
84  * at the same time. To reset the gates, call either RDC_SEMA42_ResetGate or
85  * RDC_SEMA42_ResetAllGates function.
86  *
87  * param base RDC_SEMA42 peripheral base address.
88  */
RDC_SEMA42_Init(RDC_SEMAPHORE_Type * base)89 void RDC_SEMA42_Init(RDC_SEMAPHORE_Type *base)
90 {
91 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
92 #if defined(RDC_SEMA42_CLOCKS)
93     CLOCK_EnableClock(s_sema42Clocks[RDC_SEMA42_GetInstance(base)]);
94 #endif
95 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
96 }
97 
98 /*!
99  * brief De-initializes the RDC_SEMA42 module.
100  *
101  * This function de-initializes the RDC_SEMA42 module. It only disables the clock.
102  *
103  * param base RDC_SEMA42 peripheral base address.
104  */
RDC_SEMA42_Deinit(RDC_SEMAPHORE_Type * base)105 void RDC_SEMA42_Deinit(RDC_SEMAPHORE_Type *base)
106 {
107 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
108 #if defined(RDC_SEMA42_CLOCKS)
109     CLOCK_DisableClock(s_sema42Clocks[RDC_SEMA42_GetInstance(base)]);
110 #endif
111 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
112 }
113 
114 /*!
115  * brief Tries to lock the RDC_SEMA42 gate.
116  *
117  * This function tries to lock the specific RDC_SEMA42 gate. If the gate has been
118  * locked by another processor, this function returns an error code.
119  *
120  * param base RDC_SEMA42 peripheral base address.
121  * param gateNum  Gate number to lock.
122  * param masterIndex  Current processor master index.
123  * param domainId  Current processor domain ID.
124  *
125  * retval kStatus_Success   Lock the sema42 gate successfully.
126  * retval kStatus_Failed    Sema42 gate has been locked by another processor.
127  */
RDC_SEMA42_TryLock(RDC_SEMAPHORE_Type * base,uint8_t gateNum,uint8_t masterIndex,uint8_t domainId)128 status_t RDC_SEMA42_TryLock(RDC_SEMAPHORE_Type *base, uint8_t gateNum, uint8_t masterIndex, uint8_t domainId)
129 {
130     assert(gateNum < RDC_SEMA42_GATE_COUNT);
131 
132     status_t status = kStatus_Success;
133     uint8_t regGate;
134 
135     ++masterIndex;
136 
137     regGate = (uint8_t)(RDC_SEMAPHORE_GATE_LDOM(domainId) | RDC_SEMAPHORE_GATE_GTFSM(masterIndex));
138 
139     /* Try to lock. */
140     RDC_SEMA42_GATEn(base, gateNum) = masterIndex;
141 
142     /* Check locked or not. */
143     if (regGate != RDC_SEMA42_GATEn(base, gateNum))
144     {
145         status = kStatus_Fail;
146     }
147 
148     return status;
149 }
150 
151 /*!
152  * brief Locks the RDC_SEMA42 gate.
153  *
154  * This function locks the specific RDC_SEMA42 gate. If the gate has been
155  * locked by other processors, this function waits until it is unlocked and then
156  * lock it.
157  *
158  * param base RDC_SEMA42 peripheral base address.
159  * param gateNum  Gate number to lock.
160  * param masterIndex  Current processor master index.
161  * param domainId  Current processor domain ID.
162  */
RDC_SEMA42_Lock(RDC_SEMAPHORE_Type * base,uint8_t gateNum,uint8_t masterIndex,uint8_t domainId)163 void RDC_SEMA42_Lock(RDC_SEMAPHORE_Type *base, uint8_t gateNum, uint8_t masterIndex, uint8_t domainId)
164 {
165     while (kStatus_Success != RDC_SEMA42_TryLock(base, gateNum, masterIndex, domainId))
166     {
167     }
168 }
169 
170 /*!
171  * brief Gets which domain has currently locked the gate.
172  *
173  * param base RDC_SEMA42 peripheral base address.
174  * param gateNum  Gate number.
175  *
176  * return Return -1 if the gate is not locked by any domain, otherwise return the
177  * domain ID.
178  */
RDC_SEMA42_GetLockDomainID(RDC_SEMAPHORE_Type * base,uint8_t gateNum)179 int32_t RDC_SEMA42_GetLockDomainID(RDC_SEMAPHORE_Type *base, uint8_t gateNum)
180 {
181     assert(gateNum < RDC_SEMA42_GATE_COUNT);
182 
183     int32_t ret;
184     uint8_t regGate = RDC_SEMA42_GATEn(base, gateNum);
185 
186     /* Current gate is not locked. */
187     if (0U == (regGate & RDC_SEMAPHORE_GATE_GTFSM_MASK))
188     {
189         ret = -1;
190     }
191     else
192     {
193         ret = (int32_t)((uint8_t)((regGate & RDC_SEMAPHORE_GATE_LDOM_MASK) >> RDC_SEMAPHORE_GATE_LDOM_SHIFT));
194     }
195 
196     return ret;
197 }
198 
199 /*!
200  * brief Resets the RDC_SEMA42 gate to an unlocked status.
201  *
202  * This function resets a RDC_SEMA42 gate to an unlocked status.
203  *
204  * param base RDC_SEMA42 peripheral base address.
205  * param gateNum  Gate number.
206  *
207  * retval kStatus_Success         RDC_SEMA42 gate is reset successfully.
208  * retval kStatus_Failed Some other reset process is ongoing.
209  */
RDC_SEMA42_ResetGate(RDC_SEMAPHORE_Type * base,uint8_t gateNum)210 status_t RDC_SEMA42_ResetGate(RDC_SEMAPHORE_Type *base, uint8_t gateNum)
211 {
212     status_t status;
213 
214     /*
215      * Reset all gates if gateNum >= RDC_SEMA42_GATE_NUM_RESET_ALL
216      * Reset specific gate if gateNum < RDC_SEMA42_GATE_COUNT
217      */
218 
219     /* Check whether some reset is ongoing. */
220     if (0U != (base->RSTGT_R & RDC_SEMAPHORE_RSTGT_R_RSTGSM_MASK))
221     {
222         status = kStatus_Fail;
223     }
224     else
225     {
226         /* First step. */
227         base->RSTGT_W = RDC_SEMAPHORE_RSTGT_W_RSTGDP(RDC_SEMA42_GATE_RESET_PATTERN_1);
228         /* Second step. */
229         base->RSTGT_W =
230             RDC_SEMAPHORE_RSTGT_W_RSTGDP(RDC_SEMA42_GATE_RESET_PATTERN_2) | RDC_SEMAPHORE_RSTGT_W_RSTGTN(gateNum);
231 
232         status = kStatus_Success;
233     }
234 
235     return status;
236 }
237