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