]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Mcu.c
Merge with 5d055b359c5e7fe8911e76964b2d39f0afcf4940
[arc.git] / arch / ppc / mpc55xx / drivers / Mcu.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 #include <assert.h>\r
18 #include <string.h>\r
19 #include "Std_Types.h"\r
20 #include "Mcu.h"\r
21 #include "Det.h"\r
22 #if defined(USE_DEM)\r
23 #include "Dem.h"\r
24 #endif\r
25 #include "mpc55xx.h"\r
26 #include "Cpu.h"\r
27 #include "Ramlog.h"\r
28 #include "Os.h"\r
29 #include "isr.h"\r
30 \r
31 //#define USE_LDEBUG_PRINTF 1\r
32 #include "debug.h"\r
33 \r
34 #define SYSCLOCK_SELECT_PLL     0x2\r
35 \r
36 #if defined(CFG_MPC5567)\r
37 #define CALC_SYSTEM_CLOCK(_extal,_emfd,_eprediv,_erfd)  \\r
38             ( (_extal) * ((_emfd)+4) / (((_eprediv)+1)*(1<<(_erfd))) )\r
39 #elif defined(CFG_MPC5606S)\r
40 #define CALC_SYSTEM_CLOCK(_extal,_emfd,_eprediv,_erfd)  \\r
41                 ( (_extal)*(_emfd) / ((_eprediv+1)*(2<<(_erfd))) )\r
42 #else\r
43 #define CALC_SYSTEM_CLOCK(_extal,_emfd,_eprediv,_erfd)  \\r
44             ( (_extal) * ((_emfd)+16) / (((_eprediv)+1)*((_erfd)+1)) )\r
45 #endif\r
46 \r
47 typedef void (*vfunc_t)();\r
48 \r
49 /* Function declarations. */\r
50 static void Mcu_ConfigureFlash(void);\r
51 \r
52 typedef struct{\r
53         uint32 lossOfLockCnt;\r
54         uint32 lossOfClockCnt;\r
55 } Mcu_Stats;\r
56 \r
57 /**\r
58  * Type that holds all global data for Mcu\r
59  */\r
60 typedef struct\r
61 {\r
62     // Set if Mcu_Init() have been called\r
63     boolean initRun;\r
64     // Our config\r
65     const Mcu_ConfigType *config;\r
66     Mcu_ClockType clockSetting;\r
67     Mcu_Stats stats;\r
68 } Mcu_GlobalType;\r
69 \r
70 /* Development error macros. */\r
71 #if ( MCU_DEV_ERROR_DETECT == STD_ON )\r
72 #define VALIDATE(_exp,_api,_err ) \\r
73         if( !(_exp) ) { \\r
74           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
75           return; \\r
76         }\r
77 \r
78 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
79         if( !(_exp) ) { \\r
80           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
81           return (_rv); \\r
82         }\r
83 #else\r
84 #define VALIDATE(_exp,_api,_err )\r
85 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
86 #endif\r
87 \r
88 // Global config\r
89 Mcu_GlobalType Mcu_Global =\r
90 {\r
91         .initRun = 0,\r
92         .config = &McuConfigData[0],\r
93 };\r
94 \r
95 //-------------------------------------------------------------------\r
96 \r
97 void Mcu_LossOfLock( void  ){\r
98 #if defined(USE_DEM)\r
99         Dem_ReportErrorStatus(MCU_E_CLOCK_FAILURE, DEM_EVENT_STATUS_FAILED);\r
100 #endif\r
101 \r
102   /*\r
103    * NOTE!!!\r
104    * This interrupt may be triggered more than expected.\r
105    * If you are going to use this interrupt, see [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 6764].\r
106    *\r
107    */\r
108 #if defined(CFG_MPC5606S)\r
109         /*not support*/\r
110 #else\r
111         Mcu_Global.stats.lossOfLockCnt++;\r
112         // Clear interrupt\r
113         FMPLL.SYNSR.B.LOLF = 1;\r
114 #endif\r
115 }\r
116 \r
117 //-------------------------------------------------------------------\r
118 \r
119 void Mcu_LossOfClock( void  ){\r
120         /* Should report MCU_E_CLOCK_FAILURE with DEM here */\r
121 #if defined(CFG_MPC5606S)\r
122         /*not support*/\r
123 #else\r
124         Mcu_Global.stats.lossOfClockCnt++;\r
125         // Clear interrupt\r
126         FMPLL.SYNSR.B.LOCF = 1;\r
127 #endif\r
128 }\r
129 \r
130 #define SPR_PIR 286\r
131 #define SPR_PVR 287\r
132 \r
133 #define CORE_PVR_E200Z1         0x81440000UL\r
134 #define CORE_PVR_E200Z0         0x81710000UL\r
135 #define CORE_PVR_E200Z3         0x81120000UL\r
136 #define CORE_PVR_E200Z6         0x81170000UL\r
137 #define CORE_PVR_E200Z65        0x81150000UL    /* Is actually a 5668 */\r
138 #define CORE_PVR_E200Z0H        0x817F0000UL\r
139 \r
140 typedef struct{\r
141         char *name;\r
142         uint32 pvr;\r
143 } core_info_t;\r
144 \r
145 typedef struct{\r
146         char *name;\r
147         uint32 pvr;\r
148 } cpu_info_t;\r
149 \r
150 const cpu_info_t cpu_info_list[] = {\r
151 #if defined(CFG_MPC5516)\r
152     {\r
153         .name = "MPC5516",\r
154         .pvr = CORE_PVR_E200Z1,\r
155     },\r
156     {\r
157         .name = "MPC5516",\r
158         .pvr = CORE_PVR_E200Z0,\r
159     },\r
160 #elif defined(CFG_MPC5567)\r
161     {\r
162         .name = "MPC5567",\r
163         .pvr = CORE_PVR_E200Z6,\r
164     }\r
165 #elif defined(CFG_MPC5633)\r
166     {\r
167         .name = "MPC563X",\r
168         .pvr = CORE_PVR_E200Z3,\r
169     },\r
170 #elif defined(CFG_MPC5606S)\r
171     {\r
172         .name = "MPC5606S",\r
173         .pvr = CORE_PVR_E200Z0H,\r
174     },\r
175 #elif defined(CFG_MPC5668)\r
176         {\r
177                 .name = "MPC5668",\r
178                 .pvr = CORE_PVR_E200Z65,\r
179         },\r
180         {\r
181                 .name = "MPC5668",\r
182                 .pvr = CORE_PVR_E200Z0,\r
183         },\r
184 #endif\r
185 };\r
186 \r
187 const core_info_t core_info_list[] = {\r
188 #if defined(CFG_MPC5516)\r
189         {\r
190                 .name = "CORE_E200Z1",\r
191                 .pvr = CORE_PVR_E200Z1,\r
192     },\r
193     {\r
194         .name = "CORE_E200Z1",\r
195         .pvr = CORE_PVR_E200Z1,\r
196     },\r
197 #elif defined(CFG_MPC5567)\r
198     {\r
199         .name = "CORE_E200Z6",\r
200         .pvr = CORE_PVR_E200Z6,\r
201     }\r
202 #elif defined(CFG_MPC5633)\r
203     {\r
204                 .name = "CORE_E200Z3",\r
205                 .pvr = CORE_PVR_E200Z3,\r
206     },\r
207 #elif defined(CFG_MPC5606S)\r
208     {\r
209         .name = "MPC5606S",\r
210         .pvr = CORE_PVR_E200Z0H,\r
211     },\r
212 #elif defined(CFG_MPC5668)\r
213     {\r
214         .name = "CORE_E200Z65",\r
215         .pvr = CORE_PVR_E200Z65,\r
216     },\r
217     {\r
218         .name = "CORE_E200Z0",\r
219         .pvr = CORE_PVR_E200Z1,\r
220     },\r
221 #endif\r
222 };\r
223 \r
224 // TODO: move\r
225 #if !defined(ARRAY_SIZE)\r
226 #define ARRAY_SIZE(_x)  (sizeof(_x)/sizeof((_x)[0]))\r
227 #endif\r
228 \r
229 static const cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)\r
230 {\r
231     int i;\r
232 \r
233     for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {\r
234         if (cpu_info_list[i].pvr == pvr) {\r
235                 return &cpu_info_list[i];\r
236         }\r
237     }\r
238 \r
239     return NULL;\r
240 }\r
241 \r
242 static const core_info_t *Mcu_IdentifyCore(uint32 pvr)\r
243 {\r
244         int i;\r
245 \r
246         for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {\r
247                 if (core_info_list[i].pvr == pvr) {\r
248                         return &core_info_list[i];\r
249                 }\r
250     }\r
251 \r
252   return NULL;\r
253 }\r
254 \r
255 static uint32 Mcu_CheckCpu( void ) {\r
256         uint32 pvr;\r
257         uint32 pir;\r
258         const cpu_info_t *cpuType;\r
259         const core_info_t *coreType;\r
260 \r
261     // We have to registers to read here, PIR and PVR\r
262     pir = get_spr(SPR_PIR);\r
263     pvr = get_spr(SPR_PVR);\r
264 \r
265     cpuType = Mcu_IdentifyCpu(pvr);\r
266     coreType = Mcu_IdentifyCore(pvr);\r
267 \r
268     if( (cpuType == NULL) || (coreType == NULL) ) {\r
269         // Just hang\r
270         while(1) ;\r
271     }\r
272 \r
273     //DEBUG(DEBUG_HIGH,"/drivers/mcu: Cpu:  %s( 0x%08x )\n",cpuType->name,pvr);\r
274     //DEBUG(DEBUG_HIGH,"/drivers/mcu: Core: %s( 0x%08x )\n",coreType->name,pvr);\r
275 \r
276     return 0;\r
277 }\r
278 \r
279 //-------------------------------------------------------------------\r
280 \r
281 void Mcu_Init(const Mcu_ConfigType *configPtr)\r
282 {\r
283         VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );\r
284 \r
285 #if defined(CFG_MPC5606S)\r
286         /* Disable watchdog. Watchdog is enabled default after reset.*/\r
287         SWT.SR.R = 0x0000c520;     /* Write keys to clear soft lock bit */\r
288         SWT.SR.R = 0x0000d928;\r
289         SWT.CR.R = 0x8000010A;     /* Disable watchdog */\r
290 #if defined(USE_WDG)\r
291         SWT.TO.R = 0xfa00;              /* set the timout to 500ms */\r
292         SWT.CR.R = 0x8000011B;      /* enable watchdog */\r
293 #endif\r
294 #endif\r
295 \r
296     if( !SIMULATOR() ) {\r
297         Mcu_CheckCpu();\r
298     }\r
299 \r
300     memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));\r
301 \r
302     // Setup memories\r
303     Mcu_ConfigureFlash();\r
304 \r
305     Mcu_Global.config = configPtr;\r
306 \r
307 #if defined(CFG_MPC5606S)\r
308     /* Enable DRUN, RUN0, SAFE, RESET modes */\r
309     ME.MER.R = 0x0000001D;\r
310 #endif\r
311 \r
312     Mcu_Global.initRun = 1;\r
313 \r
314     if( Mcu_Global.config->McuClockSrcFailureNotification == TRUE  ) {\r
315 #if defined(CFG_MPC5606S)\r
316         /*not support*/\r
317 #else\r
318         ISR_INSTALL_ISR1("LossOfLock", Mcu_LossOfLock, PLL_SYNSR_LOLF, 10 , 0 );\r
319 #if defined(CFG_MPC5516)  || defined(CFG_MPC5668)\r
320         FMPLL.ESYNCR2.B.LOLIRQ = 1;\r
321 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
322         FMPLL.SYNCR.B.LOLIRQ = 1;\r
323 #endif\r
324         ISR_INSTALL_ISR1("LossOfClock", Mcu_LossOfClock, PLL_SYNSR_LOLF, 10 , 0 );\r
325 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
326         FMPLL.ESYNCR2.B.LOCIRQ = 1;\r
327 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
328         FMPLL.SYNCR.B.LOCIRQ = 1;\r
329 #endif\r
330 #endif\r
331     }\r
332 }\r
333 \r
334 //-------------------------------------------------------------------\r
335 \r
336 void Mcu_DeInit()\r
337 {\r
338         Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?\r
339 }\r
340 \r
341 //-------------------------------------------------------------------\r
342 \r
343 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)\r
344 {\r
345         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
346         VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );\r
347 \r
348     /* NOT SUPPORTED, reason: no support for external RAM */\r
349 \r
350     return E_OK;\r
351 }\r
352 \r
353 //-------------------------------------------------------------------\r
354 \r
355 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)\r
356 {\r
357     Mcu_ClockSettingConfigType *clockSettingsPtr;\r
358     VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
359     VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );\r
360 \r
361     Mcu_Global.clockSetting = ClockSetting;\r
362     clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];\r
363 \r
364     // TODO: find out if the 5554 really works like the 5516 here\r
365     // All three (16, 54, 67) used to run the same code here though, so i'm sticking it with 5516\r
366 #if defined(CFG_MPC5516) || defined(CFG_MPC5554) || defined(CFG_MPC5668)\r
367     /* 5516clock info:\r
368      * Fsys - System frequency ( CPU + all periperals? )\r
369      *\r
370      *  Fsys = EXTAL_FREQ *(  (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )\r
371      */\r
372     // Check ranges...\r
373     assert((clockSettingsPtr->Pll2>=32) && (clockSettingsPtr->Pll2<=132));\r
374     assert( (clockSettingsPtr->Pll1 != 6) &&\r
375             (clockSettingsPtr->Pll1 != 8) &&\r
376             (clockSettingsPtr->Pll1 < 10) );\r
377     assert( clockSettingsPtr->Pll3 & 1); // Must be odd\r
378 #elif defined(CFG_MPC5567)\r
379     /* 5567 clock info:\r
380      *  Fsys = EXTAL_FREQ *(  (emfd+4) / ( (eprediv+1) * ( 2^erfd )) ) )\r
381      */\r
382     // Check ranges...\r
383     assert(clockSettingsPtr->Pll2 < 16);\r
384     assert(clockSettingsPtr->Pll1 <= 4);\r
385     assert(clockSettingsPtr->Pll3 < 8);\r
386 #endif\r
387 \r
388 #if defined(USE_LDEBUG_PRINTF)\r
389     {\r
390         uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
391         uint32  f_sys;\r
392 \r
393         f_sys = CALC_SYSTEM_CLOCK( extal,\r
394                 clockSettingsPtr->Pll2,\r
395                 clockSettingsPtr->Pll1,\r
396                 clockSettingsPtr->Pll3 );\r
397 \r
398         //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);\r
399     }\r
400 #endif\r
401 \r
402 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
403 \r
404     // set post divider to next valid value to ensure that an overshoot during lock phase\r
405     // won't result in a too high freq\r
406     FMPLL.ESYNCR2.B.ERFD = (clockSettingsPtr->Pll3 + 1) | 1;\r
407 \r
408     // External crystal PLL mode.\r
409     FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?\r
410 \r
411     // Write pll parameters.\r
412     FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->Pll1;\r
413     FMPLL.ESYNCR1.B.EMFD    = clockSettingsPtr->Pll2;\r
414 \r
415     while(FMPLL.SYNSR.B.LOCK != 1) {};\r
416 \r
417     FMPLL.ESYNCR2.B.ERFD    = clockSettingsPtr->Pll3;\r
418     // Connect SYSCLK to FMPLL\r
419     SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;\r
420 #elif defined(CFG_MPC5604B)\r
421     // Write pll parameters.\r
422     CGM.FMPLL_CR.B.IDF = clockSettingsPtr->Pll1;\r
423     CGM.FMPLL_CR.B.NDIV = clockSettingsPtr->Pll2;\r
424     CGM.FMPLL_CR.B.ODF = clockSettingsPtr->Pll3;\r
425 \r
426     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
427     ME.RUN[0].R = 0x001F0074;\r
428     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
429     ME.RUNPC[1].R = 0x00000010;\r
430     /* MPC56xxB/S: select ME.RUNPC[1] */\r
431     ME.PCTL[68].R = 0x01; //SIUL control\r
432     ME.PCTL[91].R = 0x01; //RTC/API control\r
433     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
434     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
435     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
436     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
437     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
438     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
439     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
440     ME.PCTL[32].R = 0x01; //ADC0 control\r
441     ME.PCTL[23].R = 0x01; //DMAMUX control\r
442     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
443     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
444     /* Mode Transition to enter RUN0 mode: */\r
445     /* Enter RUN0 Mode & Key */\r
446     ME.MCTL.R = 0x40005AF0;\r
447     /* Enter RUN0 Mode & Inverted Key */\r
448     ME.MCTL.R = 0x4000A50F;\r
449 \r
450     /* Wait for mode transition to complete */\r
451     while (ME.GS.B.S_MTRANS) {}\r
452     /* Verify RUN0 is the current mode */\r
453     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
454 #elif defined(CFG_MPC5606S)\r
455     // Write pll parameters.\r
456     CGM.FMPLL[0].CR.B.IDF = clockSettingsPtr->Pll1;\r
457     CGM.FMPLL[0].CR.B.NDIV = clockSettingsPtr->Pll2;\r
458     CGM.FMPLL[0].CR.B.ODF = clockSettingsPtr->Pll3;\r
459 \r
460     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
461     ME.RUN[0].R = 0x001F0074;\r
462     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
463     ME.RUNPC[1].R = 0x00000010;\r
464     /* MPC56xxB/S: select ME.RUNPC[1] */\r
465     ME.PCTL[68].R = 0x01; //SIUL control\r
466     ME.PCTL[91].R = 0x01; //RTC/API control\r
467     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
468     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
469     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
470     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
471     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
472     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
473     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
474     ME.PCTL[32].R = 0x01; //ADC0 control\r
475     ME.PCTL[23].R = 0x01; //DMAMUX control\r
476     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
477     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
478     /* Mode Transition to enter RUN0 mode: */\r
479     /* Enter RUN0 Mode & Key */\r
480     ME.MCTL.R = 0x40005AF0;\r
481     /* Enter RUN0 Mode & Inverted Key */\r
482     ME.MCTL.R = 0x4000A50F;\r
483 \r
484     /* Wait for mode transition to complete */\r
485     while (ME.GS.B.S_MTRANS) {}\r
486     /* Verify RUN0 is the current mode */\r
487     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
488 \r
489  #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
490     // Partially following the steps in MPC5567 RM..\r
491     FMPLL.SYNCR.B.DEPTH = 0;\r
492     FMPLL.SYNCR.B.LOLRE = 0;\r
493     FMPLL.SYNCR.B.LOLIRQ = 0;\r
494 \r
495     FMPLL.SYNCR.B.PREDIV        = clockSettingsPtr->Pll1;\r
496     FMPLL.SYNCR.B.MFD           = clockSettingsPtr->Pll2;\r
497     FMPLL.SYNCR.B.RFD           = clockSettingsPtr->Pll3;\r
498 \r
499         // Wait for PLL to sync.\r
500     while (Mcu_GetPllStatus() != MCU_PLL_LOCKED) ;\r
501 \r
502     FMPLL.SYNCR.B.LOLIRQ        = 1;\r
503 #endif\r
504 \r
505     return E_OK;\r
506 }\r
507 \r
508 //-------------------------------------------------------------------\r
509 \r
510 void Mcu_DistributePllClock(void)\r
511 {\r
512     VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
513 #if defined(CFG_MPC5606S)\r
514     VALIDATE( ( CGM.FMPLL[0].CR.B.S_LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
515 #else\r
516     VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
517 #endif\r
518     /* NOT IMPLEMENTED due to pointless function on this hardware */\r
519 \r
520 }\r
521 \r
522 //-------------------------------------------------------------------\r
523 \r
524 Mcu_PllStatusType Mcu_GetPllStatus(void)\r
525 {\r
526     VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
527     Mcu_PllStatusType rv;\r
528 \r
529     if( !SIMULATOR() )\r
530     {\r
531 #if defined(CFG_MPC5604B)\r
532         if ( !CGM.FMPLL_CR.B.S_LOCK )\r
533         {\r
534                 rv = MCU_PLL_UNLOCKED;\r
535         } else\r
536         {\r
537                 rv = MCU_PLL_LOCKED;\r
538         }\r
539 #elif defined(CFG_MPC5606S)\r
540         if ( !CGM.FMPLL[0].CR.B.S_LOCK )\r
541         {\r
542                 rv = MCU_PLL_UNLOCKED;\r
543         } else\r
544         {\r
545                 rv = MCU_PLL_LOCKED;\r
546         }\r
547 #else\r
548         if ( !FMPLL.SYNSR.B.LOCK )\r
549         {\r
550                 rv = MCU_PLL_UNLOCKED;\r
551         } else\r
552         {\r
553                 rv = MCU_PLL_LOCKED;\r
554         }\r
555 #endif\r
556     }\r
557     else\r
558     {\r
559         /* We are running on instruction set simulator. PLL is then always in sync... */\r
560         rv = MCU_PLL_LOCKED;\r
561     }\r
562 \r
563   return rv;\r
564 }\r
565 \r
566 //-------------------------------------------------------------------\r
567 \r
568 Mcu_ResetType Mcu_GetResetReason(void)\r
569 {\r
570         Mcu_ResetType rv;\r
571 \r
572         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
573 \r
574 #if defined(CFG_MPC5606S)\r
575         if( RGM.FES.B.F_SOFT ) {\r
576                 rv = MCU_SW_RESET;\r
577         } else if( RGM.DES.B.F_SWT ) {\r
578                 rv = MCU_WATCHDOG_RESET;\r
579         } else if( RGM.DES.B.F_POR ) {\r
580                 rv = MCU_POWER_ON_RESET;\r
581         } else {\r
582                 rv = MCU_RESET_UNDEFINED;\r
583         }\r
584 #else\r
585         if( SIU.RSR.B.SSRS ) {\r
586                 rv = MCU_SW_RESET;\r
587         } else if( SIU.RSR.B.WDRS ) {\r
588                 rv = MCU_WATCHDOG_RESET;\r
589         } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {\r
590                 rv = MCU_POWER_ON_RESET;\r
591         } else {\r
592                 rv = MCU_RESET_UNDEFINED;\r
593         }\r
594 #endif\r
595 \r
596         return rv;\r
597 }\r
598 \r
599 //-------------------------------------------------------------------\r
600 \r
601 Mcu_RawResetType Mcu_GetResetRawValue(void)\r
602 {\r
603         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
604 \r
605         if( !Mcu_Global.initRun ) {\r
606                 return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
607         }\r
608 \r
609 #if defined(CFG_MPC5606S)\r
610         if( RGM.DES.R )\r
611                 return RGM.DES.R;\r
612         else\r
613                 return RGM.FES.R;\r
614 #else\r
615         return SIU.RSR.R;\r
616 #endif\r
617 \r
618 }\r
619 \r
620 //-------------------------------------------------------------------\r
621 \r
622 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
623 void Mcu_PerformReset(void)\r
624 {\r
625         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
626 \r
627         // Reset\r
628 #if defined(CFG_MPC5606S)\r
629     ME.MCTL.R = 0x00005AF0;\r
630     ME.MCTL.R = 0x0000A50F;\r
631 \r
632     while (ME.GS.B.S_MTRANS) {}\r
633     while(ME.GS.B.S_CURRENTMODE != 0) {}\r
634 #else\r
635         SIU.SRCR.B.SSR = 1;\r
636 #endif\r
637 \r
638 }\r
639 #endif\r
640 \r
641 //-------------------------------------------------------------------\r
642 \r
643 void Mcu_SetMode(const Mcu_ModeType McuMode)\r
644 {\r
645         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
646         // VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
647         (void) McuMode;\r
648 \r
649         /* NOT SUPPORTED */\r
650 }\r
651 \r
652 //-------------------------------------------------------------------\r
653 \r
654 /**\r
655  * Get the system clock in Hz. It calculates the clock from the\r
656  * different register settings in HW.\r
657  */\r
658 uint32_t McuE_GetSystemClock(void)\r
659 {\r
660         /*\r
661          * System clock calculation\r
662          *\r
663          * 5516 -  f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));\r
664          * 5567 -  f_sys = extal * (emfd+4) / ( (eprediv+1) * ( 2^erfd ));\r
665          * 563x -  We run in legacy mode = 5567\r
666          * 5606s - f_sys = extal * emfd / ((eprediv+1)*(2<<(erfd)));\r
667          */\r
668 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
669         uint32_t eprediv = FMPLL.ESYNCR1.B.EPREDIV;\r
670         uint32_t emfd = FMPLL.ESYNCR1.B.EMFD;\r
671         uint32_t erfd = FMPLL.ESYNCR2.B.ERFD;\r
672 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567) || defined(CFG_MPC5633)\r
673         uint32_t eprediv = FMPLL.SYNCR.B.PREDIV;\r
674         uint32_t emfd = FMPLL.SYNCR.B.MFD;\r
675         uint32_t erfd = FMPLL.SYNCR.B.RFD;\r
676 #elif defined(CFG_MPC5604B)\r
677     uint32_t eprediv = CGM.FMPLL_CR.B.IDF;\r
678     uint32_t emfd = CGM.FMPLL_CR.B.NDIV;\r
679     uint32_t erfd = CGM.FMPLL_CR.B.ODF;\r
680 #elif defined(CFG_MPC5606S)\r
681     uint32_t eprediv = CGM.FMPLL[0].CR.B.IDF;\r
682     uint32_t emfd = CGM.FMPLL[0].CR.B.NDIV;\r
683     uint32_t erfd = CGM.FMPLL[0].CR.B.ODF;\r
684 #endif\r
685 \r
686     uint32_t f_sys;\r
687     uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
688 \r
689     f_sys = CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);\r
690 \r
691     return f_sys;\r
692 }\r
693 \r
694 #if defined(CFG_MPC5668)\r
695 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type) {\r
696         uint32_t sysClock = McuE_GetSystemClock();\r
697         vuint32_t prescaler;\r
698 \r
699         switch (type)\r
700         {\r
701                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
702                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
703                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
704                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
705                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
706                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
707                 case PERIPHERAL_CLOCK_DSPI_A:\r
708                 case PERIPHERAL_CLOCK_DSPI_B:\r
709                 case PERIPHERAL_CLOCK_DSPI_C:\r
710                 case PERIPHERAL_CLOCK_DSPI_D:\r
711                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
712                         break;\r
713                 case PERIPHERAL_CLOCK_ESCI_A:\r
714                 case PERIPHERAL_CLOCK_ESCI_B:\r
715                 case PERIPHERAL_CLOCK_ESCI_C:\r
716                 case PERIPHERAL_CLOCK_ESCI_D:\r
717                 case PERIPHERAL_CLOCK_ESCI_E:\r
718                 case PERIPHERAL_CLOCK_ESCI_F:\r
719                 case PERIPHERAL_CLOCK_IIC_A:\r
720                 case PERIPHERAL_CLOCK_IIC_B:\r
721                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
722                         break;\r
723                 case PERIPHERAL_CLOCK_ADC_A:\r
724                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
725                         break;\r
726                 case PERIPHERAL_CLOCK_EMIOS:\r
727                         prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
728                         break;\r
729                 default:\r
730                         assert(0);\r
731                         break;\r
732         }\r
733 \r
734         return sysClock/(1<<prescaler);\r
735 \r
736 }\r
737 \r
738 #else\r
739 \r
740 /**\r
741  * Get the peripheral clock in Hz for a specific device\r
742  */\r
743 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
744 {\r
745 #if defined(CFG_MPC5567)\r
746         // No peripheral dividers on 5567.\r
747         return McuE_GetSystemClock();\r
748 #else\r
749         uint32_t sysClock = McuE_GetSystemClock();\r
750         vuint32_t prescaler;\r
751 \r
752   // See table 3.1, section 3.4.5 Peripheral Clock dividers\r
753         switch (type)\r
754         {\r
755                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
756                 case PERIPHERAL_CLOCK_DSPI_A:\r
757 #if defined(CFG_MPC5516)\r
758                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
759                         break;\r
760 #elif defined(CFG_MPC5606S)\r
761                         prescaler = CGM.SC_DC[1].B.DIV;\r
762                         break;\r
763 #endif\r
764 \r
765                 case PERIPHERAL_CLOCK_PIT:\r
766                 case PERIPHERAL_CLOCK_ESCI_A:\r
767                 case PERIPHERAL_CLOCK_IIC_A:\r
768 #if defined(CFG_MPC5516)\r
769                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
770                         break;\r
771 #endif\r
772 \r
773                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
774                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
775                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
776                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
777                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
778 #if defined(CFG_MPC5516)\r
779                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
780                         break;\r
781 #elif defined(CFG_MPC5606S)\r
782                         prescaler = CGM.SC_DC[1].B.DIV;\r
783                         break;\r
784 #endif\r
785 \r
786                 case PERIPHERAL_CLOCK_DSPI_B:\r
787                 case PERIPHERAL_CLOCK_DSPI_C:\r
788                 case PERIPHERAL_CLOCK_DSPI_D:\r
789 #if defined(CFG_MPC5516)\r
790                 prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
791                         break;\r
792 #endif\r
793 \r
794                 case PERIPHERAL_CLOCK_ESCI_B:\r
795                 case PERIPHERAL_CLOCK_ESCI_C:\r
796                 case PERIPHERAL_CLOCK_ESCI_D:\r
797                 case PERIPHERAL_CLOCK_ESCI_E:\r
798                 case PERIPHERAL_CLOCK_ESCI_F:\r
799                 case PERIPHERAL_CLOCK_ESCI_G:\r
800                 case PERIPHERAL_CLOCK_ESCI_H:\r
801 #if defined(CFG_MPC5516)\r
802                         prescaler = SIU.SYSCLK.B.LPCLKDIV4;\r
803                         break;\r
804 #endif\r
805 \r
806 #if defined(CFG_MPC5606S)\r
807                 case PERIPHERAL_CLOCK_LIN_A:\r
808                 case PERIPHERAL_CLOCK_LIN_B:\r
809                         prescaler = CGM.SC_DC[0].B.DIV;\r
810                         break;\r
811                 case PERIPHERAL_CLOCK_EMIOS_0:\r
812                         prescaler = CGM.SC_DC[2].B.DIV;\r
813                         break;\r
814                 case PERIPHERAL_CLOCK_EMIOS_1:\r
815                         prescaler = CGM.SC_DC[2].B.DIV;\r
816                         break;\r
817 #else\r
818                 case PERIPHERAL_CLOCK_EMIOS:\r
819 #if defined(CFG_MPC5516)\r
820                         prescaler = SIU.SYSCLK.B.LPCLKDIV5;\r
821                         break;\r
822 #endif\r
823 #endif\r
824 \r
825                 case PERIPHERAL_CLOCK_MLB:\r
826 #if defined(CFG_MPC5516)\r
827                         prescaler = SIU.SYSCLK.B.LPCLKDIV6;\r
828                         break;\r
829 #endif\r
830 \r
831                 default:\r
832                         assert(0);\r
833                         break;\r
834         }\r
835 \r
836         return sysClock/(1<<prescaler);\r
837 #endif\r
838 }\r
839 #endif\r
840 \r
841 /**\r
842  * Function to setup the internal flash for optimal performance\r
843  */\r
844 \r
845 static void Mcu_ConfigureFlash(void)\r
846 {\r
847         /* These flash settings increases the CPU performance of 7 times compared\r
848            to reset default settings!! */\r
849 \r
850 #if defined(CFG_MPC5516)\r
851         /* Disable pipelined reads when flash options are changed. */\r
852         FLASH.MCR.B.PRD = 1;\r
853 \r
854         /* Enable master prefetch for e200z1 and eDMA. */\r
855         FLASH.PFCRP0.B.M0PFE = 1;\r
856         FLASH.PFCRP0.B.M2PFE = 1;\r
857 \r
858         /* Address pipelining control. Must be set to the same value as RWSC. */\r
859         FLASH.PFCRP0.B.APC = 2;\r
860         FLASH.PFCRP0.B.RWSC = 2;\r
861 \r
862         /* Write wait states. */\r
863         FLASH.PFCRP0.B.WWSC = 1;\r
864 \r
865         /* Enable data prefetch. */\r
866         FLASH.PFCRP0.B.DPFEN = 1;\r
867 \r
868         /* Enable instruction prefetch. */\r
869         FLASH.PFCRP0.B.IPFEN = 1;\r
870 \r
871         /* Prefetch algorithm. */\r
872         /* TODO: Ask Freescale about this option. */\r
873         FLASH.PFCRP0.B.PFLIM = 2;\r
874 \r
875         /* Enable line read buffers. */\r
876         FLASH.PFCRP0.B.BFEN = 1;\r
877 \r
878         /* Enable pipelined reads again. */\r
879         FLASH.MCR.B.PRD = 0;\r
880 #elif defined(CFG_MPC5668)\r
881         /* Check values from cookbook and MPC5668x Microcontroller Data Sheet */\r
882 \r
883         /* Should probably trim this values */\r
884         const typeof(FLASH.PFCRP0.B) val = {.M0PFE = 1, .M2PFE=1, .APC=3,\r
885                                                                  .RWSC=3, .WWSC =1, .DPFEN =1, .IPFEN = 1, .PFLIM =2,\r
886                                                                  .BFEN  = 1 };\r
887         FLASH.PFCRP0.B = val;\r
888 \r
889         /* Enable pipelined reads again. */\r
890 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
891         //TODO: Lägg till flash för mpc5554 &67\r
892 #endif\r
893 }\r
894 \r