1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_PCFG_DRV_H
9 #define HPM_PCFG_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_pcfg_regs.h"
13
14 /**
15 *
16 * @brief PCFG driver APIs
17 * @defgroup pcfg_interface PCFG driver APIs
18 * @ingroup io_interfaces
19 * @{
20 */
21 #define PCFG_CLOCK_GATE_MODE_ALWAYS_ON (0x3UL)
22 #define PCFG_CLOCK_GATE_MODE_ALWAYS_OFF (0x2UL)
23
24 #define PCFG_PERIPH_KEEP_CLOCK_ON(p) (PCFG_CLOCK_GATE_MODE_ALWAYS_ON << (p))
25 #define PCFG_PERIPH_KEEP_CLOCK_OFF(p) (PCFG_CLOCK_GATE_MODE_ALWAYS_OFF << (p))
26
27 /* @brief PCFG irc24m reference */
28 typedef enum {
29 pcfg_irc24m_reference_32k = 0,
30 pcfg_irc24m_reference_24m_xtal = 1
31 } pcfg_irc24m_reference_t;
32
33 /* @brief PCFG dcdc current limit */
34 typedef enum {
35 pcfg_dcdc_lp_current_limit_250ma = 0,
36 pcfg_dcdc_lp_current_limit_200ma = 1,
37 } pcfg_dcdc_lp_current_limit_t;
38
39 /* @brief PCFG dcdc current hys */
40 typedef enum {
41 pcfg_dcdc_current_hys_12_5mv = 0,
42 pcfg_dcdc_current_hys_25mv = 1,
43 } pcfg_dcdc_current_hys_t;
44
45 /* @brief PCFG dcdc mode */
46 typedef enum {
47 pcfg_dcdc_mode_off = 0,
48 pcfg_dcdc_mode_basic = 1,
49 pcfg_dcdc_mode_general = 3,
50 pcfg_dcdc_mode_expert = 7,
51 } pcfg_dcdc_mode_t;
52
53 /* @brief PCFG pmc domain peripherals */
54 typedef enum {
55 pcfg_pmc_periph_gpio = 6,
56 pcfg_pmc_periph_ioc = 8,
57 pcfg_pmc_periph_timer = 10,
58 pcfg_pmc_periph_wdog = 12,
59 pcfg_pmc_periph_uart = 14,
60 } pcfg_pmc_periph_t;
61
62 /* @brief PCFG status */
63 enum {
64 status_pcfg_ldo_out_of_range = MAKE_STATUS(status_group_pcfg, 1),
65 };
66
67 /* @brief PCFG irc24m config */
68 typedef struct {
69 uint32_t freq_in_hz;
70 pcfg_irc24m_reference_t reference;
71 bool return_to_default_on_xtal_loss;
72 bool free_run;
73 } pcfg_irc24m_config_t;
74
75
76 #define PCFG_CLOCK_GATE_CONTROL_MASK(module, mode) \
77 ((uint32_t) (mode) << ((module) << 1))
78
79 #ifdef __cplusplus
80 extern "C" {
81 #endif
82
83 /**
84 * @brief check if bandgap is trimmed or not
85 *
86 * @param[in] ptr base address
87 *
88 * @retval true if bandgap is trimmed
89 */
pcfg_bandgap_is_trimmed(PCFG_Type * ptr)90 static inline bool pcfg_bandgap_is_trimmed(PCFG_Type *ptr)
91 {
92 return ptr->BANDGAP & PCFG_BANDGAP_VBG_TRIMMED_MASK;
93 }
94
95 /**
96 * @brief bandgap reload trim value
97 *
98 * @param[in] ptr base address
99 */
pcfg_bandgap_reload_trim(PCFG_Type * ptr)100 static inline void pcfg_bandgap_reload_trim(PCFG_Type *ptr)
101 {
102 ptr->BANDGAP &= ~PCFG_BANDGAP_VBG_TRIMMED_MASK;
103 }
104
105 /**
106 * @brief turn off LDO2P5
107 *
108 * @param[in] ptr base address
109 */
pcfg_ldo2p5_turn_off(PCFG_Type * ptr)110 static inline void pcfg_ldo2p5_turn_off(PCFG_Type *ptr)
111 {
112 ptr->LDO2P5 &= ~PCFG_LDO2P5_ENABLE_MASK;
113 }
114
115 /**
116 * @brief turn on LDO 2.5V
117 *
118 * @param[in] ptr base address
119 */
pcfg_ldo2p5_turn_on(PCFG_Type * ptr)120 static inline void pcfg_ldo2p5_turn_on(PCFG_Type *ptr)
121 {
122 ptr->LDO2P5 |= PCFG_LDO2P5_ENABLE_MASK;
123 }
124
125 /**
126 * @brief check if LDO 2.5V is stable
127 *
128 * @param[in] ptr base address
129 *
130 * @retval true if LDO2P5 is stable
131 */
pcfg_ldo2p5_is_stable(PCFG_Type * ptr)132 static inline bool pcfg_ldo2p5_is_stable(PCFG_Type *ptr)
133 {
134 return PCFG_LDO2P5_READY_GET(ptr->LDO2P5);
135 }
136
137 /*
138 * @brief check if DCDC is stable or not
139 * @param[in] ptr base address
140 * @retval true if DCDC is stable
141 */
pcfg_dcdc_is_stable(PCFG_Type * ptr)142 static inline bool pcfg_dcdc_is_stable(PCFG_Type *ptr)
143 {
144 return PCFG_DCDC_MODE_READY_GET(ptr->DCDC_MODE);
145 }
146
147 /*
148 * @brief set DCDC work mode
149 * @param[in] ptr base address
150 */
pcfg_dcdc_set_mode(PCFG_Type * ptr,uint8_t mode)151 static inline void pcfg_dcdc_set_mode(PCFG_Type *ptr, uint8_t mode)
152 {
153 ptr->DCDC_MODE = (ptr->DCDC_MODE & ~PCFG_DCDC_MODE_MODE_MASK) | PCFG_DCDC_MODE_MODE_SET(mode);
154 }
155
156 /**
157 * @brief set low power current limit
158 *
159 * @param[in] ptr base address
160 * @param[in] limit current limit at low power mode
161 */
pcfg_dcdc_set_lp_current_limit(PCFG_Type * ptr,pcfg_dcdc_lp_current_limit_t limit)162 static inline void pcfg_dcdc_set_lp_current_limit(PCFG_Type *ptr, pcfg_dcdc_lp_current_limit_t limit)
163 {
164 ptr->DCDC_PROT = (ptr->DCDC_PROT & ~(PCFG_DCDC_PROT_ILIMIT_LP_MASK | PCFG_DCDC_PROT_OVERLOAD_LP_MASK))
165 | PCFG_DCDC_PROT_ILIMIT_LP_SET(limit);
166 }
167
168
169 /**
170 * @brief check if power loss flag is set
171 *
172 * @param[in] ptr base address
173 *
174 * @retval true if power loss is set
175 */
pcfg_dcdc_is_power_loss(PCFG_Type * ptr)176 static inline bool pcfg_dcdc_is_power_loss(PCFG_Type *ptr)
177 {
178 return PCFG_DCDC_PROT_POWER_LOSS_FLAG_GET(ptr->DCDC_PROT);
179 }
180
181 /**
182 * @brief disable over voltage protection
183 *
184 * @param[in] ptr base address
185 */
pcfg_dcdc_disable_over_voltage_prot(PCFG_Type * ptr)186 static inline void pcfg_dcdc_disable_over_voltage_prot(PCFG_Type *ptr)
187 {
188 ptr->DCDC_PROT |= PCFG_DCDC_PROT_DISABLE_OVERVOLTAGE_MASK;
189 }
190
191 /**
192 * @brief enable over voltage protection
193 *
194 * @param[in] ptr base address
195 */
pcfg_dcdc_ensable_over_voltage_prot(PCFG_Type * ptr)196 static inline void pcfg_dcdc_ensable_over_voltage_prot(PCFG_Type *ptr)
197 {
198 ptr->DCDC_PROT &= ~PCFG_DCDC_PROT_DISABLE_OVERVOLTAGE_MASK;
199 }
200
201 /**
202 * @brief checkover voltage flag
203 *
204 * @param[in] ptr base address
205 * @retval true if flag is set
206 */
pcfg_dcdc_is_over_voltage(PCFG_Type * ptr)207 static inline bool pcfg_dcdc_is_over_voltage(PCFG_Type *ptr)
208 {
209 return PCFG_DCDC_PROT_OVERVOLT_FLAG_GET(ptr->DCDC_PROT) & PCFG_DCDC_PROT_OVERVOLT_FLAG_MASK;
210 }
211
212 /**
213 * @brief disable current measurement
214 *
215 * @param[in] ptr base address
216 */
pcfg_dcdc_disable_measure_current(PCFG_Type * ptr)217 static inline void pcfg_dcdc_disable_measure_current(PCFG_Type *ptr)
218 {
219 ptr->DCDC_CURRENT &= ~PCFG_DCDC_CURRENT_ESTI_EN_MASK;
220 }
221
222 /**
223 * @brief enable current measurement
224 *
225 * @param[in] ptr base address
226 */
pcfg_dcdc_enable_measure_current(PCFG_Type * ptr)227 static inline void pcfg_dcdc_enable_measure_current(PCFG_Type *ptr)
228 {
229 ptr->DCDC_CURRENT |= PCFG_DCDC_CURRENT_ESTI_EN_MASK;
230 }
231
232 /**
233 * @brief check if measured current is valid
234 *
235 * @param[in] ptr base address
236 *
237 * @retval true if measured current is valid
238 */
pcfg_dcdc_is_measure_current_valid(PCFG_Type * ptr)239 static inline bool pcfg_dcdc_is_measure_current_valid(PCFG_Type *ptr)
240 {
241 return ptr->DCDC_CURRENT & PCFG_DCDC_CURRENT_VALID_MASK;
242 }
243
244 /**
245 * @brief get DCDC start time in number of 24MHz clock cycles
246 *
247 * @param[in] ptr base address
248 *
249 * @retval dcdc start time in cycles
250 */
pcfg_dcdc_get_start_time_in_cycle(PCFG_Type * ptr)251 static inline uint32_t pcfg_dcdc_get_start_time_in_cycle(PCFG_Type *ptr)
252 {
253 return PCFG_DCDC_START_TIME_START_TIME_GET(ptr->DCDC_START_TIME);
254 }
255
256 /**
257 * @brief get DCDC resume time in number of 24MHz clock cycles
258 *
259 * @param[in] ptr base address
260 *
261 * @retval dcdc resuem time in cycles
262 */
pcfg_dcdc_get_resume_time_in_cycle(PCFG_Type * ptr)263 static inline uint32_t pcfg_dcdc_get_resume_time_in_cycle(PCFG_Type *ptr)
264 {
265 return PCFG_DCDC_RESUME_TIME_RESUME_TIME_GET(ptr->DCDC_RESUME_TIME);
266 }
267
268 /**
269 * @brief set DCDC start time in 24MHz clock cycles
270 *
271 * @param[in] ptr base address
272 * @param[in] cycles start time in cycles
273 */
pcfg_dcdc_set_start_time_in_cycle(PCFG_Type * ptr,uint32_t cycles)274 static inline void pcfg_dcdc_set_start_time_in_cycle(PCFG_Type *ptr, uint32_t cycles)
275 {
276 ptr->DCDC_START_TIME = PCFG_DCDC_START_TIME_START_TIME_SET(cycles);
277 }
278
279 /**
280 * @brief set DCDC resuem time in 24MHz clock cycles
281 *
282 * @param[in] ptr base address
283 * @param[in] cycles resume time in cycles
284 */
pcfg_dcdc_set_resume_time_in_cycle(PCFG_Type * ptr,uint32_t cycles)285 static inline void pcfg_dcdc_set_resume_time_in_cycle(PCFG_Type *ptr, uint32_t cycles)
286 {
287 ptr->DCDC_RESUME_TIME = PCFG_DCDC_RESUME_TIME_RESUME_TIME_SET(cycles);
288 }
289
290 /**
291 * @brief set dcdc current hysteres range
292 *
293 * @param[in] ptr base address
294 * @param[in] range current hysteres range
295 */
pcfg_dcdc_set_current_hys_range(PCFG_Type * ptr,pcfg_dcdc_current_hys_t range)296 static inline void pcfg_dcdc_set_current_hys_range(PCFG_Type *ptr, pcfg_dcdc_current_hys_t range)
297 {
298 ptr->DCDC_MISC = (ptr->DCDC_MISC & (~PCFG_DCDC_MISC_OL_HYST_MASK)) | PCFG_DCDC_MISC_OL_HYST_SET(range);
299 }
300
301 /**
302 * @brief disable power trap
303 *
304 * @param[in] ptr base address
305 */
pcfg_disable_power_trap(PCFG_Type * ptr)306 static inline void pcfg_disable_power_trap(PCFG_Type *ptr)
307 {
308 ptr->POWER_TRAP &= ~PCFG_POWER_TRAP_TRAP_MASK;
309 }
310
311 /**
312 * @brief enable power trap
313 *
314 * @param[in] ptr base address
315 */
pcfg_enable_power_trap(PCFG_Type * ptr)316 static inline void pcfg_enable_power_trap(PCFG_Type *ptr)
317 {
318 ptr->POWER_TRAP |= PCFG_POWER_TRAP_TRAP_MASK;
319 }
320
321 /**
322 * @brief check if power trap is triggered
323 *
324 * @param[in] ptr base address
325 *
326 * @retval true if power trap is triggered
327 */
pcfg_is_power_trap_triggered(PCFG_Type * ptr)328 static inline bool pcfg_is_power_trap_triggered(PCFG_Type *ptr)
329 {
330 return ptr->POWER_TRAP & PCFG_POWER_TRAP_TRIGGERED_MASK;
331 }
332
333 /**
334 * @brief clear power trap trigger flag
335 *
336 * @param[in] ptr base address
337 */
pcfg_clear_power_trap_trigger_flag(PCFG_Type * ptr)338 static inline void pcfg_clear_power_trap_trigger_flag(PCFG_Type *ptr)
339 {
340 ptr->POWER_TRAP |= PCFG_POWER_TRAP_TRIGGERED_MASK;
341 }
342
343 /**
344 * @brief disable dcdc retention
345 *
346 * @param[in] ptr base address
347 */
pcfg_disable_dcdc_retention(PCFG_Type * ptr)348 static inline void pcfg_disable_dcdc_retention(PCFG_Type *ptr)
349 {
350 ptr->POWER_TRAP &= ~PCFG_POWER_TRAP_RETENTION_MASK;
351 }
352
353 /**
354 * @brief enable dcdc retention to retain soc sram data
355 *
356 * @param[in] ptr base address
357 */
pcfg_enable_dcdc_retention(PCFG_Type * ptr)358 static inline void pcfg_enable_dcdc_retention(PCFG_Type *ptr)
359 {
360 ptr->POWER_TRAP |= PCFG_POWER_TRAP_RETENTION_MASK;
361 }
362
363 /**
364 * @brief clear wakeup cause flag
365 *
366 * @param[in] ptr base address
367 * @param[in] mask mask of flags to be cleared
368 */
pcfg_clear_wakeup_cause(PCFG_Type * ptr,uint32_t mask)369 static inline void pcfg_clear_wakeup_cause(PCFG_Type *ptr, uint32_t mask)
370 {
371 ptr->WAKE_CAUSE |= mask;
372 }
373
374 /**
375 * @brief get wakeup cause
376 *
377 * @param[in] ptr base address
378 *
379 * @retval mask of wake cause
380 */
pcfg_get_wakeup_cause(PCFG_Type * ptr)381 static inline uint32_t pcfg_get_wakeup_cause(PCFG_Type *ptr)
382 {
383 return ptr->WAKE_CAUSE;
384 }
385
386 /**
387 * @brief enable wakeup source
388 *
389 * @param[in] ptr base address
390 * @param[in] mask wakeup source mask
391 */
pcfg_enable_wakeup_source(PCFG_Type * ptr,uint32_t mask)392 static inline void pcfg_enable_wakeup_source(PCFG_Type *ptr, uint32_t mask)
393 {
394 ptr->WAKE_MASK &= ~mask;
395 }
396
397 /**
398 * @brief disable wakeup source
399 *
400 * @param[in] ptr base address
401 * @param[in] mask source to be disabled as wakeup source
402 */
pcfg_disable_wakeup_source(PCFG_Type * ptr,uint32_t mask)403 static inline void pcfg_disable_wakeup_source(PCFG_Type *ptr, uint32_t mask)
404 {
405 ptr->WAKE_MASK |= mask;
406 }
407
408 /**
409 * @brief set clock gate mode in vpmc domain
410 *
411 * @param[in] ptr base address
412 * @param[in] mode clock gate mode mask
413 */
pcfg_set_periph_clock_mode(PCFG_Type * ptr,uint32_t mode)414 static inline void pcfg_set_periph_clock_mode(PCFG_Type *ptr, uint32_t mode)
415 {
416 ptr->SCG_CTRL = mode;
417 }
418
419 /**
420 * @brief check if irc24m is trimmed
421 *
422 * @param[in] ptr base address
423 *
424 * @retval true if it is trimmed
425 */
pcfg_irc24m_is_trimmed(PCFG_Type * ptr)426 static inline bool pcfg_irc24m_is_trimmed(PCFG_Type *ptr)
427 {
428 return ptr->RC24M & PCFG_RC24M_RC_TRIMMED_MASK;
429 }
430
431 /**
432 * @brief reload irc24m trim value
433 *
434 * @param[in] ptr base address
435 */
pcfg_irc24m_reload_trim(PCFG_Type * ptr)436 static inline void pcfg_irc24m_reload_trim(PCFG_Type *ptr)
437 {
438 ptr->RC24M &= ~PCFG_RC24M_RC_TRIMMED_MASK;
439 }
440
441 /**
442 * @brief config irc24m track
443 *
444 * @param[in] ptr base address
445 * @param[in] config config data
446 */
447 void pcfg_irc24m_config_track(PCFG_Type *ptr, pcfg_irc24m_config_t *config);
448
449 /*
450 * @brief set DCDC voltage at standby mode
451 * @param[in] ptr base address
452 * @param[in] mv target voltage
453 * @retval status_success if successfully configured
454 */
455 hpm_stat_t pcfg_dcdc_set_lpmode_voltage(PCFG_Type *ptr, uint16_t mv);
456
457 /*
458 * @brief set output voltage of LDO 2.5V in mV
459 * @param[in] ptr base address
460 * @param[in] mv target voltage
461 * @retval status_success if successfully configured
462 */
463 hpm_stat_t pcfg_ldo2p5_set_voltage(PCFG_Type *ptr, uint16_t mv);
464
465 /*
466 * @brief set DCDC voltage
467 * @param[in] ptr base address
468 * @param[in] mv target voltage
469 * @retval status_success if successfully configured
470 */
471 hpm_stat_t pcfg_dcdc_set_voltage(PCFG_Type *ptr, uint16_t mv);
472
473 /*
474 * @brief set output voltage of LDO 1V in mV
475 * @param[in] ptr base address
476 * @param[in] mv target voltage
477 * @retval status_success if successfully configured
478 */
479 hpm_stat_t pcfg_ldo1p1_set_voltage(PCFG_Type *ptr, uint16_t mv);
480
481 /*
482 * @brief get current DCDC current level in mA
483 *
484 * @param[in] ptr base address
485 * @retval Current level at mA
486 */
487 uint16_t pcfg_dcdc_get_current_level(PCFG_Type *ptr);
488
489
490 #ifdef __cplusplus
491 }
492 #endif
493 /**
494 * @}
495 */
496
497 #endif /* HPM_PCFG_DRV_H */
498