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