1 /***************************************************************************//**
2 * \file cyhal_scb_common.h
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 /** \cond INTERNAL */
28 /**
29  * \addtogroup group_hal_impl_scb_common SCB Common Functionality
30  * \ingroup group_hal_impl
31  * \{
32  * Code shared between the SCB resources (UART, I2C, and SPI).
33  */
34 
35 #pragma once
36 
37 #include "cy_device.h"
38 #include "cy_pdl.h"
39 #include "cyhal_utils.h"
40 #include "cyhal_irq_impl.h"
41 #include "cyhal_peri_common.h"
42 
43 #if defined(__cplusplus)
44 extern "C" {
45 #endif
46 
47 #if defined(CY_IP_MXSCB_INSTANCES)
48 #define _SCB_ARRAY_SIZE                 (CY_IP_MXSCB_INSTANCES)
49 #elif defined(CY_IP_M0S8SCB_INSTANCES)
50 #define _SCB_ARRAY_SIZE                 (CY_IP_M0S8SCB_INSTANCES)
51 #elif defined(CY_IP_MXS22SCB_INSTANCES)
52 #define _SCB_ARRAY_SIZE                 (CY_IP_MXS22SCB_INSTANCES)
53 #endif /* CY_IP_MXSCB_INSTANCES */
54 
55 /* Indicates the invalid SCB block selected */
56 #define _CYHAL_SCB_BLOCK_ID_INVALID     (0xFF)
57 
58 /* Return number of bytes to copy into the destination buffer */
59 #define _CYHAL_SCB_BYTES_TO_COPY(actBufSize, bufSize) \
60                                 (((uint32_t) (actBufSize) < (uint32_t) (bufSize)) ? \
61                                  ((uint32_t) (actBufSize)) : ((uint32_t) (bufSize)) )
62 
63 
64 /** \addtogroup group_hal_results_scb SCB HAL Results
65  *  SCB specific return codes
66  *  \ingroup group_hal_results
67  *  \{ *//**
68 
69  */
70 /** Bad argument */
71 #define CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT                     \
72     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_SCB, 0))
73 
74 /**
75  * \}
76  */
77 
78 /** SCB FIFO type */
79 typedef enum
80 {
81     CYHAL_SCB_FIFO_RX, //!< Set RX FIFO level
82     CYHAL_SCB_FIFO_TX, //!< Set TX FIFO level
83 } cyhal_scb_fifo_type_t;
84 
85 /** Enum of possible output signals from an SCB */
86 typedef enum
87 {
88     CYHAL_SCB_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED, //!< Output the RX FIFO signal which is triggered when the receive FIFO has more entries than the configured level.
89     CYHAL_SCB_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED, //!< Output the TX FIFO signal which is triggered when the transmit FIFO has less entries than the configured level.
90 } cyhal_scb_output_t;
91 
92 
93 /** The mask of available SCB blocks */
94 extern const uint32_t _CYHAL_SCB_AVAILABLE_BLOCKS_MASK;
95 /** The start address of the SCB blocks */
96 extern CySCB_Type* const _CYHAL_SCB_BASE_ADDRESSES[_SCB_ARRAY_SIZE];
97 /** The interrupt number of the SCB blocks. */
98 extern const _cyhal_system_irq_t _CYHAL_SCB_IRQ_N[_SCB_ARRAY_SIZE];
99 
100 
101 /** Get the SCB block corresponding to an IRQn.
102  *
103  * @param[in] irqn The IRQn to get the corresponding block from
104  * @return         The corresponding SCB block
105  */
106 uint8_t cyhal_scb_get_block_from_irqn(_cyhal_system_irq_t irqn);
107 
108 /** Get the index of SCB block in internal arrays corresponding to SCB instance.
109  *
110  * @param[in] scb_block_num The SCB instance number
111  * @return              The corresponding index of SCB block in internal array
112  */
113 uint8_t _cyhal_scb_get_block_index(uint8_t scb_block_num);
114 
115 #if defined (COMPONENT_CAT5)
116 /** Get the SCB object corresponding to the currently running ISR.
117  *
118  * @param[in] irqn The index of the irq object to retrieve
119  * @return A pointer to the SCB object corresponding to the currently running ISR.
120  */
121 void *_cyhal_scb_get_irq_obj(_cyhal_system_irq_t irqn);
122 #else
123 /** Get the SCB object corresponding to the currently running ISR.
124  *
125  * @return A pointer to the SCB object corresponding to the currently running ISR.
126  */
127 void *_cyhal_scb_get_irq_obj(void);
128 #endif
129 
130 /** Sets the desired clocks & data rate to achieve the specified frequency. Configuration of clock is not changed if
131  * driver does not own it.
132  * @param[in] obj       The I2C or EZI2C object to configure the peri divider for
133  * @param[in] is_i2c    Whether driver to be configured is I2C or EZI2C (I2C is true)
134  * @praam[in] freq      The desired frequency
135  * @param[in] is_slave  Is this an I2C slave (true) or master (false)
136  * @return The achieved data rate in Hz, or 0 if there was an error.
137  */
138 uint32_t _cyhal_i2c_set_peri_divider(void *obj, bool is_i2c, uint32_t freq, bool is_slave);
139 
140 /** Find an available SCB instance that matches 'pin'.
141  * @param pin Pin
142  * @param pin_map Pin mapping array
143  * @param count Number of entries in pin_map
144  * @return Pin map pointer or NULL if none found
145  */
146 const cyhal_resource_pin_mapping_t* _cyhal_scb_find_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map,
147                     size_t count, const cyhal_resource_inst_t *block_res);
148 
149 /** Find all available SCB instances that matches 'pin'.
150  * @param pin Pin
151  * @param pin_map Pin mapping array
152  * @param count Number of entries in pin_map
153  * @return Bit representation of SCB blocks, that can be wired with specified pin. 1 block - 1 bit, LSB corresponds to
154  * SCB0. Only free for reserve blocks are returned. Example, output value 0x00000006 means that certain pin can belong
155  * to next non-reserved blocks: SCB2 and SCB1.
156  */
157 uint32_t _cyhal_scb_check_pin_affiliation(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map, size_t count);
158 
159 /** Sets a threshold level for a FIFO that will generate an interrupt and a
160  * trigger output. The RX FIFO interrupt and trigger will be activated when
161  * the receive FIFO has more entries than the threshold. The TX FIFO interrupt
162  * and trigger will be activated when the transmit FIFO has less entries than
163  * the threshold.
164  *
165  * @param[in]  base       SCB base
166  * @param[in]  type       FIFO type to set level for
167  * @param[in]  level      Level threshold to set
168  * @return The status of the level set
169  * */
170 cy_rslt_t _cyhal_scb_set_fifo_level(CySCB_Type *base, cyhal_scb_fifo_type_t type, uint16_t level);
171 
172 /** Enables the specified output signal from an scb.
173  *
174  * @param[in]  resource   SCB resource
175  * @param[in]  output     Which output signal to enable
176  * @param[out] source     Pointer to user-allocated source signal object which
177  * will be initialized by enable_output. source should be passed to
178  * (dis)connect_digital functions to (dis)connect the associated endpoints.
179  * @return The status of the output enable
180  * */
181 cy_rslt_t _cyhal_scb_enable_output(cyhal_resource_inst_t resource, cyhal_scb_output_t output, cyhal_source_t *source);
182 
183 /** Disables the specified output signal from an scb
184  *
185  * @param[in]  output     Which output signal to disable
186  * @return The status of the output disable
187  * */
188 cy_rslt_t _cyhal_scb_disable_output(cyhal_scb_output_t output);
189 
190 #define _CYHAL_SCB_FIND_MAP(pin, pin_map) \
191                     _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), NULL)
192 #define _CYHAL_SCB_FIND_MAP_BLOCK(pin, pin_map, block) \
193                     _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), block)
194 #define _CYHAL_SCB_CHECK_AFFILIATION(pin, pin_map) \
195                     _cyhal_scb_check_pin_affiliation(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t))
196 
197 /**
198  * Function pointer to determine a specific scb instance can is ready for low power transition.
199  */
200 typedef bool (*cyhal_scb_instance_pm_callback)(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode);
201 
202 /** Updates data in cyhal_scb_config_structs and cyhal_scb_config_modes_t structs based on block_num proveded
203  * @param[in] block_num Index of SCB block which data to be updated
204  * @param[in] obj       SCB-based driver object (cyhal_uart_t, cyhal_spi_t, cyhal_i2c_t or cyhal_ezi2c_t)
205  */
206 void _cyhal_scb_update_instance_data(uint8_t block_num, void *obj, cyhal_scb_instance_pm_callback pm_callback);
207 
208 /** Whether power management transition is pending and communication should be suspended. */
209 bool _cyhal_scb_pm_transition_pending(void);
210 
211 /** Finds the en_clk_dst_t clock connection index for provided SCB block number
212  *
213  * @param[in] block_num Index of SCB block
214  * @return en_clk_dst_t clock connection index
215  */
_cyhal_scb_get_clock_index(uint32_t block_num)216 static inline en_clk_dst_t _cyhal_scb_get_clock_index(uint32_t block_num)
217 {
218     en_clk_dst_t clk;
219     // PSOC6A256K does not have SCB 3
220     #if defined(CY_DEVICE_PSOC6A256K)
221         if (block_num < 3)
222             clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num);
223         else
224             clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num -1);
225     #elif defined (COMPONENT_CAT5)
226         clk = (en_clk_dst_t)(block_num);
227     #elif defined (COMPONENT_CAT1D)
228         if (block_num == 0)
229             clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK);
230         else if (block_num == 1)
231             clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB1_PCLK_CLOCK);
232         else
233             clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num - 1);
234     #else
235         clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num);
236     #endif
237     return clk;
238 }
239 
240 #if defined(__cplusplus)
241 }
242 #endif
243 
244 /** \} group_hal_impl_scb_common */
245 /** \endcond */
246