1 /*
2 * Copyright (c) 2015-2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdint.h>
34 #include <stdbool.h>
35 #if defined(__IAR_SYSTEMS_ICC__)
36 #include <intrinsics.h>
37 #endif
38
39 /*
40 * By default disable both asserts and log for this module.
41 * This must be done before DebugP.h is included.
42 */
43 #ifndef DebugP_ASSERT_ENABLED
44 #define DebugP_ASSERT_ENABLED 0
45 #endif
46 #ifndef DebugP_LOG_ENABLED
47 #define DebugP_LOG_ENABLED 0
48 #endif
49
50 #include <ti/drivers/GPIO.h>
51 #include <ti/drivers/gpio/GPIOCC32XX.h>
52 #include <ti/drivers/dpl/DebugP.h>
53 #include <ti/drivers/dpl/HwiP.h>
54 #include <ti/drivers/dpl/SemaphoreP.h>
55 #include <ti/drivers/Power.h>
56 #include <ti/drivers/power/PowerCC32XX.h>
57
58 /* driverlib header files */
59 #include <ti/devices/cc32xx/inc/hw_types.h>
60 #include <ti/devices/cc32xx/inc/hw_memmap.h>
61 #include <ti/devices/cc32xx/inc/hw_gpio.h>
62 #include <ti/devices/cc32xx/inc/hw_ints.h>
63 #include <ti/devices/cc32xx/driverlib/rom.h>
64 #include <ti/devices/cc32xx/driverlib/rom_map.h>
65 #include <ti/devices/cc32xx/driverlib/gpio.h>
66 #include <ti/devices/cc32xx/driverlib/pin.h>
67 #include <ti/devices/cc32xx/driverlib/prcm.h>
68
69 /*
70 * Map GPIO_INT types to corresponding CC32XX interrupt options
71 */
72 static const uint8_t interruptType[] = {
73 0, /* Undefined interrupt type */
74 GPIO_FALLING_EDGE, /* 1 = Interrupt on falling edge */
75 GPIO_RISING_EDGE, /* 2 = Interrupt on rising edge */
76 GPIO_BOTH_EDGES, /* 3 = Interrupt on both edges */
77 GPIO_LOW_LEVEL, /* 4 = Interrupt on low level */
78 GPIO_HIGH_LEVEL /* 5 = Interrupt on high level */
79 };
80
81 /*
82 * Table of port interrupt vector numbers
83 * Used by setCallback() to create Hwis.
84 * Up to 4 port interrupts must be supported
85 */
86 static const uint8_t portInterruptIds[] = {
87 INT_GPIOA0, INT_GPIOA1,
88 INT_GPIOA2, INT_GPIOA3
89 };
90
91 /* Table of GPIO input types */
92 const uint16_t inPinTypes [] = {
93 PIN_TYPE_STD, /* GPIO_CFG_IN_NOPULL */
94 PIN_TYPE_STD_PU, /* GPIO_CFG_IN_PU */
95 PIN_TYPE_STD_PD /* GPIO_CFG_IN_PD */
96 };
97
98 /* Table of GPIO output types */
99 const uint16_t outPinTypes [] = {
100 PIN_TYPE_STD, /* GPIO_CFG_OUT_STD */
101 PIN_TYPE_OD, /* GPIO_CFG_OUT_OD_NOPULL */
102 PIN_TYPE_OD_PU, /* GPIO_CFG_OUT_OD_PU */
103 PIN_TYPE_OD_PD /* GPIO_CFG_OUT_OD_PD */
104 };
105
106 /* Table of GPIO drive strengths */
107 const uint16_t outPinStrengths [] = {
108 PIN_STRENGTH_2MA, /* GPIO_CFG_OUT_STR_LOW */
109 PIN_STRENGTH_4MA, /* GPIO_CFG_OUT_STR_MED */
110 PIN_STRENGTH_6MA /* GPIO_CFG_OUT_STR_HIGH */
111 };
112
113 /*
114 * Table of pin numbers (physical device pins) for use with PinTypeGPIO()
115 * driverlib call.
116 *
117 * Indexed by GPIO number (0-31).
118 */
119 #define PIN_XX 0xFF
120 static const uint8_t pinTable[] = {
121 /* 00 01 02 03 04 05 06 07 */
122 PIN_50, PIN_55, PIN_57, PIN_58, PIN_59, PIN_60, PIN_61, PIN_62,
123 /* 08 09 10 11 12 13 14 15 */
124 PIN_63, PIN_64, PIN_01, PIN_02, PIN_03, PIN_04, PIN_05, PIN_06,
125 /* 16 17 18 19 20 21 22 23 */
126 PIN_07, PIN_08, PIN_XX, PIN_XX, PIN_XX, PIN_XX, PIN_15, PIN_16,
127 /* 24 25 26 27 28 29 30 31 */
128 PIN_17, PIN_21, PIN_29, PIN_30, PIN_18, PIN_20, PIN_53, PIN_45,
129 /* 32 */
130 PIN_52
131 };
132
133 /*
134 * Table of port bases address. For use with most driverlib calls.
135 * Indexed by GPIO port number (0-3).
136 */
137 static const uint32_t gpioBaseAddresses[] = {
138 GPIOA0_BASE, GPIOA1_BASE,
139 GPIOA2_BASE, GPIOA3_BASE,
140 GPIOA4_BASE
141 };
142
143 static const uint32_t powerResources[] = {
144 PowerCC32XX_PERIPH_GPIOA0,
145 PowerCC32XX_PERIPH_GPIOA1,
146 PowerCC32XX_PERIPH_GPIOA2,
147 PowerCC32XX_PERIPH_GPIOA3,
148 PowerCC32XX_PERIPH_GPIOA4
149 };
150
151 #define NUM_PORTS 4
152 #define NUM_PINS_PER_PORT 8
153 #define PORT_MASK 0x3
154
155 /* Defines used by PinConfigSet() to set GPIO pin in tristate mode */
156 #define GPIOCC32XX_TRISTATE PIN_TYPE_ANALOG
157 #define GPIOCC32XX_DUMMY_STRENGTH 0x0
158
159 /* Returns the GPIO port base address */
160 #define getPortBase(port) (gpioBaseAddresses[(port) & PORT_MASK])
161
162 /* Returns the GPIO port number */
163 #define getPort(port) (port & PORT_MASK)
164
165 /* Returns the GPIO power resource ID */
166 #define getPowerResource(port) (powerResources[port & PORT_MASK])
167
168 /* Returns GPIO number from the pinConfig */
169 #define getGpioNumber(pinConfig) \
170 (((pinConfig->port & PORT_MASK) * 8) + getPinNumber(pinConfig->pin))
171
172 /* Uninitialized callbackInfo pinIndex */
173 #define CALLBACK_INDEX_NOT_CONFIGURED 0xFF
174
175 /*
176 * Device specific interpretation of the GPIO_PinConfig content
177 */
178 typedef struct {
179 uint8_t pin;
180 uint8_t port;
181 uint16_t config;
182 } PinConfig;
183
184 /*
185 * User defined pin indexes assigned to a port's 8 pins.
186 * Used by port interrupt function to locate callback assigned
187 * to a pin.
188 */
189 typedef struct {
190 /*
191 * the port's 8 corresponding
192 * user defined pinId indices
193 */
194 uint8_t pinIndex[NUM_PINS_PER_PORT];
195 } PortCallbackInfo;
196
197 /*
198 * Table of portCallbackInfos.
199 * One for each port.
200 */
201 static PortCallbackInfo gpioCallbackInfo[NUM_PORTS];
202
203 /*
204 * bit mask used to determine if a Hwi has been created/constructed
205 * for a port already.
206 * up to NUM_PORTS port interrupts must be supported
207 */
208 static uint8_t portHwiCreatedBitMask = 0;
209
210 /*
211 * Bit mask used to keep track of which of the GPIO objects in the config
212 * structure have interrupts enabled. This will be used to restore the
213 * interrupts after coming out of LPDS.
214 */
215 static uint32_t configIntsEnabledMask = 0;
216
217 /*
218 * Internal boolean to confirm that GPIO_init() has been called.
219 */
220 static bool initCalled = false;
221
222 /* Notification for going into and waking up from LPDS */
223 static Power_NotifyObj powerNotifyObj;
224
225 __attribute__((weak))extern const GPIOCC32XX_Config GPIOCC32XX_config;
226
227 static int powerNotifyFxn(unsigned int eventType, uintptr_t eventArg,
228 uintptr_t clientArg);
229
230 /*
231 * ======== getPinNumber ========
232 *
233 * Internal function to efficiently find the index of the right most set bit.
234 */
getPinNumber(uint32_t x)235 static inline uint32_t getPinNumber(uint32_t x) {
236 #if defined(__TI_COMPILER_VERSION__)
237 return (uint32_t)(__clz(__rbit(x)) & 0x7);
238 #elif defined(__GNUC__)
239 return (uint32_t)(__builtin_ctz(x) & 0x7);
240 #elif defined(__IAR_SYSTEMS_ICC__)
241 return (uint32_t)(__CLZ(__RBIT(x)) & 0x7);
242 #else
243 #error "Unsupported compiler used"
244 #endif
245 }
246
247 /*
248 * ======== getInterruptTypeIndex ========
249 */
getInterruptTypeIndex(uint32_t pinConfig)250 static inline uint32_t getInterruptTypeIndex(uint32_t pinConfig)
251 {
252 uint32_t index;
253
254 index = (pinConfig & GPIO_CFG_INT_MASK) >> GPIO_CFG_INT_LSB;
255
256 /*
257 * If index is out-of-range, default to 0. This should never
258 * happen, but it's needed to keep Klocwork checker happy.
259 */
260 if (index >= sizeof(interruptType) / sizeof(interruptType[0])) {
261 index = 0;
262 }
263
264 return (index);
265 };
266
267 /*
268 * ======== getInPinTypesIndex ========
269 */
getInPinTypesIndex(uint32_t pinConfig)270 static inline uint32_t getInPinTypesIndex(uint32_t pinConfig)
271 {
272 uint32_t index;
273
274 index = (pinConfig & GPIO_CFG_IN_TYPE_MASK) >> GPIO_CFG_IN_TYPE_LSB;
275
276 /*
277 * If index is out-of-range, default to 0. This should never
278 * happen, but it's needed to keep Klocwork checker happy.
279 */
280 if (index >= sizeof(inPinTypes) / sizeof(inPinTypes[0])) {
281 index = 0;
282 }
283
284 return (index);
285 }
286
287 /*
288 * ======== getOutPinTypesIndex ========
289 */
getOutPinTypesIndex(uint32_t pinConfig)290 static inline uint32_t getOutPinTypesIndex(uint32_t pinConfig)
291 {
292 uint32_t index;
293
294 index = (pinConfig & GPIO_CFG_OUT_TYPE_MASK) >> GPIO_CFG_OUT_TYPE_LSB;
295
296 /*
297 * If index is out-of-range, default to 0. This should never
298 * happen, but it's needed to keep Klocwork checker happy.
299 */
300 if (index >= sizeof(outPinTypes) / sizeof(outPinTypes[0])) {
301 index = 0;
302 }
303
304 return (index);
305 }
306
307 /*
308 * ======== getOutPinStrengthsIndex ========
309 */
getOutPinStrengthsIndex(uint32_t pinConfig)310 static inline uint32_t getOutPinStrengthsIndex(uint32_t pinConfig)
311 {
312 uint32_t index;
313
314 index = (pinConfig & GPIO_CFG_OUT_STRENGTH_MASK) >>
315 GPIO_CFG_OUT_STRENGTH_LSB;
316
317 /*
318 * If index is out-of-range, default to 0. This should never
319 * happen, but it's needed to keep Klocwork checker happy.
320 */
321 if (index >= sizeof(outPinStrengths) / sizeof(outPinStrengths[0])) {
322 index = 0;
323 }
324
325 return (index);
326 }
327
328 /*
329 * ======== GPIO_clearInt ========
330 */
GPIO_clearInt(uint_least8_t index)331 void GPIO_clearInt(uint_least8_t index)
332 {
333 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
334
335 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
336
337 /* Clear GPIO interrupt flag */
338 MAP_GPIOIntClear(getPortBase(config->port), config->pin);
339
340 DebugP_log2("GPIO: port 0x%x, pin 0x%x interrupt flag cleared",
341 getPort(config->port), config->pin);
342 }
343
344 /*
345 * ======== GPIO_disableInt ========
346 */
GPIO_disableInt(uint_least8_t index)347 void GPIO_disableInt(uint_least8_t index)
348 {
349 uintptr_t key;
350 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
351
352 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
353
354 /* Make atomic update */
355 key = HwiP_disable();
356
357 /* Disable GPIO interrupt */
358 MAP_GPIOIntDisable(getPortBase(config->port), config->pin);
359
360 configIntsEnabledMask &= ~(1 << index);
361
362 HwiP_restore(key);
363
364 DebugP_log2("GPIO: port 0x%x, pin 0x%x interrupts disabled",
365 getPort(config->port), config->pin);
366 }
367
368 /*
369 * ======== GPIO_enableInt ========
370 */
GPIO_enableInt(uint_least8_t index)371 void GPIO_enableInt(uint_least8_t index)
372 {
373 uintptr_t key;
374 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
375
376 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
377 DebugP_assert(*((uint16_t *) config) != GPIOCC32XX_GPIO_26 &&
378 *((uint16_t *) config) != GPIOCC32XX_GPIO_27);
379
380 /* Make atomic update */
381 key = HwiP_disable();
382
383 /* Enable GPIO interrupt */
384 MAP_GPIOIntEnable(getPortBase(config->port), config->pin);
385
386 configIntsEnabledMask |= (1 << index);
387
388 HwiP_restore(key);
389
390 DebugP_log2("GPIO: port 0x%x, pin 0x%x interrupts enabled",
391 getPort(config->port), config->pin);
392 }
393
394 /*
395 * ======== GPIO_getConfig ========
396 */
GPIO_getConfig(uint_least8_t index,GPIO_PinConfig * pinConfig)397 void GPIO_getConfig(uint_least8_t index, GPIO_PinConfig *pinConfig)
398 {
399 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
400
401 *pinConfig = GPIOCC32XX_config.pinConfigs[index];
402 }
403
404 /*
405 * ======== GPIO_hwiIntFxn ========
406 * Hwi function that processes GPIO interrupts.
407 */
GPIO_hwiIntFxn(uintptr_t portIndex)408 void GPIO_hwiIntFxn(uintptr_t portIndex)
409 {
410 unsigned int bitNum;
411 unsigned int pinIndex;
412 uint32_t pins;
413 uint32_t portBase;
414 PortCallbackInfo *portCallbackInfo;
415
416 portCallbackInfo = &gpioCallbackInfo[portIndex];
417 portBase = getPortBase(portIndex);
418
419 /* Find out which pins have their interrupt flags set */
420 pins = MAP_GPIOIntStatus(portBase, 0xFF) & 0xFF;
421
422 /* clear all the set bits at once */
423 MAP_GPIOIntClear(portBase, pins);
424
425 /* Match the interrupt to its corresponding callback function */
426 while (pins) {
427 /* Gets the lowest order set bit number */
428 bitNum = getPinNumber(pins);
429 pinIndex = portCallbackInfo->pinIndex[bitNum & 0x7];
430 /* only call plugged callbacks */
431 if (pinIndex != CALLBACK_INDEX_NOT_CONFIGURED) {
432 GPIOCC32XX_config.callbacks[pinIndex](pinIndex);
433 }
434 pins &= ~(1 << bitNum);
435 }
436 }
437
438 /*
439 * ======== GPIO_init ========
440 */
GPIO_init()441 void GPIO_init()
442 {
443 unsigned int i, j, hwiKey;
444 SemaphoreP_Handle sem;
445 static SemaphoreP_Handle initSem;
446
447 /* speculatively create a binary semaphore */
448 sem = SemaphoreP_createBinary(1);
449
450 /* There is no way to inform user of this fatal error. */
451 if (sem == NULL) return;
452
453 hwiKey = HwiP_disable();
454
455 if (initSem == NULL) {
456 initSem = sem;
457 HwiP_restore(hwiKey);
458 }
459 else {
460 /* init already called */
461 HwiP_restore(hwiKey);
462 /* delete unused Semaphore */
463 if (sem) SemaphoreP_delete(sem);
464 }
465
466 /* now use the semaphore to protect init code */
467 SemaphoreP_pend(initSem, SemaphoreP_WAIT_FOREVER);
468
469 /* Only perform init once */
470 if (initCalled) {
471 SemaphoreP_post(initSem);
472 return;
473 }
474
475 for (i = 0; i < NUM_PORTS; i++) {
476 for (j = 0; j < NUM_PINS_PER_PORT; j++) {
477 gpioCallbackInfo[i].pinIndex[j] = CALLBACK_INDEX_NOT_CONFIGURED;
478 }
479 }
480
481 /*
482 * Configure pins and create Hwis per static array content
483 */
484 for (i = 0; i < GPIOCC32XX_config.numberOfPinConfigs; i++) {
485 if (!(GPIOCC32XX_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG)) {
486
487 GPIO_setConfig(i, GPIOCC32XX_config.pinConfigs[i]);
488 }
489 if (i < GPIOCC32XX_config.numberOfCallbacks) {
490 if (GPIOCC32XX_config.callbacks[i] != NULL) {
491 /* create Hwi as necessary */
492 GPIO_setCallback(i, GPIOCC32XX_config.callbacks[i]);
493 }
494 }
495 }
496
497 Power_registerNotify(&powerNotifyObj,
498 PowerCC32XX_ENTERING_LPDS | PowerCC32XX_AWAKE_LPDS,
499 powerNotifyFxn, (uintptr_t) NULL);
500
501 initCalled = true;
502
503 SemaphoreP_post(initSem);
504 }
505
506 /*
507 * ======== GPIO_read ========
508 */
GPIO_read(uint_least8_t index)509 uint_fast8_t GPIO_read(uint_least8_t index)
510 {
511 unsigned int value;
512
513 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
514
515 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
516 DebugP_assert(*((uint16_t *) config) != GPIOCC32XX_GPIO_26 &&
517 *((uint16_t *) config) != GPIOCC32XX_GPIO_27);
518
519 value = MAP_GPIOPinRead(getPortBase(config->port), config->pin);
520
521 DebugP_log3("GPIO: port 0x%x, pin 0x%x read 0x%x",
522 getPort(config->port), config->pin, value);
523
524 value = (value & config->pin) ? 1 : 0;
525
526 return (value);
527 }
528
529 /*
530 * ======== GPIO_setCallback ========
531 */
GPIO_setCallback(uint_least8_t index,GPIO_CallbackFxn callback)532 void GPIO_setCallback(uint_least8_t index, GPIO_CallbackFxn callback)
533 {
534 uint32_t pinNum;
535 uint32_t portIndex;
536 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
537
538 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfCallbacks);
539 DebugP_assert(*((uint16_t *) config) != GPIOCC32XX_GPIO_26 &&
540 *((uint16_t *) config) != GPIOCC32XX_GPIO_27);
541
542 /*
543 * Ignore bogus callback indexes.
544 * Required to prevent out-of-range callback accesses if
545 * there are configured pins without callbacks
546 */
547 if (index >= GPIOCC32XX_config.numberOfCallbacks) {
548 return;
549 }
550
551 /*
552 * plug the pin index into the corresponding
553 * port's callbackInfo pinIndex entry
554 */
555 pinNum = getPinNumber(config->pin);
556 portIndex = config->port & PORT_MASK;
557
558 if (callback == NULL) {
559 gpioCallbackInfo[portIndex].pinIndex[pinNum] =
560 CALLBACK_INDEX_NOT_CONFIGURED;
561 }
562 else {
563 gpioCallbackInfo[portIndex].pinIndex[pinNum] = index;
564 }
565
566 /*
567 * Only update callBackFunctions entry if different.
568 * This allows the callBackFunctions array to be in flash for static systems.
569 */
570 if (GPIOCC32XX_config.callbacks[index] != callback) {
571 GPIOCC32XX_config.callbacks[index] = callback;
572 }
573 }
574
575 /*
576 * ======== GPIO_setConfig ========
577 */
GPIO_setConfig(uint_least8_t index,GPIO_PinConfig pinConfig)578 int_fast16_t GPIO_setConfig(uint_least8_t index, GPIO_PinConfig pinConfig)
579 {
580 uintptr_t key;
581 uint32_t pinMask;
582 uint32_t pin;
583 uint32_t portBase;
584 uint32_t portIndex;
585 uint32_t portBitMask;
586 uint16_t direction;
587 uint16_t strength;
588 uint16_t pinType;
589 HwiP_Handle hwiHandle;
590 HwiP_Params hwiParams;
591 GPIO_PinConfig gpioPinConfig;
592 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
593
594 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
595 DebugP_assert(*((uint16_t *) config) != GPIOCC32XX_GPIO_26 &&
596 *((uint16_t *) config) != GPIOCC32XX_GPIO_27 ||
597 (pinConfig & GPIO_CFG_INPUT) == 0);
598
599 if (pinConfig & GPIO_DO_NOT_CONFIG) {
600 return (GPIO_STATUS_SUCCESS);
601 }
602
603 portBase = getPortBase(config->port);
604 pinMask = config->pin;
605 pin = pinTable[getGpioNumber(config)];
606
607 /* Make atomic update */
608 key = HwiP_disable();
609
610 /* Configure GPIO pin as tristate */
611 MAP_PinConfigSet(pin, GPIOCC32XX_DUMMY_STRENGTH, GPIOCC32XX_TRISTATE);
612
613 /* enable clocks for the GPIO port */
614 Power_setDependency(getPowerResource(config->port));
615
616 HwiP_restore(key);
617
618 if ((pinConfig & GPIO_CFG_IN_INT_ONLY) == 0) {
619 if (pinConfig & GPIO_CFG_INPUT) {
620 /* configure input */
621 direction = GPIO_DIR_MODE_IN;
622 strength = PIN_STRENGTH_2MA;
623 pinType = inPinTypes[getInPinTypesIndex(pinConfig)];
624 }
625 else {
626 /* configure output */
627 direction = GPIO_DIR_MODE_OUT;
628 strength = outPinStrengths[getOutPinStrengthsIndex(pinConfig)];
629 pinType = outPinTypes[getOutPinTypesIndex(pinConfig)];
630 }
631
632 key = HwiP_disable();
633
634 /* Configure the GPIO pin */
635 MAP_GPIODirModeSet(portBase, pinMask, direction);
636 /* Set output value */
637 if (direction == GPIO_DIR_MODE_OUT) {
638 MAP_GPIOPinWrite(portBase, pinMask,
639 ((pinConfig & GPIO_CFG_OUT_HIGH) ? 0xFF : 0));
640 }
641
642 /* Configure pin output settings */
643 MAP_PinConfigSet(pin, strength, pinType);
644 /* Set the pin's pinType to GPIO and remove initial tristate setting */
645 MAP_PinModeSet(pin, PIN_MODE_0);
646
647 /*
648 * Update pinConfig with the latest GPIO configuration and
649 * clear the GPIO_DO_NOT_CONFIG bit if it was set.
650 */
651 gpioPinConfig = GPIOCC32XX_config.pinConfigs[index];
652 gpioPinConfig &= ~(GPIO_CFG_IO_MASK | GPIO_DO_NOT_CONFIG);
653 gpioPinConfig |= (pinConfig & GPIO_CFG_IO_MASK);
654 GPIOCC32XX_config.pinConfigs[index] = gpioPinConfig;
655
656 HwiP_restore(key);
657 }
658
659 /* Set type of interrupt and then clear it */
660 if (pinConfig & GPIO_CFG_INT_MASK) {
661 portIndex = config->port & PORT_MASK;
662 portBitMask = 1 << portIndex;
663
664 /* if Hwi has not already been created, do so */
665 if ((portHwiCreatedBitMask & portBitMask) == 0) {
666 HwiP_Params_init(&hwiParams);
667 hwiParams.arg = (uintptr_t) portIndex;
668 hwiParams.priority = GPIOCC32XX_config.intPriority;
669 hwiHandle = HwiP_create(portInterruptIds[portIndex], GPIO_hwiIntFxn,
670 &hwiParams);
671 if (hwiHandle == NULL) {
672 /* Error creating Hwi */
673 DebugP_log1("GPIO: Error constructing Hwi for GPIO Port %d",
674 getPort(config->port));
675 return (GPIO_STATUS_ERROR);
676 }
677 }
678
679 key = HwiP_disable();
680
681 /* Mark the Hwi as created */
682 portHwiCreatedBitMask |= portBitMask;
683
684 MAP_GPIOIntTypeSet(portBase, pinMask,
685 interruptType[getInterruptTypeIndex(pinConfig)]);
686 MAP_GPIOIntClear(portBase, pinMask);
687
688 /*
689 * Update pinConfig with the latest interrupt configuration and
690 * clear the GPIO_DO_NOT_CONFIG bit if it was set.
691 */
692 gpioPinConfig = GPIOCC32XX_config.pinConfigs[index];
693 gpioPinConfig &= ~(GPIO_CFG_INT_MASK | GPIO_DO_NOT_CONFIG);
694 gpioPinConfig |= (pinConfig & GPIO_CFG_INT_MASK);
695 GPIOCC32XX_config.pinConfigs[index] = gpioPinConfig;
696
697 HwiP_restore(key);
698 }
699
700 return (GPIO_STATUS_SUCCESS);
701 }
702
703 /*
704 * ======== GPIO_toggle ========
705 */
GPIO_toggle(uint_least8_t index)706 void GPIO_toggle(uint_least8_t index)
707 {
708 uintptr_t key;
709 uint32_t value;
710 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
711
712 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
713 DebugP_assert((GPIOCC32XX_config.pinConfigs[index] & GPIO_CFG_INPUT) ==
714 GPIO_CFG_OUTPUT);
715
716 /* Make atomic update */
717 key = HwiP_disable();
718
719 value = MAP_GPIOPinRead(getPortBase(config->port), config->pin);
720 value ^= (uint32_t)config->pin;
721 MAP_GPIOPinWrite(getPortBase(config->port), config->pin, value);
722
723 /* Update config table entry with value written */
724 GPIOCC32XX_config.pinConfigs[index] ^= GPIO_CFG_OUT_HIGH;
725
726 HwiP_restore(key);
727
728 DebugP_log2("GPIO: port 0x%x, pin 0x%x toggled",
729 getPort(config->port), config->pin);
730 }
731
732 /*
733 * ======== GPIO_write ========
734 */
GPIO_write(uint_least8_t index,unsigned int value)735 void GPIO_write(uint_least8_t index, unsigned int value)
736 {
737 uintptr_t key;
738 uint32_t output;
739 PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];
740
741 DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);
742 DebugP_assert((GPIOCC32XX_config.pinConfigs[index] & GPIO_CFG_INPUT) ==
743 GPIO_CFG_OUTPUT);
744
745 key = HwiP_disable();
746
747 /* Clear output from pinConfig */
748 GPIOCC32XX_config.pinConfigs[index] &= ~GPIO_CFG_OUT_HIGH;
749
750 if (value) {
751 output = config->pin;
752
753 /* Set the pinConfig output bit to high */
754 GPIOCC32XX_config.pinConfigs[index] |= GPIO_CFG_OUT_HIGH;
755 }
756 else {
757 output = value;
758 }
759
760 MAP_GPIOPinWrite(getPortBase(config->port), config->pin, output);
761
762 HwiP_restore(key);
763
764 DebugP_log3("GPIO: port 0x%x, pin 0x%x wrote 0x%x",
765 getPort(config->port), config->pin, value);
766 }
767
768 /*
769 * ======== powerNotifyFxn ========
770 */
powerNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)771 static int powerNotifyFxn(unsigned int eventType, uintptr_t eventArg,
772 uintptr_t clientArg)
773 {
774 unsigned int i;
775 GPIO_PinConfig config;
776 uint32_t output;
777 uint32_t pin;
778 PinConfig *pinConfig;
779 PowerCC32XX_ParkState state;
780
781 if (eventType == PowerCC32XX_AWAKE_LPDS) {
782
783 for (i = 0; i < GPIOCC32XX_config.numberOfPinConfigs; i++) {
784 if (!(GPIOCC32XX_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG)) {
785 config = GPIOCC32XX_config.pinConfigs[i];
786
787 GPIO_setConfig(i, config);
788
789 if (configIntsEnabledMask & (1 << i)) {
790 GPIO_enableInt(i);
791 }
792 }
793 }
794 }
795 else {
796 /* Entering LPDS */
797 /*
798 * For pins configured as GPIO output, if the GPIOCC32XX_USE_STATIC
799 * configuration flag is *not* set, get the current pin state, and
800 * then call to the Power manager to define the state to be held
801 * during LPDS.
802 * If GPIOCC32XX_USE_STATIC *is* defined, do nothing, and the pin
803 * will be parked in the state statically defined in
804 * PowerCC32XX_config.pinParkDefs[] in the board file.
805 */
806 for (i = 0; i < GPIOCC32XX_config.numberOfPinConfigs; i++) {
807 if (GPIOCC32XX_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG) {
808 continue;
809 }
810
811 config = GPIOCC32XX_config.pinConfigs[i];
812
813 /* if OUTPUT, and GPIOCC32XX_USE_STATIC flag is not set */
814 if ((!(config & GPIO_CFG_INPUT)) &&
815 (!(config & GPIOCC32XX_USE_STATIC))) {
816
817 pinConfig = (PinConfig *) &GPIOCC32XX_config.pinConfigs[i];
818
819 /* determine state to be held */
820 pin = pinTable[getGpioNumber(pinConfig)];
821 output = config & GPIO_CFG_OUT_HIGH;
822 state = (PowerCC32XX_ParkState) ((output) ? 1 : 0);
823
824 /* set the new park state */
825 PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, state);
826 }
827 }
828 }
829
830 return (Power_NOTIFYDONE);
831 }
832