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     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {2};
207     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
208 #elif (CY_IP_MXTCPWM_VERSION == 2U)
209     // Note: These devices also have support for up to 256 trigger lines total,
210     // but only 28 input triggers (on top of the 2 + TCPWM_TR_ONE_CNT_NR) are
211     // currently available, so we only support that to save RAM.
212     #if (CY_IP_MXTCPWM_INSTANCES == 1)
213     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + TCPWM_TR_ONE_CNT_NR)};
214     const uint16_t  _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(TCPWM_TR_ALL_CNT_NR)};
215     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
216     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2] = {(2 + TCPWM0_TR_ONE_CNT_NR), (2 + TCPWM1_TR_ONE_CNT_NR)};
217     const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2] = {(TCPWM0_TR_ALL_CNT_NR), (TCPWM1_TR_ALL_CNT_NR)};
218     #else
219     #warning Unhandled TCPWM instance count
220     #endif
221 #else // (CY_IP_M0S8TCPWM_VERSION == 2)
222     #if defined(CY_DEVICE_PSOC4AS1)
223         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 12)};
224         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 12)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
225     #else
226         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 7)};
227         const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 7)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
228     #endif
229 #endif
230 
231 // Get the the channel relative to the start of the first TCPWM IP block
232 #define _CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel)  ((_CYHAL_TCPWM_DATA[(_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block))].channel_offset) + (channel))
233 
234 #if (CY_IP_MXTCPWM_VERSION == 2)
235     #if (CY_IP_MXTCPWM_INSTANCES == 1)
236         uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM_CHANNELS];
237     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
238         uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS];
239     #else
240         #warning Unhandled TCPWM instance count
241     #endif // (CY_IP_MXTCPWM_INSTANCES == 1 or 2)
242 #endif // (CY_IP_MXTCPWM_VERSION == 2)
243 
244 /** Callback array for TCPWM interrupts */
245 static cyhal_tcpwm_t *_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_CHANNELS];
246 
247 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
_cyhal_tcpwm_pm_has_enabled(void)248 static bool _cyhal_tcpwm_pm_has_enabled(void)
249 {
250     for (uint8_t i = 0; i < _CYHAL_TCPWM_CHANNELS; i++)
251     {
252         if (NULL != _cyhal_tcpwm_data_structs[i])
253         {
254             return true;
255         }
256     }
257     return false;
258 }
259 
260 static bool _cyhal_tcpwm_pm_transition_pending_value = false;
261 
_cyhal_tcpwm_pm_transition_pending(void)262 bool _cyhal_tcpwm_pm_transition_pending(void)
263 {
264     return _cyhal_tcpwm_pm_transition_pending_value;
265 }
266 
_cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)267 static bool _cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
268 {
269     CY_UNUSED_PARAMETER(state);
270     CY_UNUSED_PARAMETER(callback_arg);
271     switch(mode)
272     {
273         case CYHAL_SYSPM_CHECK_FAIL:
274         {
275             _cyhal_tcpwm_pm_transition_pending_value = false;
276             break;
277         }
278         case CYHAL_SYSPM_BEFORE_TRANSITION:
279         {
280             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
281             {
282                 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
283                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
284                 {
285                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
286                     // and the macro would compress it again
287                     if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
288                     {
289                         #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
290                         uint32_t mask = ((uint32_t)1u << j);
291                         if((((TCPWM_Type *)(base))->CTRL) & mask)
292                         {
293                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
294                         }
295                         else
296                         {
297                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
298                         }
299                         #else
300                         if(_FLD2BOOL(TCPWM_GRP_CNT_V2_CTRL_ENABLED, TCPWM_GRP_CNT_CTRL(base, TCPWM_GRP_CNT_GET_GRP(j), j)))
301                         {
302                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
303                         }
304                         else
305                         {
306                             _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
307                         }
308                         #endif
309                     }
310                 }
311             }
312             break;
313         }
314         case CYHAL_SYSPM_AFTER_TRANSITION:
315         {
316             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
317             {
318                 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
319                 uint32_t enable_flag = 0;
320                 #endif
321                 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
322                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
323                 {
324                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
325                     // and the macro would compress it again
326                     if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
327                     {
328 
329                         if(_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state)
330                         {
331                             #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
332                             enable_flag |= 1u << j;
333                             #else
334                             Cy_TCPWM_Enable_Single(base, j);
335                             #endif
336                         }
337                     }
338                 }
339                 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
340                 if (0 != enable_flag)
341                 {
342                     // This only enables the counter. This does not start the timer/counter or the pwm.
343                     Cy_TCPWM_Enable_Multiple(base, enable_flag);
344                 }
345                 #endif
346             }
347             _cyhal_tcpwm_pm_transition_pending_value = false;
348             break;
349         }
350         case CYHAL_SYSPM_CHECK_READY:
351         {
352             for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
353             {
354                 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
355                 {
356                     // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
357                     // and the macro would compress it again
358                     cyhal_tcpwm_t* obj = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j];
359                     if ((NULL != obj) && (CY_TCPWM_PWM_STATUS_COUNTER_RUNNING & Cy_TCPWM_PWM_GetStatus(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource))))
360                     {
361                         return false;
362                     }
363                 }
364             }
365             _cyhal_tcpwm_pm_transition_pending_value = true;
366             break;
367         }
368         default:
369         {
370             CY_ASSERT(false);
371             break;
372         }
373     }
374     return true;
375 }
376 
377 static cyhal_syspm_callback_data_t _cyhal_tcpwm_syspm_callback_data =
378 {
379     .callback = &_cyhal_tcpwm_pm_callback,
380     .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
381     .next = NULL,
382     .args = NULL,
383     .ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION),
384 };
385 
386 #else   /* !(CYHAL_DRIVER_AVAILABLE_SYSPM) */
387 /* If SysPm driver is not available redefine function for TCPWM to return a bad value */
_cyhal_tcpwm_pm_transition_pending(void)388 bool _cyhal_tcpwm_pm_transition_pending(void)
389 {
390     return false;
391 }
392 #endif /* (CYHAL_DRIVER_AVAILABLE_SYSPM) */
393 
_cyhal_tcpwm_init_data(cyhal_tcpwm_t * tcpwm)394 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm)
395 {
396 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
397     for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
398     {
399         tcpwm->inputs[i] = CYHAL_TRIGGER_CPUSS_ZERO;
400     }
401 #endif
402     #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
403     if (!_cyhal_tcpwm_pm_has_enabled())
404     {
405         _cyhal_syspm_register_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
406     }
407     #endif
408     _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(tcpwm->resource.block_num, tcpwm->resource.channel_num)] = tcpwm;
409 }
410 
411 #if defined (COMPONENT_CAT5)
_cyhal_tcpwm_irq_handler(UINT8 group_id,UINT8 counter_id)412 static void _cyhal_tcpwm_irq_handler(UINT8 group_id, UINT8 counter_id)
413 {
414     uint8_t block = group_id;
415     uint8_t channel = counter_id;
416 #else
417 static void _cyhal_tcpwm_irq_handler(void)
418 {
419     _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
420     uint8_t block, channel = 0;
421     // Determine TCPWM block and channel from IRQn
422     for (block = 0; block < _CYHAL_TCPWM_INSTANCES; block++)
423     {
424         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))
425         {
426             channel = (uint8_t)(irqn - _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset);
427             break;
428         }
429     }
430 #endif
431 
432     if (block < _CYHAL_TCPWM_INSTANCES)
433     {
434         TCPWM_Type *blockAddr = _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].base;
435         cyhal_tcpwm_t *tcpwm = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel)];
436         #if (_CYHAL_IRQ_MUXING)
437         /* Disable any interrupts that couldn't be disabled from enable_event */
438         uint32_t saved_intr_status = cyhal_system_critical_section_enter();
439         if(0u != tcpwm->clear_intr_mask)
440         {
441             uint32_t cnt_num = _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource);
442             uint32_t old_mask = Cy_TCPWM_GetInterruptMask(blockAddr, cnt_num);
443             Cy_TCPWM_SetInterruptMask(blockAddr, cnt_num, (old_mask & ~(tcpwm->clear_intr_mask)));
444             tcpwm->clear_intr_mask = 0u;
445         }
446         cyhal_system_critical_section_exit(saved_intr_status);
447         #endif
448         uint32_t intrCause = Cy_TCPWM_GetInterruptStatusMasked(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource));
449         /* The masked status can be 0 if we updated the mask above */
450         if (0u != intrCause && tcpwm->callback_data.callback != NULL)
451         {
452             _cyhal_tcpwm_event_callback_t callback = (_cyhal_tcpwm_event_callback_t) tcpwm->callback_data.callback;
453             /* Call registered callbacks here */
454             (void) (callback) (tcpwm->callback_data.callback_arg, intrCause);
455         }
456 
457         Cy_TCPWM_ClearInterrupt(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource), intrCause);
458 
459         #if defined(COMPONENT_CAT5)
460         // CAT5 interrupt disables itself after firing, re-enable it
461         Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(group_id, counter_id));
462         #endif
463     }
464     else
465     {
466         CY_HALT(); // Could not determine the block/channel for IRQn
467     }
468 }
469 
470 /*******************************************************************************
471 *       TCPWM Shared HAL Functions
472 *******************************************************************************/
473 
474 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj)
475 {
476     CY_ASSERT(NULL != obj);
477 
478     _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);
479     _cyhal_irq_free(irqn);
480 
481     if (NULL != obj->base)
482     {
483         _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(obj->resource.block_num, obj->resource.channel_num)] = NULL;
484         #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
485         if (!_cyhal_tcpwm_pm_has_enabled())
486         {
487             _cyhal_syspm_unregister_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
488         }
489         #endif
490 
491 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
492         for (uint8_t i = 0; i < _CYHAL_TCPWM_OUTPUTS; i++)
493         {
494             _cyhal_tcpwm_disable_output(obj, (cyhal_tcpwm_output_t)i);
495         }
496         for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
497         {
498             if (CYHAL_TRIGGER_CPUSS_ZERO != obj->inputs[i])
499             {
500                 _cyhal_tcpwm_disconnect_digital(obj, obj->inputs[i], (cyhal_tcpwm_input_t)i);
501             }
502         }
503 #endif
504 
505         #if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
506         Cy_TCPWM_Disable_Single(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
507         #else
508         Cy_TCPWM_PWM_Disable(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
509         #endif
510 
511         if(false == obj->owned_by_configurator)
512         {
513             cyhal_hwmgr_free(&(obj->resource));
514         }
515 
516         obj->base = NULL;
517         obj->resource.type = CYHAL_RSC_INVALID;
518     }
519 
520     if (obj->dedicated_clock)
521     {
522         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);
523         cy_rslt_t rslt = _cyhal_utils_peri_pclk_disable_divider(pclk, &(obj->clock));
524         CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
525         CY_ASSERT(CY_RSLT_SUCCESS == rslt);
526         cyhal_clock_free(&(obj->clock));
527         obj->dedicated_clock = false;
528     }
529 }
530 
531 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg)
532 {
533     uint8_t index = _CYHAL_TCPWM_GET_ARRAY_INDEX(resource->block_num, resource->channel_num);
534     uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
535     _cyhal_tcpwm_data_structs[index]->callback_data.callback = callback;
536     _cyhal_tcpwm_data_structs[index]->callback_data.callback_arg = callback_arg;
537     cyhal_system_critical_section_exit(savedIntrStatus);
538 
539     _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);
540     /* Only enable if it's not already enabled */
541     if (false == _cyhal_irq_is_enabled(irqn))
542     {
543         #if defined (COMPONENT_CAT5)
544             Cy_TCPWM_RegisterInterruptCallback(_cyhal_tcpwm_irq_handler);
545             Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(resource->block_num, resource->channel_num));
546         #endif
547 
548         _cyhal_irq_register(irqn, CYHAL_ISR_PRIORITY_DEFAULT, (cy_israddress)_cyhal_tcpwm_irq_handler);
549         _cyhal_irq_enable(irqn);
550     }
551 }
552 
553 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable)
554 {
555     uint32_t old_mask = Cy_TCPWM_GetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource));
556     if (enable)
557     {
558         // Clear any newly enabled events so that old IRQs don't trigger ISRs
559         Cy_TCPWM_ClearInterrupt(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), ~old_mask & event);
560     }
561 #if (_CYHAL_IRQ_MUXING)
562     /* We may be in a critical section. Only clear the interrupt status if there isn't a pending interrupt */
563     if (Cy_TCPWM_GetInterruptStatus(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource)) == 0 || enable)
564 #endif
565     {
566         Cy_TCPWM_SetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), enable ? (old_mask | event) : (old_mask & ~event));
567     }
568 #if (_CYHAL_IRQ_MUXING)
569     else
570     {
571         /* Note that this interrupt cause should be cleared the next time an interrupt is triggered */
572         uint32_t saved_intr_status = cyhal_system_critical_section_enter();
573         tcpwm->clear_intr_mask |= event;
574         cyhal_system_critical_section_exit(saved_intr_status);
575     }
576 #endif
577 
578     _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);
579     _cyhal_irq_set_priority(irqn, intr_priority);
580 }
581 
582 #if (CY_IP_MXTCPWM_VERSION == 2U)
583 static uint8_t _cyhal_tcpwm_convert_output_t(cyhal_tcpwm_output_t signal)
584 {
585     switch(signal)
586     {
587         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
588             return CY_TCPWM_CNT_TRIGGER_ON_OVERFLOW;
589         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
590             return CY_TCPWM_CNT_TRIGGER_ON_UNDEFLOW;
591         case CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT:
592             return CY_TCPWM_CNT_TRIGGER_ON_TC;
593         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
594             return CY_TCPWM_CNT_TRIGGER_ON_CC0_MATCH;
595         case CYHAL_TCPWM_OUTPUT_LINE_OUT:
596             return CY_TCPWM_CNT_TRIGGER_ON_LINE_OUT;
597         default:
598             CY_ASSERT(false);
599             return 0;
600     }
601 }
602 #endif
603 
604 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
605 #if (CY_IP_MXTCPWM_VERSION == 1U) ||(CY_IP_MXTCPWM_VERSION == 2U) || (CY_IP_M0S8TCPWM_VERSION == 2)
606 // Assumes trig_index is not offset by _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET
607 // (that is, it is 0 indexed).
608 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index)
609 {
610 #if (CY_IP_MXTCPWM_VERSION == 1U)
611     if(block == 0)
612     {
613         return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_IN0 + trig_index);
614     }
615     else
616     {
617         CY_ASSERT(block == 1);
618         return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM1_TR_IN0 + trig_index);
619     }
620 #elif (CY_IP_MXTCPWM_VERSION == 2U)
621     #if (CY_IP_MXTCPWM_INSTANCES == 2)
622     return (cyhal_dest_t)(_CYHAL_TCPWM_GET_IP_BLOCK(block) == 0 ? (CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + \
623             trig_index) : (CYHAL_TRIGGER_TCPWM1_TR_ALL_CNT_IN0 + trig_index));
624     #else
625     CY_UNUSED_PARAMETER(block);
626     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + trig_index);
627     #endif
628 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
629     CY_UNUSED_PARAMETER(block);
630 #if defined(CY_DEVICE_PSOC4AS1)
631     CY_ASSERT(block == 0);
632     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN12 + trig_index);
633 #elif defined(CY_DEVICE_PMG1S3) || defined(CY_DEVICE_CCG7S)
634     CY_ASSERT(block == 0);
635     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN8 + trig_index);
636 #else
637     CY_ASSERT(block == 0);
638     return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN7 + trig_index);
639 #endif
640 #endif
641 }
642 #endif
643 
644 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
645 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t block, uint8_t chnl, cyhal_tcpwm_output_t signal)
646 {
647 #if (CY_IP_MXTCPWM_VERSION == 1U)
648     switch(signal)
649     {
650         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
651             return block == 0
652                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
653                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
654         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
655             return block == 0
656                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
657                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
658         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
659             #if defined(COMPONENT_CAT1B)
660             return block == 0
661                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
662                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
663             #else
664             return block == 0
665                 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
666                 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
667             #endif
668        default:
669             // Should never reach here
670             CY_ASSERT(false);
671             return CYHAL_TRIGGER_CPUSS_ZERO;
672     }
673 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
674     CY_UNUSED_PARAMETER(block);
675     switch(signal)
676     {
677         case CYHAL_TCPWM_OUTPUT_OVERFLOW:
678             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
679         case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
680             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
681         case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
682             return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
683        default:
684             // Should never reach here
685             CY_ASSERT(false);
686             return CYHAL_TRIGGER_CPUSS_ZERO;
687     }
688 #endif
689 }
690 #elif (CY_IP_MXTCPWM_VERSION == 2U)
691 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t out_trig_idx, uint8_t free_trig)
692 {
693     // Triggers are ordered by output trig idx, then block, then channel.
694     // Offsetting by out_trig_idx is sufficient to get the correct trigger.
695     if(free_trig == 0)
696     {
697         return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT00 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
698     }
699     else if(free_trig == 1)
700     {
701         return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT10 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
702     }
703     else
704     {
705         // Should never reach here
706         CY_ASSERT(false);
707         return CYHAL_TRIGGER_CPUSS_ZERO;
708     }
709 }
710 #endif
711 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
712 
713 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)
714 {
715 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
716     cy_rslt_t rslt = CY_RSLT_SUCCESS;
717     cyhal_signal_type_t signal_type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
718     if((CYHAL_SIGNAL_TYPE_LEVEL == signal_type) != (CYHAL_EDGE_TYPE_LEVEL == type))
719     {
720         rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
721     }
722 
723     const uint8_t block = obj->resource.block_num;
724     uint8_t trig_index = 0;
725 
726     if(CY_RSLT_SUCCESS == rslt)
727     {
728         #if defined (COMPONENT_CAT5)
729             // Note: Only applicable for Quaddec on this device. Triggers are hardcoded.
730             switch(signal)
731             {
732                 case CYHAL_TCPWM_INPUT_COUNT: /* phiA */
733                     trig_index = 0;
734                     break;
735                 case CYHAL_TCPWM_INPUT_START: /* phiB */
736                     trig_index = 1;
737                     break;
738                 case CYHAL_TCPWM_INPUT_RELOAD: /* index */
739                     trig_index = 2;
740                     break;
741                 default:
742                     rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
743                     break;
744             }
745         #else
746             // Find free input trigger index
747             uint32_t saved_intr_status = cyhal_system_critical_section_enter();
748             for(trig_index = 0; trig_index < (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) ; trig_index++)
749             {
750                 cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
751 
752                 /* On some devices, not all triggers connect uniformly to all sources, so make sure the trigger
753                 * we're trying to use can actually connect to the source we want to use */
754                 rslt = _cyhal_connect_signal(source, dest);
755                 if (rslt == CY_RSLT_SUCCESS)
756                 {
757                     break;
758                 }
759             }
760             cyhal_system_critical_section_exit(saved_intr_status);
761 
762             if(trig_index == (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]))
763             {
764                 rslt = CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS;
765             }
766         #endif
767     }
768 
769     if(CY_RSLT_SUCCESS == rslt)
770     {
771         uint16_t trigger_sig = trig_index + _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)];
772 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
773         const uint8_t chnl = obj->resource.channel_num;
774         // Clear appropriate trigger reg field and set input index and edge trigger type
775         // Note: Input trigger indices 0 and 1 are reserved for constant signals 0
776         // and 1 respectively. The first actual trigger input has index 2.
777         switch(signal)
778         {
779             case CYHAL_TCPWM_INPUT_START:
780                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
781                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_START_SEL, trigger_sig);
782                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_START_EDGE_Msk;
783                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, type);
784                 break;
785             case CYHAL_TCPWM_INPUT_STOP:
786                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
787                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_STOP_SEL, trigger_sig);
788                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_STOP_EDGE_Msk;
789                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, type);
790                 break;
791             case CYHAL_TCPWM_INPUT_RELOAD:
792                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
793                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, trigger_sig);
794                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_RELOAD_EDGE_Msk;
795                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, type);
796                 break;
797             case CYHAL_TCPWM_INPUT_COUNT:
798                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
799                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_COUNT_SEL, trigger_sig);
800                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_COUNT_EDGE_Msk;
801                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, type);
802                 break;
803             case CYHAL_TCPWM_INPUT_CAPTURE:
804                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
805                 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, trigger_sig);
806                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE_Msk;
807                 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, type);
808                 break;
809            default:
810                 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
811         }
812 
813 #elif (CY_IP_MXTCPWM_VERSION == 2U)
814         // Clear appropriate trigger reg fields and set input index and edge trigger type.
815         // Note: Cy_TCPWM_InputTriggerSetup assumes channel indices for block 0 are
816         // 0-255 and block 1 are 256-511.
817         uint8_t group = _CYHAL_TCPWM_GET_GRP(block);
818         uint32_t counter = _CYHAL_TCPWM_CNT_NUMBER(obj->resource);
819         switch(signal)
820         {
821             case CYHAL_TCPWM_INPUT_START:
822                 TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL_Msk;
823                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_START_EDGE_Msk;
824                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_START, type, trigger_sig);
825                 break;
826             case CYHAL_TCPWM_INPUT_STOP:
827                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL_Msk;
828                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_STOP_EDGE_Msk;
829                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_STOP_OR_KILL, type, trigger_sig);
830                 break;
831             case CYHAL_TCPWM_INPUT_RELOAD:
832                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL_Msk;
833                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_RELOAD_EDGE_Msk;
834                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_RELOAD_OR_INDEX, type, trigger_sig);
835                 break;
836             case CYHAL_TCPWM_INPUT_COUNT:
837                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL_Msk;
838                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_COUNT_EDGE_Msk;
839                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_COUNT, type, trigger_sig);
840                 break;
841             case CYHAL_TCPWM_INPUT_CAPTURE:
842                 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL_Msk;
843                 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_CAPTURE0_EDGE_Msk;
844                 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_CAPTURE0, type, trigger_sig);
845                 break;
846            default:
847                 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
848         }
849 #else
850 #error Unrecognized TCPWM version
851 #endif
852     }
853 
854     if(CY_RSLT_SUCCESS == rslt)
855     {
856         obj->inputs[(uint32_t)signal] = source;
857     }
858     else if((_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) != trig_index)
859     {
860         /* If we made a connection before erroring out later, undo the connection */
861         cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
862         cy_rslt_t disconnect_rslt = _cyhal_disconnect_signal(source, dest);
863         /* Deliberately not impacting the return value, because we're already in an error state. A successful
864          * disconnect won't change that. An unsuccessful disconnect should in theory never happen because if
865          * we got here we made a successful connection above. */
866         CY_ASSERT(CY_RSLT_SUCCESS == disconnect_rslt);
867         CY_UNUSED_PARAMETER(disconnect_rslt); /* Avoid unused variable warning in release builds */
868     }
869 
870     return rslt;
871 #else
872     CY_UNUSED_PARAMETER(obj);
873     CY_UNUSED_PARAMETER(source);
874     CY_UNUSED_PARAMETER(signal);
875     CY_UNUSED_PARAMETER(type);
876 
877     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
878 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
879 }
880 
881 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source)
882 {
883 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
884     const uint8_t block = obj->resource.block_num;
885     const uint8_t chnl = obj->resource.channel_num;
886 
887 // Note that triggers are always generated for TCPWMv1 so this just returns the proper source signal
888 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
889     CY_ASSERT(block < 2);
890 
891     *source = _cyhal_tcpwm_calculate_source(block, chnl, signal);
892 
893     return CY_RSLT_SUCCESS;
894 #elif (CY_IP_MXTCPWM_VERSION == 2U)
895     uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
896 
897     // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
898     // sequentially, not ordered by blocks.
899     uint8_t out_trig_idx = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
900 
901     // Find free trigger, if any
902     int8_t free_trig = -1;
903     uint32_t saved_intr_status = cyhal_system_critical_section_enter();
904     if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 1))
905     {
906         // Output trigger idx 0 is free
907         free_trig = 0;
908         _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 1;
909     }
910     else if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 2))
911     {
912         // Output trigger idx 1 is free
913         free_trig = 1;
914         _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 2;
915     }
916     cyhal_system_critical_section_exit(saved_intr_status);
917 
918     // Configure trigger out registers
919     if(free_trig == 0)
920     {
921         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
922                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
923         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
924                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, event_type);
925     }
926     else if(free_trig == 1)
927     {
928         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
929                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
930         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
931                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, event_type);
932     }
933     else
934         return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
935 
936     *source = _cyhal_tcpwm_calculate_source(out_trig_idx, free_trig);
937 
938     return CY_RSLT_SUCCESS;
939 #else
940 #error Unrecognized TCPWM version
941 #endif
942 #else
943     CY_UNUSED_PARAMETER(obj);
944     CY_UNUSED_PARAMETER(signal);
945     CY_UNUSED_PARAMETER(source);
946     return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
947 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
948 }
949 
950 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal)
951 {
952 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
953     const uint8_t block = obj->resource.block_num;
954     uint8_t trig_index;
955 
956 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
957     const uint8_t chnl = obj->resource.channel_num;
958     switch (signal)
959     {
960         // Grab trig_index then clear/reset to default (CY_TCPWM_INPUT_LEVEL is
961         // default) appropriate ctrl reg fields
962         case CYHAL_TCPWM_INPUT_START:
963             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_START_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
964             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
965             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, CY_TCPWM_INPUT_LEVEL);
966             break;
967         case CYHAL_TCPWM_INPUT_STOP:
968             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_STOP_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
969             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
970             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, CY_TCPWM_INPUT_LEVEL);
971             break;
972         case CYHAL_TCPWM_INPUT_RELOAD:
973             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
974             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
975             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, CY_TCPWM_INPUT_LEVEL);
976             break;
977         case CYHAL_TCPWM_INPUT_COUNT:
978             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_COUNT_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
979             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
980             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, CY_TCPWM_INPUT_LEVEL);
981             break;
982         case CYHAL_TCPWM_INPUT_CAPTURE:
983             trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
984             TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
985             TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, CY_TCPWM_INPUT_LEVEL);
986             break;
987        default:
988             return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
989     }
990 #elif (CY_IP_MXTCPWM_VERSION == 2U)
991     switch(signal)
992     {
993         case CYHAL_TCPWM_INPUT_START:
994             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), \
995                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
996             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;
997             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;
998             break;
999         case CYHAL_TCPWM_INPUT_STOP:
1000             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), \
1001                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1002             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;
1003             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;
1004             break;
1005         case CYHAL_TCPWM_INPUT_RELOAD:
1006             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), \
1007                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1008             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;
1009             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;
1010             break;
1011         case CYHAL_TCPWM_INPUT_COUNT:
1012             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), \
1013                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1014             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;
1015             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;
1016             break;
1017         case CYHAL_TCPWM_INPUT_CAPTURE:
1018             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), \
1019                                   _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1020             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;
1021             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;
1022             break;
1023        default:
1024             return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1025     }
1026 #else
1027 #error Unrecognized TCPWM version
1028 #endif
1029 
1030     trig_index -= (_CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)]);
1031 
1032     cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
1033 
1034     cy_rslt_t rslt = _cyhal_disconnect_signal(source, dest);
1035     if (CY_RSLT_SUCCESS == rslt)
1036     {
1037         obj->inputs[(uint32_t)signal] = CYHAL_TRIGGER_CPUSS_ZERO;
1038     }
1039     return rslt;
1040 #else
1041     CY_UNUSED_PARAMETER(obj);
1042     CY_UNUSED_PARAMETER(signal);
1043     CY_UNUSED_PARAMETER(source);
1044     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1045 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1046 }
1047 
1048 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal)
1049 {
1050 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
1051 // Triggers are always generated for TCPWMv1 so this is a noop.
1052 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
1053     CY_UNUSED_PARAMETER(obj);
1054     CY_UNUSED_PARAMETER(signal);
1055 
1056     return CY_RSLT_SUCCESS;
1057 #elif (CY_IP_MXTCPWM_VERSION == 2U)
1058     const uint8_t block = obj->resource.block_num;
1059     const uint8_t chnl = obj->resource.channel_num;
1060 
1061     uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
1062 
1063     // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
1064     // sequentially, not ordered by blocks.
1065     uint8_t trig_index = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
1066 
1067     if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1068                 _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1069     {
1070         // Disable output trigger idx 0
1071         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1072                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
1073         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1074                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1075         _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~1;
1076     }
1077     else if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1078                      _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1079     {
1080         // Disable output trigger idx 1
1081         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1082                                  &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
1083         TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1084                                  |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1085         _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~2;
1086     }
1087     else
1088         return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1089 
1090     return CY_RSLT_SUCCESS;
1091 #else
1092 #error Unrecognized TCPWM version
1093 #endif
1094 #else
1095     CY_UNUSED_PARAMETER(obj);
1096     CY_UNUSED_PARAMETER(signal);
1097 
1098     return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1099 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1100 }
1101 
1102 #if defined(__cplusplus)
1103 }
1104 #endif
1105 
1106 #endif /* _CYHAL_DRIVER_AVAILABLE_TCPWM */
1107