iLLD_TC27xC  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_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 /*----------------------------------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 
124  if (IfxGtm_Cmu_isFxClockEnabled(gtm) || (assumeEnabled != FALSE))
125  {
126  if (gtm->CMU.FXCLK.CTRL.B.FXCLK_SEL == 0)
127  {
128  frequency = IfxGtm_Cmu_getGclkFrequency(gtm);
129  }
130  else
131  {
132  frequency = IfxGtm_Cmu_getClkFrequency(gtm, IfxGtm_Cmu_Clk_5, assumeEnabled);
133  }
134 
135  switch (clkIndex)
136  {
137  case IfxGtm_Cmu_Fxclk_0:
138  frequency = frequency / 1;
139  break;
140  case IfxGtm_Cmu_Fxclk_1:
141  frequency = frequency / 16;
142  break;
143  case IfxGtm_Cmu_Fxclk_2:
144  frequency = frequency / 256;
145  break;
146  case IfxGtm_Cmu_Fxclk_3:
147  frequency = frequency / 4096;
148  break;
149  case IfxGtm_Cmu_Fxclk_4:
150  frequency = frequency / 65536;
151  break;
152  default:
153  frequency = 0.0;
154  break;
155  }
156  }
157  else
158  {
159  frequency = 0.0;
160  }
161 
162  return frequency;
163 }
164 
165 
167 {
168  float32 N = gtm->CMU.GCLK_DEN.B.GCLK_DEN;
169  float32 Z = gtm->CMU.GCLK_NUM.B.GCLK_NUM;
170  float32 multiplier = N / Z;
171 
172  return IfxGtm_Cmu_getModuleFrequency(gtm) * multiplier;
173 }
174 
175 
177 {
178  return IfxScuCcu_getSpbFrequency();
179 }
180 
181 
182 boolean IfxGtm_Cmu_isClkClockEnabled(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex)
183 {
184  return ((gtm->CMU.CLK_EN.U >> (2 * clkIndex)) & IFX_GTM_CMU_CLK_EN_EN_CLK0_MSK) == 0x3;
185 }
186 
187 
188 boolean IfxGtm_Cmu_isEclkClockEnabled(Ifx_GTM *gtm, IfxGtm_Cmu_Eclk clkIndex)
189 {
190  return ((gtm->CMU.CLK_EN.U >> (2 * clkIndex + 16)) & IFX_GTM_CMU_CLK_EN_EN_CLK0_MSK) == 0x3;
191 }
192 
193 
194 boolean IfxGtm_Cmu_isFxClockEnabled(Ifx_GTM *gtm)
195 {
196  return gtm->CMU.CLK_EN.B.EN_FXCLK == 0x3;
197 }
198 
199 
200 void IfxGtm_Cmu_selectClkInput(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex, boolean useGlobal)
201 {
202  /* FIXME is endinit required? */
203  switch (clkIndex)
204  {
205  case IfxGtm_Cmu_Clk_6:
206  gtm->CMU.CLK_6.CTRL.B.CLK6_SEL = useGlobal ? 0 : 1;
207  break;
208  case IfxGtm_Cmu_Clk_7:
209  gtm->CMU.CLK_7.CTRL.B.CLK7_SEL = useGlobal ? 0 : 1;
210  break;
211  default:
212  break;
213  }
214 }
215 
216 
217 void IfxGtm_Cmu_setClkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Clk clkIndex, float32 frequency)
218 {
219  float32 t = (IfxGtm_Cmu_getGclkFrequency(gtm) / frequency) - 1;
220  uint32 cnt = (uint32)t;
221 
222  if ((t - (float32)cnt) > 0.5)
223  { /* Round to nearest */
224  cnt++;
225  }
226 
228  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
229 
230  switch (clkIndex)
231  {
232  case IfxGtm_Cmu_Clk_0:
233  case IfxGtm_Cmu_Clk_1:
234  case IfxGtm_Cmu_Clk_2:
235  case IfxGtm_Cmu_Clk_3:
236  case IfxGtm_Cmu_Clk_4:
237  case IfxGtm_Cmu_Clk_5:
238  gtm->CMU.CLK0_5[clkIndex].CTRL.B.CLK_CNT = cnt;
239  break;
240  case IfxGtm_Cmu_Clk_6:
241  gtm->CMU.CLK_6.CTRL.B.CLK_CNT = cnt;
242  break;
243  case IfxGtm_Cmu_Clk_7:
244  gtm->CMU.CLK_7.CTRL.B.CLK_CNT = cnt;
245  break;
246  default:
247  break;
248  }
249 
251 }
252 
253 
254 void IfxGtm_Cmu_setEclkFrequency(Ifx_GTM *gtm, IfxGtm_Cmu_Eclk clkIndex, float32 frequency)
255 {
256  float32 f;
257  float32 bestDistance = frequency;
258  float32 fIn = IfxGtm_Cmu_getGclkFrequency(gtm) * 2;
259  uint32 z, n, nBest = 1, zBest = 1;
260  float32 t;
261 
262  for (z = 1; z < 0xFFFFFF; z++)
263  {
264  boolean endLoop = FALSE;
265  t = fIn / z;
266 
267  for (n = z; n > 0; n--)
268  {
269  float32 distance;
270  f = t * n;
271  distance = fabsf(frequency - f);
272 
273  if (distance < bestDistance)
274  {
275  bestDistance = distance;
276  nBest = n;
277  zBest = z;
278  }
279 
280  if (bestDistance < 0.1)
281  {
282  endLoop = TRUE;
283  break;
284  }
285  }
286 
287  if (endLoop)
288  {
289  break;
290  }
291  }
292 
294  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
295  gtm->CMU.ECLK[clkIndex].NUM.B.ECLK_NUM = zBest;
296  gtm->CMU.ECLK[clkIndex].NUM.B.ECLK_NUM = zBest; /* write twice to be sure */
297  gtm->CMU.ECLK[clkIndex].DEN.B.ECLK_DEN = nBest;
299 }
300 
301 
302 void IfxGtm_Cmu_setGclkFrequency(Ifx_GTM *gtm, float32 frequency)
303 {
304  float32 f;
305  float32 bestDistance = frequency;
307  uint32 z, n, nBest = 1, zBest = 1;
308  float32 t;
309 
310 #if 1
311 
312  for (z = 1; z < 0xFFFFFF; z++)
313  {
314  boolean endLoop = FALSE;
315  t = fIn / z;
316 
317  for (n = z; n > 0; n--)
318  {
319  float32 distance;
320  f = t * n;
321  distance = fabsf(frequency - f);
322 
323  if (distance < bestDistance)
324  {
325  bestDistance = distance;
326  nBest = n;
327  zBest = z;
328  }
329 
330  if (bestDistance < 0.1)
331  {
332  endLoop = TRUE;
333  break;
334  }
335  }
336 
337  if (endLoop)
338  {
339  break;
340  }
341  }
342 
343 #else
344 
345  for (n = 1; n < 0xFFFFFF; n++)
346  {
347  float32 distance;
348  /* get best z */
349  z = floorf(frequency * n / fIn);
350  t = fIn / n;
351 
352  /* lower value */
353  f = t * z;
354  distance = fabsf(frequency - f);
355 
356  if (distance < bestDistance)
357  {
358  bestDistance = distance;
359  nBest = n;
360  zBest = z;
361  }
362 
363  /* upper value */
364  f = t * (z + 1);
365  distance = fabsf(frequency - f);
366 
367  if (distance < bestDistance)
368  {
369  bestDistance = distance;
370  nBest = n;
371  zBest = z;
372  }
373 
374  if (bestDistance == 0.0)
375  {
376  break;
377  }
378  }
379 
380 #endif
381 
383  IfxScuWdt_clearCpuEndinit(psw); /* FIXME is this required ? */
384  gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest;
385  gtm->CMU.GCLK_NUM.B.GCLK_NUM = zBest; /* write twice to be sure */
386  gtm->CMU.GCLK_DEN.B.GCLK_DEN = nBest;
388 }