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