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