iLLD_TC27xD  1.0
IfxScuCcu.c
Go to the documentation of this file.
1 /**
2  * \file IfxScuCcu.c
3  * \brief SCU basic functionality
4  *
5  * \version iLLD_1_0_0_11_0
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  *
24  */
25 
26 /******************************************************************************/
27 /*----------------------------------Includes----------------------------------*/
28 /******************************************************************************/
29 
30 #include "IfxScuCcu.h"
31 
32 /** \addtogroup IfxLld_Scu_Std_Ccu_Ccu
33  * \{ */
34 
35 /******************************************************************************/
36 /*-----------------------Private Function Prototypes--------------------------*/
37 /******************************************************************************/
38 
39 /** \brief Check if oscillator is stable.
40  * \return Status of oscillator stability
41  * \retval TRUE: Oscillator is unstable
42  * \retval FALSE: Oscillator is stable
43  */
44 static boolean IfxScuCcu_isOscillatorStable(void);
45 
46 /** \brief API to wait for requested duration.
47  * Note: IfxScuCcu_wait shall not use STM in future, because we can guarantee that STM is enabled after reset but If PLL init is called for changing the frequency during runtime, there is no guarantee that STM is enabled
48  * \return None
49  */
50 static void IfxScuCcu_wait(float32 timeSec);
51 
52 /** \} */
53 
54 /******************************************************************************/
55 /*------------------------Private Variables/Constants-------------------------*/
56 /******************************************************************************/
57 
58 /** \brief Default configuration for the PLL initial steps
59  * This is a structure array and the values are defined at the Scu implementation as #define macro
60  */
61 static const IfxScuCcu_PllStepsConfig IfxScuCcu_aDefaultPllConfigSteps[] = {
63 };
64 
65 /** \brief Crystal Frequency
66  */
67 static uint32 IfxScuCcu_xtalFrequency = IFX_CFG_SCU_XTAL_FREQUENCY;
68 
69 /******************************************************************************/
70 /*-----------------------Exported Variables/Constants-------------------------*/
71 /******************************************************************************/
72 
74  {
75  sizeof(IfxScuCcu_aDefaultPllConfigSteps) / sizeof(IfxScuCcu_PllStepsConfig),
76  (IfxScuCcu_PllStepsConfig *)IfxScuCcu_aDefaultPllConfigSteps,
78  },
82 };
83 
85 /*{ uint8 pDivider, uint8 nDivider, uint8 k2Initial, float32 waitTime }*/
86  {(1 - 1), (24 - 1), (6 - 1), 0}
87 };
88 
89 /******************************************************************************/
90 /*-------------------------Function Implementations---------------------------*/
91 /******************************************************************************/
92 
94 {
95  boolean retVal = 0;
96  uint8 deviationAllowed = 2;
97  uint32 fOsc = cfg->xtalFrequency;
98 
99  // Dynamic PLL calculation Alg
100  /*
101  *
102  * fPLL = (N /( P * K2)) * fOSC
103  * */
104  {
105  const uint32 fPllMax = 200000000;
106  const uint32 fRefMax = 24000000;
107  const uint32 fRefMin = 8000000;
108  const uint32 fVcoMin = 400000000;
109  const uint32 fVcoMax = 800000000;
110  const uint8 pMin = 1;
111  const uint8 pMax = 16; // '4 bits
112  const uint8 k2Min = 1;
113  const uint8 k2Max = 128; // '7bits
114  const uint8 nMin = 1;
115  const uint8 nMax = 128; // '7bits
116 
117  uint32 p;
118  uint32 n;
119  uint32 k2;
120  uint32 k2Steps;
121  uint32 bestK2 = 0, bestN = 0, bestP = 0;
122 
123  uint64 fRef, fVco;
124  uint64 fPllLeastError;
125 
126  fPllLeastError = fPllMax;
127 
128  //' K2+1 div should be even for 50% duty cycle
129  k2Steps = 2;
130 
131  if (fPll > 240000000)
132  {
133  k2Steps = 1;
134  }
135 
136  for (p = pMax; p >= pMin; p--)
137  {
138  fRef = (fOsc / p);
139 
140  if ((fRef >= fRefMin) && (fRef <= fRefMax))
141  {
142  for (k2 = k2Min; k2 <= k2Max; k2 += k2Steps)
143  {
144  fVco = ((uint64)fPll) * k2;
145 
146  if ((fVco >= fVcoMin) && (fVco <= fVcoMax))
147  {
148  for (n = nMin; n <= nMax; n++)
149  {
150  uint64 fPllError;
151  fPllError = ((((n) / (p * k2)) * fOsc) - fPll);
152 
153  if (fPllError == 0)
154  {
155  fPllLeastError = fPllError;
156  bestK2 = k2;
157  bestN = n;
158  bestP = p;
159 
160  goto EXITCALC_LOOP;
161  }
162 
163  if (fPllLeastError > fPllError)
164  {
165  fPllLeastError = fPllError;
166  bestK2 = k2;
167  bestN = n;
168  bestP = p;
169  }
170  }
171  }
172  }
173  }
174  }
175 
176 EXITCALC_LOOP:
177 
178  if ((fPllLeastError) < ((fPll * deviationAllowed) / 100)) // percent ALLOWED_DEVIATION error allowed
179  {
180  cfg->sysPll.pllInitialStep.nDivider = (uint8)(bestN - 1);
181  cfg->sysPll.pllInitialStep.pDivider = (uint8)(bestP - 1);
182  cfg->sysPll.pllInitialStep.k2Initial = (uint8)(bestK2 - 1);
183  cfg->sysPll.pllInitialStep.waitTime = 0; // wait time = 0
184  cfg->sysPll.numOfPllDividerSteps = 0; // no step clock incr
185  }
186  else
187  {
188  retVal = 1;
189  }
190  }
191 
192  return retVal;
193 }
194 
195 
197 {
198  float32 frequency;
199  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
200 
201  if (ccucon0.B.BAUD1DIV == 0)
202  {
203  frequency = 0;
204  }
205  else
206  {
207  frequency = IfxScuCcu_getMaxFrequency() / ccucon0.B.BAUD1DIV;
208  }
209 
210  return frequency;
211 }
212 
213 
215 {
216  float32 frequency;
217  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
218 
219  if (ccucon0.B.BAUD2DIV == 0)
220  {
221  frequency = 0;
222  }
223  else
224  {
225  frequency = IfxScuCcu_getMaxFrequency() / ccucon0.B.BAUD2DIV;
226  }
227 
228  return frequency;
229 }
230 
231 
233 {
234  float32 bbbFrequency;
235  float32 sourceFrequency;
236  sourceFrequency = IfxScuCcu_getSourceFrequency();
237 
238  switch (SCU_CCUCON0.B.LPDIV)
239  {
240  case 0: /*Not in low power mode */
241 
242  if (SCU_CCUCON2.B.BBBDIV == 0)
243  {
244  bbbFrequency = 0.0;
245  }
246  else
247  {
248  bbbFrequency = sourceFrequency / SCU_CCUCON2.B.BBBDIV;
249  }
250 
251  break;
252  case 1:
253  bbbFrequency = sourceFrequency / 30;
254  break;
255  case 2:
256  bbbFrequency = sourceFrequency / 60;
257  break;
258  case 3:
259  bbbFrequency = sourceFrequency / 120;
260  break;
261  case 4:
262  bbbFrequency = sourceFrequency / 240;
263  break;
264  default:
265  bbbFrequency = 0.0;
266  break;
267  }
268 
269  return bbbFrequency;
270 }
271 
272 
274 {
275  float32 frequency = IfxScuCcu_getSriFrequency();
276  uint32 cpuDiv = 0;
277 
278  switch (cpu)
279  {
281  cpuDiv = SCU_CCUCON6.U;
282  break;
284  cpuDiv = SCU_CCUCON7.U;
285  break;
287  cpuDiv = SCU_CCUCON8.U;
288  break;
289 
290  default:
291  frequency = 0.0;
292  break;
293  }
294 
295  if (cpuDiv != 0)
296  {
297  frequency = frequency * (cpuDiv / 64);
298  }
299 
300  return frequency;
301 }
302 
303 
305 {
306  float32 frequency;
307  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
308 
309  if (ccucon0.B.FSI2DIV == 0)
310  {
311  frequency = 0;
312  }
313  else
314  {
315  frequency = IfxScuCcu_getSriFrequency();
316 
317  if ((ccucon0.B.SRIDIV == 1) || (ccucon0.B.SRIDIV == 2))
318  {
319  frequency = frequency / ccucon0.B.FSI2DIV;
320  }
321  }
322 
323  return frequency;
324 }
325 
326 
328 {
329  float32 frequency;
330  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
331 
332  if (ccucon0.B.FSIDIV == 0)
333  {
334  frequency = 0;
335  }
336  else
337  {
338  frequency = IfxScuCcu_getSriFrequency();
339 
340  if ((ccucon0.B.SRIDIV == 1) || (ccucon0.B.SRIDIV == 2))
341  {
342  frequency = frequency / ccucon0.B.FSIDIV;
343  }
344  }
345 
346  return frequency;
347 }
348 
349 
351 {
352  float32 maxFrequency;
353  float32 sourceFrequency;
354  sourceFrequency = IfxScuCcu_getSourceFrequency();
355 
356  switch (SCU_CCUCON0.B.LPDIV)
357  {
358  case 0: /*Not in low power mode */
359 
360  if (SCU_CCUCON5.B.MAXDIV == 0)
361  {
362  maxFrequency = sourceFrequency;
363  }
364  else
365  {
366  maxFrequency = sourceFrequency / SCU_CCUCON5.B.MAXDIV;
367  }
368 
369  break;
370  case 1:
371  maxFrequency = sourceFrequency / 15;
372  break;
373  case 2:
374  maxFrequency = sourceFrequency / 30;
375  break;
376  case 3:
377  maxFrequency = sourceFrequency / 60;
378  break;
379  case 4:
380  maxFrequency = sourceFrequency / 120;
381  break;
382  default:
383  maxFrequency = 0.0;
384  break;
385  }
386 
387  return maxFrequency;
388 }
389 
390 
392 {
393  float32 spbFreq;
394  float32 moduleFreq;
395  Ifx_SCU_FDR scuFdr;
396  scuFdr = SCU_FDR;
397  spbFreq = IfxScuCcu_getSpbFrequency();
398 
399  if (scuFdr.B.DM == 1)
400  {
401  moduleFreq = spbFreq / (1024 - scuFdr.B.STEP);
402  }
403  else if (scuFdr.B.DM == 2)
404  {
405  moduleFreq = (spbFreq * scuFdr.B.STEP) / 1024;
406  }
407  else
408  {
409  moduleFreq = 0;
410  }
411 
412  return moduleFreq;
413 }
414 
415 
417 {
418  return (float32)IfxScuCcu_xtalFrequency;
419 }
420 
421 
423 {
424  float32 freq;
425 
426  if (SCU_CCUCON1.B.INSEL == IfxScu_CCUCON1_INSEL_fOsc1)
427  {
429  }
430  else if (SCU_CCUCON1.B.INSEL == IfxScu_CCUCON1_INSEL_fOsc0)
431  {
432  freq = (float32)IfxScuCcu_xtalFrequency;
433  }
434  else
435  {
436  /* Reserved values, this */
437  freq = 0.0;
438  }
439 
440  return freq;
441 }
442 
443 
445 {
446  Ifx_SCU *scu = &MODULE_SCU;
447  float32 oscFreq;
448  float32 freq;
449 
450  oscFreq = IfxScuCcu_getOscFrequency();
451 
452  if (scu->PLLERAYSTAT.B.VCOBYST == 1)
453  {
454  /* Prescaler mode */
455  freq = oscFreq / (scu->PLLERAYCON1.B.K1DIV + 1);
456  }
457  else if (scu->PLLERAYSTAT.B.FINDIS == 1)
458  {
459  /* Free running mode */
460  freq = IFXSCU_VCO_BASE_FREQUENCY / (scu->PLLERAYCON1.B.K2DIV + 1);
461  }
462  else
463  {
464  /* Normal mode */
465  freq = (oscFreq * (scu->PLLERAYCON0.B.NDIV + 1)) / (scu->PLLERAYCON1.B.K2DIV + 1);
466  }
467 
468  return freq;
469 }
470 
471 
473 {
474  float32 vcoFreq;
475 
476  if (SCU_PLLERAYSTAT.B.FINDIS == 1)
477  {
478  /* Free running mode */
479  vcoFreq = IFXSCU_VCO_BASE_FREQUENCY;
480  }
481  else
482  {
483  /* Normal mode */
484  vcoFreq = (IfxScuCcu_getOscFrequency() * (SCU_PLLERAYCON0.B.NDIV + 1)) / (SCU_PLLERAYCON0.B.PDIV + 1);
485  }
486 
487  return vcoFreq;
488 }
489 
490 
492 {
493  Ifx_SCU *scu = &MODULE_SCU;
494  float32 oscFreq;
495  float32 freq;
496 
497  oscFreq = IfxScuCcu_getOscFrequency();
498 
499  if (scu->PLLSTAT.B.VCOBYST == 1)
500  {
501  /* Prescaler mode */
502  freq = oscFreq / (scu->PLLCON1.B.K1DIV + 1);
503  }
504  else if (scu->PLLSTAT.B.FINDIS == 1)
505  {
506  /* Free running mode */
507  freq = IFXSCU_VCO_BASE_FREQUENCY / (scu->PLLCON1.B.K2DIV + 1);
508  }
509  else
510  {
511  /* Normal mode */
512  freq = (oscFreq * (scu->PLLCON0.B.NDIV + 1)) / ((scu->PLLCON1.B.K2DIV + 1) * (scu->PLLCON0.B.PDIV + 1));
513  }
514 
515  return freq;
516 }
517 
518 
520 {
521  float32 vcoFreq;
522 
523  if (SCU_PLLSTAT.B.FINDIS == 1)
524  {
525  /* Free running mode */
526  vcoFreq = IFXSCU_VCO_BASE_FREQUENCY;
527  }
528  else
529  {
530  /* Normal mode */
531  vcoFreq = (IfxScuCcu_getOscFrequency() * (SCU_PLLCON0.B.NDIV + 1)) / (SCU_PLLCON0.B.PDIV + 1);
532  }
533 
534  return vcoFreq;
535 }
536 
537 
539 {
540  float32 sourcefreq;
541 
542  switch (SCU_CCUCON0.B.CLKSEL)
543  {
545  sourcefreq = IfxScuCcu_getEvrFrequency();
546  break;
548  sourcefreq = IfxScuCcu_getPllFrequency();
549  break;
550  default:
551  sourcefreq = 0;
552  break;
553  }
554 
555  return sourcefreq;
556 }
557 
558 
560 {
561  float32 spbFrequency;
562  float32 sourceFrequency;
563  sourceFrequency = IfxScuCcu_getSourceFrequency();
564 
565  switch (SCU_CCUCON0.B.LPDIV)
566  {
567  case 0: /*Not in low power mode */
568 
569  if (SCU_CCUCON0.B.SPBDIV == 0)
570  {
571  spbFrequency = 0.0;
572  }
573  else
574  {
575  spbFrequency = sourceFrequency / SCU_CCUCON0.B.SPBDIV;
576  }
577 
578  break;
579  case 1:
580  spbFrequency = sourceFrequency / 30;
581  break;
582  case 2:
583  spbFrequency = sourceFrequency / 60;
584  break;
585  case 3:
586  spbFrequency = sourceFrequency / 120;
587  break;
588  case 4:
589  spbFrequency = sourceFrequency / 240;
590  break;
591  default:
592  spbFrequency = 0.0;
593  break;
594  }
595 
596  return spbFrequency;
597 }
598 
599 
601 {
602  float32 sriFrequency;
603  float32 sourceFrequency;
604  sourceFrequency = IfxScuCcu_getSourceFrequency();
605 
606  switch (SCU_CCUCON0.B.LPDIV)
607  {
608  case 0: /*Not in low power mode */
609 
610  if (SCU_CCUCON0.B.SRIDIV == 0)
611  {
612  sriFrequency = 0.0;
613  }
614  else
615  {
616  sriFrequency = sourceFrequency / SCU_CCUCON0.B.SRIDIV;
617  }
618 
619  break;
620  case 1:
621  sriFrequency = sourceFrequency / 30;
622  break;
623  case 2:
624  sriFrequency = sourceFrequency / 60;
625  break;
626  case 3:
627  sriFrequency = sourceFrequency / 120;
628  break;
629  case 4:
630  sriFrequency = sourceFrequency / 240;
631  break;
632  default:
633  sriFrequency = 0.0;
634  break;
635  }
636 
637  return sriFrequency;
638 }
639 
640 
641 boolean IfxScuCcu_init(const IfxScuCcu_Config *cfg)
642 {
643  uint8 smuTrapEnable;
644  uint16 endinit_pw, endinitSfty_pw;
645  boolean status = 0;
646  /* Store the crystal frequency */
647  IfxScuCcu_xtalFrequency = cfg->xtalFrequency;
648 
649  endinit_pw = IfxScuWdt_getCpuWatchdogPassword();
650  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
651 
652  {
653  /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */
654  IfxScuWdt_clearCpuEndinit(endinit_pw);
655  smuTrapEnable = SCU_TRAPDIS.B.SMUT;
656  SCU_TRAPDIS.B.SMUT = 1U;
657  IfxScuWdt_setCpuEndinit(endinit_pw);
658  }
659 
660  {
661  /* Select fback (fosc-evr) as CCU input clock */
662  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
663 
664  while (SCU_CCUCON0.B.LCK != 0U)
665  {
666  /*Wait till ccucon0 lock is set */
667  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
668  }
669 
670  SCU_CCUCON0.B.CLKSEL = 0; /*Select the EVR as fOSC for the clock distribution */
671  SCU_CCUCON0.B.UP = 1; /*Update the ccucon0 register */
672 
673  /* Disconnet PLL (SETFINDIS=1): oscillator clock is disconnected from PLL */
674  SCU_PLLCON0.B.SETFINDIS = 1;
675  /* Now PLL is in free running mode */
676 
677  /* Select Clock Source as PLL input clock */
678  while (SCU_CCUCON0.B.LCK != 0U)
679  {
680  /*Wait till ccucon0 lock is set */
681  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
682  }
683 
684  SCU_CCUCON1.B.INSEL = 1; /*Select oscillator OSC0 as clock to PLL */
685  SCU_CCUCON1.B.UP = 1; /*Update the ccucon0 register */
686 
687  status |= IfxScuCcu_isOscillatorStable();
688 
689  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
690  }
691 
692  if (status == 0)
693  {
694  /*Start the PLL configuration sequence */
695  uint8 pllStepsCount;
696 
697  /*Setting up P N and K2 values equate pll to evr osc freq */
698  {
699  {
700  /*Set the K2 divider value for the step corresponding to step count */
701  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
702 
703  while (SCU_PLLSTAT.B.K2RDY == 0U)
704  {
705  /*Wait until K2 divider is ready */
706  /*No "timeout" required because Safety Endinit will give a trap */
707  }
708 
709  SCU_PLLCON1.B.K2DIV = cfg->sysPll.pllInitialStep.k2Initial;
710 
711  {
712  /*change P and N divider values */
713  SCU_PLLCON0.B.PDIV = cfg->sysPll.pllInitialStep.pDivider;
714  SCU_PLLCON0.B.NDIV = cfg->sysPll.pllInitialStep.nDivider;
715 
716  /* Disable oscillator disconnect feature
717  * in case of PLL unlock, PLL stays connected to fref */
718  SCU_PLLCON0.B.OSCDISCDIS = 1;
719  // workaround for Errata: PLL TC 005
720  SCU_PLLCON0.B.PLLPWD = 0; // set PLL to power down
721  /* Connect PLL to fREF as oscillator clock is connected to PLL */
722  SCU_PLLCON0.B.CLRFINDIS = 1;
723  SCU_PLLCON0.B.PLLPWD = 1; // set PLL to normal
724 
725  /* Restart PLL lock detection (RESLD = 1) */
726  SCU_PLLCON0.B.RESLD = 1;
727 
728  IfxScuCcu_wait(0.000050F); /*Wait for 50us */
729 
730  while (SCU_PLLSTAT.B.VCOLOCK == 0U)
731  {
732  /* Wait for PLL lock */
733  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
734  }
735 
736  SCU_PLLCON0.B.VCOBYP = 0; /*VCO bypass disabled */
737 
738  while (SCU_CCUCON0.B.LCK != 0U)
739  {
740  /*Wait till ccucon registers can be written with new value */
741  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
742  }
743 
744  SCU_CCUCON0.B.CLKSEL = 0x01;
745 
746  /*Configure the clock distribution */
747  while (SCU_CCUCON0.B.LCK != 0U)
748  {
749  /*Wait till ccucon registers can be written with new value */
750  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
751  }
752 
753  /*Wait until the initial clock configurations take in to effect for the PLL*/
754  IfxScuCcu_wait(cfg->sysPll.pllInitialStep.waitTime); /*Wait for configured initial time */
755 
756  { /*Write CCUCON0 configuration */
757  Ifx_SCU_CCUCON0 ccucon0;
758  ccucon0.U = SCU_CCUCON0.U & ~cfg->clockDistribution.ccucon0.mask;
759  /*update with configured value */
760  ccucon0.U |= (cfg->clockDistribution.ccucon0.mask & cfg->clockDistribution.ccucon0.value);
761  ccucon0.B.CLKSEL = 0x01; /* Select fpll as CCU input clock, even if this was not selected by configuration */
762  ccucon0.B.UP = 1;
763  SCU_CCUCON0 = ccucon0; /*Set update bit explicitly to make above configurations effective */
764  }
765 
766  while (SCU_CCUCON1.B.LCK != 0U)
767  {
768  /*Wait till ccucon registers can be written with new value */
769  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
770  }
771 
772  {
773  /*Write CCUCON1 configuration */
774  Ifx_SCU_CCUCON1 ccucon1;
775  ccucon1.U = SCU_CCUCON1.U & ~cfg->clockDistribution.ccucon1.mask;
776  /*update with configured value */
777  ccucon1.U |= (cfg->clockDistribution.ccucon1.mask & cfg->clockDistribution.ccucon1.value);
778  ccucon1.B.INSEL = 1;
779  ccucon1.B.UP = 1;
780  SCU_CCUCON1 = ccucon1;
781  }
782 
783  while (SCU_CCUCON2.B.LCK != 0U)
784  {
785  /*Wait till ccucon registers can be written with new value */
786  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
787  }
788 
789  {
790  /*Write CCUCON2 configuration */
791  Ifx_SCU_CCUCON2 ccucon2;
792  ccucon2.U = SCU_CCUCON2.U & ~cfg->clockDistribution.ccucon2.mask;
793  /*update with configured value */
794  ccucon2.U |= (cfg->clockDistribution.ccucon2.mask & cfg->clockDistribution.ccucon2.value);
795  ccucon2.B.UP = 1;
796  SCU_CCUCON2 = ccucon2;
797  }
798 
799  while (SCU_CCUCON5.B.LCK != 0U)
800  { /*Wait till ccucon registers can be written with new value */
801  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
802  }
803 
804  { /*Write CCUCON5 configuration */
805  Ifx_SCU_CCUCON5 ccucon5;
806  ccucon5.U = SCU_CCUCON5.U & ~cfg->clockDistribution.ccucon5.mask;
807  /*update with configured value */
808  ccucon5.U |= (cfg->clockDistribution.ccucon5.mask & cfg->clockDistribution.ccucon5.value);
809  ccucon5.B.UP = 1;
810  SCU_CCUCON5 = ccucon5;
811  }
812 
813  { /*Write CCUCON6 configuration */
814  Ifx_SCU_CCUCON6 ccucon6;
815  ccucon6.U = SCU_CCUCON6.U & ~cfg->clockDistribution.ccucon6.mask;
816  /*update with configured value */
817  ccucon6.U |= (cfg->clockDistribution.ccucon6.mask & cfg->clockDistribution.ccucon6.value);
818  SCU_CCUCON6 = ccucon6;
819  }
820 
821  {
822  /*Write CCUCON7 configuration */
823  Ifx_SCU_CCUCON7 ccucon7;
824  ccucon7.U = SCU_CCUCON7.U & ~cfg->clockDistribution.ccucon7.mask;
825  /*update with configured value */
826  ccucon7.U |= (cfg->clockDistribution.ccucon7.mask & cfg->clockDistribution.ccucon7.value);
827  SCU_CCUCON7 = ccucon7;
828  }
829 
830  {
831  /*Write CCUCON8 configuration */
832  Ifx_SCU_CCUCON8 ccucon8;
833  ccucon8.U = SCU_CCUCON8.U & ~cfg->clockDistribution.ccucon8.mask;
834  /*update with configured value */
835  ccucon8.U |= (cfg->clockDistribution.ccucon8.mask & cfg->clockDistribution.ccucon8.value);
836  SCU_CCUCON8 = ccucon8;
837  }
838  }
839 
840  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
841  }
842  }
843 
844  { /*Write Flash waitstate configuration */
845  Ifx_FLASH_FCON fcon;
846  fcon.U = FLASH0_FCON.U & ~cfg->flashFconWaitStateConfig.mask;
847 
848  /*update with configured value */
849  fcon.U &= ~cfg->flashFconWaitStateConfig.mask;
851  {
852  IfxScuWdt_clearCpuEndinit(endinit_pw);
853  FLASH0_FCON = fcon;
854  IfxScuWdt_setCpuEndinit(endinit_pw);
855  }
856  }
857 
858  /*Start Pll ramp up sequence */
859  for (pllStepsCount = 0; pllStepsCount < cfg->sysPll.numOfPllDividerSteps; pllStepsCount++)
860  { /*iterate through number of pll steps */
861  {
862  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
863 
864  /*Configure K2 divider */
865  while (SCU_PLLSTAT.B.K2RDY == 0U)
866  {
867  /*Wait until K2 divider is ready */
868  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
869  }
870 
871  /*Now set the K2 divider value for the step corresponding to step count */
872  SCU_PLLCON1.B.K2DIV = cfg->sysPll.pllDividerStep[pllStepsCount].k2Step;
873  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
874  }
875 
876  /*call the hook function if configured */
878  {
879  cfg->sysPll.pllDividerStep[pllStepsCount].hookFunction();
880  }
881 
882  /*Wait for waitCounter corresponding to the pll step */
883  IfxScuCcu_wait(cfg->sysPll.pllDividerStep[pllStepsCount].waitTime);
884  }
885  }
886 
887  { /* Enable oscillator disconnect feature */
888  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
889  SCU_PLLCON0.B.OSCDISCDIS = 0U;
890  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
891  }
892  {
893  /* Enable VCO unlock Trap if it was disabled before */
894  IfxScuWdt_clearCpuEndinit(endinit_pw);
895  SCU_TRAPCLR.B.SMUT = 1U;
896  SCU_TRAPDIS.B.SMUT = smuTrapEnable;
897  IfxScuWdt_setCpuEndinit(endinit_pw);
898  }
899  return status;
900 }
901 
902 
904 {
906 }
907 
908 
910 {
911  uint8 smuTrapEnable;
912  uint16 endinit_pw, endinitSfty_pw;
913  boolean status = 0;
914 
915  endinit_pw = IfxScuWdt_getCpuWatchdogPassword();
916  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
917 
918  { /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */
919  IfxScuWdt_clearCpuEndinit(endinit_pw);
920  smuTrapEnable = SCU_TRAPDIS.B.SMUT;
921  SCU_TRAPDIS.B.SMUT = 1U;
922  IfxScuWdt_setCpuEndinit(endinit_pw);
923  }
924  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
925 
926  // ensure that PLL enabled
927  if (!SCU_PLLERAYCON0.B.PLLPWD || SCU_PLLERAYCON0.B.VCOPWD || SCU_PLLERAYSTAT.B.PWDSTAT)
928  { // PLLPWD=0 or VCOPWD=1 or PWDSTAT=1?
929  // enable PLL and leave power saving mode
930  SCU_PLLERAYCON0.B.PLLPWD = 1;
931  SCU_PLLERAYCON0.B.VCOPWD = 0;
932 
933  while (SCU_PLLERAYSTAT.B.PWDSTAT) // poll PWDSTAT
934  {}
935 
936  /*Wait for waitCounter corresponding to the pll step */
937  IfxScuCcu_wait(cfg->pllInitialStep.waitTime);
938  }
939 
940  /* Enter Prescalar mode */
941  /* Update K and N dividers */
942  if (!SCU_PLLERAYSTAT.B.VCOBYST) // checking PLLERAYBYPST flag
943  { // select "secure" K1 value - please check @silicon if K1=4 is ok
944  while (!SCU_PLLERAYSTAT.B.K1RDY) // poll K1RDY before changing K
945  {}
946 
947  SCU_PLLERAYCON1.B.K1DIV = 3;
948 
949  // activate VCO bypass (bit 0: VCOBYP=1)
950  SCU_PLLERAYCON0.B.VCOBYP = 1;
951  }
952 
953  while (!SCU_PLLERAYSTAT.B.K2RDY) // poll K1RDY before changing K
954  {}
955 
956  SCU_PLLERAYCON1.B.K2DIV = cfg->pllInitialStep.k2Initial;
957  SCU_PLLERAYCON0.B.PDIV = cfg->pllInitialStep.pDivider;
958  SCU_PLLERAYCON0.B.NDIV = cfg->pllInitialStep.nDivider;
959  /*
960  * RESLD = 1 ==> Restart VCO lock detection
961  * CLRFINDIS = 1 ==> Connect OSC to PLL
962  * PLLPWD = 1 ==> PLL Power Saving Mode : Normal behaviour
963  * NDIV = NDIV
964  */
965 
966  SCU_PLLERAYCON0.B.RESLD = 1U;
967  SCU_PLLERAYCON0.B.CLRFINDIS = 1U;
968 
969  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
970 
971  // Wait until VCO LOCK bit is set
972  uint32 time_out_ctr = 50000; // higher time out value as for clib_pll, since system is clocked much faster while polling the lock flag
973 
974  while (--time_out_ctr && !SCU_PLLERAYSTAT.B.VCOLOCK)
975  {}
976 
977  // check for timeout, exit immediately (don't disable VCO bypass) of not locked
978  if (!time_out_ctr)
979  {
980  status = FALSE;
981  }
982 
983  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
984  /*Bypass VCO*/
985  SCU_PLLERAYCON0.B.VCOBYP = 0U;
986 
987  // wait until bypass has been deactivated
988  while (SCU_PLLERAYSTAT.B.VCOBYST) // poll VCOBYST
989  {}
990 
991  if (!SCU_PLLERAYSTAT.B.VCOLOCK)
992  {
993  status = FALSE;
994  }
995 
996  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
997 
998  { /* Enable VCO unlock Trap if it was disabled before */
999  IfxScuWdt_clearCpuEndinit(endinit_pw);
1000  SCU_TRAPCLR.B.SMUT = 1U;
1001  SCU_TRAPDIS.B.SMUT = smuTrapEnable;
1002  IfxScuWdt_setCpuEndinit(endinit_pw);
1003  }
1004  return status;
1005 }
1006 
1007 
1009 {
1011 }
1012 
1013 
1014 static boolean IfxScuCcu_isOscillatorStable(void)
1015 {
1016  sint32 TimeoutCtr = IFXSCUCCU_OSC_STABLECHK_TIME;
1017  boolean status = 0;
1019  /* Mode External Crystal / Ceramic Resonator Mode and External Input Clock.
1020  * The oscillator Power-Saving Mode is not entered
1021  */
1022  SCU_OSCCON.B.MODE = 0U;
1023 
1024  /* OSCVAL defines the divider value that generates the reference clock
1025  * that is supervised by the oscillator watchdog.
1026  * fOSC / (OSCVAL + 1) ~ 2.5Mhz => OSCVAL = (fOSC / 2.5Mhz) - 1 */
1027 
1028  SCU_OSCCON.B.OSCVAL = ((uint32)IfxScuCcu_xtalFrequency / 2500000) - 1;
1029  /* The Oscillator Watchdog of the PLL is cleared and restarted */
1030  SCU_OSCCON.B.OSCRES = 1U;
1031 
1032  /* wait until PLLLV and PLLHV flags are set */
1033  while ((SCU_OSCCON.B.PLLLV == 0) || (SCU_OSCCON.B.PLLHV == 0))
1034  {
1035  TimeoutCtr--;
1036 
1037  if (TimeoutCtr == 0)
1038  {
1039  status = 1;
1040  break;
1041  }
1042  }
1043 
1044  {
1045  /* clear and then set SMU trap (oscillator watchdog and unlock detection) */
1046  IfxScuWdt_clearCpuEndinit(endinitPw);
1047  SCU_TRAPCLR.B.SMUT = 1U; /* TODO Can this be removed? */
1048  SCU_TRAPDIS.B.SMUT = 1U; /* TODO Can this be removed? */
1049  IfxScuWdt_setCpuEndinit(endinitPw);
1050  }
1051  return status;
1052 }
1053 
1054 
1056 {
1057  uint16 endinitSfty_pw;
1058  float32 sriFreq;
1059  uint32 cpuDiv;
1060 
1061  sriFreq = IfxScuCcu_getSriFrequency();
1062 
1063  if (cpuFreq >= sriFreq)
1064  {
1065  cpuDiv = 0;
1066  }
1067  else
1068  {
1069  cpuDiv = (uint32)((cpuFreq * 64) / sriFreq);
1070  }
1071 
1072  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
1073 
1074  {
1075  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
1076 
1077  switch (cpu)
1078  {
1079  case IfxCpu_ResourceCpu_0:
1080  SCU_CCUCON6.U = cpuDiv;
1081  break;
1082  case IfxCpu_ResourceCpu_1:
1083  SCU_CCUCON7.U = cpuDiv;
1084  break;
1085  case IfxCpu_ResourceCpu_2:
1086  SCU_CCUCON8.U = cpuDiv;
1087  break;
1088  default:
1089  break;
1090  }
1091 
1092  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
1093  }
1094 
1095  if (cpuDiv != 0)
1096  {
1097  sriFreq = sriFreq * (cpuDiv / 64);
1098  }
1099 
1100  return sriFreq;
1101 }
1102 
1103 
1105 {
1106  uint16 l_SEndInitPW;
1107  Ifx_SCU_CCUCON1 ccucon1 = SCU_CCUCON1;
1108 
1109  float32 inputFreq = IfxScuCcu_getSourceFrequency();
1110  uint32 gtmDiv = (uint32)__roundf(inputFreq / gtmFreq);
1111  gtmDiv = __maxu(gtmDiv, 1);
1112 
1113  /*gtmDiv = gtmDiv & 0x2U;*//* only even dividers */
1114  if ((gtmDiv >= 7) && (gtmDiv < 14) && ((gtmDiv & 1) == 1))
1115  {
1116  gtmDiv = gtmDiv - 1;
1117  }
1118 
1119  if (gtmDiv == 14)
1120  {
1121  gtmDiv = 12;
1122  }
1123 
1124  l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword();
1125  IfxScuWdt_clearSafetyEndinit(l_SEndInitPW);
1126  ccucon1.B.GTMDIV = gtmDiv;
1127  ccucon1.B.UP = 1U;
1128  SCU_CCUCON1.U = ccucon1.U;
1129 
1130  IfxScuWdt_setSafetyEndinit(l_SEndInitPW);
1131 
1132  return IfxScuCcu_getGtmFrequency();
1133 }
1134 
1135 
1137 {
1139  uint32 pll2Div = (uint32)((IfxScuCcu_getPllErayVcoFrequency() / pll2ErayFreq) - 1);
1140  {
1141  IfxScuWdt_clearSafetyEndinit(password);
1142  SCU_PLLERAYCON1.B.K3DIV = pll2Div;
1143  IfxScuWdt_setSafetyEndinit(password);
1144  }
1146 }
1147 
1148 
1150 {
1151  uint16 endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
1152  uint32 pll2Div = (uint32)((IfxScuCcu_getPllVcoFrequency() / pll2Freq) - 1);
1153  {
1154  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
1155  SCU_PLLCON1.B.K3DIV = pll2Div;
1156  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
1157  }
1158  return IfxScuCcu_getPll2Frequency();
1159 }
1160 
1161 
1163 {
1164  /* TODO: check whether it is necessary to disable trap and/or the safety */
1165  uint16 l_EndInitPW;
1166  uint16 l_SEndInitPW;
1167  Ifx_SCU_CCUCON0 ccucon0;
1168  float32 inputFreq = IfxScuCcu_getSourceFrequency();
1169  uint32 spbDiv = (uint32)(inputFreq / spbFreq);
1170  spbDiv = __maxu(spbDiv, 2);
1171 
1172  if ((spbDiv >= 7) && (spbDiv < 14) && ((spbDiv & 1) == 1))
1173  {
1174  spbDiv = spbDiv - 1;
1175  }
1176 
1177  if (spbDiv == 14)
1178  {
1179  spbDiv = 12;
1180  }
1181 
1182  l_EndInitPW = IfxScuWdt_getCpuWatchdogPassword();
1183  l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword();
1184 
1185  IfxScuWdt_clearCpuEndinit(l_EndInitPW);
1186  SCU_TRAPDIS.U = SCU_TRAPDIS.U | 0x3E0U;
1187  IfxScuWdt_setCpuEndinit(l_EndInitPW);
1188 
1189  IfxScuWdt_clearSafetyEndinit(l_SEndInitPW);
1190  ccucon0.U = SCU_CCUCON0.U;
1191  ccucon0.B.SPBDIV = spbDiv;
1192  ccucon0.B.UP = 1;
1193  SCU_CCUCON0.U = ccucon0.U;
1194  IfxScuWdt_setSafetyEndinit(l_SEndInitPW);
1195 
1196  IfxScuWdt_clearCpuEndinit(l_EndInitPW);
1197  SCU_TRAPDIS.U = SCU_TRAPDIS.U & (uint32)~0x3E0UL;
1198  IfxScuWdt_setCpuEndinit(l_EndInitPW);
1199 
1200  while (SCU_CCUCON0.B.LCK != 0U)
1201  {}
1202 
1203  return IfxScuCcu_getSpbFrequency();
1204 }
1205 
1206 
1208 {
1209  float32 freq = 0;
1211  Ifx_SCU_CCUCON0 ccucon0;
1212  uint16 l_SEndInitPW;
1213  uint32 sriDiv = (uint32)__roundf(source / sriFreq);
1214  sriDiv = __maxu(sriDiv, 1);
1215 
1216  if ((sriDiv >= 7) && (sriDiv < 14) && ((sriDiv & 1) == 1))
1217  {
1218  sriDiv = sriDiv - 1;
1219  }
1220 
1221  if (sriDiv == 14)
1222  {
1223  sriDiv = 12;
1224  }
1225 
1226  l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword();
1227  IfxScuWdt_clearSafetyEndinit(l_SEndInitPW);
1228 
1229  ccucon0.U = SCU_CCUCON0.U;
1230  ccucon0.B.SRIDIV = sriDiv;
1231  ccucon0.B.UP = 1;
1232  SCU_CCUCON0.U = ccucon0.U;
1233 
1234  IfxScuWdt_setSafetyEndinit(l_SEndInitPW);
1235 
1236  while (SCU_CCUCON0.B.LCK != 0U)
1237  {}
1238 
1239  freq = IfxScuCcu_getSriFrequency();
1240  return freq;
1241 }
1242 
1243 
1245 {
1246  uint16 endinit_pw, endinitSfty_pw;
1247  int pllStepsCount;
1248  uint8 smuTrapEnable;
1249 
1250  if (SCU_CCUCON0.B.CLKSEL == 0) /* Already source is backup clock */
1251  {
1252  return;
1253  }
1254 
1255  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
1256  endinit_pw = IfxScuWdt_getCpuWatchdogPassword();
1257 
1258  /*Start Pll ramp down sequence */
1259  for (pllStepsCount = cfg->sysPll.numOfPllDividerSteps; pllStepsCount > 0; pllStepsCount--)
1260  { /*iterate through number of pll steps */
1261  {
1262  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
1263 
1264  /*Configure K2 divider */
1265  while (SCU_PLLSTAT.B.K2RDY == 0U)
1266  {
1267  /*Wait until K2 divider is ready */
1268  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
1269  }
1270 
1271  /*Now set the K2 divider value for the step corresponding to step count */
1272  SCU_PLLCON1.B.K2DIV = cfg->sysPll.pllDividerStep[pllStepsCount - 1].k2Step;
1273  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
1274 
1275  /*Wait for waitCounter corresponding to the pll step */
1276  IfxScuCcu_wait(cfg->sysPll.pllDividerStep[pllStepsCount - 1].waitTime);
1277  }
1278  }
1279 
1280  {
1281  /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */
1282  IfxScuWdt_clearCpuEndinit(endinit_pw);
1283  smuTrapEnable = SCU_TRAPDIS.B.SMUT;
1284  SCU_TRAPDIS.B.SMUT = 1U;
1285  IfxScuWdt_setCpuEndinit(endinit_pw);
1286  }
1287 
1288  {
1289  /* Select fback (fosc-evr) as CCU input clock */
1290  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
1291 
1292  while (SCU_CCUCON0.B.LCK != 0U)
1293  {
1294  /*Wait till ccucon0 lock is set */
1295  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
1296  }
1297 
1298  SCU_CCUCON0.B.CLKSEL = 0; /*Select the EVR as fOSC for the clock distribution */
1299  SCU_CCUCON0.B.UP = 1; /*Update the ccucon0 register */
1300 
1301  while (SCU_CCUCON0.B.LCK != 0U)
1302  {
1303  /*Wait till ccucon0 lock is set */
1304  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
1305  }
1306 
1307  /* Disconnet PLL (SETFINDIS=1): oscillator clock is disconnected from PLL */
1308  SCU_PLLCON0.B.SETFINDIS = 1;
1309 
1310  /* Enable oscillator disconnect feature */
1311  SCU_PLLCON0.B.OSCDISCDIS = 0U;
1312  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
1313  }
1314  {
1315  /* Enable VCO unlock Trap if it was disabled before */
1316  IfxScuWdt_clearCpuEndinit(endinit_pw);
1317  SCU_TRAPCLR.B.SMUT = 1U;
1318  SCU_TRAPDIS.B.SMUT = smuTrapEnable;
1319  IfxScuWdt_setCpuEndinit(endinit_pw);
1320  }
1321 }
1322 
1323 
1324 static void IfxScuCcu_wait(float32 timeSec)
1325 {
1326  uint32 stmCount = (uint32)(IfxScuCcu_getStmFrequency() * timeSec);
1327  uint32 stmCountBegin = STM0_TIM0.U;
1328 
1329  while ((uint32)(STM0_TIM0.U - stmCountBegin) < stmCount)
1330  {
1331  /* There is no need to check overflow of the STM timer.
1332  * When counter after overflow subtracted with counter before overflow,
1333  * the subtraction result will be as expected, as long as both are unsigned 32 bits
1334  * eg: stmCountBegin= 0xFFFFFFFE (before overflow)
1335  * stmCountNow = 0x00000002 (before overflow)
1336  * diff= stmCountNow - stmCountBegin = 4 as expected.*/
1337  }
1338 }