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