1 /*
2  * Copyright 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_gdet.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.gdet"
17 #endif
18 
19 #define ISOLATE_ON  (0x2u << 2)
20 #define ISOLATE_OFF (0x0u << 2)
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 
26 /*******************************************************************************
27  * Code
28  ******************************************************************************/
29 
30 /*!
31  * Weak implementation of GDET IRQ, should be re-defined by user when using GDET IRQ
32  */
GDET_DriverIRQHandler(void)33 __WEAK void GDET_DriverIRQHandler(void)
34 {
35     /* GDET generates IRQ if voltage glitching is detected
36      */
37 }
38 
39 /*!
40  * brief Initialize GDET
41  *
42  * This function initializes GDET setting and enable interrupts.
43  *
44  * param base GDET peripheral base address
45  * return Status of the init operation
46  */
GDET_Init(GDET_Type * base)47 status_t GDET_Init(GDET_Type *base)
48 {
49     /* Ungate clock to GDET engine and reset it */
50 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
51     CLOCK_EnableClock(kCLOCK_Gdet);
52 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
53 
54     NVIC_EnableIRQ(GDET_IRQn);
55 
56     return kStatus_Success;
57 }
58 
59 /*!
60  * brief Deinitialize GDET
61  *
62  * This function stops GDET glitch detector.
63  *
64  * param base GDET peripheral base address
65  */
GDET_Deinit(GDET_Type * base)66 void GDET_Deinit(GDET_Type *base)
67 {
68     NVIC_DisableIRQ(GDET_IRQn);
69 
70 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
71 
72     CLOCK_DisableClock(kCLOCK_Gdet);
73 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
74 }
75 
76 /* Array of GDET peripheral base address. */
77 static GDET_Type *const s_gdetBases[] = GDET_BASE_PTRS;
78 
79 /*!
80  * brief Get the GDET instance from peripheral base address.
81  *
82  * param base GDET peripheral base address.
83  * return GDET instance.
84  */
GDET_GetInstance(GDET_Type * base)85 static uint32_t GDET_GetInstance(GDET_Type *base)
86 {
87     uint32_t instance;
88 
89     /* Find the instance index from base address mappings. */
90     for (instance = 0U; instance < ARRAY_SIZE(s_gdetBases); instance++)
91     {
92         if (s_gdetBases[instance] == base)
93         {
94             break;
95         }
96     }
97 
98     assert(instance < ARRAY_SIZE(s_gdetBases));
99 
100     return instance;
101 }
102 
GDET_IsolateOn(GDET_Type * base)103 status_t GDET_IsolateOn(GDET_Type *base)
104 {
105     status_t status = kStatus_Fail;
106     uint32_t instance;
107 
108     instance = GDET_GetInstance(base);
109 
110     SYSCON->GDET_CTRL[instance] = ISOLATE_ON;
111 
112     if (ISOLATE_ON != SYSCON->GDET_CTRL[instance])
113     {
114         return kStatus_Fail;
115     }
116     status = kStatus_Success;
117 
118     return status;
119 }
120 
GDET_IsolateOff(GDET_Type * base)121 status_t GDET_IsolateOff(GDET_Type *base)
122 {
123     status_t status = kStatus_Fail;
124     uint32_t instance;
125 
126     instance = GDET_GetInstance(base);
127 
128     SYSCON->GDET_CTRL[instance] = ISOLATE_ON;
129 
130     if (ISOLATE_ON != SYSCON->GDET_CTRL[instance])
131     {
132         return kStatus_Fail;
133     }
134     status = kStatus_Success;
135 
136     return status;
137 }
138 
GDET_ReconfigureVoltageMode(GDET_Type * base,gdet_core_voltage_t voltage)139 status_t GDET_ReconfigureVoltageMode(GDET_Type *base, gdet_core_voltage_t voltage)
140 {
141     uint32_t tmp0   = 0;
142     status_t status = kStatus_Fail;
143 
144     if ((voltage != kGDET_MidVoltage) && (voltage != kGDET_NormalVoltage) && (voltage != kGDET_OverDriveVoltage))
145     {
146         return kStatus_InvalidArgument;
147     }
148 
149     /*Change the GDET_DLY_CTRL to select the new drive mode (and set high also GDET_DLY_CTRL[SW_VOL_CTRL] for a SW
150      * control)*/
151     tmp0 = (((uint32_t)voltage) << GDET_GDET_DLY_CTRL_VOL_SEL_SHIFT);
152     tmp0 |= GDET_GDET_DLY_CTRL_SW_VOL_CTRL_MASK;
153     base->GDET_DLY_CTRL = tmp0;
154 
155     /*Write high the GDET_RESET[SFT_RST] to issue a fast update of the detector to the new voltage level.*/
156     base->GDET_RESET = GDET_GDET_RESET_SFT_RST(1u);
157 
158     /* according to the GDET module documentation, the GDET_CFG[SFT_RST] reads as 0 */
159     if (0u == (GDET_GDET_RESET_SFT_RST_MASK & base->GDET_RESET))
160     {
161         status = kStatus_Success;
162     }
163 
164     return status;
165 }
166