ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_pwr.c
1 /*
2  *****************************************************************************
3  * @file: adi_pwr.c
4  * @brief: Power Management driver implementation.
5  *-----------------------------------------------------------------------------
6  *
7 Copyright (c) 2016-2017 Analog Devices, Inc.
8 
9 All rights reserved.
10 
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13  - Redistributions of source code must retain the above copyright notice,
14  this list of conditions and the following disclaimer.
15  - Redistributions in binary form must reproduce the above copyright notice,
16  this list of conditions and the following disclaimer in the documentation
17  and/or other materials provided with the distribution.
18  - Modified versions of the software must be conspicuously marked as such.
19  - This software is licensed solely and exclusively for use with processors
20  manufactured by or for Analog Devices, Inc.
21  - This software may not be combined or merged with other code in any manner
22  that would cause the software to become subject to terms and conditions
23  which differ from those listed here.
24  - Neither the name of Analog Devices, Inc. nor the names of its
25  contributors may be used to endorse or promote products derived
26  from this software without specific prior written permission.
27  - The use of this software may or may not infringe the patent rights of one
28  or more patent holders. This license does not release you from the
29  requirement that you obtain separate licenses from these patent holders
30  to use this software.
31 
32 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND ANY
33 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
34 TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
35 NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES
37 (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL
38 PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
39 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43  *
44  *****************************************************************************/
45 
56 #include <stdlib.h> /* for 'NULL' */
57 #include <adi_callback.h>
58 #include <adi_pwr_config.h>
59 #include <rtos_map/adi_rtos_map.h>
60 #include <drivers/pwr/adi_pwr.h>
61 #include "adi_pwr_def.h"
62 #include <drivers/gpio/adi_gpio.h>
63 
64 #ifdef __ICCARM__
65 /*
66 * IAR MISRA C 2004 error suppressions.
67 *
68 * Pm011 (rule 6.3): Types which specify sign and size should be used
69 * We use bool which is accepted by MISRA but the toolchain does not accept it
70 * Pm073 (rule 14.7): a function should have a single point of exit
71 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
72 * Multiple returns are used for error handling.
73 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
74 * The rule makes an exception for memory-mapped register accesses.
75 * Pm057 (rule 15.2): Every non-empty case clause in a switch statement shall be terminated with a break statement.
76 * In some cases we have return statement instead of break. It is not valid to both return and break in MISRA 2012.
77 */
78 #pragma diag_suppress=Pm011,Pm073,Pm050,Pm140,Pm143,Pm057
79 #endif /* __ICCARM__ */
80 
83 /*----------------------------------------------------------------------------
84  Internal Clock Variables. The external ones are defined in system.c
85  *---------------------------------------------------------------------------*/
86 #ifdef ADI_DEBUG
87 /* not needed unless its debug mode */
88 extern uint32_t lfClock; /* "lf_clk" coming out of LF mux */
89 #endif
90 
91 extern uint32_t hfClock; /* "root_clk" output of HF mux */
92 extern uint32_t gpioClock; /* external GPIO clock */
93 
94 static ADI_CALLBACK gpfCallbackFunction;
95 static void *gpPowcbParam = NULL;
96 static uint32_t gnLowPowerIntOccFlag = 0u;
97 
100 /*----------------------------------------------------------------------------
101  Clock functions
102  *---------------------------------------------------------------------------*/
110 {
111  /* Enable internal HF oscillators */
112  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
113 
114  pADI_CLKG0_OSC->CTL = OSCCTRL_CONFIG_VALUE;
115 
116  gpfCallbackFunction = NULL;
117  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
118 
119  /* Switch on the internal HF oscillator */
120  pADI_CLKG0_OSC->CTL |= BITM_CLKG_OSC_CTL_HFOSC_EN;
121 
122  /* wait for HF OSC to stabilize */
123  while ((pADI_CLKG0_OSC->CTL & (1U << BITP_CLKG_OSC_CTL_HFOSC_OK)) == 0u)
124  {
125  }
126 
127  /* Switch over to the internal HF oscillator */
128  pADI_CLKG0_CLK->CTL0 &= ~(BITM_CLKG_CLK_CTL0_CLKMUX);
129 
130  /* complete remaining reset sequence */
131  pADI_CLKG0_CLK->CTL0 = CLOCK_CTL0_CONFIG_VALUE;
132  pADI_CLKG0_CLK->CTL1 = CLOCK_CTL1_CONFIG_VALUE;
133 
134 #if defined(__ADUCM4x50__)
135  pADI_CLKG0_CLK->CTL2 = CLOCK_CTL2_CONFIG_VALUE;
136 #endif /*__ADUCM4x50__ */
137 
138  pADI_CLKG0_CLK->CTL3 = CLOCK_CTL3_CONFIG_VALUE;
139  /* No CLK CTL4 */
140  pADI_CLKG0_CLK->CTL5 = CLOCK_CTL5_CONFIG_VALUE;
141 
142  /*
143  * Configure the power management registers
144  */
145  pADI_PMG0->IEN = PWM_INTERRUPT_CONFIG;
146  pADI_PMG0->PWRMOD = PWM_PWRMOD_CONFIG;
147  pADI_PMG0->CTL1 = PWM_HPBUCK_CONTROL;
148 
149  /* disable external HF crystal oscillator */
150  /* (don't disable LF crystal or the RTC will lose time */
151  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
152  pADI_CLKG0_OSC->CTL &= ~BITM_CLKG_OSC_CTL_HFX_EN;
153 
154  NVIC_EnableIRQ(PMG0_VREG_OVR_IRQn);
155  NVIC_EnableIRQ(PMG0_BATT_RANGE_IRQn);
156 
157  NVIC_EnableIRQ(CLKG_XTAL_OSC_EVT_IRQn);
158  NVIC_EnableIRQ(CLKG_PLL_EVT_IRQn);
159 
160  /* compute new internal clocks based on the newly reset controller */
162 
163  return(ADI_PWR_SUCCESS);
164 }
165 
166 
180 {
182  return(ADI_PWR_SUCCESS);
183 }
184 
199  const ADI_CALLBACK pfCallback,
200  void *pcbParam
201  )
202 {
203 
204 #ifdef ADI_DEBUG
205  if(pfCallback == NULL)
206  {
207  return(ADI_PWR_NULL_POINTER);
208  }
209 #endif
210 
211  gpfCallbackFunction = pfCallback;
212  gpPowcbParam = pcbParam;
213 
214  return ADI_PWR_SUCCESS;
215 }
216 
228 ADI_PWR_RESULT adi_pwr_SetExtClkFreq (const uint32_t ExtClkFreq)
229 {
230 #ifdef ADI_DEBUG
231  if(ExtClkFreq > MAXIMUM_EXT_CLOCK)
232  {
234  }
235 #endif
236  gpioClock = ExtClkFreq;
237  return(ADI_PWR_SUCCESS);
238 }
239 
252 {
253  uint32_t tmp;
254  ADI_INT_STATUS_ALLOC();
255 
256 #ifdef ADI_DEBUG
257  /* Validate the given clock ID */
258  switch (eClockID)
259  {
262 
263 #if defined(__ADUCM4x50__)
264  case ADI_CLOCK_MUX_SPLL_GPIO:
265 #endif /* __ADUCM4x50__ */
266  break;
267 
268 
269  /* Any other clock ID is not valid since we are configuring the SPLL clock multiplexer.
270  * Only valid input clock to the multiplexer is HFOSC, HFXTAL, GPIO */
271  default:
272  return(ADI_PWR_INVALID_CLOCK_ID);
273  }
274 #endif /* ADI_DEBUG */
275 
276  /* update the mux setting inside a critical region */
277  ADI_ENTER_CRITICAL_REGION();
278  tmp = (pADI_CLKG0_CLK->CTL0 & ~BITM_CLKG_CLK_CTL0_PLL_IPSEL);
279  tmp |= (( (uint32_t)eClockID - (uint32_t)ADI_CLOCK_MUX_SPLL_HFOSC) << BITP_CLKG_CLK_CTL0_PLL_IPSEL);
280  pADI_CLKG0_CLK->CTL0 = tmp;
281  ADI_EXIT_CRITICAL_REGION();
282 
283  return(ADI_PWR_SUCCESS);
284 }
285 
299 {
300  uint32_t tmp;
301  ADI_INT_STATUS_ALLOC();
302 
303 #ifdef ADI_DEBUG
304  switch (eClockID)
305  {
306 
309  break;
310  /* Any other clock ID is not valid since we are configuring the Low frequency clock multiplexer.
311  * Only valid input clock to the multiplexer is LFOSC, LFXTAL */
312 
313  default:
314  return(ADI_PWR_INVALID_CLOCK_ID);
315 
316  }
317 #endif /* ADI_DEBUG */
318 
319  /* update the mux setting inside a critical region */
320  ADI_ENTER_CRITICAL_REGION();
321 
322  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
323  tmp = (pADI_CLKG0_OSC->CTL & ~BITM_CLKG_OSC_CTL_LFCLK_MUX);
324  tmp |=(((uint32_t)eClockID - (uint32_t)ADI_CLOCK_MUX_LFCLK_LFOSC) << BITP_CLKG_OSC_CTL_LFCLK_MUX);
325  pADI_CLKG0_OSC->CTL = tmp;
326 
327  ADI_EXIT_CRITICAL_REGION();
328 
329  return(ADI_PWR_SUCCESS);
330 }
331 
347 {
348  uint32_t tmp;
349  ADI_INT_STATUS_ALLOC();
350 
351 #ifdef ADI_DEBUG
352  switch (eClockID)
353  {
354 
358  break;
359  /* Any other clock ID is not valid since we are configuring the out clock multiplexer.*/
360 
361  default:
362  return(ADI_PWR_INVALID_CLOCK_ID);
363  }
364 #endif /* ADI_DEBUG */
365 
366  /* update the mux setting inside a critical region */
367  ADI_ENTER_CRITICAL_REGION();
368 
369  tmp = (pADI_CLKG0_CLK->CTL0 & ~BITM_CLKG_CLK_CTL0_RCLKMUX);
370  tmp |=(((uint32_t)eClockID - (uint32_t)ADI_CLOCK_MUX_REF_HFOSC_CLK) << BITP_CLKG_CLK_CTL0_RCLKMUX);
371  pADI_CLKG0_CLK->CTL0 = tmp;
372 
373  ADI_EXIT_CRITICAL_REGION();
374 
375  return(ADI_PWR_SUCCESS);
376 }
377 
391 {
392  uint32_t tmp;
393  ADI_INT_STATUS_ALLOC();
394 
395 #ifdef ADI_DEBUG
396  switch (eClockID)
397  {
402  break;
403  /* Any other clock ID is not valid since we are configuring the root clock multiplexer.
404  * Only valid input clock to the multiplexer is HFOSC, HFXTAL, SPLL, GPIO */
405  default:
406  return(ADI_PWR_INVALID_CLOCK_ID);
407  }
408 #endif /* ADI_DEBUG */
409 
410  /* update the mux setting inside a critical region */
411  ADI_ENTER_CRITICAL_REGION();
412 
413  tmp = (pADI_CLKG0_CLK->CTL0 & ~BITM_CLKG_CLK_CTL0_CLKMUX);
414  tmp |= (((uint32_t)eClockID - (uint32_t)ADI_CLOCK_MUX_ROOT_HFOSC) << BITP_CLKG_CLK_CTL0_CLKMUX);
415  pADI_CLKG0_CLK->CTL0 = tmp;
416 
417  ADI_EXIT_CRITICAL_REGION();
418 
419  return(ADI_PWR_SUCCESS);
420 }
421 
422 
435 {
436 #ifdef ADI_DEBUG
437  /* Trap here if the app fails to set the external clock frequency. */
438  if (0u == gpioClock)
439  {
440  return (ADI_PWR_FAILURE);
441  }
442 
443  if(pExtClock == NULL)
444  {
445  return (ADI_PWR_NULL_POINTER);
446  }
447 #endif
448  *pExtClock = gpioClock;
449  return ADI_PWR_SUCCESS;
450 }
451 
452 
467 ADI_PWR_RESULT adi_pwr_GetClockFrequency (const ADI_CLOCK_ID eClockId, uint32_t *pClock )
468 {
469  uint32_t src, nDiv;
470 
471 #ifdef ADI_DEBUG
472  /* trap here if the app fails to call SystemInit(). */
473  if ((0u == hfClock) || (0u == lfClock))
474  {
476  }
477 #endif
478 
479  /* refresh internal clock variables */
481  src = hfClock;
482 
483  switch (eClockId) {
484 
485  /* HCLOCK domain */
486  case ADI_CLOCK_HCLK:
487  nDiv = (pADI_CLKG0_CLK->CTL1 & BITM_CLKG_CLK_CTL1_HCLKDIVCNT) >> BITP_CLKG_CLK_CTL1_HCLKDIVCNT;
488  break;
489 
490  /* PCLOCK domain */
491  case ADI_CLOCK_PCLK:
492  nDiv = (pADI_CLKG0_CLK->CTL1 & BITM_CLKG_CLK_CTL1_PCLKDIVCNT) >> BITP_CLKG_CLK_CTL1_PCLKDIVCNT;
493  break;
494 
495  default:
497  } /* end switch */
498 
499  if(nDiv == 0u)
500  {
501  nDiv = 1u;
502  }
503 
504  *pClock = (src/nDiv);
505 
506  return ADI_PWR_SUCCESS;
507 }
508 
509 
523 ADI_PWR_RESULT adi_pwr_EnableClock (const ADI_CLOCK_GATE eClockGate, const bool bEnable)
524 {
525  uint32_t mask;
526  ADI_INT_STATUS_ALLOC();
527 
528  mask = (uint16_t)eClockGate;
529  /* update the Clock Gate register in a critical region */
530  ADI_ENTER_CRITICAL_REGION();
531 
532  /* NOTE NEGATIVE LOGIC!!! */
533  if (bEnable == true) {
534 
535  /* clear disable bit */
536  pADI_CLKG0_CLK->CTL5 &= ~mask;
537  } else {
538  /* set disable bit */
539  pADI_CLKG0_CLK->CTL5 |= mask;
540  }
541 
542  /* end critical region */
543  ADI_EXIT_CRITICAL_REGION();
544 
545  return ADI_PWR_SUCCESS;
546 }
547 
548 
565 ADI_PWR_RESULT adi_pwr_SetClockDivider (const ADI_CLOCK_ID eClockId, const uint16_t nDiv)
566 {
567  uint32_t mask;
568  uint32_t value;
569  uint32_t tmp;
570  ADI_INT_STATUS_ALLOC();
571 
572 #ifdef ADI_DEBUG
573  uint32_t hdiv, pdiv;
574 #endif /*ADI_DEBUG*/
575 
576  switch (eClockId)
577  {
578  case ADI_CLOCK_HCLK:
579 #ifdef ADI_DEBUG
580  /* Verify the divide factor is within the range */
581  if ((nDiv > CLOCK_MAX_DIV_VALUE) || (nDiv < CLOCK_MIN_DIV_VALUE))
582  {
584  }
585 
586  /* verify PCLK freq is <= requested HCLK */
587  pdiv = (pADI_CLKG0_CLK->CTL1 & BITM_CLKG_CLK_CTL1_PCLKDIVCNT) >> BITP_CLKG_CLK_CTL1_PCLKDIVCNT;
588  hdiv = nDiv;
589  if (hdiv > pdiv) {
591  }
592 
593  /* verify new PDIV:HDIV ratio will be integral */
594  if ((pdiv % hdiv) != 0u)
595  {
597  }
598 #endif /*ADI_DEBUG*/
599 
600  mask = BITM_CLKG_CLK_CTL1_HCLKDIVCNT;
601  value = (uint32_t)nDiv << BITP_CLKG_CLK_CTL1_HCLKDIVCNT;
602  break;
603 
604  case ADI_CLOCK_PCLK:
605 #ifdef ADI_DEBUG
606 
607  /* Verify the divide factor is within the range */
608  if ((nDiv > CLOCK_MAX_DIV_VALUE) || (nDiv < CLOCK_MIN_DIV_VALUE))
609  {
611  }
612 
613  /* verify requested PCLK freq is <= HCLK */
614  pdiv = nDiv;
615  hdiv = (pADI_CLKG0_CLK->CTL1 & BITM_CLKG_CLK_CTL1_HCLKDIVCNT) >> BITP_CLKG_CLK_CTL1_HCLKDIVCNT;
616  if (hdiv > pdiv) {
618  }
619 
620  /* verify new PDIV:HDIV ratio will be integral */
621  if ((pdiv % hdiv) != 0u)
622  {
624  }
625 #endif /*ADI_DEBUG*/
626  mask = BITM_CLKG_CLK_CTL1_PCLKDIVCNT;
627  value = (uint32_t)nDiv << BITP_CLKG_CLK_CTL1_PCLKDIVCNT;
628  break;
629 
630  case ADI_CLOCK_ACLK:
631 #ifdef ADI_DEBUG
632  /* Verify the divide factor is within the range */
633  if ((nDiv > ACLK_MAX_DIV_VALUE) || (nDiv < ACLK_MIN_DIV_VALUE))
634  {
636  }
637 
638  /* verify requested ACLK freq is <= HCLK */
639  pdiv = nDiv;
640  hdiv = (pADI_CLKG0_CLK->CTL1 & BITM_CLKG_CLK_CTL1_HCLKDIVCNT) >> BITP_CLKG_CLK_CTL1_HCLKDIVCNT;
641  if (hdiv > pdiv) {
643  }
644 
645  /* verify new PDIV:HDIV ratio will be integral */
646  if ((pdiv % hdiv) != 0u)
647  {
649  }
650 #endif /*ADI_DEBUG*/
651 
652  mask = BITM_CLKG_CLK_CTL1_ACLKDIVCNT;
653  value = (uint32_t)nDiv << BITP_CLKG_CLK_CTL1_ACLKDIVCNT;
654  break;
655 
656 
657  default:
659  } /* end switch */
660 
661  /* critical region */
662  ADI_ENTER_CRITICAL_REGION();
663 
664  /* read-modify-write without any interrupts */
665  /* change in a tmp variable and write entire new value all at once */
666  tmp = pADI_CLKG0_CLK->CTL1;
667  tmp &= ~mask; /* blank the field */
668  tmp |= value; /* set the new value */
669  pADI_CLKG0_CLK->CTL1 = tmp; /* write the new value */
670 
671  /* end critical region */
672  ADI_EXIT_CRITICAL_REGION();
673 
674  /* refresh internal clock variables */
676 
677  return ADI_PWR_SUCCESS;
678 }
679 
693 ADI_PWR_RESULT adi_pwr_EnableClockSource (const ADI_CLOCK_SOURCE_ID eClockSource, const bool bEnable)
694 {
695  uint32_t val = 0u;
696  volatile uint32_t *pReg = NULL;
697  uint32_t nMask = 0u;
698  ADI_INT_STATUS_ALLOC();
699 
700  /* This switch statement does not handle every value in the ADI_CLOCK_SOURCE_ID enumeration
701  * which results on a gcc warning. This is done intentionally:
702  * ADI_CLOCK_SOURCE_LFOSC is not checked because it is enabled always and it cannot be disabled
703  * ADI_CLOCK_SOURCE_GPIO is only checked if a specific configuration macro is defined
704  */
705  switch(eClockSource)
706  {
708  val = (1u << BITP_CLKG_OSC_CTL_HFX_EN);
709  pReg = &pADI_CLKG0_OSC->CTL;
710  nMask = BITM_CLKG_OSC_CTL_HFX_OK;
711  break;
712 
714  val = (1u << BITP_CLKG_OSC_CTL_LFX_EN);
715  pReg = &pADI_CLKG0_OSC->CTL;
716  nMask = BITM_CLKG_OSC_CTL_LFX_OK;
717  break;
718 
720  val = (1u << BITP_CLKG_OSC_CTL_HFOSC_EN);
721  pReg = &pADI_CLKG0_OSC->CTL;
722  nMask = BITM_CLKG_OSC_CTL_HFOSC_OK;
723  break;
724 
726  val = (1u << BITP_CLKG_CLK_CTL3_SPLLEN);
727  pReg = &pADI_CLKG0_CLK->CTL3;
728  nMask = BITM_CLKG_CLK_CTL3_SPLLEN;
729  break;
730 
731 #if (ADI_PWR_CFG_ENABLE_CLOCK_SOURCE_GPIO == 1)
734  {
735  return(ADI_PWR_FAILURE);
736  }
738  {
739  return ADI_PWR_SUCCESS;
740  }
741  break;
742 #endif
743 
744  default:
745  return(ADI_PWR_INVALID_PARAM);
746 
747  } /* end switch */
748 
749  ADI_ENTER_CRITICAL_REGION();
750 
751  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
752  if (bEnable == true)
753  {
754  *pReg |= val;
755  if( eClockSource == ADI_CLOCK_SOURCE_SPLL )
756  {
757  /* Wait for the PLL to lock */
758  uint32_t read_status;
759  do {
760  read_status = ((*pREG_CLKG0_CLK_STAT0 & BITM_CLKG_CLK_STAT0_SPLL)>>BITP_CLKG_CLK_STAT0_SPLL);
761  } while (read_status != 1u);
762  }
763  }
764  else
765  {
766  *pReg &= ~val;
767  }
768 
769  ADI_EXIT_CRITICAL_REGION();
770 
771  if((nMask !=0u) && (bEnable == true))
772  {
773  while(0u== (pADI_CLKG0_OSC->CTL & nMask)){}
774  }
775 
776 
777  return (ADI_PWR_SUCCESS);
778 }
779 
780 
795 {
796  uint32_t val = pADI_CLKG0_OSC->CTL;
797 
798 #ifdef ADI_DEBUG
799  if(peStatus == NULL)
800  {
801  return ADI_PWR_NULL_POINTER;
802  }
803 #endif /* ADI_DEBUG */
804 
805  *peStatus = ADI_CLOCK_SOURCE_DISABLED;
806 
807  switch(eClockSource)
808  {
810  if ((val & BITM_CLKG_OSC_CTL_HFOSC_EN) != 0u)
811  {
812  /* Clock source enabled, now check for stable */
813  if ((val & BITM_CLKG_OSC_CTL_HFOSC_OK) != 0u)
814  {
816  }
817  else
818  {
820  }
821  }
822  break;
823 
825  if ((val & BITM_CLKG_OSC_CTL_HFX_EN) != 0u)
826  {
827  /* Clock source enabled, now check for stable */
828  if ((val & BITM_CLKG_OSC_CTL_HFX_OK) != 0u)
829  {
831  }
832  else
833  {
835  }
836  }
837  break;
838 
840  if ((val & BITM_CLKG_OSC_CTL_LFX_EN) != 0u)
841  {
842  /* Clock source enabled, now check for stable */
843  if ((val & BITM_CLKG_OSC_CTL_LFX_OK) != 0u)
844  {
846  }
847  else
848  {
850  }
851  }
852  break;
853 
855  /* Clock source enabled, now check for stable */
856  if ((val & BITM_CLKG_OSC_CTL_LFOSC_OK) != 0u)
857  {
859  }
860  else
861  {
863  }
864  break;
865 
866  /* Since the clock through GPIO is supplied externally we cannot get
867  the clock status for GPIO */
869  default:
870  *peStatus = ADI_CLOCK_SOURCE_ID_NOT_VALID;
871  break;
872 
873  } /* end switch */
874 
875  return ADI_PWR_SUCCESS;
876 }
877 
891 {
892  ADI_INT_STATUS_ALLOC();
893  volatile uint32_t *pReg = NULL;
894  uint32_t tmp;
895 
896  switch(eIrq)
897  {
898 #if defined(__ADUCM4x50__)
899 
900  case ADI_PWR_ROOT_CLOCK_MON_IEN:
901  pReg = &pADI_CLKG0_OSC->CTL;
902  break;
903 #endif /* __ADUCM4x50__ */
904 
907  pReg = &pADI_CLKG0_OSC->CTL;
908  break;
909 
912  pReg = &pADI_CLKG0_CLK->CTL0;
913  break;
914 
917  pReg = &pADI_CLKG0_CLK->CTL0;
918  break;
919 
922  pReg = &pADI_CLKG0_CLK->CTL3;
923  break;
924 
925  default:
926  break;
927  }
928 
929  ADI_ENTER_CRITICAL_REGION();
930 
931  tmp = *pReg;
932 
933  if(bEnable == true)
934  {
935  tmp |= (uint32_t)eIrq;
936  }
937  else
938  {
939  tmp &= ~((uint32_t)eIrq);
940  }
941 
942  /* If we have to write to oscillator control register unlock it */
943  if(pReg == &pADI_CLKG0_OSC->CTL)
944  {
945  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
946  }
947  *pReg = tmp;
948 
949  ADI_EXIT_CRITICAL_REGION();
950 
951  return(ADI_PWR_SUCCESS);
952 }
953 
954 
973 ADI_PWR_RESULT adi_pwr_SetPll(uint8_t nDivFactor, const uint8_t nMulFactor, const bool bDiv2, const bool bMul2)
974 {
975  uint32_t val, cfg = 0u;
976  uint8_t nTempDivFactor = nDivFactor, nTempMulFactor = nMulFactor;
977  ADI_INT_STATUS_ALLOC();
978 
979 #ifdef ADI_DEBUG
980  /* Check if multiplication factor and division factor is more than 6 bits */
981  if (((nMulFactor & ~0x3Fu) != 0u) || ((nDivFactor & ~0x3Fu) != 0u))
982  {
984  }
985 
986  /* Check if the PLL is multipexed in as root clock source, parameters should not change in that case */
987  if((pADI_CLKG0_CLK->CTL0 & BITM_CLKG_CLK_CTL0_CLKMUX) ==
988  ((uint32_t)((ADI_CLOCK_MUX_ROOT_SPLL - ADI_CLOCK_MUX_ROOT_HFOSC) << BITP_CLKG_CLK_CTL0_CLKMUX)))
989  {
991  }
992 #endif
993 
994  if(nTempDivFactor < MINIMUM_PLL_DIVIDER)
995  {
996  nTempDivFactor = MINIMUM_PLL_DIVIDER;
997  }
998  if(nTempMulFactor < MINIMUM_PLL_MULTIPLIER)
999  {
1000  nTempMulFactor = MINIMUM_PLL_MULTIPLIER;
1001  }
1002 
1003  cfg = (((uint32_t)nTempDivFactor) << BITP_CLKG_CLK_CTL3_SPLLMSEL)|( ((uint32_t) nTempMulFactor) << BITP_CLKG_CLK_CTL3_SPLLNSEL);
1004 
1005  if(bDiv2 == true)
1006  {
1007  cfg |= (1u <<BITP_CLKG_CLK_CTL3_SPLLDIV2);
1008  }
1009  if(bMul2 == true)
1010  {
1011  cfg |= (1u <<BITP_CLKG_CLK_CTL3_SPLLMUL2);
1012  }
1013 
1014  /* critical region */
1015  ADI_ENTER_CRITICAL_REGION();
1016 
1017  val = pADI_CLKG0_CLK->CTL3;
1018  val &= ~( BITM_CLKG_CLK_CTL3_SPLLMUL2 | BITM_CLKG_CLK_CTL3_SPLLMSEL | BITM_CLKG_CLK_CTL3_SPLLDIV2 | BITM_CLKG_CLK_CTL3_SPLLNSEL);
1019  val |= cfg;
1020  pADI_CLKG0_CLK->CTL3 = val;
1021 
1022  /* end critical region */
1023  ADI_EXIT_CRITICAL_REGION();
1024 
1025  return ADI_PWR_SUCCESS;
1026 }
1027 
1028 
1044 {
1045  ADI_INT_STATUS_ALLOC();
1046 
1047 #ifdef ADI_DEBUG
1048  if(((pADI_PMG0->IEN & BITM_PMG_IEN_RANGEBAT) == 0u) || (eIrq != ADI_PWR_BATTERY_VOLTAGE_RANGE_IEN))
1049  {
1050  return(ADI_PWR_FAILURE);
1051  }
1052 #endif
1053 
1054  ADI_ENTER_CRITICAL_REGION();
1055  if(bEnable == true)
1056  {
1057  pADI_PMG0->IEN |= (uint32_t)eIrq;
1058  }
1059  else
1060  {
1061  pADI_PMG0->IEN &= ~(uint32_t)(eIrq);
1062  }
1063  ADI_EXIT_CRITICAL_REGION();
1064 
1065  return(ADI_PWR_SUCCESS);
1066 }
1067 
1068 
1069 
1082 {
1083  volatile uint32_t nDelay = 0xFFFFFFu;
1084  if(bEnable == true)
1085  {
1086  /* Write the oscillator key */
1087  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1088  /* Disable the LFXTAL */
1089  pADI_CLKG0_OSC->CTL &= ~(BITM_CLKG_OSC_CTL_LFX_EN);
1090  /* Wait till status de-asserted. */
1091  while(nDelay != 0u)
1092  {
1093  if((pADI_CLKG0_OSC->CTL & BITM_CLKG_OSC_CTL_LFX_OK) == 0u)
1094  {
1095  break;
1096  }
1097  nDelay--;
1098  }
1099 #ifdef ADI_DEBUG
1100  if(nDelay == 0u)
1101  {
1102  return(ADI_PWR_FAILURE);
1103  }
1104 #endif
1105  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1106  /* Enable the BYPASS mode */
1107  pADI_CLKG0_OSC->CTL |= (BITM_CLKG_OSC_CTL_LFX_BYP);
1108  /* Wait till status asserted. */
1109  nDelay = 0xFFFFFFu;
1110  while(nDelay != 0u)
1111  {
1112  if(((pADI_CLKG0_OSC->CTL & BITM_CLKG_OSC_CTL_LFX_OK)== BITM_CLKG_OSC_CTL_LFX_OK))
1113  {
1114  break;
1115  }
1116  nDelay--;
1117  }
1118 #ifdef ADI_DEBUG
1119  if(nDelay == 0u)
1120  {
1121  return(ADI_PWR_FAILURE);
1122  }
1123 #endif
1124 
1125  }
1126  else
1127  {
1128  /* Write the oscillator key */
1129  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1130  /* Disable the BYPASS mode */
1131  pADI_CLKG0_OSC->CTL &= ~(BITM_CLKG_OSC_CTL_LFX_BYP);
1132  /* Wait till status de-asserted. */
1133  while(nDelay != 0u)
1134  {
1135  if((pADI_CLKG0_OSC->CTL & BITM_CLKG_OSC_CTL_LFX_OK) == 0u)
1136  {
1137  break;
1138  }
1139  nDelay--;
1140  }
1141 #ifdef ADI_DEBUG
1142  if(nDelay == 0u)
1143  {
1144  return(ADI_PWR_FAILURE);
1145  }
1146 #endif
1147  }
1148 
1149  return(ADI_PWR_SUCCESS);
1150 }
1151 
1152 
1153 #if defined(__ADUCM4x50__)
1154 
1164 ADI_PWR_RESULT adi_pwr_EnableLFXTALFailAutoSwitch( const bool bEnable )
1165 {
1166  /* Write the oscillator key */
1167  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1168 
1169  if(bEnable == true)
1170  {
1171  pADI_CLKG0_OSC->CTL |= BITM_CLKG_OSC_CTL_LFX_AUTSW_EN;
1172  }
1173  else
1174  {
1175  pADI_CLKG0_OSC->CTL &= ~(BITM_CLKG_OSC_CTL_LFX_AUTSW_EN);
1176  }
1177  return(ADI_PWR_SUCCESS);
1178 }
1179 
1180 
1194 ADI_PWR_RESULT adi_pwr_EnableRootClockFailAutoSwitch( const bool bEnable )
1195 {
1196  /* Write the oscillator key */
1197  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1198 
1199  if(bEnable == true)
1200  {
1201  pADI_CLKG0_OSC->CTL |= BITM_CLKG_OSC_CTL_ROOT_AUTSW_EN;
1202  }
1203  else
1204  {
1205  pADI_CLKG0_OSC->CTL &= ~(BITM_CLKG_OSC_CTL_ROOT_AUTSW_EN);
1206  }
1207 
1208  return(ADI_PWR_SUCCESS);
1209 }
1210 
1211 
1228 ADI_PWR_RESULT adi_pwr_SetHFOscDivFactor( const ADI_PWR_HFOSC_DIV eDivFactor )
1229 {
1230  uint32_t tmp;
1231 
1232  tmp = (pADI_CLKG0_CLK->CTL2 & ~BITM_CLKG_CLK_CTL2_HFOSCDIVCLKSEL);
1233  tmp |= ((uint32_t) eDivFactor << BITP_CLKG_CLK_CTL2_HFOSCDIVCLKSEL);
1234  pADI_CLKG0_CLK->CTL2 = tmp;
1235 
1236  return(ADI_PWR_SUCCESS);
1237 }
1238 
1239 
1260 ADI_PWR_RESULT adi_pwr_EnableHFOscAutoDivBy1( const bool bEnable )
1261 {
1262  if(bEnable == true)
1263  {
1264  pADI_CLKG0_CLK->CTL2 |= BITM_CLKG_CLK_CTL2_HFOSCAUTODIV_EN;
1265  }
1266  else
1267  {
1268  pADI_CLKG0_CLK->CTL2 &= ~(BITM_CLKG_CLK_CTL2_HFOSCAUTODIV_EN);
1269  }
1270 
1271  return(ADI_PWR_SUCCESS);
1272 }
1273 
1274 
1288 ADI_PWR_RESULT adi_pwr_SetGPIOClockOutput( const ADI_CLOCK_OUTPUT_ID eClockOutput )
1289 {
1290  uint32_t tmp;
1291 
1292  tmp = (pADI_CLKG0_CLK->CTL0 & ~BITM_CLKG_CLK_CTL0_CLKOUT);
1293  tmp |= ((uint32_t)eClockOutput << BITP_CLKG_CLK_CTL0_CLKOUT);
1294  pADI_CLKG0_CLK->CTL0 = tmp;
1295 
1296  return(ADI_PWR_SUCCESS);
1297 }
1298 
1310 ADI_PWR_RESULT adi_pwr_EnableHPBuckLowPowerMode( const bool bEnable )
1311 {
1312  if(bEnable == true)
1313  {
1314  pADI_PMG0->CTL1 |= BITM_PMG_CTL1_HPBUCK_LOWPWR_MODE;
1315  }
1316  else
1317  {
1318  pADI_PMG0->CTL1 &= ~(BITM_PMG_CTL1_HPBUCK_LOWPWR_MODE);
1319  }
1320 
1321  return(ADI_PWR_SUCCESS);
1322 }
1323 
1336 ADI_PWR_RESULT adi_pwr_SetHPBuckLoadMode( const ADI_PWR_HPBUCK_LD_MODE eLoadMode )
1337 {
1338  if(eLoadMode == ADI_PWR_HPBUCK_LD_MODE_HIGH)
1339  {
1340  pADI_PMG0->CTL1 |= BITM_PMG_CTL1_HPBUCK_LD_MODE;
1341  }
1342  else
1343  {
1344  pADI_PMG0->CTL1 &= ~(BITM_PMG_CTL1_HPBUCK_LD_MODE);
1345  }
1346 
1347  return(ADI_PWR_SUCCESS);
1348 }
1349 #endif /* ADUCM4x50 */
1350 
1361 {
1362  if(bEnable == true)
1363  {
1364  pADI_PMG0->CTL1 |= BITM_PMG_CTL1_HPBUCKEN;
1365  }
1366  else
1367  {
1368  pADI_PMG0->CTL1 &= ~(BITM_PMG_CTL1_HPBUCKEN);
1369  }
1370 
1371  return(ADI_PWR_SUCCESS);
1372 }
1373 
1383 {
1384  *peStatus =(ADI_PWR_WAKEUP_STATUS) pADI_PMG0->SHDN_STAT;
1385  return(ADI_PWR_SUCCESS);
1386 }
1387 
1388 
1400 {
1401  uint32_t tmp;
1402 
1403  tmp = (pADI_PMG0->IEN & ~BITM_PMG_IEN_RANGEBAT);
1404  tmp |= ((uint32_t)eRange << BITP_PMG_IEN_RANGEBAT);
1405  pADI_PMG0->IEN = tmp;
1406 
1407  return(ADI_PWR_SUCCESS);
1408 }
1409 
1412 /*
1413  * Interrupt handler for PLL interrupts.
1414  */
1415 void PLL_Int_Handler(void)
1416 {
1417  ISR_PROLOG();
1418 
1419  /* As the same status word is shared between two interrupts
1420  Crystal_osc_Int_Handler and PLL_Int_Handler
1421  check and clear status bits handled in this handler */
1422  uint32_t nStatus = (pADI_CLKG0_CLK->STAT0 &
1423  (BITM_CLKG_CLK_STAT0_SPLLUNLK | BITM_CLKG_CLK_STAT0_SPLLLK));
1424 
1425  /* If a callback is registered notify the events */
1426  if(gpfCallbackFunction != NULL)
1427  {
1428  if((nStatus & BITM_CLKG_CLK_STAT0_SPLLUNLK ) != 0u)
1429  {
1430  /* PLL unlock event */
1431  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_PLLC_UNLOCK,(void *)0);
1432  }
1433  else if((nStatus & BITM_CLKG_CLK_STAT0_SPLLLK) != 0u)
1434  {
1435  /* PLL lock event */
1436  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_PLLC_LOCK,(void *)0);
1437  }
1438  else
1439  {
1440  /* Do nothing */
1441  }
1442  }
1443 
1444  /* Clear the status bits */
1445  pADI_CLKG0_CLK->STAT0 = nStatus;
1446 
1447  ISR_EPILOG();
1448 }
1449 
1450 /*
1451  * Interrupt handler for oscillator interrupts.
1452  */
1453 void Crystal_osc_Int_Handler(void)
1454 {
1455  ISR_PROLOG();
1456 
1457  /* As the same status word is shared between two interrupts
1458  Crystal_osc_Int_Handler and PLL_Int_Handler
1459  check and clear status bits handled in this handler */
1460  uint32_t nClkStatus = (pADI_CLKG0_CLK->STAT0 &
1461  (BITM_CLKG_CLK_STAT0_HFXTALNOK |
1462  BITM_CLKG_CLK_STAT0_HFXTALOK |
1463  BITM_CLKG_CLK_STAT0_LFXTALOK |
1464  BITM_CLKG_CLK_STAT0_LFXTALNOK));
1465 #if defined(__ADUCM4x50__)
1466  /* Check if the interrupt was generated due to failure in Root Clock or LFXTAL */
1467  uint32_t nOscStatus = (pADI_CLKG0_OSC->CTL & (BITM_CLKG_OSC_CTL_LFX_FAIL_STA |
1468  BITM_CLKG_OSC_CTL_ROOT_FAIL_STA |
1469  BITM_CLKG_OSC_CTL_ROOT_AUTSW_STA |
1470  BITM_CLKG_OSC_CTL_LFX_AUTSW_STA ));
1471 #endif /* __ADUCM4x50__ */
1472 
1473  uint32_t nEvent = 0u;
1474 
1475 
1476  if(gpfCallbackFunction != NULL)
1477  {
1478  /* Is the interrupt caused due to HFXTAL or LFXTAL status */
1479  if(nClkStatus != 0u)
1480  {
1481  if ((nClkStatus & BITM_CLKG_CLK_STAT0_HFXTALNOK) != 0u) { nEvent |= ADI_PWR_EVENT_OSC_HFXTAL_CLOCK_NO_OK; }
1482  else if ((nClkStatus & BITM_CLKG_CLK_STAT0_HFXTALOK) != 0u) { nEvent |= ADI_PWR_EVENT_OSC_HFXTAL_CLOCK_OK; }
1483  else if ((nClkStatus & BITM_CLKG_CLK_STAT0_LFXTALOK) != 0u) { nEvent |= ADI_PWR_EVENT_OSC_LFXTAL_CLOCK_OK; }
1484  else if ((nClkStatus & BITM_CLKG_CLK_STAT0_LFXTALNOK) != 0u) { nEvent |= ADI_PWR_EVENT_OSC_LFXTAL_CLOCK_NO_OK; }
1485  else { /* do nothing */ }
1486 
1487  if(nEvent != 0u) { gpfCallbackFunction( gpPowcbParam, nEvent, (void *)0u); }
1488 
1489  }
1490 #if defined(__ADUCM4x50__)
1491  /* Or is the interrupt caused due to Root Clock or LFXTAL failure status */
1492  else if(nOscStatus != 0u)
1493  {
1494  /* Did the LFXTAL failed */
1495  if( (nOscStatus & BITM_CLKG_OSC_CTL_LFX_FAIL_STA) != 0u)
1496  {
1497  /* Notifiy LFXTAL failure */
1498  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_OSC_LFXTAL_MON_FAIL, (void *)0u);
1499 
1500  /* Did the HW auto switched to LFOSC due to LFXTAL failure */
1501  if((nOscStatus & BITM_CLKG_OSC_CTL_LFX_AUTSW_STA) != 0u)
1502  {
1503  /* Notify about the auto switch to LFOSC */
1504  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_OSC_LFXTAL_AUTO_SWITCH, (void *)0u);
1505  }
1506  }
1507  /* Did the root clock failed */
1508  else if((nOscStatus & BITM_CLKG_OSC_CTL_ROOT_FAIL_STA) != 0u)
1509  {
1510  /* Indicate about the root clock failure */
1511  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_OSC_ROOT_CLOCK_MON_FAIL, (void *)0u);
1512 
1513  /* Did the HW auto switched to HFOSC due to root clock failure */
1514  if((nOscStatus & BITM_CLKG_OSC_CTL_ROOT_AUTSW_STA) != 0u)
1515  {
1516  /* Notify about auto switch to HFOSC */
1517  gpfCallbackFunction( gpPowcbParam, ADI_PWR_EVENT_OSC_ROOT_CLOCK_FAIL_AUTO_SWITCH, (void *)0u);
1518  }
1519  }
1520  else
1521  {
1522  /* Do nothing */
1523  }
1524  }
1525  else
1526  {
1527  /* Do nothing */
1528  }
1529 #endif /* __ADUCM4x50__ */
1530  }
1531 
1532  /* Clear the staus bits */
1533  if(nClkStatus != 0u)
1534  {
1535  pADI_CLKG0_CLK->STAT0 = nClkStatus;
1536  }
1537 #if defined(__ADUCM4x50__)
1538  else if(nOscStatus != 0u)
1539  {
1540  /* Write the oscillator key to clear the status bits */
1541  pADI_CLKG0_OSC->KEY = ADI_OSC_KEY;
1542 
1543  /* Clear only status bits */
1544  pADI_CLKG0_OSC->CTL |= nOscStatus;
1545  }
1546  else
1547  {
1548  /* Do nothing */
1549  }
1550 #endif /* __ADUCM4x50__ */
1551 
1552  ISR_EPILOG();
1553 }
1554 
1555 /*
1556  * Interrupt handler for battery voltage interrupt.
1557  */
1558 void Battery_Voltage_Int_Handler(void)
1559 {
1560  ISR_PROLOG();
1561  uint32_t nStatus = pADI_PMG0->PSM_STAT;
1562 
1563  if ((nStatus & BITM_PMG_PSM_STAT_VBATUNDR) != 0u)
1564  {
1565  if(gpfCallbackFunction != NULL)
1566  {
1567  gpfCallbackFunction( gpPowcbParam, (uint32_t)nStatus, (void *)0);
1568  }
1569  pADI_PMG0->PSM_STAT |= (BITM_PMG_PSM_STAT_VBATUNDR);
1570  }
1571  ISR_EPILOG();
1572 }
1573 
1574 /*
1575  * Interrupt handler for battery voltage interrupt.
1576  */
1577 void Vreg_over_Int_Handler(void)
1578 {
1579  ISR_PROLOG();
1580  uint32_t nStatus = pADI_PMG0->PSM_STAT;
1581 
1582  if(gpfCallbackFunction != NULL)
1583  {
1584  if ((nStatus & BITM_PMG_PSM_STAT_VREGOVR) != 0u)
1585  {
1586  gpfCallbackFunction(gpPowcbParam, (uint32_t)ADI_PWR_EVENT_VREG_OVER_VOLTAGE, NULL);
1587  }
1588  if ((nStatus & BITM_PMG_PSM_STAT_VREGUNDR) != 0u)
1589  {
1590  gpfCallbackFunction(gpPowcbParam, (uint32_t)ADI_PWR_EVENT_VREG_UNDER_VOLTAGE, NULL);
1591  }
1592  }
1593  pADI_PMG0->PSM_STAT |= (nStatus &(BITM_PMG_PSM_STAT_VREGOVR | BITM_PMG_PSM_STAT_VREGUNDR));
1594  ISR_EPILOG();
1595 }
1596 
1719  uint32_t volatile * pnInterruptOccurred,
1720  const uint8_t PriorityMask
1721  )
1722 {
1723  uint32_t savedPriority;
1724  uint32_t scrSetBits = 0u;
1725  uint32_t scrClrBits = 0u;
1726  uint16_t savedWDT;
1727  ADI_INT_STATUS_ALLOC();
1728 
1729 #ifdef ADI_DEBUG
1730 
1731  /* verify the requested priority mask bits are right-justified and don't exceed __NVIC_PRIO_BITS in width */
1732  if ((PriorityMask & ~((1u << __NVIC_PRIO_BITS) - 1u)) != 0u)
1733  {
1734  return ADI_PWR_INVALID_PARAM;
1735  }
1736 
1737 #endif /* ADI_DEBUG */
1738 
1739  /* pre-calculate the sleep-on-exit set/clear bits */
1740  if(NULL == pnInterruptOccurred) {
1741  scrSetBits |= SCB_SCR_SLEEPONEXIT_Msk;
1742 
1743  /* point to private control variable when in hardware (sleep-on-exit) mode */
1744  pnInterruptOccurred = &gnLowPowerIntOccFlag;
1745  }
1746 
1747  /* pre-calculate the deepsleep and sleep-on-exit set/clear bits */
1748  switch (PowerMode) {
1749 
1750  case ADI_PWR_MODE_ACTIVE: /* Note: this value is a "reserved" PWRMODE register code. */
1751  return ADI_PWR_SUCCESS; /* avoids the reserved value "1" being written to PWRMODE. */
1752 
1753  case ADI_PWR_MODE_FLEXI: /* wfi without deepsleep or sleep-on-exit */
1754  scrClrBits |= (uint32_t)(BITM_NVIC_INTCON0_SLEEPDEEP | BITM_NVIC_INTCON0_SLEEPONEXIT);
1755  break;
1756 
1757  case ADI_PWR_MODE_HIBERNATE: /* wfi with deepsleep and sleep-on-exit per pnInterruptOccurred setting */
1758  scrSetBits |= BITM_NVIC_INTCON0_SLEEPDEEP;
1759 
1760  break;
1761 
1762  case ADI_PWR_MODE_SHUTDOWN: /* wfi with both deepsleep and sleep-on-exit */
1763  /* Note: sleep-on-exit causes WFI to never exit and wakeup is only through system reset. */
1764  scrSetBits |= (uint32_t)(BITM_NVIC_INTCON0_SLEEPDEEP | BITM_NVIC_INTCON0_SLEEPONEXIT);
1765  break;
1766 
1767  default:
1769 
1770  } /* end switch */
1771 
1772  /* put the power mode and system control mods, as well as the WFI loop inside a critical section */
1773  ADI_ENTER_CRITICAL_REGION();
1774 
1775  { /* these lines must be in a success-checking loop if they are not inside critical section */
1776  /* Uninterruptable unlock sequence */
1777  pADI_PMG0->PWRKEY = ADI_PMG_KEY;
1778 
1779  /* Clear the previous mode and set new mode */
1780  pADI_PMG0->PWRMOD = (uint32_t) ( ( pADI_PMG0->PWRMOD & (uint32_t) (~BITM_PMG_PWRMOD_MODE) ) | PowerMode );
1781  }
1782 
1783  /* Update the SCR (sleepdeep and sleep-on-exit bits) */
1784  SCB->SCR = ((SCB->SCR | scrSetBits) & ~scrClrBits);
1785 
1786  /* save/restore current Base Priority Level */
1787  savedPriority = __get_BASEPRI();
1788 
1789  /* NOTE: the watchdog timer(WDT)is reset by the core hardware with every exit from low-power mode.
1790  Therefore,even though we may have disabled it during startup, it will reset
1791  itself on exit from every hibernation state. Therefore, to avoid
1792  unintended system resets every 30 seconds because of unexpected WDT
1793  timeouts, we save/restore the WDT control register around
1794  hibernation entry and exit.
1795  */
1796 
1797  /* save WDT control register */
1798  savedWDT = pADI_WDT0->CTL;
1799 
1800  /* assert caller's priority threshold (left-justified) */
1801  __set_BASEPRI((uint32_t)PriorityMask << (8u -__NVIC_PRIO_BITS));
1802 
1803  /* if we are in the software looping mode, loop on the user's variable until set */
1804  while (0u == *pnInterruptOccurred) {
1805 
1806  __DSB(); /* bus sync to insure register writes from interrupt handlers are always complete before WFI */
1807 
1808  /* NOTE: aggressive compiler optimizations can muck up critical timing here, so reduce if hangs are present */
1809 
1810  /* The WFI loop MUST reside in a critical section because we need to insure that the interrupt
1811  that is planned to take us out of WFI (via a call to adi_pwr_ExitLowPowerMode()) is not
1812  dispatched until we get into the WFI. If that interrupt sneaks in prior to our getting to the
1813  WFI, then we may end up waiting (potentially forever) for an interrupt that has already occurred.
1814  */
1815  __WFI();
1816 
1817  /* Recycle the critical section so that other (non-wakeup) interrupts are dispatched.
1818  This allows *pnInterruptOccurred to be set from any interrupt context.
1819  */
1820  ADI_EXIT_CRITICAL_REGION();
1821  /* nop */
1822  ADI_ENTER_CRITICAL_REGION();
1823 
1824  } /* end while */
1825 
1826  /* ...still within critical section... */
1827 
1828  (*pnInterruptOccurred)--; /* decrement the completion variable on exit */
1829 
1830  /* Restore previous base priority */
1831  __set_BASEPRI(savedPriority);
1832 
1833  /* restore WDT control register */
1834  pADI_WDT0->CTL = savedWDT;
1835 
1836  /* clear sleep-on-exit bit to avoid sleeping on exception return to thread level */
1837  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
1838 
1839  __DSB(); /* bus sync before re-enabling interrupts */
1840 
1841  ADI_EXIT_CRITICAL_REGION();
1842 
1843  return ADI_PWR_SUCCESS;
1844 }
1845 
1846 
1861 ADI_PWR_RESULT adi_pwr_ExitLowPowerMode(uint32_t volatile * pnInterruptOccurred)
1862 {
1863  ADI_INT_STATUS_ALLOC();
1864 
1865  /* Manage the exit depending on pnInterruptOccurred convention... */
1866  /* NULL pointer means we are using the hardware sleep-on-exit feature */
1867  /* non-NULL pointer means we are using a software looping variable top sleep */
1868 
1869  if (NULL == pnInterruptOccurred) {
1870 
1871  pnInterruptOccurred = &gnLowPowerIntOccFlag; /* point to private control variable in hardware mode */
1872 
1873  /* clear hardware sleep-on-exit feature */
1874  ADI_ENTER_CRITICAL_REGION();
1875 
1876  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
1877  __DSB(); /* bus sync before interrupt exit */
1878 
1879  ADI_EXIT_CRITICAL_REGION();
1880  }
1881 
1882  /* set control variable (whether hardware or software based) so WFI exits in SystemEnterLowPowerMode() */
1883  (*pnInterruptOccurred)++;
1884  return ADI_PWR_SUCCESS;
1885 }
1886 
1887 /*
1888 ** EOF
1889 */
1890 
ADI_PWR_RESULT adi_pwr_SetClockDivider(const ADI_CLOCK_ID eClockId, const uint16_t nDiv)
Sets the clock divide factor for an individual clock group.
Definition: adi_pwr.c:565
ADI_PWR_RESULT adi_pwr_SetVoltageRange(const ADI_PWR_VOLTAGE_RANGE eRange)
To Monitor voltage range of battery.
Definition: adi_pwr.c:1399
ADI_PWR_POWER_MODE
Definition: adi_pwr.h:298
ADI_CLOCK_SOURCE_ID
Definition: adi_pwr.h:85
ADI_CLOCK_MUX_ID
Definition: adi_pwr.h:108
ADI_PWR_PMG_IRQ
Definition: adi_pwr.h:315
ADI_PWR_RESULT adi_pwr_SetPLLClockMux(const ADI_CLOCK_MUX_ID eClockID)
Sets the input clock source for PLL multiplexer.
Definition: adi_pwr.c:251
ADI_PWR_WAKEUP_STATUS
Definition: adi_pwr.h:409
ADI_CLOCK_ID
Definition: adi_pwr.h:74
void SystemCoreClockUpdate(void)
Updates the variable SystemCoreClock and must be called whenever the core clock is changed during pro...
ADI_CLOCK_OUTPUT_ID
Definition: adi_pwr.h:167
ADI_PWR_RESULT adi_pwr_EnablePMGInterrupt(const ADI_PWR_PMG_IRQ eIrq, const bool bEnable)
Enable/Disable the power management interrupt.
Definition: adi_pwr.c:1043
ADI_PWR_CLOCK_IRQ
Definition: adi_pwr.h:332
ADI_PWR_RESULT adi_pwr_UpdateCoreClock(void)
Updates the internal SystemCoreClock variable with current core Clock retrieved from cpu registers...
Definition: adi_pwr.c:179
ADI_PWR_RESULT
Definition: adi_pwr.h:268
ADI_PWR_RESULT adi_pwr_EnableHPBuck(const bool bEnable)
Enables or disables the HP Buck.
Definition: adi_pwr.c:1360
ADI_PWR_RESULT adi_pwr_SetPll(uint8_t nDivFactor, const uint8_t nMulFactor, const bool bDiv2, const bool bMul2)
Program PLL frequency.
Definition: adi_pwr.c:973
ADI_PWR_RESULT adi_pwr_EnableClockSource(const ADI_CLOCK_SOURCE_ID eClockSource, const bool bEnable)
To Enable/disable clock sources.
Definition: adi_pwr.c:693
ADI_PWR_RESULT adi_pwr_EnterLowPowerMode(const ADI_PWR_POWER_MODE PowerMode, uint32_t volatile *pnInterruptOccurred, const uint8_t PriorityMask)
Puts the processor into given low power mode.
Definition: adi_pwr.c:1718
ADI_PWR_RESULT adi_pwr_ExitLowPowerMode(uint32_t volatile *pnInterruptOccurred)
Definition: adi_pwr.c:1861
ADI_PWR_RESULT adi_pwr_GetExtClkFreq(uint32_t *pExtClock)
Gets the system external clock frequency. Gets the clock frequency of the source connected to the ext...
Definition: adi_pwr.c:434
ADI_GPIO_RESULT adi_gpio_InputEnable(const ADI_GPIO_PORT Port, const ADI_GPIO_DATA Pins, const bool bFlag)
Enables/Disables the Input Drivers for GPIO Pin(s)
Definition: adi_gpio.c:612
ADI_PWR_RESULT adi_pwr_EnableClockInterrupt(const ADI_PWR_CLOCK_IRQ eIrq, const bool bEnable)
Enable/Disable the clock interrupt to monitor status of LFXTAL, HFXTAL and PLL.
Definition: adi_pwr.c:890
ADI_PWR_RESULT adi_pwr_RegisterCallback(const ADI_CALLBACK pfCallback, void *pcbParam)
Registers or unregister the callback function.
Definition: adi_pwr.c:198
ADI_CLOCK_GATE
Definition: adi_pwr.h:221
ADI_PWR_RESULT adi_pwr_EnableClock(const ADI_CLOCK_GATE eClockGate, const bool bEnable)
Enable/disable individual peripheral clocks.
Definition: adi_pwr.c:523
ADI_GPIO_RESULT adi_gpio_PullUpEnable(const ADI_GPIO_PORT Port, const ADI_GPIO_DATA Pins, const bool bFlag)
Enables/Disables the Pull-Up for GPIO Pin(s)
Definition: adi_gpio.c:716
ADI_PWR_RESULT adi_pwr_EnableLFXTALBypass(const bool bEnable)
Enable/disable LFXTAL bypass mode.
Definition: adi_pwr.c:1081
ADI_PWR_RESULT adi_pwr_GetClockFrequency(const ADI_CLOCK_ID eClockId, uint32_t *pClock)
Get the frequency of the given clock. Obtain individual peripheral clock frequencies.
Definition: adi_pwr.c:467
ADI_PWR_RESULT adi_pwr_SetExtClkFreq(const uint32_t ExtClkFreq)
Sets the system external clock frequency.
Definition: adi_pwr.c:228
ADI_PWR_RESULT adi_pwr_SetRootClockMux(const ADI_CLOCK_MUX_ID eClockID)
Sets the source for the root clock multiplexer.
Definition: adi_pwr.c:390
ADI_PWR_RESULT adi_pwr_SetRefClockMux(const ADI_CLOCK_MUX_ID eClockID)
Sets clock source for the Reference clock multiplexer.
Definition: adi_pwr.c:346
ADI_PWR_VOLTAGE_RANGE
Definition: adi_pwr.h:425
ADI_PWR_RESULT adi_pwr_GetWakeUpStatus(ADI_PWR_WAKEUP_STATUS *peStatus)
Function to retrieve the wakeup from shut down mode status.
Definition: adi_pwr.c:1382
ADI_PWR_RESULT adi_pwr_GetClockStatus(const ADI_CLOCK_SOURCE_ID eClockSource, ADI_CLOCK_SOURCE_STATUS *peStatus)
Return the status of a clock source.
Definition: adi_pwr.c:794
#define ADI_GPIO_PIN_10
Definition: adi_gpio.h:139
ADI_PWR_RESULT adi_pwr_Init(void)
Definition: adi_pwr.c:109
ADI_PWR_RESULT adi_pwr_SetLFClockMux(const ADI_CLOCK_MUX_ID eClockID)
Sets the input clock for low frequency clock multiplexer.
Definition: adi_pwr.c:298
ADI_CLOCK_SOURCE_STATUS
Definition: adi_pwr.h:152