1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 /* **** Includes **** */
22 #include <stddef.h>
23 #include "mxc_device.h"
24 #include "mxc_assert.h"
25 #include "gpio.h"
26 #include "gpio_reva.h"
27 #include "gpio_common.h"
28 #include "mxc_sys.h"
29 #include "lpgcr_regs.h"
30 #include "mcr_regs.h"
31 #include "pwrseq_regs.h"
32 
33 /* **** Definitions **** */
34 // Pin 3.0 Definitions
35 #define P30_DATA_OUT(pin_mask) ((pin_mask & (1 << 0)) == (1 << 0) ? MXC_F_MCR_GPIO3_CTRL_P30_DO : 0)
36 #define P30_OUT_EN(pin_mask) ((pin_mask & (1 << 0)) == (1 << 0) ? MXC_F_MCR_GPIO3_CTRL_P30_OE : 0)
37 #define P30_PULL_DIS(pin_mask) ((pin_mask & (1 << 0)) == (1 << 0) ? MXC_F_MCR_GPIO3_CTRL_P30_PE : 0)
38 #define P30_DATA_IN(pin_mask) ((pin_mask & (1 << 0)) == (1 << 0) ? MXC_F_MCR_GPIO3_CTRL_P30_IN : 0)
39 #define PDOWN_OUT_EN(pin_mask) \
40     ((pin_mask & (1 << 0)) == (1 << 0) ? MXC_F_MCR_OUTEN_PDOWN_OUT_EN : 0)
41 
42 // Pin 3.1 Definitions
43 #define P31_DATA_OUT(pin_mask) ((pin_mask & (1 << 1)) == (1 << 1) ? MXC_F_MCR_GPIO3_CTRL_P31_DO : 0)
44 #define P31_OUT_EN(pin_mask) ((pin_mask & (1 << 1)) == (1 << 1) ? MXC_F_MCR_GPIO3_CTRL_P31_OE : 0)
45 #define P31_PULL_DIS(pin_mask) ((pin_mask & (1 << 1)) == (1 << 1) ? MXC_F_MCR_GPIO3_CTRL_P31_PE : 0)
46 #define P31_DATA_IN(pin_mask) ((pin_mask & (1 << 1)) == (1 << 1) ? MXC_F_MCR_GPIO3_CTRL_P31_IN : 0)
47 #define SQWAVE_OUT_EN(pin_mask) ((pin_mask & (1 << 1)) == (1 << 1) ? MXC_F_MCR_OUTEN_SQWOUT_EN : 0)
48 
49 /* **** Globals **** */
50 
51 /* **** Functions **** */
MXC_GPIO_Init(uint32_t portmask)52 int MXC_GPIO_Init(uint32_t portmask)
53 {
54     if (portmask & 0x1) {
55         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO0);
56     }
57 
58     if (portmask & 0x2) {
59         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO1);
60     }
61 
62     if (portmask & 0x4) {
63         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO2);
64     }
65 
66     return MXC_GPIO_Common_Init(portmask);
67 }
68 
MXC_GPIO_Shutdown(uint32_t portmask)69 int MXC_GPIO_Shutdown(uint32_t portmask)
70 {
71     if (portmask & 0x1) {
72         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO0);
73     }
74 
75     if (portmask & 0x2) {
76         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO1);
77     }
78 
79     if (portmask & 0x4) {
80         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO2);
81     }
82 
83     return E_NO_ERROR;
84 }
85 
MXC_GPIO_Reset(uint32_t portmask)86 int MXC_GPIO_Reset(uint32_t portmask)
87 {
88     if (portmask & 0x1) {
89         MXC_SYS_Reset_Periph(MXC_SYS_RESET0_GPIO0);
90     }
91 
92     if (portmask & 0x2) {
93         MXC_SYS_Reset_Periph(MXC_SYS_RESET0_GPIO1);
94     }
95 
96     if (portmask & 0x4) {
97         MXC_SYS_Reset_Periph(MXC_SYS_RESET_GPIO2);
98     }
99 
100     return E_NO_ERROR;
101 }
102 
MXC_GPIO_Config(const mxc_gpio_cfg_t * cfg)103 int MXC_GPIO_Config(const mxc_gpio_cfg_t *cfg)
104 {
105     int port, error;
106     mxc_gpio_regs_t *gpio = cfg->port;
107 
108     port = MXC_GPIO_GET_IDX(cfg->port);
109 
110     MXC_GPIO_Init(1 << port);
111 
112     // Configure the vssel
113     error = MXC_GPIO_SetVSSEL(gpio, cfg->vssel, cfg->mask);
114     if (error != E_NO_ERROR) {
115         return error;
116     }
117 
118     if (cfg->port == MXC_GPIO3) {
119         switch (cfg->func) {
120         case MXC_GPIO_FUNC_IN:
121             MXC_MCR->gpio3_ctrl &= ~(P30_OUT_EN(cfg->mask) | P31_OUT_EN(cfg->mask));
122             MXC_MCR->outen &= ~(SQWAVE_OUT_EN(cfg->mask) | PDOWN_OUT_EN(cfg->mask));
123             break;
124 
125         case MXC_GPIO_FUNC_OUT:
126             MXC_MCR->gpio3_ctrl |= P30_OUT_EN(cfg->mask) | P31_OUT_EN(cfg->mask);
127             MXC_MCR->outen &= ~(SQWAVE_OUT_EN(cfg->mask) | PDOWN_OUT_EN(cfg->mask));
128             break;
129 
130         case MXC_GPIO_FUNC_ALT1:
131             MXC_MCR->gpio3_ctrl |= P30_OUT_EN(cfg->mask) | P31_OUT_EN(cfg->mask);
132             MXC_MCR->outen |= SQWAVE_OUT_EN(cfg->mask) | PDOWN_OUT_EN(cfg->mask);
133             break;
134 
135         default:
136             return E_NOT_SUPPORTED;
137         }
138 
139         switch (cfg->pad) {
140         case MXC_GPIO_PAD_NONE:
141             MXC_MCR->gpio3_ctrl |= P30_PULL_DIS(cfg->mask) | P31_PULL_DIS(cfg->mask);
142             break;
143 
144         case MXC_GPIO_PAD_PULL_UP:
145         case MXC_GPIO_PAD_WEAK_PULL_UP:
146             MXC_MCR->gpio3_ctrl |= P30_DATA_OUT(cfg->mask) | P31_DATA_OUT(cfg->mask);
147             MXC_MCR->gpio3_ctrl &= ~(P30_PULL_DIS(cfg->mask) | P31_PULL_DIS(cfg->mask));
148             break;
149 
150         case MXC_GPIO_PAD_PULL_DOWN:
151         case MXC_GPIO_PAD_WEAK_PULL_DOWN:
152             MXC_MCR->gpio3_ctrl &= ~(P30_DATA_OUT(cfg->mask) | P31_DATA_OUT(cfg->mask));
153             MXC_MCR->gpio3_ctrl &= ~(P30_PULL_DIS(cfg->mask) | P31_PULL_DIS(cfg->mask));
154             break;
155 
156         default:
157             return E_NOT_SUPPORTED;
158         }
159     } else {
160         // Configure alternate function
161         error = MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)gpio, cfg->func, cfg->mask);
162         if (error != E_NO_ERROR) {
163             return error;
164         }
165 
166         // Configure the pad
167         switch (cfg->pad) {
168         case MXC_GPIO_PAD_NONE:
169             gpio->padctrl0 &= ~cfg->mask;
170             gpio->padctrl1 &= ~cfg->mask;
171             break;
172 
173         case MXC_GPIO_PAD_WEAK_PULL_UP:
174             gpio->padctrl0 |= cfg->mask;
175             gpio->padctrl1 &= ~cfg->mask;
176             gpio->ps &= ~cfg->mask;
177             break;
178 
179         case MXC_GPIO_PAD_PULL_UP:
180             gpio->padctrl0 |= cfg->mask;
181             gpio->padctrl1 &= ~cfg->mask;
182             gpio->ps |= cfg->mask;
183             break;
184 
185         case MXC_GPIO_PAD_WEAK_PULL_DOWN:
186             gpio->padctrl0 &= ~cfg->mask;
187             gpio->padctrl1 |= cfg->mask;
188             gpio->ps &= ~cfg->mask;
189             break;
190 
191         case MXC_GPIO_PAD_PULL_DOWN:
192             gpio->padctrl0 &= ~cfg->mask;
193             gpio->padctrl1 |= cfg->mask;
194             gpio->ps |= cfg->mask;
195             break;
196 
197         default:
198             return E_BAD_PARAM;
199         }
200     }
201 
202     // Configure the drive strength
203     if (cfg->func == MXC_GPIO_FUNC_IN) {
204         return E_NO_ERROR;
205     } else {
206         return MXC_GPIO_SetDriveStrength(gpio, cfg->drvstr, cfg->mask);
207     }
208 }
209 
210 /* ************************************************************************** */
MXC_GPIO_InGet(mxc_gpio_regs_t * port,uint32_t mask)211 uint32_t MXC_GPIO_InGet(mxc_gpio_regs_t *port, uint32_t mask)
212 {
213     uint32_t in = 0;
214 
215     if (port == MXC_GPIO3) {
216         if (MXC_MCR->gpio3_ctrl & P30_DATA_IN(mask)) {
217             in |= MXC_GPIO_PIN_0;
218         }
219 
220         if (MXC_MCR->gpio3_ctrl & P31_DATA_IN(mask)) {
221             in |= MXC_GPIO_PIN_1;
222         }
223 
224         return in;
225     }
226 
227     return MXC_GPIO_RevA_InGet((mxc_gpio_reva_regs_t *)port, mask);
228 }
229 
230 /* ************************************************************************** */
MXC_GPIO_OutSet(mxc_gpio_regs_t * port,uint32_t mask)231 void MXC_GPIO_OutSet(mxc_gpio_regs_t *port, uint32_t mask)
232 {
233     if (port == MXC_GPIO3) {
234         MXC_MCR->gpio3_ctrl |= P30_DATA_OUT(mask) | P31_DATA_OUT(mask);
235         return;
236     }
237 
238     MXC_GPIO_RevA_OutSet((mxc_gpio_reva_regs_t *)port, mask);
239 }
240 
241 /* ************************************************************************** */
MXC_GPIO_OutClr(mxc_gpio_regs_t * port,uint32_t mask)242 void MXC_GPIO_OutClr(mxc_gpio_regs_t *port, uint32_t mask)
243 {
244     if (port == MXC_GPIO3) {
245         MXC_MCR->gpio3_ctrl &= ~(P30_DATA_OUT(mask) | P31_DATA_OUT(mask));
246         return;
247     }
248 
249     MXC_GPIO_RevA_OutClr((mxc_gpio_reva_regs_t *)port, mask);
250 }
251 
252 /* ************************************************************************** */
MXC_GPIO_OutGet(mxc_gpio_regs_t * port,uint32_t mask)253 uint32_t MXC_GPIO_OutGet(mxc_gpio_regs_t *port, uint32_t mask)
254 {
255     uint32_t out = 0;
256 
257     if (port == MXC_GPIO3) {
258         if (MXC_MCR->gpio3_ctrl & P30_DATA_OUT(mask)) {
259             out |= MXC_GPIO_PIN_0;
260         }
261 
262         if (MXC_MCR->gpio3_ctrl & P31_DATA_OUT(mask)) {
263             out |= MXC_GPIO_PIN_1;
264         }
265 
266         return out;
267     }
268 
269     return MXC_GPIO_RevA_OutGet((mxc_gpio_reva_regs_t *)port, mask);
270 }
271 
272 /* ************************************************************************** */
MXC_GPIO_OutPut(mxc_gpio_regs_t * port,uint32_t mask,uint32_t val)273 void MXC_GPIO_OutPut(mxc_gpio_regs_t *port, uint32_t mask, uint32_t val)
274 {
275     if (port == MXC_GPIO3) {
276         uint32_t gpio3_cp = MXC_MCR->gpio3_ctrl & ~(P30_DATA_OUT(mask) | P31_DATA_OUT(mask));
277 
278         MXC_MCR->gpio3_ctrl = gpio3_cp | P30_DATA_OUT((mask & val)) | P31_DATA_OUT((mask & val));
279         return;
280     }
281 
282     MXC_GPIO_RevA_OutPut((mxc_gpio_reva_regs_t *)port, mask, val);
283 }
284 
285 /* ************************************************************************** */
MXC_GPIO_OutToggle(mxc_gpio_regs_t * port,uint32_t mask)286 void MXC_GPIO_OutToggle(mxc_gpio_regs_t *port, uint32_t mask)
287 {
288     if (port == MXC_GPIO3) {
289         MXC_MCR->gpio3_ctrl ^= P30_DATA_OUT(mask) | P31_DATA_OUT(mask);
290         return;
291     }
292 
293     MXC_GPIO_RevA_OutToggle((mxc_gpio_reva_regs_t *)port, mask);
294 }
295 
296 /* ************************************************************************** */
MXC_GPIO_IntConfig(const mxc_gpio_cfg_t * cfg,mxc_gpio_int_pol_t pol)297 int MXC_GPIO_IntConfig(const mxc_gpio_cfg_t *cfg, mxc_gpio_int_pol_t pol)
298 {
299     if (cfg->port == MXC_GPIO3) {
300         if (pol != MXC_GPIO_INT_BOTH) {
301             return E_NOT_SUPPORTED;
302         }
303 
304         return E_NO_ERROR;
305     }
306 
307     return MXC_GPIO_RevA_IntConfig(cfg, pol);
308 }
309 
310 /* ************************************************************************** */
MXC_GPIO_EnableInt(mxc_gpio_regs_t * port,uint32_t mask)311 void MXC_GPIO_EnableInt(mxc_gpio_regs_t *port, uint32_t mask)
312 {
313     if (port == MXC_GPIO3) {
314         MXC_PWRSEQ->lpwken3 |= mask;
315         return;
316     }
317 
318     MXC_GPIO_RevA_EnableInt((mxc_gpio_reva_regs_t *)port, mask);
319 }
320 
321 /* ************************************************************************** */
MXC_GPIO_DisableInt(mxc_gpio_regs_t * port,uint32_t mask)322 void MXC_GPIO_DisableInt(mxc_gpio_regs_t *port, uint32_t mask)
323 {
324     if (port == MXC_GPIO3) {
325         MXC_PWRSEQ->lpwken3 &= ~mask;
326         return;
327     }
328 
329     MXC_GPIO_RevA_DisableInt((mxc_gpio_reva_regs_t *)port, mask);
330 }
331 
332 /* ************************************************************************** */
MXC_GPIO_RegisterCallback(const mxc_gpio_cfg_t * cfg,mxc_gpio_callback_fn func,void * cbdata)333 void MXC_GPIO_RegisterCallback(const mxc_gpio_cfg_t *cfg, mxc_gpio_callback_fn func, void *cbdata)
334 {
335     MXC_GPIO_Common_RegisterCallback(cfg, func, cbdata);
336 }
337 
338 /* ************************************************************************** */
MXC_GPIO_Handler(unsigned int port)339 void MXC_GPIO_Handler(unsigned int port)
340 {
341     MXC_GPIO_Common_Handler(port);
342 }
343 
344 /* ************************************************************************** */
MXC_GPIO_ClearFlags(mxc_gpio_regs_t * port,uint32_t flags)345 void MXC_GPIO_ClearFlags(mxc_gpio_regs_t *port, uint32_t flags)
346 {
347     if (port == MXC_GPIO3) {
348         MXC_PWRSEQ->lpwkst3 = flags;
349         return;
350     }
351 
352     MXC_GPIO_RevA_ClearFlags((mxc_gpio_reva_regs_t *)port, flags);
353 }
354 
355 /* ************************************************************************** */
MXC_GPIO_GetFlags(mxc_gpio_regs_t * port)356 uint32_t MXC_GPIO_GetFlags(mxc_gpio_regs_t *port)
357 {
358     if (port == MXC_GPIO3) {
359         return MXC_PWRSEQ->lpwkst3;
360     }
361 
362     return MXC_GPIO_RevA_GetFlags((mxc_gpio_reva_regs_t *)port);
363 }
364 
365 /* ************************************************************************** */
MXC_GPIO_SetVSSEL(mxc_gpio_regs_t * port,mxc_gpio_vssel_t vssel,uint32_t mask)366 int MXC_GPIO_SetVSSEL(mxc_gpio_regs_t *port, mxc_gpio_vssel_t vssel, uint32_t mask)
367 {
368     if (port == MXC_GPIO3) {
369         if (vssel == MXC_GPIO_VSSEL_VDDIO) {
370             return E_NOT_SUPPORTED;
371         }
372 
373         return E_NO_ERROR;
374     }
375 
376     return MXC_GPIO_RevA_SetVSSEL((mxc_gpio_reva_regs_t *)port, vssel, mask);
377 }
378 
379 /* ************************************************************************** */
MXC_GPIO_SetWakeEn(mxc_gpio_regs_t * port,uint32_t mask)380 void MXC_GPIO_SetWakeEn(mxc_gpio_regs_t *port, uint32_t mask)
381 {
382     if (port == MXC_GPIO3) {
383         MXC_PWRSEQ->lpwken3 |= mask;
384         return;
385     }
386 
387     MXC_GPIO_RevA_SetWakeEn((mxc_gpio_reva_regs_t *)port, mask);
388 }
389 
390 /* ************************************************************************** */
MXC_GPIO_ClearWakeEn(mxc_gpio_regs_t * port,uint32_t mask)391 void MXC_GPIO_ClearWakeEn(mxc_gpio_regs_t *port, uint32_t mask)
392 {
393     if (port == MXC_GPIO3) {
394         MXC_PWRSEQ->lpwken3 &= ~mask;
395         return;
396     }
397 
398     MXC_GPIO_RevA_ClearWakeEn((mxc_gpio_reva_regs_t *)port, mask);
399 }
400 
401 /* ************************************************************************** */
MXC_GPIO_GetWakeEn(mxc_gpio_regs_t * port)402 uint32_t MXC_GPIO_GetWakeEn(mxc_gpio_regs_t *port)
403 {
404     if (port == MXC_GPIO3) {
405         return MXC_PWRSEQ->lpwken3;
406     }
407 
408     return MXC_GPIO_RevA_GetWakeEn((mxc_gpio_reva_regs_t *)port);
409 }
410 
411 /* ************************************************************************** */
MXC_GPIO_SetDriveStrength(mxc_gpio_regs_t * port,mxc_gpio_drvstr_t drvstr,uint32_t mask)412 int MXC_GPIO_SetDriveStrength(mxc_gpio_regs_t *port, mxc_gpio_drvstr_t drvstr, uint32_t mask)
413 {
414     return MXC_GPIO_RevA_SetDriveStrength((mxc_gpio_reva_regs_t *)port, drvstr, mask);
415 }
416