1 /***************************************************************************//**
2 * \file cyhal_tcpwm_common.c
3 *
4 * \brief
5 * Code shared between the Cypress Timer/Counter and PWM.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 #include "cyhal_hwmgr.h"
28 #include "cyhal_utils.h"
29 #include "cyhal_irq_impl.h"
30 #include "cyhal_syspm.h"
31 #include "cyhal_system.h"
32 #include "cyhal_tcpwm_common.h"
33 #include "cyhal_clock.h"
34 
35 #if (_CYHAL_DRIVER_AVAILABLE_TCPWM)
36 
37 #if defined(__cplusplus)
38 extern "C" {
39 #endif
40 
41 #if defined(COMPONENT_CAT1B) || (COMPONENT_CAT1D)
42 #define TCPWM_CLOCK(block, channel)     (PCLK_TCPWM##block##_CLOCK_COUNTER_EN##channel)
43 #elif defined(COMPONENT_CAT5)
44 /* Note: PCLK is not used on this device */
45 #define TCPWM_CLOCK(block, channel)     (0)
46 #else
47 #define TCPWM_CLOCK(block, channel)     (PCLK_TCPWM##block##_CLOCKS##channel)
48 #endif
49 
50 #if defined(COMPONENT_CAT5)
51 /* Used to calculate which TCPWM_INTR_MASK_t to use when enabling interrupts */
52 #define _GET_TCPWM_INTR_MASK(group, counter) (1 << (((group) * 2) + counter))
53 #endif
54 
55 #if defined(CY_IP_MXTCPWM_INSTANCES)
56 #if (CY_IP_MXTCPWM_VERSION == 1)
57     #if (CY_IP_MXTCPWM_INSTANCES == 0)
58         #define _CYHAL_TCPWM_CHANNELS (0u)
59     #elif (CY_IP_MXTCPWM_INSTANCES == 1)
60         #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR)
61     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
62         #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR + TCPWM1_CNT_NR)
63     #else
64         #warning Unhandled TCPWM instance count
65     #endif
66 #else // (CY_IP_MXTCPWM_VERSION >= 2)
67     #if (CY_IP_MXTCPWM_INSTANCES == 1)
68         #if (TCPWM_GRP_NR == 0)
69             #define _CYHAL_TCPWM_CHANNELS (0U)
70         #elif (TCPWM_GRP_NR == 1)
71             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR)
72         #elif (TCPWM_GRP_NR == 2)
73             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR)
74         #elif (TCPWM_GRP_NR == 3)
75             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR)
76         #elif (TCPWM_GRP_NR == 4)
77             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR + TCPWM_GRP_NR3_GRP_GRP_CNT_NR)
78         #endif
79     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
80         #if (TCPWM0_GRP_NR == 0)
81             #define _CYHAL_TCPWM0_CHANNELS (0U)
82         #elif (TCPWM0_GRP_NR == 1)
83             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR)
84         #elif (TCPWM0_GRP_NR == 2)
85             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR)
86         #elif (TCPWM0_GRP_NR == 3)
87             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR)
88         #elif (TCPWM0_GRP_NR == 4)
89             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR + TCPWM0_GRP_NR3_GRP_GRP_CNT_NR)
90         #endif
91         #ifndef _CYHAL_TCPWM0_CHANNELS
92             #error "Unhandled TCPWM0_GRP_NR count"
93         #endif
94         #if (TCPWM1_GRP_NR == 0)
95             #define _CYHAL_TCPWM1_CHANNELS (0U)
96         #elif (TCPWM1_GRP_NR == 1)
97             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR)
98         #elif (TCPWM1_GRP_NR == 2)
99             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR)
100         #elif (TCPWM1_GRP_NR == 3)
101             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR)
102         #elif (TCPWM1_GRP_NR == 4)
103             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR + TCPWM1_GRP_NR3_GRP_GRP_CNT_NR)
104         #endif
105         #ifndef _CYHAL_TCPWM1_CHANNELS
106             #error "Unhandled TCPWM1_GRP_NR count"
107         #endif
108 
109         #define _CYHAL_TCPWM_CHANNELS (_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS)
110     #else
111         #warning Unhandled TCPWM instance count
112     #endif
113 #endif
114 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
115     #if (CY_IP_M0S8TCPWM_INSTANCES == 1)
116         #define _CYHAL_TCPWM_CHANNELS (TCPWM_CNT_NR)
117     #else
118         #warning Unhandled TCPWM instance count
119     #endif
120 #endif
121 
122 const _cyhal_tcpwm_data_t _CYHAL_TCPWM_DATA[] =
123 {
124 #if defined(CY_IP_MXTCPWM_INSTANCES)
125     #if (CY_IP_MXTCPWM_VERSION == 1)
126         #if (CY_IP_MXTCPWM_INSTANCES > 0)
127             {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM0_CNT_CNT_WIDTH, TCPWM0_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
128         #endif
129         #if (CY_IP_MXTCPWM_INSTANCES > 1)
130             {TCPWM1, TCPWM_CLOCK(1, 0), TCPWM1_CNT_CNT_WIDTH, TCPWM1_CNT_NR, TCPWM0_CNT_NR, tcpwm_1_interrupts_0_IRQn },
131         #endif
132         #if (CY_IP_MXTCPWM_INSTANCES > 2)
133             #warning Unhandled TCPWM instance count
134         #endif
135     #else // (CY_IP_MXTCPWM_VERSION >= 2)
136         #if (CY_IP_MXTCPWM_INSTANCES == 1)
137             #if (TCPWM_GRP_NR > 0)
138                 {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR0_GRP_GRP_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
139             #endif
140             #if (TCPWM_GRP_NR > 1)
141                 {TCPWM0, TCPWM_CLOCK(0, 256), TCPWM_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR1_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_0_interrupts_256_IRQn },
142             #endif
143             #if (TCPWM_GRP_NR > 2)
144                 {TCPWM0, TCPWM_CLOCK(0, 512), TCPWM_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR2_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_0_interrupts_512_IRQn },
145             #endif
146             #if (TCPWM_GRP_NR > 3)
147                 {TCPWM0, TCPWM_CLOCK(0, 768), TCPWM_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR3_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_0_interrupts_768_IRQn },
148             #endif
149         #endif
150         #if (CY_IP_MXTCPWM_INSTANCES == 2)
151             #if (TCPWM0_GRP_NR > 0)
152                 {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM0_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
153             #endif
154             #if (TCPWM0_GRP_NR > 1)
155                 {TCPWM0, TCPWM_CLOCK(0, 256), TCPWM0_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR1_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_0_interrupts_256_IRQn },
156             #endif
157             #if (TCPWM0_GRP_NR > 2)
158                 {TCPWM0, TCPWM_CLOCK(0, 512), TCPWM0_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR2_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_0_interrupts_512_IRQn },
159             #endif
160             #if (TCPWM0_GRP_NR > 3)
161                 {TCPWM0, TCPWM_CLOCK(0, 768), TCPWM0_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR3_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_0_interrupts_768_IRQn },
162             #endif
163             #if (TCPWM0_GRP_NR > 4)
164                 #error "Unhandled TCPWM0_GRP_NR count"
165             #endif
166             #if (TCPWM1_GRP_NR > 0)
167                 {TCPWM1, TCPWM_CLOCK(1, 0), TCPWM1_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR0_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS, tcpwm_1_interrupts_0_IRQn },
168             #endif
169             #if (TCPWM1_GRP_NR > 1)
170                 {TCPWM1, TCPWM_CLOCK(1, 256), TCPWM1_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR1_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_1_interrupts_256_IRQn },
171             #endif
172             #if (TCPWM1_GRP_NR > 2)
173                 {TCPWM1, TCPWM_CLOCK(1, 512), TCPWM1_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR2_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_1_interrupts_512_IRQn },
174             #endif
175             #if (TCPWM1_GRP_NR > 3)
176                 {TCPWM1, TCPWM_CLOCK(1, 768), TCPWM1_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR3_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_1_interrupts_768_IRQn },
177             #endif
178             #if (TCPWM1_GRP_NR > 4)
179                 #error "Unhandled TCPWM1_GRP_NR count"
180             #endif
181         #endif
182         #if (CY_IP_MXTCPWM_INSTANCES > 2)
183             #warning Unhandled TCPWM instance count
184         #endif
185     #endif
186 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
187     #if (CY_IP_M0S8TCPWM_INSTANCES == 1)
188         {TCPWM, PCLK_TCPWM_CLOCKS0, 16, TCPWM_CNT_NR, 0, tcpwm_interrupts_0_IRQn },
189     #endif
190     #if (CY_IP_M0S8TCPWM_INSTANCES > 1)
191         #warning Unhandled TCPWM instance count
192     #endif
193 #endif
194 };
195 
196 
197 // There are some number of input trigger indices (starting at 0) that are
198 // reserved for various purposes. Here we are dealing with inputs from the
199 // trigmux which start after the reserved inputs so we must always offset the
200 // trigger index after reservation. For all devices, indices 0 and 1 are
201 // reserved for constant signals 0 and 1 respectively (so offset by 2 to
202 // start). Depending on device, further offsetting may be needed as well. The
203 // number of trigmux tcpwm inputs (but not the total number of tcpwm trigger
204 // inputs) per tcpwm block is also defined here.
205 #if (CY_IP_MXTCPWM_VERSION == 1U)
206     #if (CY_IP_MXTCPWM_INSTANCES == 1)
207     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {2};
208     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
209     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
210     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2] = {2, 2};
211     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2] = {(16 - 2), (16 - 2)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
212     #endif
213 #elif (CY_IP_MXTCPWM_VERSION == 2U)
214     // Note: These devices also have support for up to 256 trigger lines total,
215     // but only 28 input triggers (on top of the 2 + TCPWM_TR_ONE_CNT_NR) are
216     // currently available, so we only support that to save RAM.
217     #if (CY_IP_MXTCPWM_INSTANCES == 1)
218     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + TCPWM_TR_ONE_CNT_NR)};
219     const uint16_t  _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(TCPWM_TR_ALL_CNT_NR)};
220     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
221     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2] = {(2 + TCPWM0_TR_ONE_CNT_NR), (2 + TCPWM1_TR_ONE_CNT_NR)};
222     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2] = {(TCPWM0_TR_ALL_CNT_NR), (TCPWM1_TR_ALL_CNT_NR)};
223     #else
224     #warning Unhandled TCPWM instance count
225     #endif
226 #else // (CY_IP_M0S8TCPWM_VERSION == 2)
227     #if defined(CY_DEVICE_PSOC4AS1)
228         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 12)};
229         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 12)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
230     #else
231         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 7)};
232         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 7)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
233     #endif
234 #endif
235 
236 // Get the the channel relative to the start of the first TCPWM IP block
237 #define _CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel)  ((_CYHAL_TCPWM_DATA[(_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block))].channel_offset) + (channel))
238 
239 #if (CY_IP_MXTCPWM_VERSION == 2)
240     #if (CY_IP_MXTCPWM_INSTANCES == 1)
241         uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM_CHANNELS];
242     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
243         uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS];
244     #else
245         #warning Unhandled TCPWM instance count
246     #endif // (CY_IP_MXTCPWM_INSTANCES == 1 or 2)
247 #endif // (CY_IP_MXTCPWM_VERSION == 2)
248 
249 /** Callback array for TCPWM interrupts */
250 static cyhal_tcpwm_t *_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_CHANNELS];
251 
252 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
_cyhal_tcpwm_pm_has_enabled(void)253 static bool _cyhal_tcpwm_pm_has_enabled(void)
254 {
255     for (uint8_t i = 0; i < _CYHAL_TCPWM_CHANNELS; i++)
256     {
257         if (NULL != _cyhal_tcpwm_data_structs[i])
258         {
259             return true;
260         }
261     }
262     return false;
263 }
264 
265 static bool _cyhal_tcpwm_pm_transition_pending_value = false;
266 
_cyhal_tcpwm_pm_transition_pending(void)267 bool _cyhal_tcpwm_pm_transition_pending(void)
268 {
269     return _cyhal_tcpwm_pm_transition_pending_value;
270 }
271 
_cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)272 static bool _cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
273 {
274     CY_UNUSED_PARAMETER(state);
275     CY_UNUSED_PARAMETER(callback_arg);
276     switch(mode)
277     {
278         case CYHAL_SYSPM_CHECK_FAIL:
279         {
280             _cyhal_tcpwm_pm_transition_pending_value = false;
281             break;
282         }
283         case CYHAL_SYSPM_BEFORE_TRANSITION:
284         {
285             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
286             {
287                 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
288                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
289                 {
290                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
291                     // and the macro would compress it again
292                     if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
293                     {
294                         #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
295                         uint32_t mask = ((uint32_t)1u << j);
296                         if((((TCPWM_Type *)(base))->CTRL) & mask)
297                         {
298                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
299                         }
300                         else
301                         {
302                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
303                         }
304                         #else
305                         if(_FLD2BOOL(TCPWM_GRP_CNT_V2_CTRL_ENABLED, TCPWM_GRP_CNT_CTRL(base, TCPWM_GRP_CNT_GET_GRP(j), j)))
306                         {
307                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
308                         }
309                         else
310                         {
311                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
312                         }
313                         #endif
314                     }
315                 }
316             }
317             break;
318         }
319         case CYHAL_SYSPM_AFTER_TRANSITION:
320         {
321             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
322             {
323                 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
324                 uint32_t enable_flag = 0;
325                 #endif
326                 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
327                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
328                 {
329                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
330                     // and the macro would compress it again
331                     if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
332                     {
333 
334                         if(_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state)
335                         {
336                             #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
337                             enable_flag |= 1u << j;
338                             #else
339                             Cy_TCPWM_Enable_Single(base, j);
340                             #endif
341                         }
342                     }
343                 }
344                 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
345                 if (0 != enable_flag)
346                 {
347                     // This only enables the counter. This does not start the timer/counter or the pwm.
348                     Cy_TCPWM_Enable_Multiple(base, enable_flag);
349                 }
350                 #endif
351             }
352             _cyhal_tcpwm_pm_transition_pending_value = false;
353             break;
354         }
355         case CYHAL_SYSPM_CHECK_READY:
356         {
357             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
358             {
359                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
360                 {
361                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
362                     // and the macro would compress it again
363                     cyhal_tcpwm_t* obj = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j];
364                     if ((NULL != obj) && (CY_TCPWM_PWM_STATUS_COUNTER_RUNNING & Cy_TCPWM_PWM_GetStatus(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource))))
365                     {
366                         return false;
367                     }
368                 }
369             }
370             _cyhal_tcpwm_pm_transition_pending_value = true;
371             break;
372         }
373         default:
374         {
375             CY_ASSERT(false);
376             break;
377         }
378     }
379     return true;
380 }
381 
382 static cyhal_syspm_callback_data_t _cyhal_tcpwm_syspm_callback_data =
383 {
384     .callback = &_cyhal_tcpwm_pm_callback,
385     .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
386     .next = NULL,
387     .args = NULL,
388     .ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION),
389 };
390 
391 #else   /* !(CYHAL_DRIVER_AVAILABLE_SYSPM) */
392 /* If SysPm driver is not available redefine function for TCPWM to return a bad value */
_cyhal_tcpwm_pm_transition_pending(void)393 bool _cyhal_tcpwm_pm_transition_pending(void)
394 {
395     return false;
396 }
397 #endif /* (CYHAL_DRIVER_AVAILABLE_SYSPM) */
398 
_cyhal_tcpwm_init_data(cyhal_tcpwm_t * tcpwm)399 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm)
400 {
401 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
402     for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
403     {
404         tcpwm->inputs[i] = CYHAL_TRIGGER_CPUSS_ZERO;
405     }
406 #endif
407     #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
408     if (!_cyhal_tcpwm_pm_has_enabled())
409     {
410         _cyhal_syspm_register_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
411     }
412     #endif
413     _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(tcpwm->resource.block_num, tcpwm->resource.channel_num)] = tcpwm;
414 }
415 
416 #if defined (COMPONENT_CAT5)
_cyhal_tcpwm_irq_handler(UINT8 group_id,UINT8 counter_id)417 static void _cyhal_tcpwm_irq_handler(UINT8 group_id, UINT8 counter_id)
418 {
419     uint8_t block = group_id;
420     uint8_t channel = counter_id;
421 #else
422 static void _cyhal_tcpwm_irq_handler(void)
423 {
424     _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
425     uint8_t block, channel = 0;
426     // Determine TCPWM block and channel from IRQn
427     for (block = 0; block < _CYHAL_TCPWM_INSTANCES; block++)
428     {
429         if ((irqn >= _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset) && (irqn < _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset + _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].num_channels))
430         {
431             channel = (uint8_t)(irqn - _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset);
432             break;
433         }
434     }
435 #endif
436 
437     if (block < _CYHAL_TCPWM_INSTANCES)
438     {
439         TCPWM_Type *blockAddr = _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].base;
440         cyhal_tcpwm_t *tcpwm = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel)];
441         #if (_CYHAL_IRQ_MUXING)
442         /* Disable any interrupts that couldn't be disabled from enable_event */
443         uint32_t saved_intr_status = cyhal_system_critical_section_enter();
444         if(0u != tcpwm->clear_intr_mask)
445         {
446             uint32_t cnt_num = _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource);
447             uint32_t old_mask = Cy_TCPWM_GetInterruptMask(blockAddr, cnt_num);
448             Cy_TCPWM_SetInterruptMask(blockAddr, cnt_num, (old_mask & ~(tcpwm->clear_intr_mask)));
449             tcpwm->clear_intr_mask = 0u;
450         }
451         cyhal_system_critical_section_exit(saved_intr_status);
452         #endif
453         uint32_t intrCause = Cy_TCPWM_GetInterruptStatusMasked(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource));
454         /* The masked status can be 0 if we updated the mask above */
455         if (0u != intrCause && tcpwm->callback_data.callback != NULL)
456         {
457             _cyhal_tcpwm_event_callback_t callback = (_cyhal_tcpwm_event_callback_t) tcpwm->callback_data.callback;
458             /* Call registered callbacks here */
459             (void) (callback) (tcpwm->callback_data.callback_arg, intrCause);
460         }
461 
462         Cy_TCPWM_ClearInterrupt(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource), intrCause);
463 
464         #if defined(COMPONENT_CAT5)
465         // CAT5 interrupt disables itself after firing, re-enable it
466         Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(group_id, counter_id));
467         #endif
468     }
469     else
470     {
471         CY_HALT(); // Could not determine the block/channel for IRQn
472     }
473 }
474 
475 /*******************************************************************************
476 *       TCPWM Shared HAL Functions
477 *******************************************************************************/
478 
479 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj)
480 {
481     CY_ASSERT(NULL != obj);
482 
483     _cyhal_system_irq_t irqn = (_cyhal_system_irq_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(obj->resource.block_num)].isr_offset + obj->resource.channel_num);
484     _cyhal_irq_free(irqn);
485 
486     if (NULL != obj->base)
487     {
488         _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(obj->resource.block_num, obj->resource.channel_num)] = NULL;
489         #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
490         if (!_cyhal_tcpwm_pm_has_enabled())
491         {
492             _cyhal_syspm_unregister_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
493         }
494         #endif
495 
496 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
497         for (uint8_t i = 0; i < _CYHAL_TCPWM_OUTPUTS; i++)
498         {
499             _cyhal_tcpwm_disable_output(obj, (cyhal_tcpwm_output_t)i);
500         }
501         for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
502         {
503             if (CYHAL_TRIGGER_CPUSS_ZERO != obj->inputs[i])
504             {
505                 _cyhal_tcpwm_disconnect_digital(obj, obj->inputs[i], (cyhal_tcpwm_input_t)i);
506             }
507         }
508 #endif
509 
510         #if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
511         Cy_TCPWM_Disable_Single(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
512         #else
513         Cy_TCPWM_PWM_Disable(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
514         #endif
515 
516         if(false == obj->owned_by_configurator)
517         {
518             cyhal_hwmgr_free(&(obj->resource));
519         }
520 
521         obj->base = NULL;
522         obj->resource.type = CYHAL_RSC_INVALID;
523     }
524 
525     if (obj->dedicated_clock)
526     {
527         en_clk_dst_t pclk = (en_clk_dst_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(obj->resource.block_num)].clock_dst + obj->resource.channel_num);
528         cy_rslt_t rslt = _cyhal_utils_peri_pclk_disable_divider(pclk, &(obj->clock));
529         CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
530         CY_ASSERT(CY_RSLT_SUCCESS == rslt);
531         cyhal_clock_free(&(obj->clock));
532         obj->dedicated_clock = false;
533     }
534 }
535 
536 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg)
537 {
538     uint8_t index = _CYHAL_TCPWM_GET_ARRAY_INDEX(resource->block_num, resource->channel_num);
539     uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
540     _cyhal_tcpwm_data_structs[index]->callback_data.callback = callback;
541     _cyhal_tcpwm_data_structs[index]->callback_data.callback_arg = callback_arg;
542     cyhal_system_critical_section_exit(savedIntrStatus);
543 
544     _cyhal_system_irq_t irqn = (_cyhal_system_irq_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(resource->block_num)].isr_offset + resource->channel_num);
545     /* Only enable if it's not already enabled */
546     if (false == _cyhal_irq_is_enabled(irqn))
547     {
548         #if defined (COMPONENT_CAT5)
549             Cy_TCPWM_RegisterInterruptCallback(_cyhal_tcpwm_irq_handler);
550             Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(resource->block_num, resource->channel_num));
551         #endif
552 
553         _cyhal_irq_register(irqn, CYHAL_ISR_PRIORITY_DEFAULT, (cy_israddress)_cyhal_tcpwm_irq_handler);
554         _cyhal_irq_enable(irqn);
555     }
556 }
557 
558 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable)
559 {
560     uint32_t old_mask = Cy_TCPWM_GetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource));
561     if (enable)
562     {
563         // Clear any newly enabled events so that old IRQs don't trigger ISRs
564         Cy_TCPWM_ClearInterrupt(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), ~old_mask & event);
565     }
566 #if (_CYHAL_IRQ_MUXING)
567     /* We may be in a critical section. Only clear the interrupt status if there isn't a pending interrupt */
568     if (Cy_TCPWM_GetInterruptStatus(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource)) == 0 || enable)
569 #endif
570     {
571         Cy_TCPWM_SetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), enable ? (old_mask | event) : (old_mask & ~event));
572     }
573 #if (_CYHAL_IRQ_MUXING)
574     else
575     {
576         /* Note that this interrupt cause should be cleared the next time an interrupt is triggered */
577         uint32_t saved_intr_status = cyhal_system_critical_section_enter();
578         tcpwm->clear_intr_mask |= event;
579         cyhal_system_critical_section_exit(saved_intr_status);
580     }
581 #endif
582 
583     _cyhal_system_irq_t irqn = (_cyhal_system_irq_t) (_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(resource->block_num)].isr_offset + resource->channel_num);
584     _cyhal_irq_set_priority(irqn, intr_priority);
585 }
586 
587 #if (CY_IP_MXTCPWM_VERSION == 2U)
588 static uint8_t _cyhal_tcpwm_convert_output_t(cyhal_tcpwm_output_t signal)
589 {
590     switch(signal)
591     {
592         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
593             return CY_TCPWM_CNT_TRIGGER_ON_OVERFLOW;
594         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
595             return CY_TCPWM_CNT_TRIGGER_ON_UNDEFLOW;
596         case CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT:
597             return CY_TCPWM_CNT_TRIGGER_ON_TC;
598         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
599             return CY_TCPWM_CNT_TRIGGER_ON_CC0_MATCH;
600         case CYHAL_TCPWM_OUTPUT_LINE_OUT:
601             return CY_TCPWM_CNT_TRIGGER_ON_LINE_OUT;
602         default:
603             CY_ASSERT(false);
604             return 0;
605     }
606 }
607 #endif
608 
609 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
610 #if (CY_IP_MXTCPWM_VERSION == 1U) ||(CY_IP_MXTCPWM_VERSION == 2U) || (CY_IP_M0S8TCPWM_VERSION == 2)
611 // Assumes trig_index is not offset by _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET
612 // (that is, it is 0 indexed).
613 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index)
614 {
615 #if (CY_IP_MXTCPWM_VERSION == 1U)
616     if(block == 0)
617     {
618         return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_IN0 + trig_index);
619     }
620     else
621     {
622         CY_ASSERT(block == 1);
623         return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM1_TR_IN0 + trig_index);
624     }
625 #elif (CY_IP_MXTCPWM_VERSION == 2U)
626     #if (CY_IP_MXTCPWM_INSTANCES == 2)
627     return (cyhal_dest_t)(_CYHAL_TCPWM_GET_IP_BLOCK(block) == 0 ? (CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + \
628             trig_index) : (CYHAL_TRIGGER_TCPWM1_TR_ALL_CNT_IN0 + trig_index));
629     #else
630     CY_UNUSED_PARAMETER(block);
631     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + trig_index);
632     #endif
633 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
634     CY_UNUSED_PARAMETER(block);
635 #if defined(CY_DEVICE_PSOC4AS1)
636     CY_ASSERT(block == 0);
637     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN12 + trig_index);
638 #elif defined(CY_DEVICE_PMG1S3) || defined(CY_DEVICE_CCG7S)
639     CY_ASSERT(block == 0);
640     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN8 + trig_index);
641 #else
642     CY_ASSERT(block == 0);
643     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN7 + trig_index);
644 #endif
645 #endif
646 }
647 #endif
648 
649 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
650 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t block, uint8_t chnl, cyhal_tcpwm_output_t signal)
651 {
652 #if (CY_IP_MXTCPWM_VERSION == 1U)
653     switch(signal)
654     {
655         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
656             return block == 0
657                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
658                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
659         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
660             return block == 0
661                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
662                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
663         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
664             #if defined(COMPONENT_CAT1B)
665             return block == 0
666                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
667                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
668             #else
669             return block == 0
670                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
671                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
672             #endif
673        default:
674             // Should never reach here
675             CY_ASSERT(false);
676             return CYHAL_TRIGGER_CPUSS_ZERO;
677     }
678 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
679     CY_UNUSED_PARAMETER(block);
680     switch(signal)
681     {
682         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
683             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
684         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
685             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
686         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
687             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
688        default:
689             // Should never reach here
690             CY_ASSERT(false);
691             return CYHAL_TRIGGER_CPUSS_ZERO;
692     }
693 #endif
694 }
695 #elif (CY_IP_MXTCPWM_VERSION == 2U)
696 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t out_trig_idx, uint8_t free_trig)
697 {
698     // Triggers are ordered by output trig idx, then block, then channel.
699     // Offsetting by out_trig_idx is sufficient to get the correct trigger.
700     if(free_trig == 0)
701     {
702         return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT00 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
703     }
704     else if(free_trig == 1)
705     {
706         return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT10 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
707     }
708     else
709     {
710         // Should never reach here
711         CY_ASSERT(false);
712         return CYHAL_TRIGGER_CPUSS_ZERO;
713     }
714 }
715 #endif
716 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
717 
718 cy_rslt_t _cyhal_tcpwm_connect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal, cyhal_edge_type_t type)
719 {
720 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
721     cy_rslt_t rslt = CY_RSLT_SUCCESS;
722     cyhal_signal_type_t signal_type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
723     if((CYHAL_SIGNAL_TYPE_LEVEL == signal_type) != (CYHAL_EDGE_TYPE_LEVEL == type))
724     {
725         rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
726     }
727 
728     const uint8_t block = obj->resource.block_num;
729     uint8_t trig_index = 0;
730 
731     if(CY_RSLT_SUCCESS == rslt)
732     {
733         #if defined (COMPONENT_CAT5)
734             // Note: Only applicable for Quaddec on this device. Triggers are hardcoded.
735             switch(signal)
736             {
737                 case CYHAL_TCPWM_INPUT_COUNT: /* phiA */
738                     trig_index = 0;
739                     break;
740                 case CYHAL_TCPWM_INPUT_START: /* phiB */
741                     trig_index = 1;
742                     break;
743                 case CYHAL_TCPWM_INPUT_RELOAD: /* index */
744                     trig_index = 2;
745                     break;
746                 default:
747                     rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
748                     break;
749             }
750         #else
751             // Find free input trigger index
752             uint32_t saved_intr_status = cyhal_system_critical_section_enter();
753             for(trig_index = 0; trig_index < (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) ; trig_index++)
754             {
755                 cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
756 
757                 /* On some devices, not all triggers connect uniformly to all sources, so make sure the trigger
758                 * we're trying to use can actually connect to the source we want to use */
759                 rslt = _cyhal_connect_signal(source, dest);
760                 if (rslt == CY_RSLT_SUCCESS)
761                 {
762                     break;
763                 }
764             }
765             cyhal_system_critical_section_exit(saved_intr_status);
766 
767             if(trig_index == (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]))
768             {
769                 rslt = CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS;
770             }
771         #endif
772     }
773 
774     if(CY_RSLT_SUCCESS == rslt)
775     {
776         uint16_t trigger_sig = trig_index + _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)];
777 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
778         const uint8_t chnl = obj->resource.channel_num;
779         // Clear appropriate trigger reg field and set input index and edge trigger type
780         // Note: Input trigger indices 0 and 1 are reserved for constant signals 0
781         // and 1 respectively. The first actual trigger input has index 2.
782         switch(signal)
783         {
784             case CYHAL_TCPWM_INPUT_START:
785                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
786                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_START_SEL, trigger_sig);
787                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_START_EDGE_Msk;
788                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, type);
789                 break;
790             case CYHAL_TCPWM_INPUT_STOP:
791                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
792                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_STOP_SEL, trigger_sig);
793                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_STOP_EDGE_Msk;
794                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, type);
795                 break;
796             case CYHAL_TCPWM_INPUT_RELOAD:
797                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
798                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, trigger_sig);
799                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_RELOAD_EDGE_Msk;
800                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, type);
801                 break;
802             case CYHAL_TCPWM_INPUT_COUNT:
803                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
804                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_COUNT_SEL, trigger_sig);
805                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_COUNT_EDGE_Msk;
806                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, type);
807                 break;
808             case CYHAL_TCPWM_INPUT_CAPTURE:
809                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
810                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, trigger_sig);
811                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE_Msk;
812                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, type);
813                 break;
814            default:
815                 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
816         }
817 
818 #elif (CY_IP_MXTCPWM_VERSION == 2U)
819         // Clear appropriate trigger reg fields and set input index and edge trigger type.
820         // Note: Cy_TCPWM_InputTriggerSetup assumes channel indices for block 0 are
821         // 0-255 and block 1 are 256-511.
822         uint8_t group = _CYHAL_TCPWM_GET_GRP(block);
823         uint32_t counter = _CYHAL_TCPWM_CNT_NUMBER(obj->resource);
824         switch(signal)
825         {
826             case CYHAL_TCPWM_INPUT_START:
827                 TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL_Msk;
828                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_START_EDGE_Msk;
829                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_START, type, trigger_sig);
830                 break;
831             case CYHAL_TCPWM_INPUT_STOP:
832                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL_Msk;
833                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_STOP_EDGE_Msk;
834                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_STOP_OR_KILL, type, trigger_sig);
835                 break;
836             case CYHAL_TCPWM_INPUT_RELOAD:
837                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL_Msk;
838                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_RELOAD_EDGE_Msk;
839                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_RELOAD_OR_INDEX, type, trigger_sig);
840                 break;
841             case CYHAL_TCPWM_INPUT_COUNT:
842                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL_Msk;
843                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_COUNT_EDGE_Msk;
844                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_COUNT, type, trigger_sig);
845                 break;
846             case CYHAL_TCPWM_INPUT_CAPTURE:
847                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL_Msk;
848                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_CAPTURE0_EDGE_Msk;
849                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_CAPTURE0, type, trigger_sig);
850                 break;
851            default:
852                 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
853         }
854 #else
855 #error Unrecognized TCPWM version
856 #endif
857     }
858 
859     if(CY_RSLT_SUCCESS == rslt)
860     {
861         obj->inputs[(uint32_t)signal] = source;
862     }
863     else if((_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) != trig_index)
864     {
865         /* If we made a connection before erroring out later, undo the connection */
866         cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
867         cy_rslt_t disconnect_rslt = _cyhal_disconnect_signal(source, dest);
868         /* Deliberately not impacting the return value, because we're already in an error state. A successful
869          * disconnect won't change that. An unsuccessful disconnect should in theory never happen because if
870          * we got here we made a successful connection above. */
871         CY_ASSERT(CY_RSLT_SUCCESS == disconnect_rslt);
872         CY_UNUSED_PARAMETER(disconnect_rslt); /* Avoid unused variable warning in release builds */
873     }
874 
875     return rslt;
876 #else
877     CY_UNUSED_PARAMETER(obj);
878     CY_UNUSED_PARAMETER(source);
879     CY_UNUSED_PARAMETER(signal);
880     CY_UNUSED_PARAMETER(type);
881 
882     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
883 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
884 }
885 
886 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source)
887 {
888 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
889     const uint8_t block = obj->resource.block_num;
890     const uint8_t chnl = obj->resource.channel_num;
891 
892 // Note that triggers are always generated for TCPWMv1 so this just returns the proper source signal
893 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
894     CY_ASSERT(block < 2);
895 
896     *source = _cyhal_tcpwm_calculate_source(block, chnl, signal);
897 
898     return CY_RSLT_SUCCESS;
899 #elif (CY_IP_MXTCPWM_VERSION == 2U)
900     uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
901 
902     // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
903     // sequentially, not ordered by blocks.
904     uint8_t out_trig_idx = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
905 
906     // Find free trigger, if any
907     int8_t free_trig = -1;
908     uint32_t saved_intr_status = cyhal_system_critical_section_enter();
909     if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 1))
910     {
911         // Output trigger idx 0 is free
912         free_trig = 0;
913         _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 1;
914     }
915     else if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 2))
916     {
917         // Output trigger idx 1 is free
918         free_trig = 1;
919         _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 2;
920     }
921     cyhal_system_critical_section_exit(saved_intr_status);
922 
923     // Configure trigger out registers
924     if(free_trig == 0)
925     {
926         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
927                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
928         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
929                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, event_type);
930     }
931     else if(free_trig == 1)
932     {
933         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
934                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
935         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
936                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, event_type);
937     }
938     else
939         return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
940 
941     *source = _cyhal_tcpwm_calculate_source(out_trig_idx, free_trig);
942 
943     return CY_RSLT_SUCCESS;
944 #else
945 #error Unrecognized TCPWM version
946 #endif
947 #else
948     CY_UNUSED_PARAMETER(obj);
949     CY_UNUSED_PARAMETER(signal);
950     CY_UNUSED_PARAMETER(source);
951     return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
952 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
953 }
954 
955 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal)
956 {
957 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
958     const uint8_t block = obj->resource.block_num;
959     uint8_t trig_index;
960 
961 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
962     const uint8_t chnl = obj->resource.channel_num;
963     switch (signal)
964     {
965         // Grab trig_index then clear/reset to default (CY_TCPWM_INPUT_LEVEL is
966         // default) appropriate ctrl reg fields
967         case CYHAL_TCPWM_INPUT_START:
968             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_START_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
969             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
970             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, CY_TCPWM_INPUT_LEVEL);
971             break;
972         case CYHAL_TCPWM_INPUT_STOP:
973             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_STOP_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
974             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
975             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, CY_TCPWM_INPUT_LEVEL);
976             break;
977         case CYHAL_TCPWM_INPUT_RELOAD:
978             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
979             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
980             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, CY_TCPWM_INPUT_LEVEL);
981             break;
982         case CYHAL_TCPWM_INPUT_COUNT:
983             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_COUNT_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
984             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
985             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, CY_TCPWM_INPUT_LEVEL);
986             break;
987         case CYHAL_TCPWM_INPUT_CAPTURE:
988             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
989             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
990             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, CY_TCPWM_INPUT_LEVEL);
991             break;
992        default:
993             return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
994     }
995 #elif (CY_IP_MXTCPWM_VERSION == 2U)
996     switch(signal)
997     {
998         case CYHAL_TCPWM_INPUT_START:
999             trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL, TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1000                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1001             TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL_Msk;
1002             TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_START_EDGE_Msk;
1003             break;
1004         case CYHAL_TCPWM_INPUT_STOP:
1005             trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1006                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1007             TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL_Msk;
1008             TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_STOP_EDGE_Msk;
1009             break;
1010         case CYHAL_TCPWM_INPUT_RELOAD:
1011             trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1012                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1013             TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL_Msk;
1014             TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_RELOAD_EDGE_Msk;
1015             break;
1016         case CYHAL_TCPWM_INPUT_COUNT:
1017             trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1018                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1019             TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL_Msk;
1020             TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_COUNT_EDGE_Msk;
1021             break;
1022         case CYHAL_TCPWM_INPUT_CAPTURE:
1023             trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1024                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1025             TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL_Msk;
1026             TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_CAPTURE0_EDGE_Msk;
1027             break;
1028        default:
1029             return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1030     }
1031 #else
1032 #error Unrecognized TCPWM version
1033 #endif
1034 
1035     trig_index -= (_CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)]);
1036 
1037     cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
1038 
1039     cy_rslt_t rslt = _cyhal_disconnect_signal(source, dest);
1040     if (CY_RSLT_SUCCESS == rslt)
1041     {
1042         obj->inputs[(uint32_t)signal] = CYHAL_TRIGGER_CPUSS_ZERO;
1043     }
1044     return rslt;
1045 #else
1046     CY_UNUSED_PARAMETER(obj);
1047     CY_UNUSED_PARAMETER(signal);
1048     CY_UNUSED_PARAMETER(source);
1049     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1050 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1051 }
1052 
1053 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal)
1054 {
1055 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
1056 // Triggers are always generated for TCPWMv1 so this is a noop.
1057 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
1058     CY_UNUSED_PARAMETER(obj);
1059     CY_UNUSED_PARAMETER(signal);
1060 
1061     return CY_RSLT_SUCCESS;
1062 #elif (CY_IP_MXTCPWM_VERSION == 2U)
1063     const uint8_t block = obj->resource.block_num;
1064     const uint8_t chnl = obj->resource.channel_num;
1065 
1066     uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
1067 
1068     // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
1069     // sequentially, not ordered by blocks.
1070     uint8_t trig_index = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
1071 
1072     if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1073                 _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1074     {
1075         // Disable output trigger idx 0
1076         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1077                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
1078         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1079                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1080         _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~1;
1081     }
1082     else if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1083                      _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1084     {
1085         // Disable output trigger idx 1
1086         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1087                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
1088         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1089                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1090         _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~2;
1091     }
1092     else
1093         return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1094 
1095     return CY_RSLT_SUCCESS;
1096 #else
1097 #error Unrecognized TCPWM version
1098 #endif
1099 #else
1100     CY_UNUSED_PARAMETER(obj);
1101     CY_UNUSED_PARAMETER(signal);
1102 
1103     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1104 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1105 }
1106 
1107 #if defined(__cplusplus)
1108 }
1109 #endif
1110 
1111 #endif /* _CYHAL_DRIVER_AVAILABLE_TCPWM */
1112