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