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