iLLD_TC27xC  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_0_1_0_10
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 #include "IfxStm_reg.h"
32 #include "IfxFlash_reg.h"
33 
34 /** \addtogroup IfxLld_Scu_Std_Ccu
35  * \{ */
36 
37 /******************************************************************************/
38 /*-----------------------Private Function Prototypes--------------------------*/
39 /******************************************************************************/
40 
41 /** \brief Check if oscillator is stable.
42  * \return Status of oscillator stability
43  * \retval TRUE: Oscillator is unstable
44  * \retval FALSE: Oscillator is stable
45  */
46 static boolean IfxScuCcu_isOscillatorStable(void);
47 
48 /** \brief API to wait for requested duration.
49  * 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
50  * \return None
51  */
52 static void IfxScuCcu_wait(float32 timeSec);
53 
54 /** \} */
55 
56 /******************************************************************************/
57 /*------------------------Private Variables/Constants-------------------------*/
58 /******************************************************************************/
59 
60 /** \brief Default configuration for the PLL initial steps
61  * This is a structure array and the values are defined at the Scu implementation as #define macro
62  */
63 static const IfxScuCcu_PllStepsConfig IfxScuCcu_aDefaultPllConfigSteps[] = {
65 };
66 
67 /******************************************************************************/
68 /*-----------------------Exported Variables/Constants-------------------------*/
69 /******************************************************************************/
70 
72  sizeof(IfxScuCcu_aDefaultPllConfigSteps) / sizeof(IfxScuCcu_PllStepsConfig),
73  (IfxScuCcu_PllStepsConfig *)IfxScuCcu_aDefaultPllConfigSteps,
77 };
78 
80 /*{ uint8 pDivider, uint8 nDivider, uint8 k2Initial, float32 waitTime }*/
81  {(1 - 1), (24 - 1), (6 - 1), 0}
82 };
83 
84 /******************************************************************************/
85 /*-------------------------Function Implementations---------------------------*/
86 /******************************************************************************/
87 
89 {
90  float32 frequency;
91  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
92 
93  if (ccucon0.B.BAUD1DIV == 0)
94  {
95  frequency = 0;
96  }
97  else
98  {
99  frequency = IfxScuCcu_getMaxFrequency() / ccucon0.B.BAUD1DIV;
100  }
101 
102  return frequency;
103 }
104 
105 
107 {
108  float32 frequency;
109  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
110 
111  if (ccucon0.B.BAUD2DIV == 0)
112  {
113  frequency = 0;
114  }
115  else
116  {
117  frequency = IfxScuCcu_getMaxFrequency() / ccucon0.B.BAUD2DIV;
118  }
119 
120  return frequency;
121 }
122 
123 
125 {
126  float32 bbbFrequency;
127  float32 sourceFrequency;
128  sourceFrequency = IfxScuCcu_getSourceFrequency();
129 
130  switch (SCU_CCUCON0.B.LPDIV)
131  {
132  case 0: /*Not in low power mode */
133 
134  if (SCU_CCUCON2.B.BBBDIV == 0)
135  {
136  bbbFrequency = 0.0;
137  }
138  else
139  {
140  bbbFrequency = sourceFrequency / SCU_CCUCON2.B.BBBDIV;
141  }
142 
143  break;
144  case 1:
145  bbbFrequency = sourceFrequency / 30;
146  break;
147  case 2:
148  bbbFrequency = sourceFrequency / 60;
149  break;
150  case 3:
151  bbbFrequency = sourceFrequency / 120;
152  break;
153  case 4:
154  bbbFrequency = sourceFrequency / 240;
155  break;
156  default:
157  bbbFrequency = 0.0;
158  break;
159  }
160 
161  return bbbFrequency;
162 }
163 
164 
166 {
167  float32 frequency = IfxScuCcu_getSriFrequency();
168  uint32 cpuDiv = 0;
169 
170  switch (cpu)
171  {
173  cpuDiv = SCU_CCUCON6.U;
174  break;
176  cpuDiv = SCU_CCUCON7.U;
177  break;
179  cpuDiv = SCU_CCUCON8.U;
180  break;
181  default:
182  frequency = 0.0;
183  break;
184  }
185 
186  if (cpuDiv != 0)
187  {
188  frequency = frequency * (cpuDiv / 64);
189  }
190 
191  return frequency;
192 }
193 
194 
196 {
197  float32 frequency;
198  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
199 
200  if (ccucon0.B.FSIDIV == 0)
201  {
202  frequency = 0;
203  }
204  else
205  {
206  frequency = IfxScuCcu_getSriFrequency();
207 
208  if ((ccucon0.B.FSIDIV == 1) || (ccucon0.B.SRIDIV == 1) || (ccucon0.B.SRIDIV == 2))
209  {
210  frequency = frequency / ccucon0.B.FSIDIV;
211  }
212  }
213 
214  return frequency;
215 }
216 
217 
219 {
220  float32 frequency;
221  Ifx_SCU_CCUCON0 ccucon0 = SCU_CCUCON0;
222 
223  if (ccucon0.B.FSIDIV == 0)
224  {
225  frequency = 0;
226  }
227  else
228  {
229  frequency = IfxScuCcu_getSriFrequency();
230 
231  if ((ccucon0.B.FSIDIV == 1) || (ccucon0.B.SRIDIV == 1) || (ccucon0.B.SRIDIV == 2))
232  {
233  frequency = frequency / ccucon0.B.FSIDIV;
234  }
235  }
236 
237  return frequency;
238 }
239 
240 
242 {
243  float32 maxFrequency;
244  float32 sourceFrequency;
245  sourceFrequency = IfxScuCcu_getSourceFrequency();
246 
247  switch (SCU_CCUCON0.B.LPDIV)
248  {
249  case 0: /*Not in low power mode */
250 
251  if (SCU_CCUCON5.B.MAXDIV == 0)
252  {
253  maxFrequency = sourceFrequency;
254  }
255  else
256  {
257  maxFrequency = sourceFrequency / SCU_CCUCON5.B.MAXDIV;
258  }
259 
260  break;
261  case 1:
262  maxFrequency = sourceFrequency / 15;
263  break;
264  case 2:
265  maxFrequency = sourceFrequency / 30;
266  break;
267  case 3:
268  maxFrequency = sourceFrequency / 60;
269  break;
270  case 4:
271  maxFrequency = sourceFrequency / 120;
272  break;
273  default:
274  maxFrequency = 0.0;
275  break;
276  }
277 
278  return maxFrequency;
279 }
280 
281 
283 {
284  float32 spbFreq;
285  float32 moduleFreq;
286  Ifx_SCU_FDR scuFdr;
287  scuFdr = SCU_FDR;
288  spbFreq = IfxScuCcu_getSpbFrequency();
289 
290  if (scuFdr.B.DM == 1)
291  {
292  moduleFreq = spbFreq / (1024 - scuFdr.B.STEP);
293  }
294  else if (scuFdr.B.DM == 2)
295  {
296  moduleFreq = (spbFreq * scuFdr.B.STEP) / 1024;
297  }
298  else
299  {
300  moduleFreq = 0;
301  }
302 
303  return moduleFreq;
304 }
305 
306 
308 {
309  Ifx_SCU *scu = &MODULE_SCU;
310  float32 oscFreq;
311  float32 freq;
312 
313  oscFreq = IfxScuCcu_getOscFrequency();
314 
315  if (scu->PLLERAYSTAT.B.VCOBYST == 1)
316  {
317  /* Prescaler mode */
318  freq = oscFreq / (scu->PLLERAYCON1.B.K1DIV + 1);
319  }
320  else if (scu->PLLERAYSTAT.B.FINDIS == 1)
321  {
322  /* Free running mode */
323  freq = IFXSCU_VCO_BASE_FREQUENCY / (scu->PLLERAYCON1.B.K2DIV + 1);
324  }
325  else
326  {
327  /* Normal mode */
328  freq = (oscFreq * (scu->PLLERAYCON0.B.NDIV + 1)) / (scu->PLLERAYCON1.B.K2DIV + 1);
329  }
330 
331  return freq;
332 }
333 
334 
336 {
337  float32 vcoFreq;
338 
339  if (SCU_PLLERAYSTAT.B.FINDIS == 1)
340  {
341  /* Free running mode */
342  vcoFreq = IFXSCU_VCO_BASE_FREQUENCY;
343  }
344  else
345  {
346  /* Normal mode */
347  vcoFreq = (IfxScuCcu_getOscFrequency() * (SCU_PLLERAYCON0.B.NDIV + 1)) / (SCU_PLLERAYCON0.B.PDIV + 1);
348  }
349 
350  return vcoFreq;
351 }
352 
353 
355 {
356  Ifx_SCU *scu = &MODULE_SCU;
357  float32 oscFreq;
358  float32 freq;
359 
360  oscFreq = IfxScuCcu_getOscFrequency();
361 
362  if (scu->PLLSTAT.B.VCOBYST == 1)
363  {
364  /* Prescaler mode */
365  freq = oscFreq / (scu->PLLCON1.B.K1DIV + 1);
366  }
367  else if (scu->PLLSTAT.B.FINDIS == 1)
368  {
369  /* Free running mode */
370  freq = IFXSCU_VCO_BASE_FREQUENCY / (scu->PLLCON1.B.K2DIV + 1);
371  }
372  else
373  {
374  /* Normal mode */
375  freq = (oscFreq * (scu->PLLCON0.B.NDIV + 1)) / ((scu->PLLCON1.B.K2DIV + 1) * (scu->PLLCON0.B.PDIV + 1));
376  }
377 
378  return freq;
379 }
380 
381 
383 {
384  float32 vcoFreq;
385 
386  if (SCU_PLLSTAT.B.FINDIS == 1)
387  {
388  /* Free running mode */
389  vcoFreq = IFXSCU_VCO_BASE_FREQUENCY;
390  }
391  else
392  {
393  /* Normal mode */
394  vcoFreq = (IfxScuCcu_getOscFrequency() * (SCU_PLLCON0.B.NDIV + 1)) / (SCU_PLLCON0.B.PDIV + 1);
395  }
396 
397  return vcoFreq;
398 }
399 
400 
402 {
403  float32 sourcefreq;
404 
405  switch (SCU_CCUCON0.B.CLKSEL)
406  {
408  sourcefreq = IfxScuCcu_getEvrFrequency();
409  break;
411  sourcefreq = IfxScuCcu_getPllFrequency();
412  break;
413  default:
414  sourcefreq = 0;
415  break;
416  }
417 
418  return sourcefreq;
419 }
420 
421 
423 {
424  float32 spbFrequency;
425  float32 sourceFrequency;
426  sourceFrequency = IfxScuCcu_getSourceFrequency();
427 
428  switch (SCU_CCUCON0.B.LPDIV)
429  {
430  case 0: /*Not in low power mode */
431 
432  if (SCU_CCUCON0.B.SPBDIV == 0)
433  {
434  spbFrequency = 0.0;
435  }
436  else
437  {
438  spbFrequency = sourceFrequency / SCU_CCUCON0.B.SPBDIV;
439  }
440 
441  break;
442  case 1:
443  spbFrequency = sourceFrequency / 30;
444  break;
445  case 2:
446  spbFrequency = sourceFrequency / 60;
447  break;
448  case 3:
449  spbFrequency = sourceFrequency / 120;
450  break;
451  case 4:
452  spbFrequency = sourceFrequency / 240;
453  break;
454  default:
455  spbFrequency = 0.0;
456  break;
457  }
458 
459  return spbFrequency;
460 }
461 
462 
464 {
465  float32 sriFrequency;
466  float32 sourceFrequency;
467  sourceFrequency = IfxScuCcu_getSourceFrequency();
468 
469  switch (SCU_CCUCON0.B.LPDIV)
470  {
471  case 0: /*Not in low power mode */
472 
473  if (SCU_CCUCON0.B.SRIDIV == 0)
474  {
475  sriFrequency = 0.0;
476  }
477  else
478  {
479  sriFrequency = sourceFrequency / SCU_CCUCON0.B.SRIDIV;
480  }
481 
482  break;
483  case 1:
484  sriFrequency = sourceFrequency / 30;
485  break;
486  case 2:
487  sriFrequency = sourceFrequency / 60;
488  break;
489  case 3:
490  sriFrequency = sourceFrequency / 120;
491  break;
492  case 4:
493  sriFrequency = sourceFrequency / 240;
494  break;
495  default:
496  sriFrequency = 0.0;
497  break;
498  }
499 
500  return sriFrequency;
501 }
502 
503 
504 boolean IfxScuCcu_init(const IfxScuCcu_Config *cfg)
505 {
506  uint8 smuTrapEnable;
507  uint16 endinit_pw, endinitSfty_pw;
508  boolean status = 0;
509 
510  endinit_pw = IfxScuWdt_getCpuWatchdogPassword();
511  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
512 
513  { /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */
514  IfxScuWdt_clearCpuEndinit(endinit_pw);
515  smuTrapEnable = SCU_TRAPDIS.B.SMUT;
516  SCU_TRAPDIS.B.SMUT = 1U;
517  IfxScuWdt_setCpuEndinit(endinit_pw);
518  }
519 
520  { /* Select fback (fosc-evr) as CCU input clock */
521  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
522 
523  while (SCU_CCUCON0.B.LCK != 0U)
524  { /*Wait till ccucon0 lock is set */
525  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
526  }
527 
528  SCU_CCUCON0.B.CLKSEL = 0; /*Select the EVR as fOSC for the clock distribution */
529  SCU_CCUCON0.B.UP = 1; /*Update the ccucon0 register */
530 
531  /* Disconnet PLL (SETFINDIS=1): oscillator clock is disconnected from PLL */
532  SCU_PLLCON0.B.SETFINDIS = 1;
533  /* Now PLL is in free running mode */
534 
535  /* Select Clock Source as PLL input clock */
536  while (SCU_CCUCON0.B.LCK != 0U)
537  { /*Wait till ccucon0 lock is set */
538  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
539  }
540 
541  SCU_CCUCON1.B.INSEL = 1; /*Select oscillator OSC0 as clock to PLL */
542  SCU_CCUCON1.B.UP = 1; /*Update the ccucon0 register */
543 
544  status |= IfxScuCcu_isOscillatorStable();
545 
546  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
547  }
548 
549  if (status == 0)
550  { /*Start the PLL configuration sequence */
551  uint8 pllStepsCount;
552 
553  /*Setting up P N and K2 values equate pll to evr osc freq */
554  {
555  { /*Set the K2 divider value for the step corresponding to step count */
556  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
557 
558  while (SCU_PLLSTAT.B.K2RDY == 0U)
559  { /*Wait until K2 divider is ready */
560  /*No "timeout" required because Safety Endinit will give a trap */
561  }
562 
563  SCU_PLLCON1.B.K2DIV = cfg->pllInitialStep.k2Initial;
564 
565  if ((SCU_PLLCON0.B.PDIV != cfg->pllInitialStep.pDivider) ||
566  (SCU_PLLCON0.B.NDIV != cfg->pllInitialStep.nDivider))
567  {
568  /*change P and N divider values */
569  SCU_PLLCON0.B.PDIV = cfg->pllInitialStep.pDivider;
570  SCU_PLLCON0.B.NDIV = cfg->pllInitialStep.nDivider;
571 
572  /* Disable oscillator disconnect feature
573  * in case of PLL unlock, PLL stays connected to fref */
574  SCU_PLLCON0.B.OSCDISCDIS = 1;
575  /* Connect PLL to fREF as oscillator clock is connected to PLL */
576  SCU_PLLCON0.B.CLRFINDIS = 1;
577 
578  IfxScuCcu_wait(0.000050F); /*Wait for 50us */
579 
580  /* Restart PLL lock detection (RESLD = 1) */
581  SCU_PLLCON0.B.RESLD = 1;
582 
583  while (SCU_PLLSTAT.B.VCOLOCK == 0U)
584  { /* Wait for PLL lock */
585  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
586  }
587 
588  SCU_PLLCON0.B.VCOBYP = 0; /*VCO bypass disabled */
589 
590  while (SCU_CCUCON0.B.LCK != 0U)
591  { /*Wait till ccucon registers can be written with new value */
592  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
593  }
594 
595  SCU_CCUCON0.B.CLKSEL = 0x01;
596 
597  /*Configure the clock distribution */
598  while (SCU_CCUCON0.B.LCK != 0U)
599  { /*Wait till ccucon registers can be written with new value */
600  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
601  }
602 
603  /*Wait until the initial clock configurations take in to effect for the PLL*/
604  IfxScuCcu_wait(cfg->pllInitialStep.waitTime); /*Wait for configured initial time */
605 
606  { /*Write CCUCON0 configuration */
607  Ifx_SCU_CCUCON0 ccucon0;
608  ccucon0.U = SCU_CCUCON0.U & ~cfg->clockDistribution.ccucon0.mask;
609  /*update with configured value */
610  ccucon0.U |= (cfg->clockDistribution.ccucon0.mask & cfg->clockDistribution.ccucon0.value);
611  ccucon0.B.CLKSEL = 0x01; /* Select fpll as CCU input clock, even if this was not selected by configuration */
612  ccucon0.B.UP = 1;
613  SCU_CCUCON0 = ccucon0; /*Set update bit explicitly to make above configurations effective */
614  }
615 
616  while (SCU_CCUCON1.B.LCK != 0U)
617  { /*Wait till ccucon registers can be written with new value */
618  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
619  }
620 
621  { /*Write CCUCON1 configuration */
622  Ifx_SCU_CCUCON1 ccucon1;
623  ccucon1.U = SCU_CCUCON1.U & ~cfg->clockDistribution.ccucon1.mask;
624  /*update with configured value */
625  ccucon1.U |= (cfg->clockDistribution.ccucon1.mask & cfg->clockDistribution.ccucon1.value);
626  ccucon1.B.INSEL = 1;
627  ccucon1.B.UP = 1;
628  SCU_CCUCON1 = ccucon1;
629  }
630 
631  while (SCU_CCUCON2.B.LCK != 0U)
632  { /*Wait till ccucon registers can be written with new value */
633  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
634  }
635 
636  { /*Write CCUCON2 configuration */
637  Ifx_SCU_CCUCON2 ccucon2;
638  ccucon2.U = SCU_CCUCON2.U & ~cfg->clockDistribution.ccucon2.mask;
639  /*update with configured value */
640  ccucon2.U |= (cfg->clockDistribution.ccucon2.mask & cfg->clockDistribution.ccucon2.value);
641  ccucon2.B.UP = 1;
642  SCU_CCUCON2 = ccucon2;
643  }
644 
645  while (SCU_CCUCON5.B.LCK != 0U)
646  { /*Wait till ccucon registers can be written with new value */
647  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
648  }
649 
650  { /*Write CCUCON5 configuration */
651  Ifx_SCU_CCUCON5 ccucon5;
652  ccucon5.U = SCU_CCUCON5.U & ~cfg->clockDistribution.ccucon5.mask;
653  /*update with configured value */
654  ccucon5.U |= (cfg->clockDistribution.ccucon5.mask & cfg->clockDistribution.ccucon5.value);
655  ccucon5.B.UP = 1;
656  SCU_CCUCON5 = ccucon5;
657  }
658 
659  { /*Write CCUCON6 configuration */
660  Ifx_SCU_CCUCON6 ccucon6;
661  ccucon6.U = SCU_CCUCON6.U & ~cfg->clockDistribution.ccucon6.mask;
662  /*update with configured value */
663  ccucon6.U |= (cfg->clockDistribution.ccucon6.mask & cfg->clockDistribution.ccucon6.value);
664  SCU_CCUCON6 = ccucon6;
665  }
666 
667  { /*Write CCUCON7 configuration */
668  Ifx_SCU_CCUCON7 ccucon7;
669  ccucon7.U = SCU_CCUCON7.U & ~cfg->clockDistribution.ccucon7.mask;
670  /*update with configured value */
671  ccucon7.U |= (cfg->clockDistribution.ccucon7.mask & cfg->clockDistribution.ccucon7.value);
672  SCU_CCUCON7 = ccucon7;
673  }
674 
675  { /*Write CCUCON8 configuration */
676  Ifx_SCU_CCUCON8 ccucon8;
677  ccucon8.U = SCU_CCUCON8.U & ~cfg->clockDistribution.ccucon8.mask;
678  /*update with configured value */
679  ccucon8.U |= (cfg->clockDistribution.ccucon8.mask & cfg->clockDistribution.ccucon8.value);
680  SCU_CCUCON8 = ccucon8;
681  }
682  }
683 
684  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
685  }
686  }
687 
688  { /*Write Flash waitstate configuration */
689  Ifx_FLASH_FCON fcon;
690  fcon.U = FLASH0_FCON.U & ~cfg->flashFconWaitStateConfig.mask;
691 
692  /*update with configured value */
693  fcon.U &= ~cfg->flashFconWaitStateConfig.mask;
695  {
696  IfxScuWdt_clearCpuEndinit(endinit_pw);
697  FLASH0_FCON = fcon;
698  IfxScuWdt_setCpuEndinit(endinit_pw);
699  }
700  }
701 
702  /*Start Pll ramp up sequence */
703  for (pllStepsCount = 0; pllStepsCount < cfg->numOfPllDividerSteps; pllStepsCount++)
704  { /*iterate through number of pll steps */
705  {
706  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
707 
708  /*Configure K2 divider */
709  while (SCU_PLLSTAT.B.K2RDY == 0U)
710  { /*Wait until K2 divider is ready */
711  /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */
712  }
713 
714  /*Now set the K2 divider value for the step corresponding to step count */
715  SCU_PLLCON1.B.K2DIV = cfg->pllDividerStep[pllStepsCount].k2Step;
716  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
717  }
718 
719  /*call the hook function if configured */
720  if (cfg->pllDividerStep[pllStepsCount].hookFunction != (IfxScuCcu_PllStepsFunctionHook)0)
721  {
722  cfg->pllDividerStep[pllStepsCount].hookFunction();
723  }
724 
725  /*Wait for waitCounter corresponding to the pll step */
726  IfxScuCcu_wait(cfg->pllDividerStep[pllStepsCount].waitTime);
727  }
728  }
729 
730  { /* Enable oscillator disconnect feature */
731  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
732  SCU_PLLCON0.B.OSCDISCDIS = 0U;
733  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
734  }
735  { /* Enable VCO unlock Trap if it was disabled before */
736  IfxScuWdt_clearCpuEndinit(endinit_pw);
737  SCU_TRAPCLR.B.SMUT = 1U;
738  SCU_TRAPDIS.B.SMUT = smuTrapEnable;
739  IfxScuWdt_setCpuEndinit(endinit_pw);
740  }
741  return status;
742 }
743 
744 
746 {
748 }
749 
750 
752 {
753  uint8 smuTrapEnable;
754  uint16 endinit_pw, endinitSfty_pw;
755  boolean status = 0;
756  uint8 i;
757 
758  endinit_pw = IfxScuWdt_getCpuWatchdogPassword();
759  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
760 
761  { /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */
762  IfxScuWdt_clearCpuEndinit(endinit_pw);
763  smuTrapEnable = SCU_TRAPDIS.B.SMUT;
764  SCU_TRAPDIS.B.SMUT = 1U;
765  IfxScuWdt_setCpuEndinit(endinit_pw);
766  }
767  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
768 
769  // ensure that PLL enabled
770  if (!SCU_PLLERAYCON0.B.PLLPWD || SCU_PLLERAYCON0.B.VCOPWD || SCU_PLLERAYSTAT.B.PWDSTAT)
771  { // PLLPWD=0 or VCOPWD=1 or PWDSTAT=1?
772  // enable PLL and leave power saving mode
773  SCU_PLLERAYCON0.B.PLLPWD = 1;
774  SCU_PLLERAYCON0.B.VCOPWD = 0;
775 
776  while (SCU_PLLERAYSTAT.B.PWDSTAT) // poll PWDSTAT
777  {}
778 
779  /*Wait for waitCounter corresponding to the pll step */
780  IfxScuCcu_wait(cfg->pllInitialStep.waitTime);
781  }
782 
783  /* Enter Prescalar mode */
784  /* Update K and N dividers */
785  if (!SCU_PLLERAYSTAT.B.VCOBYST) // checking PLLERAYBYPST flag
786  { // select "secure" K1 value - please check @silicon if K1=4 is ok
787  while (!SCU_PLLERAYSTAT.B.K1RDY) // poll K1RDY before changing K
788  {}
789 
790  SCU_PLLERAYCON1.B.K1DIV = 3;
791 
792  // activate VCO bypass (bit 0: VCOBYP=1)
793  SCU_PLLERAYCON0.B.VCOBYP = 1;
794  }
795 
796  while (!SCU_PLLERAYSTAT.B.K2RDY) // poll K1RDY before changing K
797  {}
798 
799  SCU_PLLERAYCON1.B.K2DIV = cfg->pllInitialStep.k2Initial;
800 
801  SCU_PLLERAYCON0.B.PDIV = cfg->pllInitialStep.pDivider;
802  SCU_PLLERAYCON0.B.NDIV = cfg->pllInitialStep.nDivider;
803  /*
804  * RESLD = 1 ==> Restart VCO lock detection
805  * CLRFINDIS = 1 ==> Connect OSC to PLL
806  * PLLPWD = 1 ==> PLL Power Saving Mode : Normal behaviour
807  * NDIV = NDIV
808  */
809 
810  SCU_PLLERAYCON0.B.RESLD = 1U;
811  SCU_PLLERAYCON0.B.CLRFINDIS = 1U;
812 
813  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
814 
815  // Wait until VCO LOCK bit is set
816  uint32 time_out_ctr = 50000; // higher time out value as for clib_pll, since system is clocked much faster while polling the lock flag
817 
818  while (--time_out_ctr && !SCU_PLLERAYSTAT.B.VCOLOCK)
819  {}
820 
821  // check for timeout, exit immediately (don't disable VCO bypass) of not locked
822  if (!time_out_ctr)
823  {
824  status = FALSE;
825  }
826 
827  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
828  /*Bypass VCO*/
829  SCU_PLLERAYCON0.B.VCOBYP = 0U;
830 
831  // wait until bypass has been deactivated
832  while (SCU_PLLERAYSTAT.B.VCOBYST) // poll VCOBYST
833  {}
834 
835  if (!SCU_PLLERAYSTAT.B.VCOLOCK)
836  {
837  status = FALSE;
838  }
839 
840  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
841 
842  /*Wait for waitCounter corresponding to the pll step */
843  for (i = 0; i < 100; i++)
844  {}
845 
846  { /* Enable VCO unlock Trap if it was disabled before */
847  IfxScuWdt_clearCpuEndinit(endinit_pw);
848  SCU_TRAPCLR.B.SMUT = 1U;
849  SCU_TRAPDIS.B.SMUT = smuTrapEnable;
850  IfxScuWdt_setCpuEndinit(endinit_pw);
851  }
852  return status;
853 }
854 
855 
857 {
859 }
860 
861 
862 static boolean IfxScuCcu_isOscillatorStable(void)
863 {
866  boolean status = 0;
867 
868  /* Mode External Crystal / Ceramic Resonator Mode and External Input Clock.
869  * The oscillator Power-Saving Mode is not entered
870  */
871  SCU_OSCCON.B.MODE = 0U;
872 
873  if (IFX_CFG_SCU_XTAL_FREQUENCY <= 8000000)
874  {
875  SCU_OSCCON.B.OSCVAL = 2;
876  }
877  else
878  {
879  SCU_OSCCON.B.OSCVAL = 7;
880  }
881 
882  /* The Oscillator Watchdog of the PLL is cleared and restarted */
883  SCU_OSCCON.B.OSCRES = 1U;
884 
885  /* wait until PLLLV and PLLHV flags are set */
886  while ((SCU_OSCCON.B.PLLLV == 0) || (SCU_OSCCON.B.PLLHV == 0))
887  {
888  TimeoutCtr--;
889 
890  if (TimeoutCtr == 0)
891  {
892  status = 1;
893  break;
894  }
895  }
896 
897  { /* clear and then set SMU trap (oscillator watchdog and unlock detection) */
898  IfxScuWdt_clearCpuEndinit(endinitPw);
899  SCU_TRAPCLR.B.SMUT = 1U; /* TODO Can this be removed? */
900  SCU_TRAPDIS.B.SMUT = 1U; /* TODO Can this be removed? */
901  IfxScuWdt_setCpuEndinit(endinitPw);
902  }
903  return status;
904 }
905 
906 
908 {
909  uint16 endinitSfty_pw;
910  float32 sriFreq;
911  uint32 cpuDiv;
912 
913  sriFreq = IfxScuCcu_getSriFrequency();
914 
915  if (cpuFreq >= sriFreq)
916  {
917  cpuDiv = 0;
918  }
919  else
920  {
921  cpuDiv = (uint32)((cpuFreq * 64) / sriFreq);
922  }
923 
924  endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
925 
926  {
927  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
928 
929  switch (cpu)
930  {
932  SCU_CCUCON6.U = cpuDiv;
933  break;
935  SCU_CCUCON7.U = cpuDiv;
936  break;
938  SCU_CCUCON8.U = cpuDiv;
939  break;
940  default:
941  break;
942  }
943 
944  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
945  }
946 
947  if (cpuDiv != 0)
948  {
949  sriFreq = sriFreq * (cpuDiv / 64);
950  }
951 
952  return sriFreq;
953 }
954 
955 
957 {
959  uint32 pll2Div = (uint32)((IfxScuCcu_getPllErayVcoFrequency() / pll2ErayFreq) - 1);
960  {
962  SCU_PLLERAYCON1.B.K3DIV = pll2Div;
963  IfxScuWdt_setSafetyEndinit(password);
964  }
966 }
967 
968 
970 {
971  uint16 endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();
972  uint32 pll2Div = (uint32)((IfxScuCcu_getPllVcoFrequency() / pll2Freq) - 1);
973  {
974  IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
975  SCU_PLLCON1.B.K3DIV = pll2Div;
976  IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
977  }
979 }
980 
981 
983 {
984  /* TODO: check whether it is necessary to disable trap and/or the safety */
985  uint16 l_EndInitPW;
986  uint16 l_SEndInitPW;
988  uint32 spbDiv = (uint32)(inputFreq / spbFreq);
989  spbDiv = __maxu(spbDiv, 2);
990  spbDiv = spbDiv & 0x2U; /* only even dividers */
991 
992  l_EndInitPW = IfxScuWdt_getCpuWatchdogPassword();
993  l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword();
994 
995  IfxScuWdt_clearCpuEndinit(l_EndInitPW);
996  SCU_TRAPDIS.U = SCU_TRAPDIS.U | 0x3E0U;
997  IfxScuWdt_setCpuEndinit(l_EndInitPW);
998 
999  IfxScuWdt_clearSafetyEndinit(l_SEndInitPW);
1000  SCU_CCUCON0.B.SPBDIV = spbDiv;
1001  IfxScuWdt_setSafetyEndinit(l_SEndInitPW);
1002 
1003  IfxScuWdt_clearCpuEndinit(l_EndInitPW);
1004  SCU_TRAPDIS.U = SCU_TRAPDIS.U & (uint32)~0x3E0UL;
1005  IfxScuWdt_setCpuEndinit(l_EndInitPW);
1006 
1007  return IfxScuCcu_getSpbFrequency();
1008 }
1009 
1010 
1011 static void IfxScuCcu_wait(float32 timeSec)
1012 {
1013  uint32 stmCount = (uint32)(IfxScuCcu_getStmFrequency() * timeSec);
1014  uint32 stmCountBegin = STM0_TIM0.U;
1015 
1016  while ((uint32)(STM0_TIM0.U - stmCountBegin) < stmCount)
1017  {
1018  /* There is no need to check overflow of the STM timer.
1019  * When counter after overflow subtracted with counter before overflow,
1020  * the subtraction result will be as expected, as long as both are unsigned 32 bits
1021  * eg: stmCountBegin= 0xFFFFFFFE (before overflow)
1022  * stmCountNow = 0x00000002 (before overflow)
1023  * diff= stmCountNow - stmCountBegin = 4 as expected.*/
1024  }
1025 }
1026 
1027 
1029 {
1030  uint16 l_SEndInitPW;
1031  Ifx_SCU_CCUCON1 ccucon1 = SCU_CCUCON1;
1032 
1033  float32 inputFreq = IfxScuCcu_getSourceFrequency();
1034  uint32 gtmDiv = (uint32)__roundf(inputFreq / gtmFreq);
1035  gtmDiv = __maxu(gtmDiv, 1);
1036 
1037  /*gtmDiv = gtmDiv & 0x2U;*//* only even dividers */
1038  if ((gtmDiv >= 7) && (gtmDiv < 14) && ((gtmDiv & 1) == 1))
1039  {
1040  gtmDiv = gtmDiv - 1;
1041  }
1042 
1043  if (gtmDiv == 14)
1044  {
1045  gtmDiv = 12;
1046  }
1047 
1048  l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword();
1049  IfxScuWdt_clearSafetyEndinit(l_SEndInitPW);
1050  ccucon1.B.GTMDIV = gtmDiv;
1051  ccucon1.B.UP = 1U;
1052  SCU_CCUCON1.U = ccucon1.U;
1053 
1054  IfxScuWdt_setSafetyEndinit(l_SEndInitPW);
1055 
1056  return IfxScuCcu_getGtmFrequency();
1057 }