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