iLLD_TC27xD  1.0
IfxGtm_Cmu.c
Go to the documentation of this file.
1 /**
2  * \file IfxGtm_Cmu.c
3  * \brief GTM 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 /*----------------------------------Includes----------------------------------*/
27 /******************************************************************************/
28 
29 #include "IfxGtm_Cmu.h"
30 #include "IfxGtm_Dpll.h"
31 #include "Scu/Std/IfxScuCcu.h"
32 #include "Scu/Std/IfxScuWdt.h"
33 #include "math.h"
34 #include "IfxGtm_bf.h"
35 
36 /******************************************************************************/
37 /*-------------------------Function Implementations---------------------------*/
38 /******************************************************************************/
39 
40 void IfxGtm_Cmu_enableClocks(Ifx_GTM *gtm, uint32 clkMask)
41 {
42  gtm->CMU.CLK_EN.U = clkMask;
43 }
44 
45 
46 float32 IfxGtm_Cmu_getClkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex, boolean assumeEnabled)
47 {
48  float32 frequency;
49 
50  if ((IfxGtm_Cmu_isClkClockEnabled(gtm, clkIndex) != FALSE) || (assumeEnabled != FALSE))
51  {
52  switch (clkIndex)
53  {
54  case IfxGtm_Cmu_Clk_0:
55  case IfxGtm_Cmu_Clk_1:
56  case IfxGtm_Cmu_Clk_2:
57  case IfxGtm_Cmu_Clk_3:
58  case IfxGtm_Cmu_Clk_4:
59  case IfxGtm_Cmu_Clk_5:
60  frequency = IfxGtm_Cmu_getGclkFrequency(gtm) / (gtm->CMU.CLK0_5[clkIndex].CTRL.B.CLK_CNT + 1);
61  break;
62  case IfxGtm_Cmu_Clk_6:
63 
64  if (gtm->CMU.CLK_6.CTRL.B.CLK6_SEL == 0)
65  {
66  frequency = IfxGtm_Cmu_getGclkFrequency(gtm) / (gtm->CMU.CLK_6.CTRL.B.CLK_CNT + 1);
67  }
68  else
69  {
71  }
72 
73  break;
74  case IfxGtm_Cmu_Clk_7:
75 
76  if (gtm->CMU.CLK_7.CTRL.B.CLK7_SEL == 0)
77  {
78  frequency = IfxGtm_Cmu_getGclkFrequency(gtm) / (gtm->CMU.CLK_7.CTRL.B.CLK_CNT + 1);
79  }
80  else
81  {
83  }
84 
85  break;
86  default:
87  frequency = 0.0;
88  break;
89  }
90  }
91  else
92  {
93  frequency = 0.0;
94  }
95 
96  return frequency;
97 }
98 
99 
100 float32 IfxGtm_Cmu_getEclkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Eclk clkIndex, boolean assumeEnabled)
101 {
102  float32 frequency;
103 
104  if (IfxGtm_Cmu_isEclkClockEnabled(gtm, clkIndex) || (assumeEnabled != FALSE))
105  {
106  float32 Z = gtm->CMU.ECLK[clkIndex].NUM.B.ECLK_NUM;
107  float32 N = gtm->CMU.ECLK[clkIndex].DEN.B.ECLK_DEN;
108  float32 multiplier = N / Z / 2;
109  frequency = IfxGtm_Cmu_getGclkFrequency(gtm) * multiplier;
110  }
111  else
112  {
113  frequency = 0.0;
114  }
115 
116  return frequency;
117 }
118 
119 
120 float32 IfxGtm_Cmu_getFxClkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Fxclk clkIndex, boolean assumeEnabled)
121 {
122  float32 frequency;
123  uint8 fxSelect;
124 
125  if (IfxGtm_Cmu_isFxClockEnabled(gtm) || (assumeEnabled != FALSE))
126  {
127  fxSelect = gtm->CMU.FXCLK.CTRL.B.FXCLK_SEL;
128 
129  if (fxSelect == 0)
130  {
131  frequency = IfxGtm_Cmu_getGclkFrequency(gtm);
132  }
133  else if (fxSelect <= 6)
134  {
135  frequency = IfxGtm_Cmu_getClkFrequency(gtm, IfxGtm_Cmu_Clk_5, assumeEnabled);
136  }
137  else if (fxSelect == 7)
138  {
139  frequency = IfxGtm_Cmu_getClkFrequency(gtm, IfxGtm_Cmu_Clk_6, assumeEnabled);
140  }
141  else if (fxSelect == 8)
142  {
143  frequency = IfxGtm_Cmu_getClkFrequency(gtm, IfxGtm_Cmu_Clk_7, assumeEnabled);
144  }
145  else
146  {
147  frequency = IfxGtm_Cmu_getGclkFrequency(gtm);
148  }
149 
150  switch (clkIndex)
151  {
152  case IfxGtm_Cmu_Fxclk_0:
153  frequency = frequency / 1;
154  break;
155  case IfxGtm_Cmu_Fxclk_1:
156  frequency = frequency / 16;
157  break;
158  case IfxGtm_Cmu_Fxclk_2:
159  frequency = frequency / 256;
160  break;
161  case IfxGtm_Cmu_Fxclk_3:
162  frequency = frequency / 4096;
163  break;
164  case IfxGtm_Cmu_Fxclk_4:
165  frequency = frequency / 65536;
166  break;
167  default:
168  frequency = 0.0;
169  break;
170  }
171  }
172  else
173  {
174  frequency = 0.0;
175  }
176 
177  return frequency;
178 }
179 
180 
182 {
183  float32 N = gtm->CMU.GCLK_DEN.B.GCLK_DEN;
184  float32 Z = gtm->CMU.GCLK_NUM.B.GCLK_NUM;
185  float32 multiplier = N / Z;
186 
187  return IfxGtm_Cmu_getModuleFrequency(gtm) * multiplier;
188 }
189 
190 
192 {
193  return IfxScuCcu_getSpbFrequency();
194 }
195 
196 
197 boolean IfxGtm_Cmu_isClkClockEnabled(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex)
198 {
199  return ((gtm->CMU.CLK_EN.U >> (2 * clkIndex)) & IFX_GTM_CMU_CLK_EN_EN_CLK0_MSK) == 0x3;
200 }
201 
202 
203 boolean IfxGtm_Cmu_isEclkClockEnabled(Ifx_GTM *gtm, IfxGtm_Cmu_Eclk clkIndex)
204 {
205  return ((gtm->CMU.CLK_EN.U >> (2 * clkIndex + 16)) & IFX_GTM_CMU_CLK_EN_EN_CLK0_MSK) == 0x3;
206 }
207 
208 
209 boolean IfxGtm_Cmu_isFxClockEnabled(Ifx_GTM *gtm)
210 {
211  return gtm->CMU.CLK_EN.B.EN_FXCLK == 0x3;
212 }
213 
214 
215 void IfxGtm_Cmu_selectClkInput(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex, boolean useGlobal)
216 {
217  /* FIXME is endinit required? */
218  switch (clkIndex)
219  {
220  case IfxGtm_Cmu_Clk_6:
221  gtm->CMU.CLK_6.CTRL.B.CLK6_SEL = useGlobal ? 0 : 1;
222  break;
223  case IfxGtm_Cmu_Clk_7:
224  gtm->CMU.CLK_7.CTRL.B.CLK7_SEL = useGlobal ? 0 : 1;
225  break;
226  default:
227  break;
228  }
229 }
230 
231 
232 void IfxGtm_Cmu_setClkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex, float32 frequency)
233 {
234  float32 t = (IfxGtm_Cmu_getGclkFrequency(gtm) / frequency) - 1;
235  uint32 cnt = (uint32)t;
236 
237  if ((t - (float32)cnt) > 0.5)
238  { /* Round to nearest */
239  cnt++;
240  }
241 
243  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
244 
245  switch (clkIndex)
246  {
247  case IfxGtm_Cmu_Clk_0:
248  case IfxGtm_Cmu_Clk_1:
249  case IfxGtm_Cmu_Clk_2:
250  case IfxGtm_Cmu_Clk_3:
251  case IfxGtm_Cmu_Clk_4:
252  case IfxGtm_Cmu_Clk_5:
253  gtm->CMU.CLK0_5[clkIndex].CTRL.B.CLK_CNT = cnt;
254  break;
255  case IfxGtm_Cmu_Clk_6:
256  gtm->CMU.CLK_6.CTRL.B.CLK_CNT = cnt;
257  break;
258  case IfxGtm_Cmu_Clk_7:
259  gtm->CMU.CLK_7.CTRL.B.CLK_CNT = cnt;
260  break;
261  default:
262  break;
263  }
264 
266 }
267 
268 
269 void IfxGtm_Cmu_setEclkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Eclk clkIndex, float32 frequency)
270 {
271  float32 f;
272  float32 bestDistance = frequency;
273  float32 fIn = IfxGtm_Cmu_getGclkFrequency(gtm) * 2;
274  uint32 z, n, nBest = 1, zBest = 1;
275  float32 t;
276 
277  for (z = 1; z < 0xFFFFFF; z++)
278  {
279  boolean endLoop = FALSE;
280  t = fIn / z;
281 
282  for (n = z; n > 0; n--)
283  {
284  float32 distance;
285  f = t * n;
286  distance = fabsf(frequency - f);
287 
288  if (distance < bestDistance)
289  {
290  bestDistance = distance;
291  nBest = n;
292  zBest = z;
293  }
294 
295  if (bestDistance < 0.1)
296  {
297  endLoop = TRUE;
298  break;
299  }
300  }
301 
302  if (endLoop)
303  {
304  break;
305  }
306  }
307 
309  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
310  gtm->CMU.ECLK[clkIndex].NUM.B.ECLK_NUM = zBest;
311  gtm->CMU.ECLK[clkIndex].NUM.B.ECLK_NUM = zBest; /* write twice to be sure */
312  gtm->CMU.ECLK[clkIndex].DEN.B.ECLK_DEN = nBest;
314 }
315 
316 
317 void IfxGtm_Cmu_setGclkFrequency(Ifx_GTM *gtm, float32 frequency)
318 {
319  float32 f;
320  float32 bestDistance = frequency;
322  uint32 z, n, nBest = 1, zBest = 1;
323  float32 t;
324 
325 #if 1
326 
327  for (z = 1; z < 0xFFFFFF; z++)
328  {
329  boolean endLoop = FALSE;
330  t = fIn / z;
331 
332  for (n = z; n > 0; n--)
333  {
334  float32 distance;
335  f = t * n;
336  distance = fabsf(frequency - f);
337 
338  if (distance < bestDistance)
339  {
340  bestDistance = distance;
341  nBest = n;
342  zBest = z;
343  }
344 
345  if (bestDistance < 0.1)
346  {
347  endLoop = TRUE;
348  break;
349  }
350  }
351 
352  if (endLoop)
353  {
354  break;
355  }
356  }
357 
358 #else
359 
360  for (n = 1; n < 0xFFFFFF; n++)
361  {
362  float32 distance;
363  /* get best z */
364  z = floorf(frequency * n / fIn);
365  t = fIn / n;
366 
367  /* lower value */
368  f = t * z;
369  distance = fabsf(frequency - f);
370 
371  if (distance < bestDistance)
372  {
373  bestDistance = distance;
374  nBest = n;
375  zBest = z;
376  }
377 
378  /* upper value */
379  f = t * (z + 1);
380  distance = fabsf(frequency - f);
381 
382  if (distance < bestDistance)
383  {
384  bestDistance = distance;
385  nBest = n;
386  zBest = z;
387  }
388 
389  if (bestDistance == 0.0)
390  {
391  break;
392  }
393  }
394 
395 #endif
396 
398  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
399  gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest;
400  gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest; /* write twice to be sure */
401  gtm->CMU.GCLK_DEN.B.GCLK_DEN = nBest;
403 }