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 "gpio.h"
24 #include "gpio_common.h"
25 #include "gpio_reva.h"
26 // #include "lpgcr_regs.h"
27 #include "mcr_regs.h"
28 #include "mxc_device.h"
29 #include "mxc_sys.h"
30 #include "pwrseq_regs.h"
31 
32 /* **** Definitions **** */
33 #define GPIO4_PIN_MASK 0x00000003
34 #define GPIO4_RESET_MASK 0xFFFFFF77
35 #define GPIO4_OUTEN_MASK(mask)                                \
36     (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_OE_POS) | \
37      ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_OE_POS - 1)))
38 #define GPIO4_PULLDIS_MASK(mask)                              \
39     (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_PE_POS) | \
40      ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_PE_POS - 1)))
41 #define GPIO4_DATAOUT_MASK(mask)                              \
42     (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \
43      ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1)))
44 #define GPIO4_DATAOUT_GET_MASK(mask)                                                             \
45     ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_DO) >> MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \
46       ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_DO) >>                                    \
47        (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1))) &                                                 \
48      mask)
49 #define GPIO4_DATAIN_MASK(mask)                                                                  \
50     ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_IN) >> MXC_F_MCR_GPIO4_CTRL_P40_IN_POS) | \
51       ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_IN) >>                                    \
52        (MXC_F_MCR_GPIO4_CTRL_P41_IN_POS - 1))) &                                                 \
53      mask)
54 #define GPIO4_AFEN_MASK(mask)                                  \
55     (((mask & (1 << 0)) << MXC_F_MCR_OUTEN_PDOWN_OUT_EN_POS) | \
56      ((mask & (1 << 1)) >> (MXC_F_MCR_OUTEN_SQWOUT_EN_POS + 1)))
57 
58 /* **** Globals **** */
59 
60 /* **** Functions **** */
MXC_GPIO_Init(uint32_t portmask)61 int MXC_GPIO_Init(uint32_t portmask)
62 {
63     if (portmask & 0x1) {
64         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO0);
65     }
66 
67     if (portmask & 0x2) {
68         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO1);
69     }
70 
71     if (portmask & 0x4) {
72         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO2);
73     }
74 
75     if (portmask & 0x8) {
76         MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_GPIO3);
77     }
78 
79     return MXC_GPIO_Common_Init(portmask);
80 }
81 
MXC_GPIO_Shutdown(uint32_t portmask)82 int MXC_GPIO_Shutdown(uint32_t portmask)
83 {
84     if (portmask & 0x1) {
85         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO0);
86     }
87 
88     if (portmask & 0x2) {
89         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO1);
90     }
91 
92     if (portmask & 0x4) {
93         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO2);
94     }
95 
96     if (portmask & 0x8) {
97         MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_GPIO3);
98     }
99 
100     return E_NO_ERROR;
101 }
102 
MXC_GPIO_Reset(uint32_t portmask)103 int MXC_GPIO_Reset(uint32_t portmask)
104 {
105     if (portmask & 0x1) {
106         MXC_SYS_Reset_Periph(MXC_SYS_RESET0_GPIO0);
107     }
108 
109     if (portmask & 0x2) {
110         MXC_SYS_Reset_Periph(MXC_SYS_RESET0_GPIO1);
111     }
112 
113     if (portmask & 0x4) {
114         MXC_SYS_Reset_Periph(MXC_SYS_RESET0_GPIO2);
115     }
116 
117     if (portmask & 0x8) {
118         MXC_SYS_Reset_Periph(MXC_SYS_RESET_GPIO3);
119     }
120 
121     if (portmask & 0x10) {
122         MXC_MCR->gpio4_ctrl &= ~GPIO4_RESET_MASK;
123     }
124 
125     return E_NO_ERROR;
126 }
127 
MXC_GPIO_Config(const mxc_gpio_cfg_t * cfg)128 int MXC_GPIO_Config(const mxc_gpio_cfg_t *cfg)
129 {
130     int port, error;
131     mxc_gpio_regs_t *gpio = cfg->port;
132 
133     port = MXC_GPIO_GET_IDX(cfg->port);
134     if (port == -1) {
135         return E_BAD_PARAM;
136     }
137 
138     // Initialize callback function pointers
139     MXC_GPIO_Init(1 << port);
140 
141     // Configure the vssel
142     if (port < 4) {
143         error = MXC_GPIO_SetVSSEL(gpio, cfg->vssel, cfg->mask);
144         if (error != E_NO_ERROR) {
145             return error;
146         }
147     }
148 
149     // Configure alternate function
150     if (port < 4) {
151         error = MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)gpio, cfg->func, cfg->mask);
152     } else {
153         error = E_NO_ERROR;
154 
155         switch (cfg->func) {
156         case MXC_GPIO_FUNC_ALT1:
157             // Set GPIO(s) to AF1
158             MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(cfg->mask);
159             MXC_MCR->outen |= GPIO4_AFEN_MASK(cfg->mask);
160             break;
161 
162         case MXC_GPIO_FUNC_OUT:
163             // Set GPIO(s) to output mode
164             MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(cfg->mask);
165             MXC_MCR->outen &= ~GPIO4_AFEN_MASK(cfg->mask);
166             break;
167 
168         case MXC_GPIO_FUNC_IN:
169             // Set GPIO(s) to input mode
170             MXC_MCR->gpio4_ctrl &= ~GPIO4_OUTEN_MASK(cfg->mask);
171             MXC_MCR->outen &= ~GPIO4_AFEN_MASK(cfg->mask);
172             break;
173 
174         default:
175             error = E_NOT_SUPPORTED;
176             break;
177         }
178     }
179 
180     if (error != E_NO_ERROR) {
181         return error;
182     }
183 
184     // Configure the pad
185     if (port < 4) {
186         switch (cfg->pad) {
187         case MXC_GPIO_PAD_NONE:
188             gpio->padctrl0 &= ~cfg->mask;
189             gpio->padctrl1 &= ~cfg->mask;
190             break;
191 
192         case MXC_GPIO_PAD_WEAK_PULL_UP:
193             gpio->padctrl0 |= cfg->mask;
194             gpio->padctrl1 &= ~cfg->mask;
195             gpio->ps &= ~cfg->mask;
196             break;
197 
198         case MXC_GPIO_PAD_PULL_UP:
199             gpio->padctrl0 |= cfg->mask;
200             gpio->padctrl1 &= ~cfg->mask;
201             gpio->ps |= cfg->mask;
202             break;
203 
204         case MXC_GPIO_PAD_WEAK_PULL_DOWN:
205             gpio->padctrl0 &= ~cfg->mask;
206             gpio->padctrl1 |= cfg->mask;
207             gpio->ps &= ~cfg->mask;
208             break;
209 
210         case MXC_GPIO_PAD_PULL_DOWN:
211             gpio->padctrl0 &= ~cfg->mask;
212             gpio->padctrl1 |= cfg->mask;
213             gpio->ps |= cfg->mask;
214             break;
215 
216         default:
217             return E_BAD_PARAM;
218         }
219     } else {
220         switch (cfg->pad) {
221         case MXC_GPIO_PAD_NONE:
222             // Disable pull-up/down resistors
223             MXC_MCR->gpio4_ctrl |= GPIO4_PULLDIS_MASK(cfg->mask);
224             break;
225 
226         case MXC_GPIO_PAD_WEAK_PULL_UP:
227         case MXC_GPIO_PAD_PULL_UP:
228             // Set to input mode, enable pull-up/down resistors
229             MXC_MCR->gpio4_ctrl &= ~(GPIO4_OUTEN_MASK(cfg->mask) | GPIO4_PULLDIS_MASK(cfg->mask));
230 
231             // Set to pullup mode
232             MXC_MCR->gpio4_ctrl |= GPIO4_DATAOUT_MASK(cfg->mask);
233             break;
234 
235         case MXC_GPIO_PAD_WEAK_PULL_DOWN:
236         case MXC_GPIO_PAD_PULL_DOWN:
237             // Set to input mode, enable pull-up/down resistors, set to pulldown mode
238             MXC_MCR->gpio4_ctrl &= ~(GPIO4_OUTEN_MASK(cfg->mask) | GPIO4_PULLDIS_MASK(cfg->mask) |
239                                      GPIO4_DATAOUT_MASK(cfg->mask));
240             break;
241 
242         default:
243             return E_BAD_PARAM;
244         }
245     }
246 
247     // Configure the drive strength
248     if (cfg->func == MXC_GPIO_FUNC_IN) {
249         return E_NO_ERROR;
250     } else {
251         return MXC_GPIO_SetDriveStrength(gpio, cfg->drvstr, cfg->mask);
252     }
253 }
254 
255 /* ************************************************************************** */
MXC_GPIO_InGet(mxc_gpio_regs_t * port,uint32_t mask)256 uint32_t MXC_GPIO_InGet(mxc_gpio_regs_t *port, uint32_t mask)
257 {
258     if (port == MXC_GPIO4) {
259         uint32_t gpio40 = (MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_IN) >>
260                           MXC_F_MCR_GPIO4_CTRL_P40_IN_POS;
261         uint32_t gpio41 = (MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_IN) >>
262                           (MXC_F_MCR_GPIO4_CTRL_P41_IN_POS - 1);
263         return ((gpio40 | gpio41) & mask);
264     }
265 
266     return MXC_GPIO_RevA_InGet((mxc_gpio_reva_regs_t *)port, mask);
267 }
268 
269 /* ************************************************************************** */
MXC_GPIO_OutSet(mxc_gpio_regs_t * port,uint32_t mask)270 void MXC_GPIO_OutSet(mxc_gpio_regs_t *port, uint32_t mask)
271 {
272     if (port == MXC_GPIO4) {
273         MXC_MCR->gpio4_ctrl |= GPIO4_DATAOUT_MASK(mask);
274         return;
275     }
276 
277     MXC_GPIO_RevA_OutSet((mxc_gpio_reva_regs_t *)port, mask);
278 }
279 
280 /* ************************************************************************** */
MXC_GPIO_OutClr(mxc_gpio_regs_t * port,uint32_t mask)281 void MXC_GPIO_OutClr(mxc_gpio_regs_t *port, uint32_t mask)
282 {
283     if (port == MXC_GPIO4) {
284         MXC_MCR->gpio4_ctrl &= ~GPIO4_DATAOUT_MASK(mask);
285         return;
286     }
287 
288     MXC_GPIO_RevA_OutClr((mxc_gpio_reva_regs_t *)port, mask);
289 }
290 
291 /* ************************************************************************** */
MXC_GPIO_OutGet(mxc_gpio_regs_t * port,uint32_t mask)292 uint32_t MXC_GPIO_OutGet(mxc_gpio_regs_t *port, uint32_t mask)
293 {
294     if (port == MXC_GPIO4) {
295         uint32_t gpio40 = (MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_DO) >>
296                           MXC_F_MCR_GPIO4_CTRL_P40_DO_POS;
297         uint32_t gpio41 = (MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_DO) >>
298                           (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1);
299         return ((gpio40 | gpio41) & mask);
300     }
301 
302     return MXC_GPIO_RevA_OutGet((mxc_gpio_reva_regs_t *)port, mask);
303 }
304 
305 /* ************************************************************************** */
MXC_GPIO_OutPut(mxc_gpio_regs_t * port,uint32_t mask,uint32_t val)306 void MXC_GPIO_OutPut(mxc_gpio_regs_t *port, uint32_t mask, uint32_t val)
307 {
308     if (port == MXC_GPIO4) {
309         uint32_t gpio4_cp = MXC_MCR->gpio4_ctrl;
310 
311         MXC_MCR->gpio4_ctrl = (gpio4_cp & ~GPIO4_DATAOUT_MASK(mask)) |
312                               GPIO4_DATAOUT_MASK((mask & val));
313         return;
314     }
315 
316     MXC_GPIO_RevA_OutPut((mxc_gpio_reva_regs_t *)port, mask, val);
317 }
318 
319 /* ************************************************************************** */
MXC_GPIO_OutToggle(mxc_gpio_regs_t * port,uint32_t mask)320 void MXC_GPIO_OutToggle(mxc_gpio_regs_t *port, uint32_t mask)
321 {
322     if (port == MXC_GPIO4) {
323         MXC_MCR->gpio4_ctrl ^= GPIO4_DATAOUT_MASK(mask);
324         return;
325     }
326 
327     MXC_GPIO_RevA_OutToggle((mxc_gpio_reva_regs_t *)port, mask);
328 }
329 
330 /* ************************************************************************** */
MXC_GPIO_IntConfig(const mxc_gpio_cfg_t * cfg,mxc_gpio_int_pol_t pol)331 int MXC_GPIO_IntConfig(const mxc_gpio_cfg_t *cfg, mxc_gpio_int_pol_t pol)
332 {
333     if (cfg->port == MXC_GPIO4) {
334         if (pol != MXC_GPIO_INT_BOTH) {
335             return E_NOT_SUPPORTED;
336         }
337 
338         return E_NO_ERROR;
339     }
340 
341     return MXC_GPIO_RevA_IntConfig(cfg, pol);
342 }
343 
344 /* ************************************************************************** */
MXC_GPIO_EnableInt(mxc_gpio_regs_t * port,uint32_t mask)345 void MXC_GPIO_EnableInt(mxc_gpio_regs_t *port, uint32_t mask)
346 {
347     if (port == MXC_GPIO4) {
348         MXC_PWRSEQ->lpwken4 |= (mask & GPIO4_PIN_MASK);
349         return;
350     }
351 
352     MXC_GPIO_RevA_EnableInt((mxc_gpio_reva_regs_t *)port, mask);
353 }
354 
355 /* ************************************************************************** */
MXC_GPIO_DisableInt(mxc_gpio_regs_t * port,uint32_t mask)356 void MXC_GPIO_DisableInt(mxc_gpio_regs_t *port, uint32_t mask)
357 {
358     if (port == MXC_GPIO4) {
359         MXC_PWRSEQ->lpwken4 &= ~(mask & GPIO4_PIN_MASK);
360         return;
361     }
362 
363     MXC_GPIO_RevA_DisableInt((mxc_gpio_reva_regs_t *)port, mask);
364 }
365 
366 /* ************************************************************************** */
MXC_GPIO_RegisterCallback(const mxc_gpio_cfg_t * cfg,mxc_gpio_callback_fn func,void * cbdata)367 void MXC_GPIO_RegisterCallback(const mxc_gpio_cfg_t *cfg, mxc_gpio_callback_fn func, void *cbdata)
368 {
369     MXC_GPIO_Common_RegisterCallback(cfg, func, cbdata);
370 }
371 
372 /* ************************************************************************** */
MXC_GPIO_Handler(unsigned int port)373 void MXC_GPIO_Handler(unsigned int port)
374 {
375     MXC_GPIO_Common_Handler(port);
376 }
377 
378 /* ************************************************************************** */
MXC_GPIO_ClearFlags(mxc_gpio_regs_t * port,uint32_t flags)379 void MXC_GPIO_ClearFlags(mxc_gpio_regs_t *port, uint32_t flags)
380 {
381     if (port == MXC_GPIO4) {
382         MXC_PWRSEQ->lpwkst4 = flags & GPIO4_PIN_MASK;
383         return;
384     }
385 
386     MXC_GPIO_RevA_ClearFlags((mxc_gpio_reva_regs_t *)port, flags);
387 }
388 
389 /* ************************************************************************** */
MXC_GPIO_GetFlags(mxc_gpio_regs_t * port)390 uint32_t MXC_GPIO_GetFlags(mxc_gpio_regs_t *port)
391 {
392     if (port == MXC_GPIO4) {
393         return MXC_PWRSEQ->lpwkst4 & GPIO4_PIN_MASK;
394     }
395 
396     return MXC_GPIO_RevA_GetFlags((mxc_gpio_reva_regs_t *)port);
397 }
398 
399 /* ************************************************************************** */
MXC_GPIO_SetVSSEL(mxc_gpio_regs_t * port,mxc_gpio_vssel_t vssel,uint32_t mask)400 int MXC_GPIO_SetVSSEL(mxc_gpio_regs_t *port, mxc_gpio_vssel_t vssel, uint32_t mask)
401 {
402     if (port == MXC_GPIO4) {
403         return E_NOT_SUPPORTED;
404     }
405 
406     return MXC_GPIO_RevA_SetVSSEL((mxc_gpio_reva_regs_t *)port, vssel, mask);
407 }
408 
409 /* ************************************************************************** */
MXC_GPIO_SetWakeEn(mxc_gpio_regs_t * port,uint32_t mask)410 void MXC_GPIO_SetWakeEn(mxc_gpio_regs_t *port, uint32_t mask)
411 {
412     if (port == MXC_GPIO4) {
413         return;
414     }
415 
416     MXC_GPIO_RevA_SetWakeEn((mxc_gpio_reva_regs_t *)port, mask);
417 }
418 
419 /* ************************************************************************** */
MXC_GPIO_ClearWakeEn(mxc_gpio_regs_t * port,uint32_t mask)420 void MXC_GPIO_ClearWakeEn(mxc_gpio_regs_t *port, uint32_t mask)
421 {
422     if (port == MXC_GPIO4) {
423         return;
424     }
425 
426     MXC_GPIO_RevA_ClearWakeEn((mxc_gpio_reva_regs_t *)port, mask);
427 }
428 
429 /* ************************************************************************** */
MXC_GPIO_GetWakeEn(mxc_gpio_regs_t * port)430 uint32_t MXC_GPIO_GetWakeEn(mxc_gpio_regs_t *port)
431 {
432     // GPIO Port 4 not a wakeup source. Return 0.
433     //  Can't return error code (negative values) due to return type.
434     if (port == MXC_GPIO4) {
435         return 0;
436     }
437 
438     return MXC_GPIO_RevA_GetWakeEn((mxc_gpio_reva_regs_t *)port);
439 }
440 
441 /* ************************************************************************** */
MXC_GPIO_SetDriveStrength(mxc_gpio_regs_t * port,mxc_gpio_drvstr_t drvstr,uint32_t mask)442 int MXC_GPIO_SetDriveStrength(mxc_gpio_regs_t *port, mxc_gpio_drvstr_t drvstr, uint32_t mask)
443 {
444     return MXC_GPIO_RevA_SetDriveStrength((mxc_gpio_reva_regs_t *)port, drvstr, mask);
445 }
446