1 /*
2  * Copyright 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_common.h"
9 #include "fsl_glikey.h"
10 
11 /*******************************************************************************
12  * Definitions
13  *******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.glikey"
18 #endif
19 
20 #define GLIKEY_SFR_LOCK   0x05u
21 #define GLIKEY_SFR_UNLOCK 0x0Au
22 
23 /* Define to select between write to CTRL0_WR_0 or CTRL1_WR_1 */
24 #define WR_EN0 (0x0Fu)
25 #define WR_EN1 (0xF0u)
26 
27 #define WR_EN0_VALUE_SHIFT (0u)
28 #define WR_EN1_VALUE_SHIFT (16u)
29 
30 #define CTRL_SEL_CODEWORD_SHIFT (24u)
31 
32 #define WR_0_INIT (0x2u)
33 #define WR_1_INIT (0x0u)
34 
35 /*******************************************************************************
36  * Prototypes
37  ******************************************************************************/
38 static inline void Glikey_Internal_Set_WR_0(GLIKEY_Type *base, uint32_t value);
39 static inline void Glikey_Internal_Set_WR_1(GLIKEY_Type *base, uint32_t value);
40 /*******************************************************************************
41  * Code
42  ******************************************************************************/
43 
44 /*!
45  * Weak implementation of GLIKEY IRQ, should be re-defined by user when using GLIKEY IRQ
46 
47 __WEAK void GLIKEY0_DriverIRQHandler(void)
48 {
49     GLIKEY generates IRQ until corresponding bit in STATUS is cleared by calling
50     GLIKEY_ClearStatusFlags();
51 }
52 */
53 
Glikey_Internal_Set_WR_0(GLIKEY_Type * base,uint32_t value)54 static inline void Glikey_Internal_Set_WR_0(GLIKEY_Type *base, uint32_t value)
55 {
56     uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
57 
58     /* Clear WR_0 */
59     ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WR_EN_0_MASK);
60 
61     /* Assign value */
62     ((GLIKEY_Type *)base)->CTRL_0 = ctrl0 | GLIKEY_CTRL_0_WR_EN_0(value);
63 }
64 
Glikey_Internal_Set_WR_1(GLIKEY_Type * base,uint32_t value)65 static inline void Glikey_Internal_Set_WR_1(GLIKEY_Type *base, uint32_t value)
66 {
67     uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
68 
69     /* Clear WR_1 */
70     ctrl1 = ctrl1 & (~GLIKEY_CTRL_1_WR_EN_1_MASK);
71 
72     /* Assign value */
73     ((GLIKEY_Type *)base)->CTRL_1 = ctrl1 | GLIKEY_CTRL_1_WR_EN_1(value);
74 }
75 
GLIKEY_GetStatus(GLIKEY_Type * base)76 uint32_t GLIKEY_GetStatus(GLIKEY_Type *base)
77 {
78     return ((GLIKEY_Type *)base)->STATUS;
79 }
80 
GLIKEY_IsLocked(GLIKEY_Type * base)81 status_t GLIKEY_IsLocked(GLIKEY_Type *base)
82 {
83     status_t retCode = GLIKEY_CheckLock(base);
84     if (kStatus_GLIKEY_NotLocked == retCode)
85     {
86         return kStatus_GLIKEY_NotLocked;
87     }
88     else
89     {
90         return kStatus_GLIKEY_Locked;
91     }
92 }
93 
GLIKEY_CheckLock(GLIKEY_Type * base)94 status_t GLIKEY_CheckLock(GLIKEY_Type *base)
95 {
96     uint32_t sfrLock = (((GLIKEY_Type *)base)->CTRL_1 & GLIKEY_CTRL_1_SFR_LOCK_MASK) >> GLIKEY_CTRL_1_SFR_LOCK_SHIFT;
97 
98     if (GLIKEY_SFR_UNLOCK != sfrLock) /* Locked */
99     {
100         return kStatus_GLIKEY_LockedError;
101     }
102 
103     return kStatus_GLIKEY_NotLocked;
104 }
105 
106 #if defined(GLIKEY_VERSION_FSM_CONFIG)
GLIKEY_GetVersion(GLIKEY_Type * base,uint32_t * result)107 status_t GLIKEY_GetVersion(GLIKEY_Type *base, uint32_t *result)
108 {
109     *result = ((GLIKEY_Type *)base)->VERSION;
110 
111     return kStatus_Success;
112 }
113 #endif /* GLIKEY_VERSION_FSM_CONFIG */
114 
GLIKEY_SyncReset(GLIKEY_Type * base)115 status_t GLIKEY_SyncReset(GLIKEY_Type *base)
116 {
117     status_t retCode = GLIKEY_CheckLock(base);
118     if (kStatus_GLIKEY_NotLocked != retCode)
119     {
120         return retCode;
121     }
122 
123     /* Set CTRL_0.SFT_RST = 1 */
124     ((GLIKEY_Type *)base)->CTRL_0 |= GLIKEY_CTRL_0_SFT_RST_MASK;
125 
126     return kStatus_Success;
127 }
128 
GLIKEY_SetIntEnable(GLIKEY_Type * base,uint32_t value)129 status_t GLIKEY_SetIntEnable(GLIKEY_Type *base, uint32_t value)
130 {
131     status_t retCode = GLIKEY_CheckLock(base);
132     if (kStatus_GLIKEY_NotLocked != retCode)
133     {
134         return retCode;
135     }
136 
137     ((GLIKEY_Type *)base)->INTR_CTRL = GLIKEY_INTR_CTRL_INT_EN(value);
138 
139     return kStatus_Success;
140 }
141 
GLIKEY_GetIntEnable(GLIKEY_Type * base,uint32_t * value)142 status_t GLIKEY_GetIntEnable(GLIKEY_Type *base, uint32_t *value)
143 {
144     *value = ((GLIKEY_Type *)base)->INTR_CTRL & GLIKEY_INTR_CTRL_INT_EN_MASK;
145 
146     return kStatus_Success;
147 }
148 
GLIKEY_ClearIntStatus(GLIKEY_Type * base)149 status_t GLIKEY_ClearIntStatus(GLIKEY_Type *base)
150 {
151     status_t retCode = GLIKEY_CheckLock(base);
152     if (kStatus_GLIKEY_NotLocked != retCode)
153     {
154         return retCode;
155     }
156 
157     ((GLIKEY_Type *)base)->INTR_CTRL |= GLIKEY_INTR_CTRL_INT_CLR_MASK;
158 
159     return kStatus_Success;
160 }
161 
GLIKEY_SetIntStatus(GLIKEY_Type * base)162 status_t GLIKEY_SetIntStatus(GLIKEY_Type *base)
163 {
164     status_t retCode = GLIKEY_CheckLock(base);
165     if (kStatus_GLIKEY_NotLocked != retCode)
166     {
167         return retCode;
168     }
169 
170     ((GLIKEY_Type *)base)->INTR_CTRL |= GLIKEY_INTR_CTRL_INT_SET_MASK;
171 
172     return kStatus_Success;
173 }
174 
GLIKEY_Lock(GLIKEY_Type * base)175 status_t GLIKEY_Lock(GLIKEY_Type *base)
176 {
177     /* Check if SFR_LOCK is locked */
178     status_t retCode = GLIKEY_CheckLock(base);
179     if (kStatus_GLIKEY_NotLocked != retCode) /* Glikey is not locked -> lock */
180     {
181         uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
182         /* Clear SFR_LOCK */
183         ctrl1 = ctrl1 & (~GLIKEY_CTRL_1_SFR_LOCK_MASK);
184         /* Lock Gliekey */
185         ((GLIKEY_Type *)base)->CTRL_1 = ctrl1 | GLIKEY_CTRL_1_SFR_LOCK(GLIKEY_SFR_LOCK);
186     }
187 
188     return kStatus_Success;
189 }
190 
GLIKEY_IsIndexLocked(GLIKEY_Type * base,uint32_t index)191 status_t GLIKEY_IsIndexLocked(GLIKEY_Type *base, uint32_t index)
192 {
193     /* Set CTRL_1.READ_INDEX = index */
194     uint32_t ctr1Val = ((GLIKEY_Type *)base)->CTRL_1;
195     /* Clear READ_INDEX */
196     ctr1Val = ctr1Val & (~GLIKEY_CTRL_1_READ_INDEX_MASK);
197     /* Set index value */
198     ((GLIKEY_Type *)base)->CTRL_1 = ctr1Val | GLIKEY_CTRL_1_READ_INDEX(index);
199 
200     /* Check ERROR_STATUS */
201     if (0u != (GLIKEY_GetStatus(base) & GLIKEY_STATUS_ERROR_STATUS_MASK))
202     {
203         return kStatus_Fail;
204     }
205 
206     /* Check if STATUS.LOCK_STATUS is 0 */
207     if (0u == (GLIKEY_GetStatus(base) & GLIKEY_STATUS_LOCK_STATUS_MASK))
208     {
209         return kStatus_GLIKEY_NotLocked;
210     }
211     else
212     {
213         return kStatus_GLIKEY_Locked;
214     }
215 }
216 
GLIKEY_LockIndex(GLIKEY_Type * base)217 status_t GLIKEY_LockIndex(GLIKEY_Type *base)
218 {
219     /* Check if Glikey SFR locked */
220     status_t retCode = GLIKEY_CheckLock(base);
221     if (kStatus_GLIKEY_NotLocked != retCode)
222     {
223         return retCode;
224     }
225 
226     /* Check if FSM is in WR_EN state */
227     uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
228     if (GLIKEY_FSM_WR_EN == state)
229     {
230         /* Set WR_EN0 = b11 */
231         ((GLIKEY_Type *)base)->CTRL_0 |= GLIKEY_CTRL_0_WR_EN_0(0x3u);
232         return kStatus_GLIKEY_Locked;
233     }
234     else
235     {
236         return kStatus_GLIKEY_DisabledError;
237     }
238 }
239 
GLIKEY_StartEnable(GLIKEY_Type * base,uint32_t index)240 status_t GLIKEY_StartEnable(GLIKEY_Type *base, uint32_t index)
241 {
242     /* Check if Glikey SFR locked */
243     status_t retCode = GLIKEY_CheckLock(base);
244     if (kStatus_GLIKEY_NotLocked != retCode)
245     {
246         return retCode;
247     }
248 
249     /* Check if index is locked */
250     retCode = GLIKEY_IsIndexLocked(base, index);
251     if (kStatus_GLIKEY_NotLocked != retCode)
252     {
253         return retCode;
254     }
255 
256     /* CTRL0 */
257     uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
258     /* Clear old index */
259     ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WRITE_INDEX_MASK);
260     /* Clear old CTRL0.WR_EN_0 */
261     ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WR_EN_0_MASK);
262     /* Set new index */
263     ctrl0 |= GLIKEY_CTRL_0_WRITE_INDEX(index);
264 
265     /* Start the enable process by writting 0x01 to CTRL0.WR_EN_0 */
266     ctrl0 = ctrl0 | ((uint32_t)0x01u << GLIKEY_CTRL_0_WR_EN_0_SHIFT);
267 
268     /* Write to CTRL0 (new index and WR_EN_0 = 0x01) */
269     ((GLIKEY_Type *)base)->CTRL_0 = ctrl0;
270 
271     /* CTRL1 */
272     uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
273     /* Clear CTRL1.WR_EN_1 */
274     ctrl1 &= ~GLIKEY_CTRL_1_WR_EN_1_MASK;
275     ((GLIKEY_Type*)base)->CTRL_1 = ctrl1;
276 
277     return kStatus_Success;
278 }
279 
GLIKEY_ContinueEnable(GLIKEY_Type * base,uint32_t codeword)280 status_t GLIKEY_ContinueEnable(GLIKEY_Type *base, uint32_t codeword)
281 {
282     /* Check if Glikey SFR locked */
283     status_t retCode = GLIKEY_CheckLock(base);
284     if (kStatus_GLIKEY_NotLocked != retCode)
285     {
286         return retCode;
287     }
288 
289     /* Set correctly we_en0 and wr_en1 according to codeword */
290     /* Select between CTRL0/CTRL1 */
291     if (WR_EN1 == (codeword >> CTRL_SEL_CODEWORD_SHIFT))
292     {
293         Glikey_Internal_Set_WR_1(base, codeword >> WR_EN1_VALUE_SHIFT);
294     }
295     else if (WR_EN0 == (codeword >> CTRL_SEL_CODEWORD_SHIFT))
296     {
297         Glikey_Internal_Set_WR_0(base, codeword >> WR_EN0_VALUE_SHIFT);
298     }
299     else
300     {
301         return kStatus_Fail;
302     }
303 
304     if (0u != (GLIKEY_GetStatus(base) & GLIKEY_STATUS_ERROR_STATUS_MASK))
305     {
306         return kStatus_GLIKEY_DisabledError;
307     }
308 
309     /* Validate codeword - check if XXYZ^UUVW == 0xFFFF */
310     if (0xFFFFu != (((codeword) ^ (codeword >> 16u)) & 0xFFFFu))
311     {
312         return kStatus_Fail;
313     }
314 
315     return kStatus_Success;
316 }
317 
GLIKEY_EndOperation(GLIKEY_Type * base)318 status_t GLIKEY_EndOperation(GLIKEY_Type *base)
319 {
320     /* Check if Glikey SFR locked */
321     status_t retCode = GLIKEY_CheckLock(base);
322     if (kStatus_GLIKEY_NotLocked != retCode)
323     {
324         return retCode;
325     }
326 
327     // check state
328     uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
329 
330     switch (state)
331     {
332         case GLIKEY_FSM_LOCKED:
333         {
334             /* If locked -> try to go to init with wr_en0 = WR_0_INIT (0x02); wr_en1 = WR_1_INIT (0x00) */
335             Glikey_Internal_Set_WR_0(base, WR_0_INIT);
336             Glikey_Internal_Set_WR_1(base, WR_1_INIT);
337 
338             /* if still locked return locked - need to change index */
339             if (GLIKEY_FSM_LOCKED ==
340                 (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT)
341             {
342                 return kStatus_GLIKEY_Locked;
343             }
344 
345             retCode = kStatus_Success;
346             break;
347         }
348 
349         case GLIKEY_FSM_SSR_RESET:
350         case GLIKEY_FSM_WR_EN:
351         {
352             /* If FSM in RESET -> wr_en0 = WR_0_INIT; wr_en1 = WR_1_INIT */
353             /* If FSM in WR_EN -> wr_en0 = WR_0_INIT; wr_en1 = WR_1_INIT */
354             Glikey_Internal_Set_WR_0(base, WR_0_INIT);
355             Glikey_Internal_Set_WR_1(base, WR_1_INIT);
356 
357             retCode = kStatus_Success;
358             break;
359         }
360 
361         default:
362             /* Disabled error */
363             retCode = kStatus_GLIKEY_DisabledError;
364             break;
365     }
366 
367     return retCode;
368 }
369 
GLIKEY_ResetIndex(GLIKEY_Type * base,uint32_t index)370 status_t GLIKEY_ResetIndex(GLIKEY_Type *base, uint32_t index)
371 {
372     /* Check if Glikey SFR locked */
373     status_t retCode = GLIKEY_CheckLock(base);
374     if (kStatus_GLIKEY_NotLocked != retCode)
375     {
376         return retCode;
377     }
378 
379     /* Check if index is locked */
380     retCode = GLIKEY_IsIndexLocked(base, index);
381     if (kStatus_GLIKEY_NotLocked != retCode)
382     {
383         return retCode;
384     }
385 
386     /* Check if FSM is in INIT state */
387     uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
388     if (GLIKEY_FSM_INIT == state)
389     {
390         /* CTRL0.WRITE_INDEX = index */
391         uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
392         /* Clear index */
393         ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WRITE_INDEX_MASK);
394         /* Write new value */
395         ((GLIKEY_Type *)base)->CTRL_0 = ctrl0 | GLIKEY_CTRL_0_WRITE_INDEX(index);
396 
397         return kStatus_Success;
398     }
399     else
400     {
401         return kStatus_GLIKEY_DisabledError;
402     }
403 }
404