]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Mcu.c
Updated after mcaltest run
[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_MPC560X)\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_MPC560X)\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_MPC560X)\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_MPC5604B)\r
171     {\r
172         .name = "MPC5604B",\r
173         .pvr = CORE_PVR_E200Z0H,\r
174     },\r
175 #elif defined(CFG_MPC5606B)\r
176     {\r
177         .name = "MPC5606B",\r
178         .pvr = CORE_PVR_E200Z0H,\r
179     },\r
180 #elif defined(CFG_MPC5606S)\r
181     {\r
182         .name = "MPC5606S",\r
183         .pvr = CORE_PVR_E200Z0H,\r
184     },\r
185 #elif defined(CFG_MPC5668)\r
186         {\r
187                 .name = "MPC5668",\r
188                 .pvr = CORE_PVR_E200Z65,\r
189         },\r
190         {\r
191                 .name = "MPC5668",\r
192                 .pvr = CORE_PVR_E200Z0,\r
193         },\r
194 #endif\r
195 };\r
196 \r
197 const core_info_t core_info_list[] = {\r
198 #if defined(CFG_MPC5516)\r
199         {\r
200                 .name = "CORE_E200Z1",\r
201                 .pvr = CORE_PVR_E200Z1,\r
202     },\r
203     {\r
204         .name = "CORE_E200Z1",\r
205         .pvr = CORE_PVR_E200Z1,\r
206     },\r
207 #elif defined(CFG_MPC5567)\r
208     {\r
209         .name = "CORE_E200Z6",\r
210         .pvr = CORE_PVR_E200Z6,\r
211     }\r
212 #elif defined(CFG_MPC5633)\r
213     {\r
214                 .name = "CORE_E200Z3",\r
215                 .pvr = CORE_PVR_E200Z3,\r
216     },\r
217 #elif defined(CFG_MPC5604B)\r
218     {\r
219         .name = "MPC5604B",\r
220         .pvr = CORE_PVR_E200Z0H,\r
221     },\r
222 #elif defined(CFG_MPC5606B)\r
223     {\r
224         .name = "MPC5606B",\r
225         .pvr = CORE_PVR_E200Z0H,\r
226     },\r
227 #elif defined(CFG_MPC5606S)\r
228     {\r
229         .name = "MPC5606S",\r
230         .pvr = CORE_PVR_E200Z0H,\r
231     },\r
232 #elif defined(CFG_MPC5668)\r
233     {\r
234         .name = "CORE_E200Z65",\r
235         .pvr = CORE_PVR_E200Z65,\r
236     },\r
237     {\r
238         .name = "CORE_E200Z0",\r
239         .pvr = CORE_PVR_E200Z1,\r
240     },\r
241 #endif\r
242 };\r
243 \r
244 // TODO: move\r
245 #if !defined(ARRAY_SIZE)\r
246 #define ARRAY_SIZE(_x)  (sizeof(_x)/sizeof((_x)[0]))\r
247 #endif\r
248 \r
249 static const cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)\r
250 {\r
251     int i;\r
252 \r
253     for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {\r
254         if (cpu_info_list[i].pvr == pvr) {\r
255                 return &cpu_info_list[i];\r
256         }\r
257     }\r
258 \r
259     return NULL;\r
260 }\r
261 \r
262 static const core_info_t *Mcu_IdentifyCore(uint32 pvr)\r
263 {\r
264         int i;\r
265 \r
266         for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {\r
267                 if (core_info_list[i].pvr == pvr) {\r
268                         return &core_info_list[i];\r
269                 }\r
270     }\r
271 \r
272   return NULL;\r
273 }\r
274 \r
275 static uint32 Mcu_CheckCpu( void ) {\r
276         uint32 pvr;\r
277         // uint32 pir;\r
278         const cpu_info_t *cpuType;\r
279         const core_info_t *coreType;\r
280 \r
281     // We have to registers to read here, PIR and PVR\r
282     // pir = get_spr(SPR_PIR);\r
283     pvr = get_spr(SPR_PVR);\r
284 \r
285     cpuType = Mcu_IdentifyCpu(pvr);\r
286     coreType = Mcu_IdentifyCore(pvr);\r
287 \r
288     if( (cpuType == NULL) || (coreType == NULL) ) {\r
289         // Just hang\r
290         while(1) ;\r
291     }\r
292 \r
293     //DEBUG(DEBUG_HIGH,"/drivers/mcu: Cpu:  %s( 0x%08x )\n",cpuType->name,pvr);\r
294     //DEBUG(DEBUG_HIGH,"/drivers/mcu: Core: %s( 0x%08x )\n",coreType->name,pvr);\r
295 \r
296     return 0;\r
297 }\r
298 \r
299 //-------------------------------------------------------------------\r
300 \r
301 void Mcu_Init(const Mcu_ConfigType *configPtr)\r
302 {\r
303         VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );\r
304 \r
305 #if defined(CFG_MPC560X)\r
306         /* Disable watchdog. Watchdog is enabled default after reset.*/\r
307         SWT.SR.R = 0x0000c520;     /* Write keys to clear soft lock bit */\r
308         SWT.SR.R = 0x0000d928;\r
309         SWT.CR.R = 0x8000010A;     /* Disable watchdog */\r
310 #if defined(USE_WDG)\r
311         SWT.TO.R = 0xfa00;              /* set the timout to 500ms */\r
312         SWT.CR.R = 0x8000011B;      /* enable watchdog */\r
313 #endif\r
314 #endif\r
315 \r
316     if( !SIMULATOR() ) {\r
317         Mcu_CheckCpu();\r
318     }\r
319 \r
320     memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));\r
321 \r
322     // Setup memories\r
323     Mcu_ConfigureFlash();\r
324 \r
325     Mcu_Global.config = configPtr;\r
326 \r
327 #if defined(CFG_MPC560X)\r
328     /* Enable DRUN, RUN0, SAFE, RESET modes */\r
329     ME.MER.R = 0x0000001D;\r
330 #endif\r
331 \r
332     Mcu_Global.initRun = 1;\r
333 \r
334     if( Mcu_Global.config->McuClockSrcFailureNotification == TRUE  ) {\r
335 #if defined(CFG_MPC560X)\r
336         /*not support*/\r
337 #else\r
338         ISR_INSTALL_ISR1("LossOfLock", Mcu_LossOfLock, PLL_SYNSR_LOLF, 10 , 0 );\r
339 #if defined(CFG_MPC5516)  || defined(CFG_MPC5668)\r
340         FMPLL.ESYNCR2.B.LOLIRQ = 1;\r
341 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
342         FMPLL.SYNCR.B.LOLIRQ = 1;\r
343 #endif\r
344         ISR_INSTALL_ISR1("LossOfClock", Mcu_LossOfClock, PLL_SYNSR_LOLF, 10 , 0 );\r
345 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
346         FMPLL.ESYNCR2.B.LOCIRQ = 1;\r
347 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
348         FMPLL.SYNCR.B.LOCIRQ = 1;\r
349 #endif\r
350 #endif\r
351     }\r
352 }\r
353 \r
354 //-------------------------------------------------------------------\r
355 \r
356 void Mcu_DeInit()\r
357 {\r
358         Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?\r
359 }\r
360 \r
361 //-------------------------------------------------------------------\r
362 \r
363 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)\r
364 {\r
365         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
366         VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );\r
367 \r
368     /* NOT SUPPORTED, reason: no support for external RAM */\r
369 \r
370     return E_OK;\r
371 }\r
372 \r
373 //-------------------------------------------------------------------\r
374 \r
375 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)\r
376 {\r
377     Mcu_ClockSettingConfigType *clockSettingsPtr;\r
378     VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
379     VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );\r
380 \r
381     Mcu_Global.clockSetting = ClockSetting;\r
382     clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];\r
383 \r
384     // TODO: find out if the 5554 really works like the 5516 here\r
385     // All three (16, 54, 67) used to run the same code here though, so i'm sticking it with 5516\r
386 #if defined(CFG_MPC5516) || defined(CFG_MPC5554) || defined(CFG_MPC5668)\r
387     /* 5516clock info:\r
388      * Fsys - System frequency ( CPU + all periperals? )\r
389      *\r
390      *  Fsys = EXTAL_FREQ *(  (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )\r
391      */\r
392     // Check ranges...\r
393     assert((clockSettingsPtr->Pll2>=32) && (clockSettingsPtr->Pll2<=132));\r
394     assert( (clockSettingsPtr->Pll1 != 6) &&\r
395             (clockSettingsPtr->Pll1 != 8) &&\r
396             (clockSettingsPtr->Pll1 < 10) );\r
397     assert( clockSettingsPtr->Pll3 & 1); // Must be odd\r
398 #elif defined(CFG_MPC5567)\r
399     /* 5567 clock info:\r
400      *  Fsys = EXTAL_FREQ *(  (emfd+4) / ( (eprediv+1) * ( 2^erfd )) ) )\r
401      */\r
402     // Check ranges...\r
403     assert(clockSettingsPtr->Pll2 < 16);\r
404     assert(clockSettingsPtr->Pll1 <= 4);\r
405     assert(clockSettingsPtr->Pll3 < 8);\r
406 #endif\r
407 \r
408 #if defined(USE_LDEBUG_PRINTF)\r
409     {\r
410         uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
411         uint32  f_sys;\r
412 \r
413         f_sys = CALC_SYSTEM_CLOCK( extal,\r
414                 clockSettingsPtr->Pll2,\r
415                 clockSettingsPtr->Pll1,\r
416                 clockSettingsPtr->Pll3 );\r
417 \r
418         //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);\r
419     }\r
420 #endif\r
421 \r
422 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
423 \r
424     // set post divider to next valid value to ensure that an overshoot during lock phase\r
425     // won't result in a too high freq\r
426     FMPLL.ESYNCR2.B.ERFD = (clockSettingsPtr->Pll3 + 1) | 1;\r
427 \r
428     // External crystal PLL mode.\r
429     FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?\r
430 \r
431     // Write pll parameters.\r
432     FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->Pll1;\r
433     FMPLL.ESYNCR1.B.EMFD    = clockSettingsPtr->Pll2;\r
434 \r
435     while(FMPLL.SYNSR.B.LOCK != 1) {};\r
436 \r
437     FMPLL.ESYNCR2.B.ERFD    = clockSettingsPtr->Pll3;\r
438     // Connect SYSCLK to FMPLL\r
439     SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;\r
440 #elif defined(CFG_MPC5604B) || defined(CFG_MPC5606B)\r
441     // Write pll parameters.\r
442     CGM.FMPLL_CR.B.IDF = clockSettingsPtr->Pll1;\r
443     CGM.FMPLL_CR.B.NDIV = clockSettingsPtr->Pll2;\r
444     CGM.FMPLL_CR.B.ODF = clockSettingsPtr->Pll3;\r
445 \r
446     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
447     ME.RUN[0].R = 0x001F0074;\r
448     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
449     ME.RUNPC[1].R = 0x00000010;\r
450     /* MPC56xxB/S: select ME.RUNPC[1] */\r
451     ME.PCTL[68].R = 0x01; //SIUL control\r
452     ME.PCTL[91].R = 0x01; //RTC/API control\r
453     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
454     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
455     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
456     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
457     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
458     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
459     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
460     ME.PCTL[32].R = 0x01; //ADC0 control\r
461 #if defined(CFG_MPC5606B)\r
462     ME.PCTL[33].R = 0x01; //ADC1 control\r
463 #endif\r
464     ME.PCTL[23].R = 0x01; //DMAMUX control\r
465     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
466     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
467     /* Mode Transition to enter RUN0 mode: */\r
468     /* Enter RUN0 Mode & Key */\r
469     ME.MCTL.R = 0x40005AF0;\r
470     /* Enter RUN0 Mode & Inverted Key */\r
471     ME.MCTL.R = 0x4000A50F;\r
472 \r
473     /* Wait for mode transition to complete */\r
474     while (ME.GS.B.S_MTRANS) {}\r
475     /* Verify RUN0 is the current mode */\r
476     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
477 \r
478     CGM.SC_DC[0].R = 0x80; /* MPC56xxB/S: Enable peri set 1 sysclk divided by 1 */\r
479     CGM.SC_DC[1].R = 0x80; /* MPC56xxB/S: Enable peri set 2 sysclk divided by 1 */\r
480     CGM.SC_DC[2].R = 0x80; /* MPC56xxB/S: Enable peri set 3 sysclk divided by 1 */\r
481 \r
482     SIU.PSMI[0].R = 0x01; /* CAN1RX on PCR43 */\r
483     SIU.PSMI[6].R = 0x01; /* CS0/DSPI_0 on PCR15 */\r
484 \r
485 #elif defined(CFG_MPC5606S)\r
486     // Write pll parameters.\r
487     CGM.FMPLL[0].CR.B.IDF = clockSettingsPtr->Pll1;\r
488     CGM.FMPLL[0].CR.B.NDIV = clockSettingsPtr->Pll2;\r
489     CGM.FMPLL[0].CR.B.ODF = clockSettingsPtr->Pll3;\r
490 \r
491     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
492     ME.RUN[0].R = 0x001F0074;\r
493     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
494     ME.RUNPC[1].R = 0x00000010;\r
495     /* MPC56xxB/S: select ME.RUNPC[1] */\r
496     ME.PCTL[68].R = 0x01; //SIUL control\r
497     ME.PCTL[91].R = 0x01; //RTC/API control\r
498     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
499     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
500     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
501     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
502     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
503     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
504     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
505     ME.PCTL[32].R = 0x01; //ADC0 control\r
506     ME.PCTL[23].R = 0x01; //DMAMUX control\r
507     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
508     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
509     /* Mode Transition to enter RUN0 mode: */\r
510     /* Enter RUN0 Mode & Key */\r
511     ME.MCTL.R = 0x40005AF0;\r
512     /* Enter RUN0 Mode & Inverted Key */\r
513     ME.MCTL.R = 0x4000A50F;\r
514 \r
515     /* Wait for mode transition to complete */\r
516     while (ME.GS.B.S_MTRANS) {}\r
517     /* Verify RUN0 is the current mode */\r
518     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
519 \r
520     CGM.SC_DC[0].R = 0x80; /* MPC56xxB/S: Enable peri set 1 sysclk divided by 1 */\r
521     CGM.SC_DC[1].R = 0x80; /* MPC56xxB/S: Enable peri set 2 sysclk divided by 1 */\r
522     CGM.SC_DC[2].R = 0x80; /* MPC56xxB/S: Enable peri set 3 sysclk divided by 1 */\r
523 \r
524  #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
525     // Partially following the steps in MPC5567 RM..\r
526     FMPLL.SYNCR.B.DEPTH = 0;\r
527     FMPLL.SYNCR.B.LOLRE = 0;\r
528     FMPLL.SYNCR.B.LOLIRQ = 0;\r
529 \r
530     FMPLL.SYNCR.B.PREDIV        = clockSettingsPtr->Pll1;\r
531     FMPLL.SYNCR.B.MFD           = clockSettingsPtr->Pll2;\r
532     FMPLL.SYNCR.B.RFD           = clockSettingsPtr->Pll3;\r
533 \r
534         // Wait for PLL to sync.\r
535     while (Mcu_GetPllStatus() != MCU_PLL_LOCKED) ;\r
536 \r
537     FMPLL.SYNCR.B.LOLIRQ        = 1;\r
538 #endif\r
539 \r
540     return E_OK;\r
541 }\r
542 \r
543 //-------------------------------------------------------------------\r
544 \r
545 void Mcu_DistributePllClock(void)\r
546 {\r
547     VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
548 #if defined(CFG_MPC560XB)\r
549     VALIDATE( ( CGM.FMPLL_CR.B.S_LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
550 #elif defined(CFG_MPC5606S)\r
551     VALIDATE( ( CGM.FMPLL[0].CR.B.S_LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
552 #else\r
553     VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
554 #endif\r
555     /* NOT IMPLEMENTED due to pointless function on this hardware */\r
556 \r
557 }\r
558 \r
559 //-------------------------------------------------------------------\r
560 \r
561 Mcu_PllStatusType Mcu_GetPllStatus(void)\r
562 {\r
563     VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
564     Mcu_PllStatusType rv;\r
565 \r
566     if( !SIMULATOR() )\r
567     {\r
568 #if defined(CFG_MPC560XB)\r
569         if ( !CGM.FMPLL_CR.B.S_LOCK )\r
570         {\r
571                 rv = MCU_PLL_UNLOCKED;\r
572         } else\r
573         {\r
574                 rv = MCU_PLL_LOCKED;\r
575         }\r
576 #elif defined(CFG_MPC5606S)\r
577         if ( !CGM.FMPLL[0].CR.B.S_LOCK )\r
578         {\r
579                 rv = MCU_PLL_UNLOCKED;\r
580         } else\r
581         {\r
582                 rv = MCU_PLL_LOCKED;\r
583         }\r
584 #else\r
585         if ( !FMPLL.SYNSR.B.LOCK )\r
586         {\r
587                 rv = MCU_PLL_UNLOCKED;\r
588         } else\r
589         {\r
590                 rv = MCU_PLL_LOCKED;\r
591         }\r
592 #endif\r
593     }\r
594     else\r
595     {\r
596         /* We are running on instruction set simulator. PLL is then always in sync... */\r
597         rv = MCU_PLL_LOCKED;\r
598     }\r
599 \r
600   return rv;\r
601 }\r
602 \r
603 //-------------------------------------------------------------------\r
604 \r
605 Mcu_ResetType Mcu_GetResetReason(void)\r
606 {\r
607         Mcu_ResetType rv;\r
608 \r
609         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
610 \r
611 #if defined(CFG_MPC560X)\r
612         if( RGM.FES.B.F_SOFT ) {\r
613                 rv = MCU_SW_RESET;\r
614         } else if( RGM.DES.B.F_SWT ) {\r
615                 rv = MCU_WATCHDOG_RESET;\r
616         } else if( RGM.DES.B.F_POR ) {\r
617                 rv = MCU_POWER_ON_RESET;\r
618         } else {\r
619                 rv = MCU_RESET_UNDEFINED;\r
620         }\r
621 #else\r
622         if( SIU.RSR.B.SSRS ) {\r
623                 rv = MCU_SW_RESET;\r
624         } else if( SIU.RSR.B.WDRS ) {\r
625                 rv = MCU_WATCHDOG_RESET;\r
626         } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {\r
627                 rv = MCU_POWER_ON_RESET;\r
628         } else {\r
629                 rv = MCU_RESET_UNDEFINED;\r
630         }\r
631 #endif\r
632 \r
633         return rv;\r
634 }\r
635 \r
636 //-------------------------------------------------------------------\r
637 \r
638 Mcu_RawResetType Mcu_GetResetRawValue(void)\r
639 {\r
640         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
641 \r
642         if( !Mcu_Global.initRun ) {\r
643                 return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
644         }\r
645 \r
646 #if defined(CFG_MPC560X)\r
647         if( RGM.DES.R )\r
648                 return RGM.DES.R;\r
649         else\r
650                 return RGM.FES.R;\r
651 #else\r
652         return SIU.RSR.R;\r
653 #endif\r
654 \r
655 }\r
656 \r
657 //-------------------------------------------------------------------\r
658 \r
659 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
660 void Mcu_PerformReset(void)\r
661 {\r
662         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
663 \r
664         // Reset\r
665 #if defined(CFG_MPC560X)\r
666     ME.MCTL.R = 0x00005AF0;\r
667     ME.MCTL.R = 0x0000A50F;\r
668 \r
669     while (ME.GS.B.S_MTRANS) {}\r
670     while(ME.GS.B.S_CURRENTMODE != 0) {}\r
671 #else\r
672         SIU.SRCR.B.SSR = 1;\r
673 #endif\r
674 \r
675 }\r
676 #endif\r
677 \r
678 //-------------------------------------------------------------------\r
679 \r
680 void Mcu_SetMode(const Mcu_ModeType McuMode)\r
681 {\r
682         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
683         // VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
684         (void) McuMode;\r
685 \r
686         /* NOT SUPPORTED */\r
687 }\r
688 \r
689 //-------------------------------------------------------------------\r
690 \r
691 /**\r
692  * Get the system clock in Hz. It calculates the clock from the\r
693  * different register settings in HW.\r
694  */\r
695 uint32_t McuE_GetSystemClock(void)\r
696 {\r
697         /*\r
698          * System clock calculation\r
699          *\r
700          * 5516 -  f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));\r
701          * 5567 -  f_sys = extal * (emfd+4) / ( (eprediv+1) * ( 2^erfd ));\r
702          * 563x -  We run in legacy mode = 5567\r
703          * 5606s - f_sys = extal * emfd / ((eprediv+1)*(2<<(erfd)));\r
704          */\r
705 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
706         uint32_t eprediv = FMPLL.ESYNCR1.B.EPREDIV;\r
707         uint32_t emfd = FMPLL.ESYNCR1.B.EMFD;\r
708         uint32_t erfd = FMPLL.ESYNCR2.B.ERFD;\r
709 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567) || defined(CFG_MPC5633)\r
710         uint32_t eprediv = FMPLL.SYNCR.B.PREDIV;\r
711         uint32_t emfd = FMPLL.SYNCR.B.MFD;\r
712         uint32_t erfd = FMPLL.SYNCR.B.RFD;\r
713 #elif defined(CFG_MPC560XB)\r
714     uint32_t eprediv = CGM.FMPLL_CR.B.IDF;\r
715     uint32_t emfd = CGM.FMPLL_CR.B.NDIV;\r
716     uint32_t erfd = CGM.FMPLL_CR.B.ODF;\r
717 #elif defined(CFG_MPC5606S)\r
718     uint32_t eprediv = CGM.FMPLL[0].CR.B.IDF;\r
719     uint32_t emfd = CGM.FMPLL[0].CR.B.NDIV;\r
720     uint32_t erfd = CGM.FMPLL[0].CR.B.ODF;\r
721 #endif\r
722 \r
723     uint32_t f_sys;\r
724     uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
725 \r
726     f_sys = CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);\r
727 \r
728     return f_sys;\r
729 }\r
730 \r
731 #if defined(CFG_MPC5668)\r
732 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type) {\r
733         uint32_t sysClock = McuE_GetSystemClock();\r
734         vuint32_t prescaler;\r
735 \r
736         switch (type)\r
737         {\r
738                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
739                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
740                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
741                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
742                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
743                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
744                 case PERIPHERAL_CLOCK_DSPI_A:\r
745                 case PERIPHERAL_CLOCK_DSPI_B:\r
746                 case PERIPHERAL_CLOCK_DSPI_C:\r
747                 case PERIPHERAL_CLOCK_DSPI_D:\r
748                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
749                         break;\r
750                 case PERIPHERAL_CLOCK_ESCI_A:\r
751                 case PERIPHERAL_CLOCK_ESCI_B:\r
752                 case PERIPHERAL_CLOCK_ESCI_C:\r
753                 case PERIPHERAL_CLOCK_ESCI_D:\r
754                 case PERIPHERAL_CLOCK_ESCI_E:\r
755                 case PERIPHERAL_CLOCK_ESCI_F:\r
756                 case PERIPHERAL_CLOCK_IIC_A:\r
757                 case PERIPHERAL_CLOCK_IIC_B:\r
758                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
759                         break;\r
760                 case PERIPHERAL_CLOCK_ADC_A:\r
761                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
762                         break;\r
763                 case PERIPHERAL_CLOCK_EMIOS:\r
764                         prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
765                         break;\r
766                 default:\r
767                         assert(0);\r
768                         break;\r
769         }\r
770 \r
771         return sysClock/(1<<prescaler);\r
772 \r
773 }\r
774 \r
775 #else\r
776 \r
777 /**\r
778  * Get the peripheral clock in Hz for a specific device\r
779  */\r
780 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
781 {\r
782 #if defined(CFG_MPC5567)\r
783         // No peripheral dividers on 5567.\r
784         return McuE_GetSystemClock();\r
785 #else\r
786         uint32_t sysClock = McuE_GetSystemClock();\r
787         vuint32_t prescaler;\r
788 \r
789   // See table 3.1, section 3.4.5 Peripheral Clock dividers\r
790         switch (type)\r
791         {\r
792                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
793                 case PERIPHERAL_CLOCK_DSPI_A:\r
794 #if defined(CFG_MPC5516)\r
795                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
796                         break;\r
797 #elif defined(CFG_MPC560X)\r
798                         prescaler = CGM.SC_DC[1].B.DIV;\r
799                         break;\r
800 #endif\r
801 \r
802                 case PERIPHERAL_CLOCK_PIT:\r
803                 case PERIPHERAL_CLOCK_ESCI_A:\r
804                 case PERIPHERAL_CLOCK_IIC_A:\r
805 #if defined(CFG_MPC5516)\r
806                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
807                         break;\r
808 #endif\r
809 \r
810                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
811                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
812                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
813                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
814                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
815 #if defined(CFG_MPC5516)\r
816                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
817                         break;\r
818 #elif defined(CFG_MPC560X)\r
819                         prescaler = CGM.SC_DC[1].B.DIV;\r
820                         break;\r
821 #endif\r
822 \r
823                 case PERIPHERAL_CLOCK_DSPI_B:\r
824                 case PERIPHERAL_CLOCK_DSPI_C:\r
825                 case PERIPHERAL_CLOCK_DSPI_D:\r
826                 case PERIPHERAL_CLOCK_DSPI_E:\r
827                 case PERIPHERAL_CLOCK_DSPI_F:\r
828 #if defined(CFG_MPC5516)\r
829                 prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
830                         break;\r
831 #endif\r
832 \r
833                 case PERIPHERAL_CLOCK_ESCI_B:\r
834                 case PERIPHERAL_CLOCK_ESCI_C:\r
835                 case PERIPHERAL_CLOCK_ESCI_D:\r
836                 case PERIPHERAL_CLOCK_ESCI_E:\r
837                 case PERIPHERAL_CLOCK_ESCI_F:\r
838                 case PERIPHERAL_CLOCK_ESCI_G:\r
839                 case PERIPHERAL_CLOCK_ESCI_H:\r
840 #if defined(CFG_MPC5516)\r
841                         prescaler = SIU.SYSCLK.B.LPCLKDIV4;\r
842                         break;\r
843 #endif\r
844 \r
845 #if defined(CFG_MPC560X)\r
846                 case PERIPHERAL_CLOCK_LIN_A:\r
847                 case PERIPHERAL_CLOCK_LIN_B:\r
848 #if defined(CFG_MPC560XB)\r
849                 case PERIPHERAL_CLOCK_LIN_C:\r
850                 case PERIPHERAL_CLOCK_LIN_D:\r
851 #endif\r
852                         prescaler = CGM.SC_DC[0].B.DIV;\r
853                         break;\r
854                 case PERIPHERAL_CLOCK_EMIOS_0:\r
855                         prescaler = CGM.SC_DC[2].B.DIV;\r
856                         break;\r
857                 case PERIPHERAL_CLOCK_EMIOS_1:\r
858                         prescaler = CGM.SC_DC[2].B.DIV;\r
859                         break;\r
860 #else\r
861                 case PERIPHERAL_CLOCK_EMIOS:\r
862 #if defined(CFG_MPC5516)\r
863                         prescaler = SIU.SYSCLK.B.LPCLKDIV5;\r
864                         break;\r
865 #endif\r
866 #endif\r
867 \r
868                 case PERIPHERAL_CLOCK_MLB:\r
869 #if defined(CFG_MPC5516)\r
870                         prescaler = SIU.SYSCLK.B.LPCLKDIV6;\r
871                         break;\r
872 #endif\r
873 \r
874                 default:\r
875                         assert(0);\r
876                         break;\r
877         }\r
878 \r
879         return sysClock/(1<<prescaler);\r
880 #endif\r
881 }\r
882 #endif\r
883 \r
884 /**\r
885  * Function to setup the internal flash for optimal performance\r
886  */\r
887 \r
888 static void Mcu_ConfigureFlash(void)\r
889 {\r
890         /* These flash settings increases the CPU performance of 7 times compared\r
891            to reset default settings!! */\r
892 \r
893 #if defined(CFG_MPC5516)\r
894         /* Disable pipelined reads when flash options are changed. */\r
895         FLASH.MCR.B.PRD = 1;\r
896 \r
897         /* Enable master prefetch for e200z1 and eDMA. */\r
898         FLASH.PFCRP0.B.M0PFE = 1;\r
899         FLASH.PFCRP0.B.M2PFE = 1;\r
900 \r
901         /* Address pipelining control. Must be set to the same value as RWSC. */\r
902         FLASH.PFCRP0.B.APC = 2;\r
903         FLASH.PFCRP0.B.RWSC = 2;\r
904 \r
905         /* Write wait states. */\r
906         FLASH.PFCRP0.B.WWSC = 1;\r
907 \r
908         /* Enable data prefetch. */\r
909         FLASH.PFCRP0.B.DPFEN = 1;\r
910 \r
911         /* Enable instruction prefetch. */\r
912         FLASH.PFCRP0.B.IPFEN = 1;\r
913 \r
914         /* Prefetch algorithm. */\r
915         /* TODO: Ask Freescale about this option. */\r
916         FLASH.PFCRP0.B.PFLIM = 2;\r
917 \r
918         /* Enable line read buffers. */\r
919         FLASH.PFCRP0.B.BFEN = 1;\r
920 \r
921         /* Enable pipelined reads again. */\r
922         FLASH.MCR.B.PRD = 0;\r
923 #elif defined(CFG_MPC5668)\r
924         /* Check values from cookbook and MPC5668x Microcontroller Data Sheet */\r
925 \r
926         /* Should probably trim this values */\r
927         const typeof(FLASH.PFCRP0.B) val = {.M0PFE = 1, .M2PFE=1, .APC=3,\r
928                                                                  .RWSC=3, .WWSC =1, .DPFEN =1, .IPFEN = 1, .PFLIM =2,\r
929                                                                  .BFEN  = 1 };\r
930         FLASH.PFCRP0.B = val;\r
931 \r
932         /* Enable pipelined reads again. */\r
933 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
934         //TODO: Lägg till flash för mpc5554 &67\r
935 #endif\r
936 }\r
937 \r