1 /*
2 * Copyright (c) 2021-2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef _HPM_COMMON_H
9 #define _HPM_COMMON_H
10
11 #include <assert.h>
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <string.h>
15 #include <stdlib.h>
16
17 /**
18 *
19 * @brief COMMON driver APIs
20 * @defgroup common_interface COMMON driver APIs
21 * @{
22 *
23 */
24
25 #define __R volatile const /* Define "read-only" permission */
26 #define __RW volatile /* Define "read-write" permission */
27 #define __W volatile /* Define "write-only" permission */
28
29 #ifndef __I
30 #define __I __R
31 #endif
32
33 #ifndef __IO
34 #define __IO __RW
35 #endif
36
37 #ifndef __O
38 #define __O __W
39 #endif
40
41 #ifndef ARRAY_SIZE
42 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
43 #endif
44
45 #ifndef MAX
46 #define MAX(a, b) ((a) > (b) ? (a) : (b))
47 #endif
48 #ifndef MIN
49 #define MIN(a, b) ((a) < (b) ? (a) : (b))
50 #endif
51
52 #ifndef HPM_ALIGN_DOWN
53 #define HPM_ALIGN_DOWN(a, n) ((uint32_t)(a) & ~(n-1U))
54 #endif
55
56 #ifndef HPM_ALIGN_UP
57 #define HPM_ALIGN_UP(a, n) (((uint32_t)(a) + (n-1U)) & ~(n-1U))
58 #endif
59
60 #define HPM_BITSMASK(val, offset) ((uint32_t)(val) << (offset))
61 #define IS_HPM_BITMASK_SET(val, mask) (((uint32_t)(val) & (uint32_t)(mask)) != 0U)
62 #define IS_HPM_BIT_SET(val, offset) (((uint32_t)(val) & (1UL << (offset))) != 0U)
63 #define IS_HPM_BITMASK_CLR(val, mask) (((uint32_t)(val) & (uint32_t)(mask)) == 0U)
64 #define IS_HPM_BIT_CLR(val, offset) (((uint32_t)(val) & (1UL << (offset))) == 0U)
65
66 #define HPM_BREAK_IF(cond) if (cond) { break; }
67 #define HPM_CONTINUE_IF(cond) if (cond) { continue; }
68
69 #define HPM_DIV_ROUND_CLOSEST(x, div) (((x) + (div) / 2) / (div))
70 #define HPM_DIV_ROUND_UP(x, div) (((x) + (div) - 1) / (div))
71
72 #define HPM_NUM_TO_EVEN_CEILING(x) ((x + 1) & 0xFFFFFFFEUL)
73 #define HPM_NUM_TO_EVEN_FLOOR(x) ((x) & 0xFFFFFFFEUL)
74
75 #define HPM_CHECK_RET(x) \
76 do { \
77 stat = (x); \
78 if (status_success != stat) { \
79 return stat; \
80 } \
81 } while (false)
82
83 #define SIZE_1KB (1024UL)
84 #define SIZE_1MB (1048576UL)
85
86 #define BIT0_MASK (0x00000001UL)
87 #define BIT1_MASK (0x00000002UL)
88 #define BIT2_MASK (0x00000004UL)
89 #define BIT3_MASK (0x00000008UL)
90 #define BIT4_MASK (0x00000010UL)
91 #define BIT5_MASK (0x00000020UL)
92 #define BIT6_MASK (0x00000040UL)
93 #define BIT7_MASK (0x00000080UL)
94 #define BIT8_MASK (0x00000100UL)
95 #define BIT9_MASK (0x00000200UL)
96 #define BIT10_MASK (0x00000400UL)
97 #define BIT11_MASK (0x00000800UL)
98 #define BIT12_MASK (0x00001000UL)
99 #define BIT13_MASK (0x00002000UL)
100 #define BIT14_MASK (0x00004000UL)
101 #define BIT15_MASK (0x00008000UL)
102 #define BIT16_MASK (0x00010000UL)
103 #define BIT17_MASK (0x00020000UL)
104 #define BIT18_MASK (0x00040000UL)
105 #define BIT19_MASK (0x00080000UL)
106 #define BIT20_MASK (0x00100000UL)
107 #define BIT21_MASK (0x00200000UL)
108 #define BIT22_MASK (0x00400000UL)
109 #define BIT23_MASK (0x00800000UL)
110 #define BIT24_MASK (0x01000000UL)
111 #define BIT25_MASK (0x02000000UL)
112 #define BIT26_MASK (0x04000000UL)
113 #define BIT27_MASK (0x08000000UL)
114 #define BIT28_MASK (0x10000000UL)
115 #define BIT29_MASK (0x20000000UL)
116 #define BIT30_MASK (0x40000000UL)
117 #define BIT31_MASK (0x80000000UL)
118
119 typedef uint32_t hpm_stat_t;
120
121 /* @brief Enum definition for the Status group
122 * Rule:
123 * [Group] 0-999 for the SoC driver and the corresponding components
124 * 1000 or above for the application status group
125 * [Code] Valid value: 0-999
126 *
127 */
128 #define MAKE_STATUS(group, code) ((uint32_t)(group)*1000U + (uint32_t)(code))
129 /* @brief System status group definitions */
130 enum {
131 status_group_common = 0,
132 status_group_uart = 1,
133 status_group_i2c = 2,
134 status_group_spi = 3,
135 status_group_usb = 4,
136 status_group_i2s = 5,
137 status_group_xpi = 6,
138 status_group_l1c,
139 status_group_dma,
140 status_group_femc,
141 status_group_sdp,
142 status_group_xpi_nor,
143 status_group_otp,
144 status_group_lcdc,
145 status_group_mbx,
146 status_group_rng,
147 status_group_pdma,
148 status_group_wdg,
149 status_group_pmic_sec,
150 status_group_can,
151 status_group_sdxc,
152 status_group_pcfg,
153 status_group_clk,
154 status_group_pllctl,
155 status_group_pllctlv2,
156 status_group_ffa,
157 status_group_mcan,
158 status_group_ewdg,
159 status_group_esc,
160
161 status_group_middleware_start = 500,
162 status_group_sdmmc = status_group_middleware_start,
163 status_group_audio_codec,
164 status_group_dma_manager,
165 status_group_spi_nor_flash,
166 status_group_touch,
167 };
168
169 /* @brief Common status code definitions */
170 enum {
171 status_success = MAKE_STATUS(status_group_common, 0),
172 status_fail = MAKE_STATUS(status_group_common, 1),
173 status_invalid_argument = MAKE_STATUS(status_group_common, 2),
174 status_timeout = MAKE_STATUS(status_group_common, 3),
175 };
176
177 #if defined(__GNUC__)
178 /* weak */
179 #define ATTR_WEAK __attribute__((weak))
180
181 #define HPM_ATTR_MACHINE_INTERRUPT __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)))
182 #define HPM_ATTR_SUPERVISOR_INTERRUPT __attribute__ ((section(".isr_s_vector"), interrupt("supervisor"), aligned(4)))
183
184 #elif defined(__ICCRISCV__)
185 /* weak */
186 #define ATTR_WEAK __weak
187
188 #define HPM_ATTR_MACHINE_INTERRUPT __machine __interrupt
189 #define HPM_ATTR_SUPERVISOR_INTERRUPT __supervisor __interrupt
190
191 #ifndef __TIMEVAL_DEFINED
192 #define __TIMEVAL_DEFINED 1
193 struct timeval {
194 long tv_sec; /* Seconds since the Epoch */
195 long tv_usec; /* Microseconds */
196 };
197 #endif
198
199 #else
200 #error Unknown toolchain
201 #endif
202
203 #if defined(__GNUC__) || defined(__ICCRISCV__)
204
205 /* alway_inline */
206 #define ATTR_ALWAYS_INLINE __attribute__((always_inline))
207
208 /* alignment */
209 #define ATTR_ALIGN(alignment) __attribute__((aligned(alignment)))
210 #define ATTR_PACKED __attribute__((packed, aligned(1)))
211
212 /* place var_declare at section_name, e.x. PLACE_AT(".target_section", var); */
213 #define ATTR_PLACE_AT(section_name) __attribute__((section(section_name)))
214
215 #define ATTR_PLACE_AT_WITH_ALIGNMENT(section_name, alignment) \
216 ATTR_PLACE_AT(section_name) ATTR_ALIGN(alignment)
217
218 #define ATTR_PLACE_AT_NONCACHEABLE ATTR_PLACE_AT(".noncacheable")
219 #define ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(alignment) \
220 ATTR_PLACE_AT_NONCACHEABLE ATTR_ALIGN(alignment)
221
222 #define ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_PLACE_AT(".noncacheable.bss")
223 #define ATTR_PLACE_AT_NONCACHEABLE_BSS_WITH_ALIGNMENT(alignment) \
224 ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_ALIGN(alignment)
225
226 /* initialize variable x with y using PLACE_AT_NONCACHEABLE_INIT(x) = {y}; */
227 #define ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_PLACE_AT(".noncacheable.init")
228 #define ATTR_PLACE_AT_NONCACHEABLE_INIT_WITH_ALIGNMENT(alignment) \
229 ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_ALIGN(alignment)
230
231 /* .fast_ram section */
232 #define ATTR_PLACE_AT_FAST_RAM ATTR_PLACE_AT(".fast_ram")
233 #define ATTR_PLACE_AT_FAST_RAM_WITH_ALIGNMENT(alignment) \
234 ATTR_PLACE_AT_FAST_RAM ATTR_ALIGN(alignment)
235
236 #define ATTR_PLACE_AT_FAST_RAM_BSS ATTR_PLACE_AT(".fast_ram.bss")
237 #define ATTR_PLACE_AT_FAST_RAM_BSS_WITH_ALIGNMENT(alignment) \
238 ATTR_PLACE_AT_FAST_RAM_BSS ATTR_ALIGN(alignment)
239
240 #define ATTR_PLACE_AT_FAST_RAM_INIT ATTR_PLACE_AT(".fast_ram.init")
241 #define ATTR_PLACE_AT_FAST_RAM_INIT_WITH_ALIGNMENT(alignment) \
242 ATTR_PLACE_AT_FAST_RAM_INIT ATTR_ALIGN(alignment)
243
244 #define ATTR_RAMFUNC ATTR_PLACE_AT(".fast")
245 #define ATTR_RAMFUNC_WITH_ALIGNMENT(alignment) \
246 ATTR_RAMFUNC ATTR_ALIGN(alignment)
247
248 #define ATTR_SHARE_MEM ATTR_PLACE_AT(".sh_mem")
249
250 #define NOP() __asm volatile("nop")
251 #define WFI() __asm volatile("wfi")
252
253 #endif
254
255 #ifdef __cplusplus
256 extern "C" {
257 #endif
258
259
260 /**
261 * @brief Count bits set to 1
262 *
263 * @param value Data to be counted
264 *
265 * @return number of bits set to 1
266 */
count_set_bits(uint32_t value)267 static inline uint32_t count_set_bits(uint32_t value)
268 {
269 if (value == 0) {
270 return 0;
271 }
272 return 1 + count_set_bits(value & (value - 1));
273 }
274
275 /**
276 * @brief Count bits set to 1 from least significant bit
277 *
278 * @param value Data to be counted
279 *
280 * @return number of bits set to 1
281 * @return 0xFFFFFFFF if no bit was set to 1
282 */
get_first_set_bit_from_lsb(uint32_t value)283 static inline uint32_t get_first_set_bit_from_lsb(uint32_t value)
284 {
285 uint32_t i = 0;
286 if (!value) {
287 return 0xFFFFFFFFUL;
288 }
289 while (value && !(value & 0x1)) {
290 value >>= 1;
291 i++;
292 }
293 return i;
294 }
295
296 /**
297 * @brief Count bits set to 1 from most significant bit
298 *
299 * @param value Data to be counted
300 *
301 * @return number of bits set to 1
302 * @return 0xFFFFFFFF if no bit was set to 1
303 */
get_first_set_bit_from_msb(uint32_t value)304 static inline uint32_t get_first_set_bit_from_msb(uint32_t value)
305 {
306 uint32_t i = 31;
307 if (!value) {
308 return 0xFFFFFFFFUL;
309 }
310 while (value && !(value & 0x80000000)) {
311 value <<= 1;
312 value &= ~1;
313 i--;
314 }
315 return i;
316 }
317
318 /**
319 * @brief Convert the elapsed ticks to microseconds according to the source clock frequency
320 * @param [in] ticks elapsed ticks
321 * @param [in] src_clk_freq The Frequency of the source
322 *
323 * @return elapsed microseconds
324 */
hpm_convert_ticks_to_us(uint32_t ticks,uint32_t src_clk_freq)325 static inline uint32_t hpm_convert_ticks_to_us(uint32_t ticks, uint32_t src_clk_freq)
326 {
327 uint32_t ticks_per_us = (src_clk_freq + 1000000UL - 1UL) / 1000000UL;
328 return (ticks + ticks_per_us - 1UL) / ticks_per_us;
329 }
330
331 /**
332 * @brief Convert the elapsed ticks to milliseconds according to the source clock frequency
333 * @param [in] ticks elapsed ticks
334 * @param [in] src_clk_freq The Frequency of the source
335 *
336 * @return elapsed milliseconds
337 */
hpm_convert_ticks_to_ms(uint32_t ticks,uint32_t src_clk_freq)338 static inline uint32_t hpm_convert_ticks_to_ms(uint32_t ticks, uint32_t src_clk_freq)
339 {
340 uint32_t ticks_per_ms = (src_clk_freq + 1000UL - 1UL) / 1000UL;
341 return (ticks + ticks_per_ms - 1UL) / ticks_per_ms;
342 }
343
344 #ifdef __cplusplus
345 }
346 #endif
347
348 /**
349 * @}
350 */
351 #endif /* _HPM_COMMON_H */
352