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