1 /***************************************************************************//**
2 * \file cyhal_gpio.c
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Infineon GPIO. This is
6 * a wrapper around the lower level PDL API.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 *     http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27 
28 #include "cyhal_gpio_impl.h"
29 #include "cyhal_interconnect.h"
30 #include "cyhal_system.h"
31 #include "cyhal_hwmgr.h"
32 #include "cyhal_irq_impl.h"
33 
34 #if (CYHAL_DRIVER_AVAILABLE_GPIO)
35 
36 #if defined(__cplusplus)
37 extern "C" {
38 #endif /* __cplusplus */
39 
40 
41 /*******************************************************************************
42 *       Internal
43 *******************************************************************************/
44 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
45 #define _CYHAL_GPIO_DIRECTION_OUTPUT_MASK        (0x07UL)   /**< Mask to disable the input buffer */
46 #elif defined(COMPONENT_CAT2)
47 #define _CYHAL_GPIO_DIRECTION_OUTPUT_MASK        (0x08UL)   /**< Mask to disable the input buffer */
48 #endif
49 
50 /* Callback array for GPIO interrupts */
51 static bool _cyhal_gpio_arrays_initialized = false;
52 CY_NOINIT static cyhal_gpio_callback_data_t* _cyhal_gpio_callbacks[IOSS_GPIO_GPIO_PORT_NR];
53 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
54 #define _CYHAL_GPIO_SOURCE_SIGNAL_COUNT (sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t))
55 CY_NOINIT static cyhal_source_t _cyhal_gpio_source_signals[_CYHAL_GPIO_SOURCE_SIGNAL_COUNT];
56 #endif
57 
58 #if defined(CY_DEVICE_PMG1S3)
59 /* PMG1-S3: Work-around as device does not support any GPIO port specific interrupts. */
60 #define ioss_interrupts_gpio_0_IRQn     (ioss_interrupt_gpio_IRQn)
61 #endif
62 
63 /* Macro that masks unneeded fields in port interrupt mask register, and generates true if any interrupt is set and false otherwise */
64 #if defined(COMPONENT_CAT2)
65 #define _CYHAL_GPIO_IS_PORT_INTERRUPT_SET(pin)       ((bool)(GPIO_PRT_INTR_CFG(CYHAL_GET_PORTADDR(pin)) & 0xFFFFUL))
66 #else
67 #define _CYHAL_GPIO_IS_PORT_INTERRUPT_SET(pin)       ((bool)(GPIO_PRT_INTR_MASK(CYHAL_GET_PORTADDR(pin)) & 0x7FUL))
68 #endif
69 
70 
71 /*******************************************************************************
72 *       Internal Interrupt Service Routine
73 *******************************************************************************/
74 
_cyhal_gpio_irq_handler(void)75 static void _cyhal_gpio_irq_handler(void)
76 {
77     _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
78 #if defined(COMPONENT_CAT1D)
79     uint32_t port;
80     if(irqn >= ioss_interrupts_gpio_0_IRQn && irqn < ioss_interrupts_gpio_2_IRQn)
81     {
82         port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn);
83     }
84     else if(irqn >= ioss_interrupts_gpio_2_IRQn && irqn < ioss_interrupts_gpio_5_IRQn)
85     {
86         port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn + 1);
87     }
88     else if(irqn >= ioss_interrupts_gpio_5_IRQn && irqn <= ioss_interrupts_gpio_21_IRQn)
89     {
90         port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn + 2);
91     }
92     else
93     {
94         port = 0u;
95         CY_ASSERT(false); /* Unknown port */
96     }
97 #elif defined(COMPONENT_CAT1C)
98     #if defined(CY_DEVICE_TVIIBH4M) || defined(CY_DEVICE_TVIIBH8M)
99         /* Port 0-23 and 28-32 (inclusive) are DeepSleep capable. Port 24-27 and 33-34
100         * (inclusive) are active mode only. The interrupt numbers are grouped by power
101         * domain which means the numbers are non-contiguous - and die specific */
102         uint32_t port;
103         if(irqn <= ioss_interrupts_gpio_dpslp_23_IRQn)
104         {
105             port = (uint32_t)(irqn - ioss_interrupts_gpio_dpslp_0_IRQn);
106         }
107         else if((irqn >= ioss_interrupts_gpio_act_24_IRQn) && (irqn <= ioss_interrupts_gpio_act_27_IRQn))
108         {
109             port = 24u + (uint32_t)(irqn - ioss_interrupts_gpio_act_24_IRQn);
110         }
111         else if((irqn >= ioss_interrupts_gpio_dpslp_28_IRQn) && (irqn <= ioss_interrupts_gpio_dpslp_32_IRQn))
112         {
113             port = 28u + (uint32_t)(irqn - ioss_interrupts_gpio_dpslp_28_IRQn);
114         }
115     #if defined(CY_DEVICE_TVIIBH8M) /* Ports 33 and 34 don't exist on the 4M part */
116         else if((irqn >= ioss_interrupts_gpio_act_33_IRQn) && (irqn <= ioss_interrupts_gpio_act_34_IRQn))
117         {
118             port = 33u + (uint32_t)(irqn - ioss_interrupts_gpio_act_33_IRQn);
119         }
120     #endif /* defined(CY_DEVICE_TVIIBH8M) */
121         else
122         {
123             port = 0u;
124             CY_ASSERT(false); /* Unknown port */
125         }
126     #else
127         #error "Unknown base die"
128     #endif /* defined(CY_DEVICE_TVIIBH4M) || defined(CY_DEVICE_TVIIBH8M) */
129 
130 #else /* other components */
131     uint32_t port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn);
132 #endif /* defined(COMPONENT_CAT1D) */
133     uint32_t intr_cause = 1 << port;
134 #if defined(COMPONENT_CAT2)
135     if (irqn == ioss_interrupt_gpio_IRQn)
136     {
137         intr_cause = Cy_GPIO_GetInterruptCause();
138     }
139 #endif
140 
141     while(intr_cause != 0)
142     {
143         uint32_t curr_port = (uint32_t) (31U - __CLZ(intr_cause));
144         GPIO_PRT_Type *portAddr = Cy_GPIO_PortToAddr(curr_port);
145         cyhal_gpio_callback_data_t* cb_data = _cyhal_gpio_callbacks[curr_port];
146         while (NULL != cb_data)
147         {
148             uint8_t pin = CYHAL_GET_PIN(cb_data->pin);
149             /* Each supported architecture much have a way to check the interrupt status of a pin on a port. */
150 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
151             if (Cy_GPIO_GetInterruptStatusMasked(portAddr, pin))
152 #elif defined(COMPONENT_CAT2)
153             if (Cy_GPIO_GetInterruptStatus(portAddr, pin))
154 #else
155     #error "Unsupported architecture"
156 #endif
157             {
158                 /* Call registered callbacks here */
159                 cyhal_gpio_event_t event, edge = (cyhal_gpio_event_t)Cy_GPIO_GetInterruptEdge(portAddr, pin);
160                 switch (edge)
161                 {
162                     case CYHAL_GPIO_IRQ_RISE:
163                     case CYHAL_GPIO_IRQ_FALL:
164                         event = edge;
165                         break;
166                     default:
167                         event = (Cy_GPIO_Read(portAddr, pin) != 0) ? CYHAL_GPIO_IRQ_RISE : CYHAL_GPIO_IRQ_FALL;
168                         break;
169                 }
170                 cb_data->callback(cb_data->callback_arg, event);
171             }
172 
173             cb_data = cb_data->next;
174         }
175         // Since the HAL has taken over the interrupt, make sure we clear any triggers to avoid an
176         // infinite loop.
177         for (uint8_t i = 0; i < CY_GPIO_PINS_MAX; i++)
178         {
179             Cy_GPIO_ClearInterrupt(portAddr, i);
180         }
181         intr_cause &= ~(1 << curr_port);
182     }
183 }
184 
_cyhal_gpio_convert_drive_mode(cyhal_gpio_drive_mode_t drive_mode,cyhal_gpio_direction_t direction)185 static uint32_t _cyhal_gpio_convert_drive_mode(cyhal_gpio_drive_mode_t drive_mode, cyhal_gpio_direction_t direction)
186 {
187     uint32_t drvMode;
188     switch (drive_mode)
189     {
190         /* For DRIVE_NONE and DRIVE_ANALOG: Return immediately so drvMode is
191          * not modified after switch statement based on direction as direction
192          * does not make sense for input only drive modes */
193         case CYHAL_GPIO_DRIVE_NONE:
194             drvMode = CY_GPIO_DM_HIGHZ;
195             return drvMode;
196         case CYHAL_GPIO_DRIVE_ANALOG:
197             drvMode = CY_GPIO_DM_ANALOG;
198             return drvMode;
199         case CYHAL_GPIO_DRIVE_PULLUP:
200             drvMode = CY_GPIO_DM_PULLUP;
201             break;
202         case CYHAL_GPIO_DRIVE_PULLDOWN:
203             drvMode = CY_GPIO_DM_PULLDOWN;
204             break;
205         case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW:
206             drvMode = CY_GPIO_DM_OD_DRIVESLOW;
207             break;
208         case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH:
209             drvMode = CY_GPIO_DM_OD_DRIVESHIGH;
210             break;
211         case CYHAL_GPIO_DRIVE_STRONG:
212             drvMode = CY_GPIO_DM_STRONG;
213             break;
214         case CYHAL_GPIO_DRIVE_PULLUPDOWN:
215             drvMode = CY_GPIO_DM_PULLUP_DOWN;
216             break;
217         case CYHAL_GPIO_DRIVE_PULL_NONE:
218             if ((direction == CYHAL_GPIO_DIR_OUTPUT) || (direction == CYHAL_GPIO_DIR_BIDIRECTIONAL))
219             {
220                 drvMode = CY_GPIO_DM_STRONG;
221             }
222             else
223             {
224                 drvMode = CY_GPIO_DM_HIGHZ;
225             }
226             break;
227         default:
228             CY_ASSERT(false);
229             drvMode = CY_GPIO_DM_HIGHZ;
230     }
231 
232     if (direction == CYHAL_GPIO_DIR_OUTPUT)
233     {
234 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
235         drvMode &= _CYHAL_GPIO_DIRECTION_OUTPUT_MASK;
236 #elif defined(COMPONENT_CAT2)
237         drvMode |= _CYHAL_GPIO_DIRECTION_OUTPUT_MASK;
238 #endif
239     }
240     return drvMode;
241 }
242 
_cyhal_get_irqn(cyhal_gpio_t pin)243 static _cyhal_system_irq_t _cyhal_get_irqn(cyhal_gpio_t pin)
244 {
245     _cyhal_system_irq_t irqn;
246 #if defined(COMPONENT_CAT1D)
247     uint32_t port = CYHAL_GET_PORT(pin);
248     if(port <= 2u)
249     {
250         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + port);
251     }
252     else if(port <= 4u)
253     {
254         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + (port - 1u));
255     }
256     else if(port <= 21u)
257     {
258         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + (port - 2u));
259     }
260     else
261     {
262         irqn = (_cyhal_system_irq_t)0u;
263         CY_ASSERT(false); /* Unknown port */
264     }
265 #elif defined(COMPONENT_CAT1C)
266     uint32_t port = CYHAL_GET_PORT(pin);
267     /* Port 0-23 and 28-32 (inclusive) are DeepSleep capable. Port 24-27 and 33-34
268     * (inclusive) are active mode only. The interrupt numbers are grouped by power
269     * domain which means the numbers are non-contiguous - and die specific */
270     if(port <= 23u)
271     {
272         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_dpslp_0_IRQn + port);
273     }
274     else if(port <= 27u)
275     {
276         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_act_24_IRQn + (port - 24u));
277     }
278     else if(port <= 32u)
279     {
280         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_dpslp_28_IRQn + (port - 28u));
281     }
282 #if defined(CY_DEVICE_TVIIBH8M) /* Ports 33 and 34 don't exist on the 4M part */
283     else if(port <= 34u)
284     {
285         irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_act_33_IRQn + (port - 33u));
286     }
287 #endif /* defined(CY_DEVICE_TVIIBH8M) */
288     else
289     {
290         irqn = (_cyhal_system_irq_t)0u;
291         CY_ASSERT(false); /* Unknown port */
292     }
293 #else /* other components */
294     irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + CYHAL_GET_PORT(pin));
295 #endif /* defined(COMPONENT_CAT1D) */
296     return irqn;
297 }
298 
299 /*******************************************************************************
300 *       HAL Implementation
301 *******************************************************************************/
302 
cyhal_gpio_init(cyhal_gpio_t pin,cyhal_gpio_direction_t direction,cyhal_gpio_drive_mode_t drive_mode,bool init_val)303 cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode, bool init_val)
304 {
305     if (!_cyhal_gpio_arrays_initialized)
306     {
307         for (uint8_t i = 0; i < IOSS_GPIO_GPIO_PORT_NR; i++)
308         {
309             _cyhal_gpio_callbacks[i] = NULL;
310         }
311 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
312         for (uint8_t i = 0; i < _CYHAL_GPIO_SOURCE_SIGNAL_COUNT; i++)
313         {
314             _cyhal_gpio_source_signals[i] = CYHAL_TRIGGER_CPUSS_ZERO;
315         }
316 #endif
317         _cyhal_gpio_arrays_initialized = true;
318     }
319 
320     /* Mbed creates GPIOs for pins that are dedicated to other peripherals in some cases. */
321 #ifndef __MBED__
322     cyhal_resource_inst_t pinRsc = _cyhal_utils_get_gpio_resource(pin);
323     cy_rslt_t status = cyhal_hwmgr_reserve(&pinRsc);
324 #else
325     cy_rslt_t status = CY_RSLT_SUCCESS;
326 #endif
327 
328     if (status == CY_RSLT_SUCCESS)
329     {
330         uint32_t pdl_drive_mode = _cyhal_gpio_convert_drive_mode(drive_mode, direction);
331         Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdl_drive_mode, init_val, HSIOM_SEL_GPIO);
332     }
333 
334     return status;
335 }
336 
cyhal_gpio_free(cyhal_gpio_t pin)337 void cyhal_gpio_free(cyhal_gpio_t pin)
338 {
339     if(_cyhal_gpio_arrays_initialized)
340     {
341         if (pin != CYHAL_NC_PIN_VALUE)
342         {
343 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
344             Cy_GPIO_SetInterruptMask(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), 0);
345 #elif defined(COMPONENT_CAT2)
346             Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), CY_GPIO_INTR_DISABLE);
347 #endif
348             cyhal_gpio_register_callback(pin, NULL);
349 
350             /* Disable interrupts for port if no other pins in port have interrupts enabled */
351             _cyhal_system_irq_t irqn = _cyhal_get_irqn(pin);
352             if(!_CYHAL_GPIO_IS_PORT_INTERRUPT_SET(pin))
353             {
354                 _cyhal_irq_free(irqn);
355             }
356 
357             (void)cyhal_gpio_disable_output(pin);
358             #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined(CY_IP_MXS22IOSS)
359             for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
360             {
361                 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
362                 if(mapping.pin == pin)
363                 {
364                     if (CYHAL_TRIGGER_CPUSS_ZERO != _cyhal_gpio_source_signals[i])
365                     {
366                         (void)cyhal_gpio_disconnect_digital(pin, _cyhal_gpio_source_signals[i]);
367                     }
368                 }
369             }
370             #endif
371 
372             Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), CY_GPIO_DM_ANALOG, 0UL, HSIOM_SEL_GPIO);
373 
374             /* Do not attempt to free the resource we don't reserve in mbed. */
375 #ifndef __MBED__
376             cyhal_resource_inst_t pinRsc = _cyhal_utils_get_gpio_resource(pin);
377             cyhal_hwmgr_free(&pinRsc);
378 #endif
379         }
380     }
381     else
382     {
383         CY_ASSERT(false); /* Should not be freeing if we never initialized anything */
384     }
385 }
386 
cyhal_gpio_configure(cyhal_gpio_t pin,cyhal_gpio_direction_t direction,cyhal_gpio_drive_mode_t drive_mode)387 cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode)
388 {
389     uint32_t pdldrive_mode = _cyhal_gpio_convert_drive_mode(drive_mode, direction);
390     Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdldrive_mode);
391 
392     return CY_RSLT_SUCCESS;
393 }
394 
cyhal_gpio_register_callback(cyhal_gpio_t pin,cyhal_gpio_callback_data_t * callback_data)395 void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_callback_data_t* callback_data)
396 {
397     uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
398 
399     // Remove if already registered;
400     cyhal_gpio_callback_data_t** ptr = &(_cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)]);
401     while (NULL != *ptr)
402     {
403         if ((*ptr)->pin == pin)
404         {
405             *ptr = (*ptr)->next;
406             break;
407         }
408         ptr = &((*ptr)->next);
409     }
410     // Add if requested
411     if (NULL != callback_data)
412     {
413         CY_ASSERT(NULL != callback_data->callback);
414         callback_data->pin = pin;
415         callback_data->next = _cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)];
416         _cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)] = callback_data;
417     }
418 
419     cyhal_system_critical_section_exit(savedIntrStatus);
420 }
421 
cyhal_gpio_enable_event(cyhal_gpio_t pin,cyhal_gpio_event_t event,uint8_t intr_priority,bool enable)422 void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intr_priority, bool enable)
423 {
424 #if (_CYHAL_IRQ_MUXING)
425     /* We may be in a critical section. Only clear the interrupt status if there isn't a pending interrupt */
426     if ((Cy_GPIO_GetInterruptStatus(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin)) == 0) || enable)
427 #endif
428     {
429         Cy_GPIO_ClearInterrupt(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin));
430     }
431 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
432     Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), (uint32_t)event);
433     Cy_GPIO_SetInterruptMask(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), (uint32_t)enable);
434 #elif defined(COMPONENT_CAT2)
435     uint32_t intr_val = enable ? (uint32_t)event : CY_GPIO_INTR_DISABLE;
436     Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), intr_val);
437 #endif
438 
439     _cyhal_system_irq_t irqn = _cyhal_get_irqn(pin);
440 
441     /* If we are disabling event and no pins are configured for interruption, disable port interrupts*/
442     if(enable == false && !_CYHAL_GPIO_IS_PORT_INTERRUPT_SET(pin))
443     {
444         _cyhal_irq_free(irqn);
445     }
446     else if(enable == true)
447     {
448         /* Unconditionally registering interrupt as we could be the first pin in the port to be enabled through HAL */
449         _cyhal_irq_register(irqn, intr_priority, _cyhal_gpio_irq_handler);
450         _cyhal_irq_enable(irqn);
451     }
452 }
453 
454 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
cyhal_gpio_connect_digital(cyhal_gpio_t pin,cyhal_source_t source)455 cy_rslt_t cyhal_gpio_connect_digital(cyhal_gpio_t pin, cyhal_source_t source)
456 {
457     // Search through cyhal_pin_map_peri_tr_io_output to determine if a trigger
458     // can be routed to it. (Note: tr_io_output refers to trigger mux output,
459     // not peripheral output. A trigger mux output is routed to a peripheral
460     // input.)
461     for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
462     {
463         cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
464         if(mapping.pin == pin)
465         {
466             Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), mapping.hsiom);
467 
468 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
469             cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_PERI_TR_IO_OUTPUT0 + mapping.channel_num);
470 #elif defined(COMPONENT_CAT1B)
471             cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_IOSS_PERI_TR_IO_OUTPUT_OUT0 + mapping.channel_num);
472 #elif defined(COMPONENT_CAT1D)
473             cyhal_dest_t dest;
474             if(0u == mapping.block_num)
475             {
476                 dest = CYHAL_TRIGGER_IOSS_PERI0_TR_IO_OUTPUT_OUT0;
477             }
478             else
479             {
480                 CY_ASSERT(1u == mapping.block_num);
481                 dest = CYHAL_TRIGGER_IOSS_PERI1_TR_IO_OUTPUT_OUT0;
482             }
483 
484             dest = (cyhal_dest_t)(dest + mapping.channel_num);
485 #endif
486 
487             cy_rslt_t rslt = _cyhal_connect_signal(source, dest);
488             if (CY_RSLT_SUCCESS == rslt)
489             {
490                 _cyhal_gpio_source_signals[i] = source;
491             }
492             return rslt;
493         }
494     }
495 
496     return CYHAL_GPIO_RSLT_ERR_NO_INPUT_SIGNAL;
497 }
498 
cyhal_gpio_enable_output(cyhal_gpio_t pin,cyhal_signal_type_t type,cyhal_source_t * source)499 cy_rslt_t cyhal_gpio_enable_output(cyhal_gpio_t pin, cyhal_signal_type_t type, cyhal_source_t *source)
500 {
501     // Search through cyhal_pin_map_peri_tr_io_input to determine if pin can be
502     // used to drive a trigger line. (Note: tr_io_input refers to trigger mux
503     // input, not peripheral input. A peripheral output is routed to a trigger
504     // mux input.)
505     for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_input)/sizeof(cyhal_resource_pin_mapping_t)); i++)
506     {
507         cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_input[i];
508         if(mapping.pin == pin)
509         {
510             Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), mapping.hsiom);
511 
512 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
513             cyhal_internal_source_t int_src = (cyhal_internal_source_t)(_CYHAL_TRIGGER_PERI_TR_IO_INPUT0 + mapping.channel_num);
514 #elif defined(COMPONENT_CAT1B)
515             cyhal_internal_source_t int_src = (cyhal_internal_source_t)(_CYHAL_TRIGGER_IOSS_PERI_TR_IO_INPUT_IN0 + mapping.channel_num);
516 #elif defined(COMPONENT_CAT1D)
517             cyhal_internal_source_t int_src;
518             if(0u == mapping.block_num)
519             {
520                 int_src = _CYHAL_TRIGGER_IOSS_PERI0_TR_IO_INPUT_IN0;
521             }
522             else
523             {
524                 CY_ASSERT(1u == mapping.block_num);
525                 int_src = _CYHAL_TRIGGER_IOSS_PERI1_TR_IO_INPUT_IN0;
526             }
527 
528             int_src = (cyhal_internal_source_t)(int_src + mapping.channel_num);
529 #endif
530             *source = (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(int_src, type);
531 
532             return CY_RSLT_SUCCESS;
533         }
534     }
535 
536     return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
537 }
538 
cyhal_gpio_disconnect_digital(cyhal_gpio_t pin,cyhal_source_t source)539 cy_rslt_t cyhal_gpio_disconnect_digital(cyhal_gpio_t pin, cyhal_source_t source)
540 {
541     for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
542     {
543         cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
544         if(mapping.pin == pin)
545         {
546             Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), HSIOM_SEL_GPIO);
547 
548 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
549             cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_PERI_TR_IO_OUTPUT0 + mapping.channel_num);
550 #elif defined(COMPONENT_CAT1B)
551             cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_IOSS_PERI_TR_IO_OUTPUT_OUT0 + mapping.channel_num);
552 #elif defined(COMPONENT_CAT1D)
553             cyhal_dest_t dest;
554             if(0u == mapping.block_num)
555             {
556                 dest = CYHAL_TRIGGER_IOSS_PERI0_TR_IO_OUTPUT_OUT0;
557             }
558             else
559             {
560                 CY_ASSERT(1u == mapping.block_num);
561                 dest = CYHAL_TRIGGER_IOSS_PERI1_TR_IO_OUTPUT_OUT0;
562             }
563 
564             dest = (cyhal_dest_t)(dest + mapping.channel_num);
565 #endif
566 
567             cy_rslt_t rslt = _cyhal_disconnect_signal(source, dest);
568             if (CY_RSLT_SUCCESS == rslt)
569             {
570                 _cyhal_gpio_source_signals[i] = CYHAL_TRIGGER_CPUSS_ZERO;
571             }
572             return rslt;
573         }
574     }
575 
576     return CYHAL_GPIO_RSLT_ERR_NO_INPUT_SIGNAL;
577 }
578 
cyhal_gpio_disable_output(cyhal_gpio_t pin)579 cy_rslt_t cyhal_gpio_disable_output(cyhal_gpio_t pin)
580 {
581     for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_input)/sizeof(cyhal_resource_pin_mapping_t)); i++)
582     {
583         cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_input[i];
584         if(mapping.pin == pin)
585         {
586             Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), HSIOM_SEL_GPIO);
587 
588             return CY_RSLT_SUCCESS;
589         }
590     }
591 
592     return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
593 }
594 #elif defined(CY_IP_M0S8IOSS)
595 // M0S8 devices do not have gpio triggers
cyhal_gpio_connect_digital(cyhal_gpio_t pin,cyhal_source_t source)596 cy_rslt_t cyhal_gpio_connect_digital(cyhal_gpio_t pin, cyhal_source_t source)
597 {
598     CY_UNUSED_PARAMETER(pin);
599     CY_UNUSED_PARAMETER(source);
600     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
601 }
602 
cyhal_gpio_enable_output(cyhal_gpio_t pin,cyhal_signal_type_t type,cyhal_source_t * source)603 cy_rslt_t cyhal_gpio_enable_output(cyhal_gpio_t pin, cyhal_signal_type_t type, cyhal_source_t *source)
604 {
605     CY_UNUSED_PARAMETER(pin);
606     CY_UNUSED_PARAMETER(source);
607     CY_UNUSED_PARAMETER(type);
608     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
609 }
610 
cyhal_gpio_disconnect_digital(cyhal_gpio_t pin,cyhal_source_t source)611 cy_rslt_t cyhal_gpio_disconnect_digital(cyhal_gpio_t pin, cyhal_source_t source)
612 {
613     CY_UNUSED_PARAMETER(pin);
614     CY_UNUSED_PARAMETER(source);
615     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
616 }
617 
cyhal_gpio_disable_output(cyhal_gpio_t pin)618 cy_rslt_t cyhal_gpio_disable_output(cyhal_gpio_t pin)
619 {
620     CY_UNUSED_PARAMETER(pin);
621     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
622 }
623 #endif
624 
625 #if defined(__cplusplus)
626 }
627 #endif /* __cplusplus */
628 
629 #endif /* CYHAL_DRIVER_AVAILABLE_GPIO */
630