1 /***************************************************************************//**
2 * \file cyhal_scb_common.c
3 *
4 * \brief
5 * Provides a struct definitions for configuration resources in the SCB (UART, I2C, SPI).
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_scb_common.h"
28 #include "cyhal_hwmgr.h"
29 #include "cyhal_syspm.h"
30 #include "cyhal_clock.h"
31 #include "cyhal_interconnect.h"
32 #include "cyhal_peri_common.h"
33 
34 #if (_CYHAL_DRIVER_AVAILABLE_SCB)
35 
36 #if defined(__cplusplus)
37 extern "C"
38 {
39 #endif
40 
41 const uint32_t _CYHAL_SCB_AVAILABLE_BLOCKS_MASK =
42 {
43 #ifdef SCB0
44     1 << 0u
45 #endif
46 #ifdef SCB1
47     | 1 << 1u
48 #endif
49 #ifdef SCB2
50     | 1 << 2u
51 #endif
52 #ifdef SCB3
53     | 1 << 3u
54 #endif
55 #ifdef SCB4
56     | 1 << 4u
57 #endif
58 #ifdef SCB5
59     | 1 << 5u
60 #endif
61 #ifdef SCB6
62     | 1 << 6u
63 #endif
64 #ifdef SCB7
65     | 1 << 7u
66 #endif
67 #ifdef SCB8
68     | 1 << 8u
69 #endif
70 #ifdef SCB9
71     | 1 << 9u
72 #endif
73 #ifdef SCB10
74     | 1 << 10u
75 #endif
76 #ifdef SCB11
77     | 1 << 11u
78 #endif
79 #ifdef SCB12
80     | 1 << 12u
81 #endif
82 #ifdef SCB13
83     | 1 << 13u
84 #endif
85 #ifdef SCB14
86     | 1 << 14u
87 #endif
88 #ifdef SCB15
89     | 1 << 15u
90 #endif
91 };
92 
93 const uint8_t _CYHAL_SCB_BASE_ADDRESS_INDEX[_SCB_ARRAY_SIZE] =
94 {
95 #ifdef SCB0
96     0u,
97 #endif
98 #ifdef SCB1
99     1u,
100 #endif
101 #ifdef SCB2
102     2u,
103 #endif
104 #ifdef SCB3
105     3u,
106 #endif
107 #ifdef SCB4
108     4u,
109 #endif
110 #ifdef SCB5
111     5u,
112 #endif
113 #ifdef SCB6
114     6u,
115 #endif
116 #ifdef SCB7
117     7u,
118 #endif
119 #ifdef SCB8
120     8u,
121 #endif
122 #ifdef SCB9
123     9u,
124 #endif
125 #ifdef SCB10
126     10u,
127 #endif
128 #ifdef SCB11
129     11u,
130 #endif
131 #ifdef SCB12
132     12u,
133 #endif
134 #ifdef SCB13
135     13u,
136 #endif
137 #ifdef SCB14
138     14u,
139 #endif
140 #ifdef SCB15
141     15u,
142 #endif
143 };
144 
145 CySCB_Type* const _CYHAL_SCB_BASE_ADDRESSES[_SCB_ARRAY_SIZE] =
146 {
147 #ifdef SCB0
148     SCB0,
149 #endif
150 #ifdef SCB1
151     SCB1,
152 #endif
153 #ifdef SCB2
154     SCB2,
155 #endif
156 #ifdef SCB3
157     SCB3,
158 #endif
159 #ifdef SCB4
160     SCB4,
161 #endif
162 #ifdef SCB5
163     SCB5,
164 #endif
165 #ifdef SCB6
166     SCB6,
167 #endif
168 #ifdef SCB7
169     SCB7,
170 #endif
171 #ifdef SCB8
172     SCB8,
173 #endif
174 #ifdef SCB9
175     SCB9,
176 #endif
177 #ifdef SCB10
178     SCB10,
179 #endif
180 #ifdef SCB11
181     SCB11,
182 #endif
183 #ifdef SCB12
184     SCB12,
185 #endif
186 #ifdef SCB13
187     SCB13,
188 #endif
189 #ifdef SCB14
190     SCB14,
191 #endif
192 #ifdef SCB15
193     SCB15,
194 #endif
195 };
196 
197 const _cyhal_system_irq_t _CYHAL_SCB_IRQ_N[_SCB_ARRAY_SIZE] =
198 {
199 #ifdef SCB0
200     scb_0_interrupt_IRQn,
201 #endif
202 #ifdef SCB1
203     scb_1_interrupt_IRQn,
204 #endif
205 #ifdef SCB2
206     scb_2_interrupt_IRQn,
207 #endif
208 #ifdef SCB3
209     scb_3_interrupt_IRQn,
210 #endif
211 #ifdef SCB4
212     scb_4_interrupt_IRQn,
213 #endif
214 #ifdef SCB5
215     scb_5_interrupt_IRQn,
216 #endif
217 #ifdef SCB6
218     scb_6_interrupt_IRQn,
219 #endif
220 #ifdef SCB7
221     scb_7_interrupt_IRQn,
222 #endif
223 #ifdef SCB8
224     scb_8_interrupt_IRQn,
225 #endif
226 #ifdef SCB9
227     scb_9_interrupt_IRQn,
228 #endif
229 #ifdef SCB10
230     scb_10_interrupt_IRQn,
231 #endif
232 #ifdef SCB11
233     scb_11_interrupt_IRQn,
234 #endif
235 #ifdef SCB12
236     scb_12_interrupt_IRQn,
237 #endif
238 #ifdef SCB13
239     scb_13_interrupt_IRQn,
240 #endif
241 #ifdef SCB14
242     scb_14_interrupt_IRQn,
243 #endif
244 #ifdef SCB15
245     scb_15_interrupt_IRQn,
246 #endif
247 };
248 
249 /** The configuration structs for the resource in use on each SCB block */
250 static void *_cyhal_scb_config_structs[_SCB_ARRAY_SIZE];
251 /** The callback to use for each scb instance */
252 static bool (*_cyhal_scb_config_pm_callback[_SCB_ARRAY_SIZE]) (void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode);
253 
_cyhal_scb_get_block_from_irqn(_cyhal_system_irq_t irqn)254 static uint8_t _cyhal_scb_get_block_from_irqn(_cyhal_system_irq_t irqn)
255 {
256     uint8_t scb_block_num = 0;
257     switch (irqn)
258     {
259     #ifdef SCB0
260         case scb_0_interrupt_IRQn:
261             scb_block_num = 0;
262             break;
263     #endif
264     #ifdef SCB1
265         case scb_1_interrupt_IRQn:
266             scb_block_num = 1;
267             break;
268     #endif
269     #ifdef SCB2
270         case scb_2_interrupt_IRQn:
271             scb_block_num = 2;
272             break;
273     #endif
274     #ifdef SCB3
275         case scb_3_interrupt_IRQn:
276             scb_block_num = 3;
277             break;
278     #endif
279     #ifdef SCB4
280         case scb_4_interrupt_IRQn:
281             scb_block_num = 4;
282             break;
283     #endif
284     #ifdef SCB5
285         case scb_5_interrupt_IRQn:
286             scb_block_num = 5;
287             break;
288     #endif
289     #ifdef SCB6
290         case scb_6_interrupt_IRQn:
291             scb_block_num = 6;
292             break;
293     #endif
294     #ifdef SCB7
295         case scb_7_interrupt_IRQn:
296             scb_block_num = 7;
297             break;
298     #endif
299     #ifdef SCB8
300         case scb_8_interrupt_IRQn:
301             scb_block_num = 8;
302             break;
303     #endif
304     #ifdef SCB9
305         case scb_9_interrupt_IRQn:
306             scb_block_num = 9;
307             break;
308     #endif
309     #ifdef SCB10
310         case scb_10_interrupt_IRQn:
311             scb_block_num = 10;
312             break;
313     #endif
314     #ifdef SCB11
315         case scb_11_interrupt_IRQn:
316             scb_block_num = 11;
317             break;
318     #endif
319     #ifdef SCB12
320         case scb_12_interrupt_IRQn:
321             scb_block_num = 12;
322             break;
323     #endif
324     #ifdef SCB13
325         case scb_13_interrupt_IRQn:
326             scb_block_num = 13;
327             break;
328     #endif
329     #ifdef SCB14
330         case scb_14_interrupt_IRQn:
331             scb_block_num = 14;
332             break;
333     #endif
334     #ifdef SCB15
335         case scb_15_interrupt_IRQn:
336             scb_block_num = 15;
337             break;
338     #endif
339     #if (_SCB_ARRAY_SIZE > 16)
340     #error "Unhandled scb count"
341     #endif
342         default:
343             CY_ASSERT(false); // Should never be called with a non-SCB IRQn
344             scb_block_num = _CYHAL_SCB_BLOCK_ID_INVALID;
345     }
346 
347     return _cyhal_scb_get_block_index(scb_block_num);
348 }
349 
_cyhal_scb_get_block_index(uint8_t scb_block_num)350 uint8_t _cyhal_scb_get_block_index(uint8_t scb_block_num)
351 {
352     uint8_t arr_index = _CYHAL_SCB_BLOCK_ID_INVALID;
353     for (uint8_t instance_idx = 0; instance_idx < _SCB_ARRAY_SIZE; instance_idx++)
354     {
355         if (_CYHAL_SCB_BASE_ADDRESS_INDEX[instance_idx] == scb_block_num)
356         {
357             arr_index = instance_idx;
358             break;
359         }
360     }
361     return arr_index;
362 }
363 
364 #if defined (COMPONENT_CAT5)
_cyhal_scb_get_irq_obj(_cyhal_system_irq_t irqn)365 void *_cyhal_scb_get_irq_obj(_cyhal_system_irq_t irqn)
366 {
367     uint8_t block = _cyhal_scb_get_block_from_irqn(irqn);
368     return _cyhal_scb_config_structs[block];
369 }
370 #else
_cyhal_scb_get_irq_obj(void)371 void *_cyhal_scb_get_irq_obj(void)
372 {
373     _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
374     if ((_cyhal_system_irq_t)unconnected_IRQn == irqn)
375     {
376         return NULL;
377     }
378     else
379     {
380         uint8_t block = _cyhal_scb_get_block_from_irqn(irqn);
381         return _cyhal_scb_config_structs[block];
382     }
383 }
384 #endif
385 
386 /* Peripheral clock values for different I2C speeds according PDL API Reference Guide */
387 #if defined(COMPONENT_CAT1D)
388     /* Must be between 1.55 MHz and 12.8 MHz for running i2c master at 100KHz   */
389     #define _CYHAL_SCB_PERI_CLOCK_SLAVE_STD      6000000
390     /* Must be between 7.82 MHz and 15.38 MHz for running i2c master at 400KHz  */
391     #define _CYHAL_SCB_PERI_CLOCK_SLAVE_FST      12000000
392 #else
393     /* Must be between 1.55 MHz and 12.8 MHz for running i2c master at 100KHz   */
394     #define _CYHAL_SCB_PERI_CLOCK_SLAVE_STD      8000000
395     /* Must be between 7.82 MHz and 15.38 MHz for running i2c master at 400KHz  */
396     #define _CYHAL_SCB_PERI_CLOCK_SLAVE_FST      12500000
397 #endif /* defined(COMPONENT_CAT1D) */
398 
399 
400 /* Must be between 15.84 MHz and 89.0 MHz for running i2c master at 1MHz */
401 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
402 #define _CYHAL_SCB_PERI_CLOCK_SLAVE_FSTP     50000000
403 #elif defined(COMPONENT_CAT2)
404 #define _CYHAL_SCB_PERI_CLOCK_SLAVE_FSTP     24000000
405 #elif defined(COMPONENT_CAT5)
406 #define _CYHAL_SCB_PERI_CLOCK_SLAVE_FSTP     96000000
407 #endif
408 
409 /* Must be between 1.55 MHz and 3.2 MHz for running i2c slave at 100KHz     */
410 #define _CYHAL_SCB_PERI_CLOCK_MASTER_STD     2000000
411 /* Must be between 7.82 MHz and 10 MHz for running i2c slave at 400KHz      */
412 #define _CYHAL_SCB_PERI_CLOCK_MASTER_FST     8500000
413 /* Must be between 14.32 MHz and 25.8 MHz for running i2c slave at 1MHz  */
414 #define _CYHAL_SCB_PERI_CLOCK_MASTER_FSTP    20000000
415 
416 #if !defined(COMPONENT_CAT5)
_cyhal_scb_configure_peri_clock(cyhal_clock_t * clock,const cyhal_resource_inst_t * resource,uint32_t freq,bool is_clock_owned)417 static cy_rslt_t _cyhal_scb_configure_peri_clock(cyhal_clock_t *clock, const cyhal_resource_inst_t *resource, uint32_t freq, bool is_clock_owned)
418 {
419     cy_rslt_t result = CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
420     cyhal_clock_block_t clk_type = (cyhal_clock_block_t)_CYHAL_PERIPHERAL_GROUP_GET_DIVIDER_TYPE(clock->block);
421 
422     const cyhal_clock_block_t PERI_DIVIDERS[] =
423     {
424         CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT,
425         CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT,
426         CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT,
427         CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT
428     };
429 
430     const cyhal_clock_tolerance_t tolerance = {
431         .type = CYHAL_TOLERANCE_PERCENT,
432         .value = 5
433     };
434 
435     if (freq == 0)
436     {
437         return CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
438     }
439     else if (is_clock_owned)
440     {
441         for (uint8_t i = 0; i < sizeof(PERI_DIVIDERS)/sizeof(cyhal_clock_block_t); i++)
442         {
443             if (PERI_DIVIDERS[i] < clk_type)
444             {
445                 continue;
446             }
447             else if (PERI_DIVIDERS[i] > clk_type)
448             {
449                 result = _cyhal_utils_allocate_clock(clock, resource, PERI_DIVIDERS[i], true);
450             }
451             else
452             {
453                 result = CY_RSLT_SUCCESS;
454             }
455 
456             if (CY_RSLT_SUCCESS == result)
457             {
458                 result = cyhal_clock_set_frequency(clock, freq, &tolerance);
459                 if (CY_RSLT_SUCCESS != result)
460                 {
461                     cyhal_clock_free(clock);
462                 }
463                 else
464                 {
465                     break;
466                 }
467 
468             }
469         }
470     }
471     else
472     {
473         result = CY_RSLT_SUCCESS;
474     }
475     return result;
476 }
477 #endif /* !defined(COMPONENT_CAT5) */
478 
_cyhal_i2c_set_peri_divider(void * obj,bool is_i2c,uint32_t freq,bool is_slave)479 uint32_t _cyhal_i2c_set_peri_divider(void *obj, bool is_i2c, uint32_t freq, bool is_slave)
480 {
481     CySCB_Type *base = is_i2c ? ((cyhal_i2c_t *)obj)->base : ((cyhal_ezi2c_t *)obj)->base;
482     uint32_t block_num = is_i2c ? ((cyhal_i2c_t *)obj)->resource.block_num : ((cyhal_ezi2c_t *)obj)->resource.block_num;
483     cyhal_clock_t *clock = is_i2c ? &(((cyhal_i2c_t *)obj)->clock) : &(((cyhal_ezi2c_t *)obj)->clock);
484     bool is_clock_owned = is_i2c ? ((cyhal_i2c_t *)obj)->is_clock_owned : ((cyhal_ezi2c_t *)obj)->is_clock_owned;
485 
486     /* Return the actual data rate on success, 0 otherwise */
487     uint32_t data_rate = 0;
488     uint32_t peri_freq = 0;
489     if (freq != 0)
490     {
491         if (freq <= CY_SCB_I2C_STD_DATA_RATE)
492         {
493             peri_freq = is_slave ? _CYHAL_SCB_PERI_CLOCK_SLAVE_STD : _CYHAL_SCB_PERI_CLOCK_MASTER_STD;
494         }
495         else if (freq <= CY_SCB_I2C_FST_DATA_RATE)
496         {
497             peri_freq = is_slave ? _CYHAL_SCB_PERI_CLOCK_SLAVE_FST : _CYHAL_SCB_PERI_CLOCK_MASTER_FST;
498         }
499         else if (freq <= CY_SCB_I2C_FSTP_DATA_RATE)
500         {
501             peri_freq = is_slave ? _CYHAL_SCB_PERI_CLOCK_SLAVE_FSTP : _CYHAL_SCB_PERI_CLOCK_MASTER_FSTP;
502         }
503 
504     #if !defined(COMPONENT_CAT5)
505         cyhal_resource_inst_t *resource = is_i2c ? &(((cyhal_i2c_t *)obj)->resource) : &(((cyhal_ezi2c_t *)obj)->resource);
506         cy_rslt_t status = _cyhal_scb_configure_peri_clock(clock, resource, peri_freq, is_clock_owned);
507     #else
508         cy_rslt_t status = CY_RSLT_SUCCESS;
509     #endif /* !defined(COMPONENT_CAT5) */
510 
511         if ((CY_RSLT_SUCCESS == status) && (peri_freq > 0) && _cyhal_utils_peri_pclk_assign_divider(
512             _cyhal_scb_get_clock_index(block_num), clock) == CY_SYSCLK_SUCCESS)
513         {
514             if (is_clock_owned)
515             {
516                 status = cyhal_clock_set_enabled(clock, false, false);
517                 if (status == CY_RSLT_SUCCESS)
518                 {
519                     status = cyhal_clock_set_frequency(clock, peri_freq, NULL);
520                 }
521                 if (status == CY_RSLT_SUCCESS)
522                 {
523                     status = cyhal_clock_set_enabled(clock, true, false);
524                 }
525             }
526 
527             if(status == CY_RSLT_SUCCESS)
528             {
529                 data_rate = (is_slave)
530                     ? Cy_SCB_I2C_GetDataRate(base, cyhal_clock_get_frequency(clock))
531                     : Cy_SCB_I2C_SetDataRate(base, freq, cyhal_clock_get_frequency(clock));
532             }
533         }
534     }
535     return data_rate;
536 }
537 
_cyhal_scb_find_map(cyhal_gpio_t pin,const cyhal_resource_pin_mapping_t * pin_map,size_t count,const cyhal_resource_inst_t * block_res)538 const cyhal_resource_pin_mapping_t* _cyhal_scb_find_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map,
539         size_t count, const cyhal_resource_inst_t *block_res)
540 {
541     for (size_t i = 0; i < count; i++)
542     {
543         if (pin == pin_map[i].pin)
544         {
545             /* Block is already found, check if certain pin can work for provided block  */
546             if ((NULL != block_res) && (CYHAL_RSC_SCB == block_res->type))
547             {
548                 if (_cyhal_utils_map_resource_equal(block_res, &(pin_map[i]), false))
549                 {
550                     return &pin_map[i];
551                 }
552             }
553             /* No block provided */
554             else
555             {
556                 cyhal_resource_inst_t rsc = { CYHAL_RSC_SCB, pin_map[i].block_num, pin_map[i].channel_num };
557                 if (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&rsc))
558                 {
559                     cyhal_hwmgr_free(&rsc);
560                     return &pin_map[i];
561                 }
562             }
563         }
564     }
565     return NULL;
566 }
567 
_cyhal_scb_check_pin_affiliation(cyhal_gpio_t pin,const cyhal_resource_pin_mapping_t * pin_map,size_t count)568 uint32_t _cyhal_scb_check_pin_affiliation(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map,
569         size_t count)
570 {
571     uint32_t bitband_blocks = 0;
572     for (size_t i = 0; i < count; i++)
573     {
574         if (pin == pin_map[i].pin)
575         {
576             uint8_t scb_arr_index = _cyhal_scb_get_block_index(pin_map[i].block_num);
577             cyhal_resource_inst_t rsc = { CYHAL_RSC_SCB, scb_arr_index, pin_map[i].channel_num };
578             if (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&rsc))
579             {
580                 cyhal_hwmgr_free(&rsc);
581                 bitband_blocks |= 1 << pin_map[i].block_num;
582             }
583         }
584     }
585     return bitband_blocks;
586 }
587 
_cyhal_scb_set_fifo_level(CySCB_Type * base,cyhal_scb_fifo_type_t type,uint16_t level)588 cy_rslt_t _cyhal_scb_set_fifo_level(CySCB_Type *base, cyhal_scb_fifo_type_t type, uint16_t level)
589 {
590     if(!CY_SCB_IS_TRIGGER_LEVEL_VALID(base, level))
591         return CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
592 
593     if(type == CYHAL_SCB_FIFO_RX)
594     {
595         SCB_RX_FIFO_CTRL(base) &= ~SCB_RX_FIFO_CTRL_TRIGGER_LEVEL_Msk;
596         SCB_RX_FIFO_CTRL(base) |= _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, level);
597 
598         return CY_RSLT_SUCCESS;
599     }
600     else if(type == CYHAL_SCB_FIFO_TX)
601     {
602         SCB_TX_FIFO_CTRL(base) &= ~SCB_TX_FIFO_CTRL_TRIGGER_LEVEL_Msk;
603         SCB_TX_FIFO_CTRL(base) |= _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, level);
604 
605         return CY_RSLT_SUCCESS;
606     }
607 
608     return CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
609 }
610 
_cyhal_scb_enable_output(cyhal_resource_inst_t resource,cyhal_scb_output_t output,cyhal_source_t * source)611 cy_rslt_t _cyhal_scb_enable_output(cyhal_resource_inst_t resource, cyhal_scb_output_t output, cyhal_source_t *source)
612 {
613 // All PSoC™ 6 devices have scb triggers but not all PSoC™ 4 devices do
614 #if ((defined(CY_IP_MXSCB) && !defined(COMPONENT_CAT2)) || defined(CY_DEVICE_PSOC4AMC) || defined(CY_DEVICE_PSOC4AS3) || defined(CY_DEVICE_PSOC4AS4) || defined(CY_IP_MXS22SCB))
615     // This just returns a proper cyhal_source_t. Use _cyhal_scb_set_fifo_level
616     // to actually set level.
617     cyhal_internal_source_t src_int;
618     uint8_t scb_arr_index = _cyhal_scb_get_block_index(resource.block_num);
619     if(output == CYHAL_SCB_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED)
620     {
621         src_int = (cyhal_internal_source_t)(_CYHAL_TRIGGER_SCB0_TR_RX_REQ + scb_arr_index);
622         *source = (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(src_int, CYHAL_SIGNAL_TYPE_LEVEL);
623         return CY_RSLT_SUCCESS;
624     }
625     // This just returns a proper cyhal_source_t. Use _cyhal_scb_set_fifo_level
626     // to actually set level.
627     else if(output == CYHAL_SCB_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED)
628     {
629         src_int = (cyhal_internal_source_t)(_CYHAL_TRIGGER_SCB0_TR_TX_REQ + scb_arr_index);
630         *source = (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(src_int, CYHAL_SIGNAL_TYPE_LEVEL);
631         return CY_RSLT_SUCCESS;
632     }
633 
634     return CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
635 #else
636     CY_UNUSED_PARAMETER(resource);
637     CY_UNUSED_PARAMETER(output);
638     CY_UNUSED_PARAMETER(source);
639     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
640 #endif
641 }
642 
_cyhal_scb_disable_output(cyhal_scb_output_t output)643 cy_rslt_t _cyhal_scb_disable_output(cyhal_scb_output_t output)
644 {
645 // All PSoC™ 6 devices have scb triggers but not all PSoC™ 4 devices do
646 #if (defined(CY_IP_MXSCB) || defined(CY_DEVICE_PSOC4AMC) || defined(CY_DEVICE_PSOC4AS3) || defined(CY_DEVICE_PSOC4AS4) || defined(CY_IP_MXS22SCB))
647     // Noop: Use _cyhal_scb_set_fifo_level to actually set level
648     if (output == CYHAL_SCB_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED ||
649         output == CYHAL_SCB_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED)
650     {
651         return CY_RSLT_SUCCESS;
652     }
653 
654     return CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT;
655 #else
656     CY_UNUSED_PARAMETER(output);
657     return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
658 #endif
659 }
660 
661 static bool __cyhal_scb_pm_transition_pending_value = false;
662 
_cyhal_scb_pm_transition_pending(void)663 bool _cyhal_scb_pm_transition_pending(void)
664 {
665     return __cyhal_scb_pm_transition_pending_value;
666 }
667 
_cyhal_scb_pm_callback_index(uint8_t index,cyhal_syspm_callback_state_t state,cy_en_syspm_callback_mode_t pdl_mode)668 static bool _cyhal_scb_pm_callback_index(uint8_t index, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
669 {
670     void *obj = _cyhal_scb_config_structs[index];
671     cyhal_scb_instance_pm_callback callback = _cyhal_scb_config_pm_callback[index];
672     return ((NULL != obj) && (callback != NULL)) ? callback(obj, state, pdl_mode) : true;
673 }
674 
_cyhal_scb_pm_callback_common(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)675 static bool _cyhal_scb_pm_callback_common(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
676 {
677     CY_UNUSED_PARAMETER(callback_arg);
678     bool allow = true;
679     cy_en_syspm_callback_mode_t pdl_mode = _cyhal_utils_convert_haltopdl_pm_mode(mode);
680     for (uint8_t instance_idx = 0; instance_idx < _SCB_ARRAY_SIZE; instance_idx++)
681     {
682         allow = _cyhal_scb_pm_callback_index(instance_idx, state, pdl_mode);
683 
684         if (!allow && mode == CYHAL_SYSPM_CHECK_READY)
685         {
686             for (uint8_t revert_idx = 0; revert_idx < instance_idx; revert_idx++)
687             {
688                 _cyhal_scb_pm_callback_index(revert_idx, state, CY_SYSPM_CHECK_FAIL);
689             }
690             break;
691         }
692     }
693 
694     if (mode == CYHAL_SYSPM_CHECK_FAIL || mode == CYHAL_SYSPM_AFTER_TRANSITION)
695     {
696         __cyhal_scb_pm_transition_pending_value = false;
697     }
698     else if (mode == CYHAL_SYSPM_CHECK_READY && allow)
699     {
700         __cyhal_scb_pm_transition_pending_value = true;
701     }
702     return allow;
703 }
704 
705 cyhal_syspm_callback_data_t _cyhal_scb_pm_callback_data =
706 {
707     .callback = &_cyhal_scb_pm_callback_common,
708     .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE | CYHAL_SYSPM_CB_SYSTEM_NORMAL | CYHAL_SYSPM_CB_SYSTEM_LOW),
709     .args = NULL,
710     .next = NULL,
711     .ignore_modes = (cyhal_syspm_callback_mode_t)0,
712 };
713 
_cyhal_scb_update_instance_data(uint8_t block_num,void * obj,cyhal_scb_instance_pm_callback pm_callback)714 void _cyhal_scb_update_instance_data(uint8_t block_num, void *obj, cyhal_scb_instance_pm_callback pm_callback)
715 {
716     uint8_t scb_arr_index = _cyhal_scb_get_block_index(block_num);
717 
718     _cyhal_scb_config_structs[scb_arr_index] = obj;
719     _cyhal_scb_config_pm_callback[scb_arr_index] = pm_callback;
720 
721     int count = 0;
722     for (uint8_t i = 0; i < _SCB_ARRAY_SIZE; i++)
723     {
724         if (NULL != _cyhal_scb_config_structs[i])
725         {
726             if (count == 1)
727             {
728                 return;
729             }
730             count++;
731         }
732     }
733 
734     if (count == 0)
735     {
736         CY_ASSERT(obj == NULL);
737         #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
738         _cyhal_syspm_unregister_peripheral_callback(&_cyhal_scb_pm_callback_data);
739         #endif
740     }
741     else if (count == 1 && obj != NULL)
742     {
743         #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
744         _cyhal_syspm_register_peripheral_callback(&_cyhal_scb_pm_callback_data);
745         #endif
746     }
747 }
748 
749 #if defined(__cplusplus)
750 }
751 #endif
752 
753 #endif /* _CYHAL_DRIVER_AVAILABLE_SCB */
754