• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 #define PCFG_DCDC_MODE_TURN_OFF   (0U)
23 #define PCFG_DCDC_MODE_PERFORMACE (1U)
24 #define PCFG_DCDC_MODE_GENERIC    (2U)
25 #define PCFG_DCDC_MODE_EXPERT     (3U)
26 
27 #define PCFG_CLOCK_GATE_MODE_ALWAYS_ON          (0x11U)
28 #define PCFG_CLOCK_GATE_MODE_ALWAYS_OFF         (0x10U)
29 #define PCFG_CLOCK_GATE_MODE_ALWAYS_FOLLOW_FLOW (0x01U)
30 
31 /* @brief PCFG modules */
32 typedef enum {
33     pcfg_module_fuse = 0,
34     pcfg_module_sram,
35     pcfg_module_vad,
36     pcfg_module_gpio,
37     pcfg_module_ioc,
38     pcfg_module_timer,
39     pcfg_module_wdog,
40     pcfg_module_uart,
41     pcfg_module_debug,
42 } pcfg_module_t;
43 
44 /* @brief PCFG irc24m reference */
45 typedef enum {
46     pcfg_irc24m_reference_32k = 0,
47     pcfg_irc24m_reference_24m_xtal = 1
48 } pcfg_irc24m_reference_t;
49 
50 /* @brief PCFG status */
51 enum {
52     status_pcfg_ldo_out_of_range = MAKE_STATUS(status_group_pcfg, 1),
53 };
54 
55 /* @brief PCFG irc24m config */
56 typedef struct {
57     uint32_t freq_in_hz;
58     pcfg_irc24m_reference_t reference;
59     bool return_to_default_on_xtal_loss;
60     bool free_run;
61 } pcfg_irc24m_config_t;
62 
63 
64 #define PCFG_CLOCK_GATE_CONTROL_MASK(module, mode) \
65     ((uint32_t) (mode) << ((module) << 1))
66 
67 #define PCFG_DEBUG_STOP_SOURCE_ENABLE_CORE0 (PCFG_DEBUG_STOP_CPU0_MASK)
68 #define PCFG_DEBUG_STOP_SOURCE_DISABLE_CORE0 (0)
69 #define PCFG_DEBUG_STOP_SOURCE_ENABLE_CORE1 (PCFG_DEBUG_STOP_CPU1_MASK)
70 #define PCFG_DEBUG_STOP_SOURCE_DISABLE_CORE1 (0)
71 
72 #ifdef __cplusplus
73 extern "C" {
74 #endif
75 
76 /**
77  * @brief bandgap disable power save mode
78  *
79  * @param ptr base address
80  */
pcfg_bandgap_disable_power_save_mode(PCFG_Type * ptr)81 static inline void pcfg_bandgap_disable_power_save_mode(PCFG_Type *ptr)
82 {
83     ptr->BANDGAP &= ~PCFG_BANDGAP_POWER_SAVE_MASK;
84 }
85 
86 /**
87  * @brief bandgap enable power save mode
88  *
89  * @param ptr base address
90  */
pcfg_bandgap_enable_power_save_mode(PCFG_Type * ptr)91 static inline void pcfg_bandgap_enable_power_save_mode(PCFG_Type *ptr)
92 {
93     ptr->BANDGAP |= PCFG_BANDGAP_POWER_SAVE_MASK;
94 }
95 
pcfg_bandgap_disable_lowpower_mode(PCFG_Type * ptr)96 static inline void pcfg_bandgap_disable_lowpower_mode(PCFG_Type *ptr)
97 {
98     ptr->BANDGAP &= ~PCFG_BANDGAP_LOWPOWER_MODE_MASK;
99 }
100 
101 /**
102  * @brief bandgap enable low power mode
103  *
104  * @param ptr base address
105  */
pcfg_bandgap_enable_lowpower_mode(PCFG_Type * ptr)106 static inline void pcfg_bandgap_enable_lowpower_mode(PCFG_Type *ptr)
107 {
108     ptr->BANDGAP |= PCFG_BANDGAP_LOWPOWER_MODE_MASK;
109 }
110 
111 /**
112  * @brief check if bandgap is trimmed or not
113  *
114  * @param ptr base address
115  *
116  * @return true if bandgap is trimmed
117  */
pcfg_bandgap_is_trimmed(PCFG_Type * ptr)118 static inline bool pcfg_bandgap_is_trimmed(PCFG_Type *ptr)
119 {
120     return ptr->BANDGAP & PCFG_BANDGAP_VBG_TRIMMED_MASK;
121 }
122 
123 /**
124  * @brief bandgap reload trim value
125  *
126  * @param ptr base address
127  */
pcfg_bandgap_reload_trim(PCFG_Type * ptr)128 static inline void pcfg_bandgap_reload_trim(PCFG_Type *ptr)
129 {
130     ptr->BANDGAP &= ~PCFG_BANDGAP_VBG_TRIMMED_MASK;
131 }
132 
133 /**
134  * @brief turn off LDO 1V
135  *
136  * @param ptr base address
137  */
pcfg_ldo1p1_turn_off(PCFG_Type * ptr)138 static inline void pcfg_ldo1p1_turn_off(PCFG_Type *ptr)
139 {
140     ptr->LDO1P1 &= ~PCFG_LDO1P1_ENABLE_MASK;
141 }
142 
143 /**
144  * @brief turn of LDO 1V
145  *
146  * @param ptr base address
147  */
pcfg_ldo1p1_turn_on(PCFG_Type * ptr)148 static inline void pcfg_ldo1p1_turn_on(PCFG_Type *ptr)
149 {
150     ptr->LDO1P1 |= PCFG_LDO1P1_ENABLE_MASK;
151 }
152 
153 /*
154  * @brief set output voltage of LDO 1V in mV
155  * @param ptr base address
156  * @param mv target voltage
157  * @retval status_success if successfully configured
158  */
159 hpm_stat_t pcfg_ldo1p1_set_voltage(PCFG_Type *ptr, uint16_t mv);
160 
161 /**
162  * @brief turn off LDO2P5
163  *
164  * @param ptr base address
165  */
pcfg_ldo2p5_turn_off(PCFG_Type * ptr)166 static inline void pcfg_ldo2p5_turn_off(PCFG_Type *ptr)
167 {
168     ptr->LDO2P5 &= ~PCFG_LDO2P5_ENABLE_MASK;
169 }
170 
171 /**
172  * @brief turn on LDO 2.5V
173  *
174  * @param ptr base address
175  */
pcfg_ldo2p5_turn_on(PCFG_Type * ptr)176 static inline void pcfg_ldo2p5_turn_on(PCFG_Type *ptr)
177 {
178     ptr->LDO2P5 |= PCFG_LDO2P5_ENABLE_MASK;
179 }
180 
181 /**
182  * @brief check if LDO 2.5V is stable
183  *
184  * @param ptr base address
185  *
186  * @return true if LDO2P5 is stable
187  */
pcfg_ldo2p5_is_stable(PCFG_Type * ptr)188 static inline bool pcfg_ldo2p5_is_stable(PCFG_Type *ptr)
189 {
190     return PCFG_LDO2P5_READY_GET(ptr->LDO2P5);
191 }
192 /*
193  * @brief set output voltage of LDO 2.5V in mV
194  * @param ptr base address
195  * @param mv target voltage
196  * @retval status_success if successfully configured
197  */
198 hpm_stat_t pcfg_ldo2p5_set_voltage(PCFG_Type *ptr, uint16_t mv);
199 
200 /*
201  * @brief set DCDC voltage
202  * @param ptr base address
203  * @param mv target voltage
204  * @retval status_success if successfully configured
205  */
206 hpm_stat_t pcfg_dcdc_set_voltage(PCFG_Type *ptr, uint16_t mv);
207 
208 /*
209  * @brief check if DCDC is stable or not
210  * @param ptr base address
211  * @retval true if DCDC is stable
212  */
pcfg_dcdc_is_stable(PCFG_Type * ptr)213 static inline bool pcfg_dcdc_is_stable(PCFG_Type *ptr)
214 {
215     return PCFG_DCDC_MODE_READY_GET(ptr->DCDC_MODE);
216 }
217 
218 /*
219  * @brief check if DCDC is stable or not
220  * @param ptr base address
221  */
pcfg_dcdc_set_mode(PCFG_Type * ptr,uint8_t mode)222 static inline void pcfg_dcdc_set_mode(PCFG_Type *ptr, uint8_t mode)
223 {
224     ptr->DCDC_MODE = (ptr->DCDC_MODE & ~PCFG_DCDC_MODE_MODE_MASK) | PCFG_DCDC_MODE_MODE_SET(ptr->DCDC_MODE);
225 }
226 
227 /*
228  * @brief set DCDC voltage at standby mode
229  * @param ptr base address
230  * @param mv target voltage
231  * @retval status_success if successfully configured
232  */
233 hpm_stat_t pcfg_dcdc_set_lpmode_voltage(PCFG_Type *ptr, uint16_t mv);
234 
235 /**
236  * @brief set low power current limit
237  *
238  * @param ptr base address
239  * @param limit current limit at low power mode
240  * @param under_limit set to true means current is less than limit
241  */
pcfg_dcdc_set_lp_current_limit(PCFG_Type * ptr,uint8_t limit,bool under_limit)242 static inline void pcfg_dcdc_set_lp_current_limit(PCFG_Type *ptr, uint8_t limit, bool under_limit)
243 {
244     ptr->DCDC_PROT = (ptr->DCDC_PROT & ~(PCFG_DCDC_PROT_ILIMIT_LP_MASK | PCFG_DCDC_PROT_OVERLOAD_LP_MASK))
245         | PCFG_DCDC_PROT_ILIMIT_LP_SET(limit) | PCFG_DCDC_PROT_OVERLOAD_LP_SET(!under_limit);
246 }
247 
248 /**
249  * @brief disable power loss protection
250  *
251  * @param ptr base address
252  */
pcfg_dcdc_disable_power_loss_prot(PCFG_Type * ptr)253 static inline void pcfg_dcdc_disable_power_loss_prot(PCFG_Type *ptr)
254 {
255     ptr->DCDC_PROT |= PCFG_DCDC_PROT_DISABLE_POWER_LOSS_MASK;
256 }
257 
258 /**
259  * @brief enable power loss protection
260  *
261  * @param ptr base address
262  */
pcfg_dcdc_enable_power_loss_prot(PCFG_Type * ptr)263 static inline void pcfg_dcdc_enable_power_loss_prot(PCFG_Type *ptr)
264 {
265     ptr->DCDC_PROT &= ~PCFG_DCDC_PROT_DISABLE_POWER_LOSS_MASK;
266 }
267 
268 /**
269  * @brief check if power loss flag is set
270  *
271  * @param ptr base address
272  *
273  * @return true if power loss is set
274  */
pcfg_dcdc_is_power_loss(PCFG_Type * ptr)275 static inline bool pcfg_dcdc_is_power_loss(PCFG_Type *ptr)
276 {
277     return PCFG_DCDC_PROT_POWER_LOSS_FLAG_GET(ptr->DCDC_PROT);
278 }
279 
280 /**
281  * @brief disable over voltage protection
282  *
283  * @param ptr base address
284  */
pcfg_dcdc_disable_over_voltage_prot(PCFG_Type * ptr)285 static inline void pcfg_dcdc_disable_over_voltage_prot(PCFG_Type *ptr)
286 {
287     ptr->DCDC_PROT |= PCFG_DCDC_PROT_DISABLE_OVERVOLTAGE_MASK;
288 }
289 
290 /**
291  * @brief enable over voltage protection
292  *
293  * @param ptr base address
294  */
pcfg_dcdc_ensable_over_voltage_prot(PCFG_Type * ptr)295 static inline void pcfg_dcdc_ensable_over_voltage_prot(PCFG_Type *ptr)
296 {
297     ptr->DCDC_PROT &= ~PCFG_DCDC_PROT_DISABLE_OVERVOLTAGE_MASK;
298 }
299 
300 /**
301  * @brief checkover voltage flag
302  *
303  * @param ptr base address
304  * @return true if flag is set
305  */
pcfg_dcdc_is_over_voltage(PCFG_Type * ptr)306 static inline bool pcfg_dcdc_is_over_voltage(PCFG_Type *ptr)
307 {
308     return PCFG_DCDC_PROT_OVERVOLT_FLAG_GET(ptr->DCDC_PROT) & PCFG_DCDC_PROT_OVERVOLT_FLAG_MASK;
309 }
310 
311 /**
312  * @brief disable current measurement
313  *
314  * @param ptr base address
315  */
pcfg_dcdc_disable_measure_current(PCFG_Type * ptr)316 static inline void pcfg_dcdc_disable_measure_current(PCFG_Type *ptr)
317 {
318     ptr->DCDC_CURRENT &= ~PCFG_DCDC_CURRENT_ESTI_EN_MASK;
319 }
320 
321 /**
322  * @brief enable current measurement
323  *
324  * @param ptr base address
325  */
pcfg_dcdc_enable_measure_current(PCFG_Type * ptr)326 static inline void pcfg_dcdc_enable_measure_current(PCFG_Type *ptr)
327 {
328     ptr->DCDC_CURRENT |= PCFG_DCDC_CURRENT_ESTI_EN_MASK;
329 }
330 
331 /**
332  * @brief check if measured current is valid
333  *
334  * @param ptr base address
335  *
336  * @return true if measured current is valid
337  */
pcfg_dcdc_is_measure_current_valid(PCFG_Type * ptr)338 static inline bool pcfg_dcdc_is_measure_current_valid(PCFG_Type *ptr)
339 {
340     return ptr->DCDC_CURRENT & PCFG_DCDC_CURRENT_VALID_MASK;
341 }
342 
343 /*
344  * @brief get current DCDC current level in mA
345  *
346  * @param ptr base address
347  * @retval Current level at mA
348  */
349 uint16_t pcfg_dcdc_get_current_level(PCFG_Type *ptr);
350 
351 /**
352  * @brief get DCDC start time in number of 24MHz clock cycles
353  *
354  * @param ptr base address
355  *
356  * @return dcdc start time in cycles
357  */
pcfg_get_dcdc_start_time_in_cycle(PCFG_Type * ptr)358 static inline uint32_t pcfg_get_dcdc_start_time_in_cycle(PCFG_Type *ptr)
359 {
360     return PCFG_DCDC_START_TIME_START_TIME_GET(ptr->DCDC_START_TIME);
361 }
362 
363 /**
364  * @brief get DCDC resume time in number of 24MHz clock cycles
365  *
366  * @param ptr base address
367  *
368  * @return dcdc resuem time in cycles
369  */
pcfg_get_dcdc_resume_time_in_cycle(PCFG_Type * ptr)370 static inline uint32_t pcfg_get_dcdc_resume_time_in_cycle(PCFG_Type *ptr)
371 {
372     return PCFG_DCDC_RESUME_TIME_RESUME_TIME_GET(ptr->DCDC_RESUME_TIME);
373 }
374 
375 /**
376  * @brief set DCDC start time in 24MHz clock cycles
377  *
378  * @param ptr base address
379  * @param cycles start time in cycles
380  */
pcfg_set_dcdc_start_time_in_cycle(PCFG_Type * ptr,uint32_t cycles)381 static inline void pcfg_set_dcdc_start_time_in_cycle(PCFG_Type *ptr, uint32_t cycles)
382 {
383     ptr->DCDC_START_TIME = PCFG_DCDC_START_TIME_START_TIME_SET(cycles);
384 }
385 
386 /**
387  * @brief set DCDC resuem time in 24MHz clock cycles
388  *
389  * @param ptr base address
390  * @param cycles resume time in cycles
391  */
pcfg_set_dcdc_resume_time_in_cycle(PCFG_Type * ptr,uint32_t cycles)392 static inline void pcfg_set_dcdc_resume_time_in_cycle(PCFG_Type *ptr, uint32_t cycles)
393 {
394     ptr->DCDC_RESUME_TIME = PCFG_DCDC_RESUME_TIME_RESUME_TIME_SET(cycles);
395 }
396 
397 /**
398  * @brief disable power trap
399  *
400  * @param ptr base address
401  */
pcfg_disable_power_trap(PCFG_Type * ptr)402 static inline void pcfg_disable_power_trap(PCFG_Type *ptr)
403 {
404     ptr->POWER_TRAP &= ~PCFG_POWER_TRAP_TRAP_MASK;
405 }
406 
407 /**
408  * @brief enable power trap
409  *
410  * @param ptr base address
411  */
pcfg_enable_power_trap(PCFG_Type * ptr)412 static inline void pcfg_enable_power_trap(PCFG_Type *ptr)
413 {
414     ptr->POWER_TRAP |= PCFG_POWER_TRAP_TRAP_MASK;
415 }
416 
417 /**
418  * @brief check if power trap is triggered
419  *
420  * @param ptr base address
421  *
422  * @return true if power trap is triggered
423  */
pcfg_is_power_trap_triggered(PCFG_Type * ptr)424 static inline bool pcfg_is_power_trap_triggered(PCFG_Type *ptr)
425 {
426     return ptr->POWER_TRAP & PCFG_POWER_TRAP_TRIGGERED_MASK;
427 }
428 
429 /**
430  * @brief clear power trap trigger flag
431  *
432  * @param ptr base address
433  */
pcfg_clear_power_trap_trigger_flag(PCFG_Type * ptr)434 static inline void pcfg_clear_power_trap_trigger_flag(PCFG_Type *ptr)
435 {
436     ptr->POWER_TRAP |= PCFG_POWER_TRAP_TRIGGERED_MASK;
437 }
438 
439 /**
440  * @brief disable dcdc retention
441  *
442  * @param ptr base address
443  */
pcfg_disable_dcdc_retention(PCFG_Type * ptr)444 static inline void pcfg_disable_dcdc_retention(PCFG_Type *ptr)
445 {
446     ptr->POWER_TRAP &= ~PCFG_POWER_TRAP_RETENTION_MASK;
447 }
448 
449 /**
450  * @brief enable dcdc retention to retain soc sram data
451  *
452  * @param ptr base address
453  */
pcfg_enable_dcdc_retention(PCFG_Type * ptr)454 static inline void pcfg_enable_dcdc_retention(PCFG_Type *ptr)
455 {
456     ptr->POWER_TRAP |= PCFG_POWER_TRAP_RETENTION_MASK;
457 }
458 
459 /**
460  * @brief clear wakeup cause flag
461  *
462  * @param ptr base address
463  * @param mask mask of flags to be cleared
464  */
pcfg_clear_wakeup_cause(PCFG_Type * ptr,uint32_t mask)465 static inline void pcfg_clear_wakeup_cause(PCFG_Type *ptr, uint32_t mask)
466 {
467     ptr->WAKE_CAUSE |= mask;
468 }
469 
470 /**
471  * @brief get wakeup cause
472  *
473  * @param ptr base address
474  *
475  * @return mask of wake cause
476  */
pcfg_get_wakeup_cause(PCFG_Type * ptr)477 static inline uint32_t pcfg_get_wakeup_cause(PCFG_Type *ptr)
478 {
479     return ptr->WAKE_CAUSE;
480 }
481 
482 /**
483  * @brief enable wakeup source
484  *
485  * @param ptr base address
486  * @param mask wakeup source mask
487  */
pcfg_enable_wakeup_source(PCFG_Type * ptr,uint32_t mask)488 static inline void pcfg_enable_wakeup_source(PCFG_Type *ptr, uint32_t mask)
489 {
490     ptr->WAKE_MASK &= ~mask;
491 }
492 
493 /**
494  * @brief disable wakeup source
495  *
496  * @param ptr base address
497  * @param mask source to be disabled as wakeup source
498  */
pcfg_disable_wakeup_source(PCFG_Type * ptr,uint32_t mask)499 static inline void pcfg_disable_wakeup_source(PCFG_Type *ptr, uint32_t mask)
500 {
501     ptr->WAKE_MASK |= mask;
502 }
503 
504 /**
505  * @brief set clock gate mode in pmic domain
506  *
507  * @param ptr base address
508  * @param mode clock gate mode mask
509  */
pcfg_set_clock_gate_in_pmic(PCFG_Type * ptr,uint32_t mode)510 static inline void pcfg_set_clock_gate_in_pmic(PCFG_Type *ptr, uint32_t mode)
511 {
512     ptr->SCG_CTRL = mode;
513 }
514 
pcfg_config_debug_stop_source(PCFG_Type * ptr,uint8_t mask)515 static inline void pcfg_config_debug_stop_source(PCFG_Type *ptr, uint8_t mask)
516 {
517     ptr->DEBUG_STOP = mask;
518 }
519 
520 /**
521  * @brief check if irc24m is trimmed
522  *
523  * @param ptr base address
524  *
525  * @return true if it is trimmed
526  */
pcfg_irc24m_is_trimmed(PCFG_Type * ptr)527 static inline bool pcfg_irc24m_is_trimmed(PCFG_Type *ptr)
528 {
529     return ptr->RC24M & PCFG_RC24M_RC_TRIMMED_MASK;
530 }
531 
532 /**
533  * @brief reload irc24m trim value
534  *
535  * @param ptr base address
536  */
pcfg_irc24m_reload_trim(PCFG_Type * ptr)537 static inline void pcfg_irc24m_reload_trim(PCFG_Type *ptr)
538 {
539     ptr->RC24M &= ~PCFG_RC24M_RC_TRIMMED_MASK;
540 }
541 
542 /**
543  * @brief config irc24m track
544  *
545  * @param ptr base address
546  * @param config config data
547  */
548 void pcfg_irc24m_config_track(PCFG_Type *ptr, pcfg_irc24m_config_t *config);
549 
550 #ifdef __cplusplus
551 }
552 #endif
553 /**
554  * @}
555  */
556 
557 #endif /* HPM_PMIC_PCFG_DRV_H */
558