]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Mcu.c
Mcu: Fixed hang when running the ISS
[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_SIMULATOR)\r
387     return E_OK;\r
388 #elif defined(CFG_MPC5516) || defined(CFG_MPC5554) || defined(CFG_MPC5668)\r
389     /* 5516clock info:\r
390      * Fsys - System frequency ( CPU + all periperals? )\r
391      *\r
392      *  Fsys = EXTAL_FREQ *(  (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )\r
393      */\r
394     // Check ranges...\r
395     assert((clockSettingsPtr->Pll2>=32) && (clockSettingsPtr->Pll2<=132));\r
396     assert( (clockSettingsPtr->Pll1 != 6) &&\r
397             (clockSettingsPtr->Pll1 != 8) &&\r
398             (clockSettingsPtr->Pll1 < 10) );\r
399     assert( clockSettingsPtr->Pll3 & 1); // Must be odd\r
400 #elif defined(CFG_MPC5567)\r
401     /* 5567 clock info:\r
402      *  Fsys = EXTAL_FREQ *(  (emfd+4) / ( (eprediv+1) * ( 2^erfd )) ) )\r
403      */\r
404     // Check ranges...\r
405     assert(clockSettingsPtr->Pll2 < 16);\r
406     assert(clockSettingsPtr->Pll1 <= 4);\r
407     assert(clockSettingsPtr->Pll3 < 8);\r
408 #endif\r
409 \r
410 #if defined(USE_LDEBUG_PRINTF)\r
411     {\r
412         uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
413         uint32  f_sys;\r
414 \r
415         f_sys = CALC_SYSTEM_CLOCK( extal,\r
416                 clockSettingsPtr->Pll2,\r
417                 clockSettingsPtr->Pll1,\r
418                 clockSettingsPtr->Pll3 );\r
419 \r
420         //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);\r
421     }\r
422 #endif\r
423 \r
424 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
425 \r
426     // set post divider to next valid value to ensure that an overshoot during lock phase\r
427     // won't result in a too high freq\r
428     FMPLL.ESYNCR2.B.ERFD = (clockSettingsPtr->Pll3 + 1) | 1;\r
429 \r
430     // External crystal PLL mode.\r
431     FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?\r
432 \r
433     // Write pll parameters.\r
434     FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->Pll1;\r
435     FMPLL.ESYNCR1.B.EMFD    = clockSettingsPtr->Pll2;\r
436 \r
437     while(FMPLL.SYNSR.B.LOCK != 1) {};\r
438 \r
439     FMPLL.ESYNCR2.B.ERFD    = clockSettingsPtr->Pll3;\r
440     // Connect SYSCLK to FMPLL\r
441     SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;\r
442 #elif defined(CFG_MPC5604B) || defined(CFG_MPC5606B)\r
443     // Write pll parameters.\r
444     CGM.FMPLL_CR.B.IDF = clockSettingsPtr->Pll1;\r
445     CGM.FMPLL_CR.B.NDIV = clockSettingsPtr->Pll2;\r
446     CGM.FMPLL_CR.B.ODF = clockSettingsPtr->Pll3;\r
447 \r
448     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
449     ME.RUN[0].R = 0x001F0074;\r
450     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
451     ME.RUNPC[1].R = 0x00000010;\r
452     /* MPC56xxB/S: select ME.RUNPC[1] */\r
453     ME.PCTL[68].R = 0x01; //SIUL control\r
454     ME.PCTL[91].R = 0x01; //RTC/API control\r
455     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
456     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
457     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
458     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
459     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
460     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
461     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
462     ME.PCTL[32].R = 0x01; //ADC0 control\r
463 #if defined(CFG_MPC5606B)\r
464     ME.PCTL[33].R = 0x01; //ADC1 control\r
465 #endif\r
466     ME.PCTL[23].R = 0x01; //DMAMUX control\r
467     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
468     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
469     /* Mode Transition to enter RUN0 mode: */\r
470     /* Enter RUN0 Mode & Key */\r
471     ME.MCTL.R = 0x40005AF0;\r
472     /* Enter RUN0 Mode & Inverted Key */\r
473     ME.MCTL.R = 0x4000A50F;\r
474 \r
475     /* Wait for mode transition to complete */\r
476     while (ME.GS.B.S_MTRANS) {}\r
477     /* Verify RUN0 is the current mode */\r
478     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
479 \r
480     CGM.SC_DC[0].R = 0x80; /* MPC56xxB/S: Enable peri set 1 sysclk divided by 1 */\r
481     CGM.SC_DC[1].R = 0x80; /* MPC56xxB/S: Enable peri set 2 sysclk divided by 1 */\r
482     CGM.SC_DC[2].R = 0x80; /* MPC56xxB/S: Enable peri set 3 sysclk divided by 1 */\r
483 \r
484     SIU.PSMI[0].R = 0x01; /* CAN1RX on PCR43 */\r
485     SIU.PSMI[6].R = 0x01; /* CS0/DSPI_0 on PCR15 */\r
486 \r
487 #elif defined(CFG_MPC5606S)\r
488     // Write pll parameters.\r
489     CGM.FMPLL[0].CR.B.IDF = clockSettingsPtr->Pll1;\r
490     CGM.FMPLL[0].CR.B.NDIV = clockSettingsPtr->Pll2;\r
491     CGM.FMPLL[0].CR.B.ODF = clockSettingsPtr->Pll3;\r
492 \r
493     /* RUN0 cfg: 16MHzIRCON,OSC0ON,PLL0ON,syclk=PLL0 */\r
494     ME.RUN[0].R = 0x001F0074;\r
495     /* Peri. Cfg. 1 settings: only run in RUN0 mode */\r
496     ME.RUNPC[1].R = 0x00000010;\r
497     /* MPC56xxB/S: select ME.RUNPC[1] */\r
498     ME.PCTL[68].R = 0x01; //SIUL control\r
499     ME.PCTL[91].R = 0x01; //RTC/API control\r
500     ME.PCTL[92].R = 0x01; //PIT_RTI control\r
501     ME.PCTL[72].R = 0x01; //eMIOS0 control\r
502     ME.PCTL[73].R = 0x01; //eMIOS1 control\r
503     ME.PCTL[16].R = 0x01; //FlexCAN0 control\r
504     ME.PCTL[17].R = 0x01; //FlexCAN1 control\r
505     ME.PCTL[4].R = 0x01;  /* MPC56xxB/P/S DSPI0  */\r
506     ME.PCTL[5].R = 0x01;  /* MPC56xxB/P/S DSPI1:  */\r
507     ME.PCTL[32].R = 0x01; //ADC0 control\r
508     ME.PCTL[23].R = 0x01; //DMAMUX control\r
509     ME.PCTL[48].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
510     ME.PCTL[49].R = 0x01; /* MPC56xxB/P/S LINFlex  */\r
511     /* Mode Transition to enter RUN0 mode: */\r
512     /* Enter RUN0 Mode & Key */\r
513     ME.MCTL.R = 0x40005AF0;\r
514     /* Enter RUN0 Mode & Inverted Key */\r
515     ME.MCTL.R = 0x4000A50F;\r
516 \r
517     /* Wait for mode transition to complete */\r
518     while (ME.GS.B.S_MTRANS) {}\r
519     /* Verify RUN0 is the current mode */\r
520     while(ME.GS.B.S_CURRENTMODE != 4) {}\r
521 \r
522     CGM.SC_DC[0].R = 0x80; /* MPC56xxB/S: Enable peri set 1 sysclk divided by 1 */\r
523     CGM.SC_DC[1].R = 0x80; /* MPC56xxB/S: Enable peri set 2 sysclk divided by 1 */\r
524     CGM.SC_DC[2].R = 0x80; /* MPC56xxB/S: Enable peri set 3 sysclk divided by 1 */\r
525 \r
526  #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
527     // Partially following the steps in MPC5567 RM..\r
528     FMPLL.SYNCR.B.DEPTH = 0;\r
529     FMPLL.SYNCR.B.LOLRE = 0;\r
530     FMPLL.SYNCR.B.LOLIRQ = 0;\r
531 \r
532     FMPLL.SYNCR.B.PREDIV        = clockSettingsPtr->Pll1;\r
533     FMPLL.SYNCR.B.MFD           = clockSettingsPtr->Pll2;\r
534     FMPLL.SYNCR.B.RFD           = clockSettingsPtr->Pll3;\r
535 \r
536         // Wait for PLL to sync.\r
537     while (Mcu_GetPllStatus() != MCU_PLL_LOCKED) ;\r
538 \r
539     FMPLL.SYNCR.B.LOLIRQ        = 1;\r
540 #endif\r
541 \r
542     return E_OK;\r
543 }\r
544 \r
545 //-------------------------------------------------------------------\r
546 \r
547 void Mcu_DistributePllClock(void)\r
548 {\r
549     VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
550 #if defined(CFG_MPC560XB)\r
551     VALIDATE( ( CGM.FMPLL_CR.B.S_LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
552 #elif defined(CFG_MPC5606S)\r
553     VALIDATE( ( CGM.FMPLL[0].CR.B.S_LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
554 #else\r
555     VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
556 #endif\r
557     /* NOT IMPLEMENTED due to pointless function on this hardware */\r
558 \r
559 }\r
560 \r
561 //-------------------------------------------------------------------\r
562 \r
563 Mcu_PllStatusType Mcu_GetPllStatus(void)\r
564 {\r
565     VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
566     Mcu_PllStatusType rv;\r
567 \r
568     if( !SIMULATOR() )\r
569     {\r
570 #if defined(CFG_MPC560XB)\r
571         if ( !CGM.FMPLL_CR.B.S_LOCK )\r
572         {\r
573                 rv = MCU_PLL_UNLOCKED;\r
574         } else\r
575         {\r
576                 rv = MCU_PLL_LOCKED;\r
577         }\r
578 #elif defined(CFG_MPC5606S)\r
579         if ( !CGM.FMPLL[0].CR.B.S_LOCK )\r
580         {\r
581                 rv = MCU_PLL_UNLOCKED;\r
582         } else\r
583         {\r
584                 rv = MCU_PLL_LOCKED;\r
585         }\r
586 #else\r
587         if ( !FMPLL.SYNSR.B.LOCK )\r
588         {\r
589                 rv = MCU_PLL_UNLOCKED;\r
590         } else\r
591         {\r
592                 rv = MCU_PLL_LOCKED;\r
593         }\r
594 #endif\r
595     }\r
596     else\r
597     {\r
598         /* We are running on instruction set simulator. PLL is then always in sync... */\r
599         rv = MCU_PLL_LOCKED;\r
600     }\r
601 \r
602   return rv;\r
603 }\r
604 \r
605 //-------------------------------------------------------------------\r
606 \r
607 Mcu_ResetType Mcu_GetResetReason(void)\r
608 {\r
609         Mcu_ResetType rv;\r
610 \r
611         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
612 \r
613 #if defined(CFG_MPC560X)\r
614         if( RGM.FES.B.F_SOFT ) {\r
615                 rv = MCU_SW_RESET;\r
616         } else if( RGM.DES.B.F_SWT ) {\r
617                 rv = MCU_WATCHDOG_RESET;\r
618         } else if( RGM.DES.B.F_POR ) {\r
619                 rv = MCU_POWER_ON_RESET;\r
620         } else {\r
621                 rv = MCU_RESET_UNDEFINED;\r
622         }\r
623 #else\r
624         if( SIU.RSR.B.SSRS ) {\r
625                 rv = MCU_SW_RESET;\r
626         } else if( SIU.RSR.B.WDRS ) {\r
627                 rv = MCU_WATCHDOG_RESET;\r
628         } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {\r
629                 rv = MCU_POWER_ON_RESET;\r
630         } else {\r
631                 rv = MCU_RESET_UNDEFINED;\r
632         }\r
633 #endif\r
634 \r
635         return rv;\r
636 }\r
637 \r
638 //-------------------------------------------------------------------\r
639 \r
640 Mcu_RawResetType Mcu_GetResetRawValue(void)\r
641 {\r
642         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
643 \r
644         if( !Mcu_Global.initRun ) {\r
645                 return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
646         }\r
647 \r
648 #if defined(CFG_MPC560X)\r
649         if( RGM.DES.R )\r
650                 return RGM.DES.R;\r
651         else\r
652                 return RGM.FES.R;\r
653 #else\r
654         return SIU.RSR.R;\r
655 #endif\r
656 \r
657 }\r
658 \r
659 //-------------------------------------------------------------------\r
660 \r
661 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
662 void Mcu_PerformReset(void)\r
663 {\r
664         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
665 \r
666         // Reset\r
667 #if defined(CFG_MPC560X)\r
668     ME.MCTL.R = 0x00005AF0;\r
669     ME.MCTL.R = 0x0000A50F;\r
670 \r
671     while (ME.GS.B.S_MTRANS) {}\r
672     while(ME.GS.B.S_CURRENTMODE != 0) {}\r
673 #else\r
674         SIU.SRCR.B.SSR = 1;\r
675 #endif\r
676 \r
677 }\r
678 #endif\r
679 \r
680 //-------------------------------------------------------------------\r
681 \r
682 /**\r
683  *\r
684  * Application Notes!\r
685  * - AN3584, "MPC5510 Family Low Power Features"\r
686  *   Since it's not complete also check MPC5668\r
687  * - AN4150 , "Using Sleep Mode on the MPC5668x" and it's code\r
688  *\r
689  *\r
690  * @param LPM\r
691  */\r
692 static void enterLowPower (Mcu_ModeType mcuMode )\r
693 {\r
694 #if defined(CFG_MPC5668)\r
695         uint32 timeout;\r
696         /* Set the sleep bit; following a WAIT instruction, the device will go to sleep */\r
697         CRP.PSCR.B.SLEEP = 1;\r
698 \r
699         /* 0x1 32k, 0x2 64k, 0x3 128k -- RAMs maintain power */\r
700         CRP.PSCR.B.RAMSEL = 0x3;                // Keep all 128K\r
701 \r
702         CRP.Z6VEC.R = (uint32)&McuE_LowPowerRecoverFlash;\r
703 #if defined(CFG_VLE)\r
704         CRP.Z6VEC.VLE = 1;\r
705 #endif\r
706 \r
707         /* If we "Mcu_Wakeup()" is located in RAM, set FASTREC */\r
708         CRP.RECPTR.B.FASTREC = 0;\r
709 \r
710         /* Halt everything */\r
711     SIU.HLT0.R = 0x037FFF3D;\r
712     SIU.HLT1.R = 0x18000F3C;\r
713     while((SIU.HLTACK0.R != 0x037FFF3D) && (SIU.HLTACK1.R != 0x18000F3C) && (timeout<3000)){}\r
714 \r
715         /* put Z0 in reset if not used for wakeup */\r
716         CRP.Z0VEC.B.Z0RST = 1;\r
717 \r
718         // TODO: Enable_all_internal_pull_devices (PULL_DOWN);\r
719 \r
720         /* Save context and execute wait instruction.\r
721          *\r
722          * Things that matter here are\r
723          * - Z1VEC, determines where TLB0 will point. TLB0 is written with a\r
724          *   value at startup that 4K aligned to this address.\r
725          * - LowPower_Sleep() will save a interrupt context so we will return\r
726          *   intact.\r
727          * - For devices with little RAM we don't want to impose the alignment\r
728          *   requirements there. Almost as we have to occupy a 4K block for this..\r
729          *   although the code does not take that much space.\r
730          * */\r
731         McuE_EnterLowPower(mcuMode);\r
732 \r
733     /* Clear sleep flags to allow pads to operate */\r
734         CRP.PSCR.B.SLEEPF = 0x1;\r
735 \r
736 #elif defined(CFG_MPC5516)\r
737         uint32 timeout;\r
738         /* Set the sleep bit; following a WAIT instruction, the device will go to sleep */\r
739         CRP.PSCR.B.SLEEP = 1;\r
740         /* enable the 1.2V internal regulator when in sleep mode only */\r
741         CRP.PSCR.B.STOP12EN = 1;\r
742         /* 0x1 8k, 0x2 16k, 0x3 32k, 0x6 64k -- RAMs maintain power */\r
743         CRP.PSCR.B.RAMSEL = 0x7;                // Keep all 80K\r
744 \r
745         CRP.Z1VEC.R = (uint32)&McuE_LowPowerRecoverFlash;\r
746 #if defined(CFG_VLE)\r
747         CRP.VLE = 1;\r
748 #endif\r
749 \r
750         /* If we "Mcu_Wakeup()" is located in RAM, set FASTREC */\r
751         CRP.RECPRTR.B.FASTREC = 0;\r
752 \r
753         /* Halt everything */\r
754         SIU.HLT.R = 0x3FFFFFFF;\r
755         while((SIU.HLTACK.R != 0x3FFFFFFF) && (timeout<3000)) {}\r
756 \r
757         /* put Z0 in reset if not used for wakeup */\r
758         CRP.Z0VEC.B.Z0RST = 1;\r
759 \r
760         // TODO: Enable_all_internal_pull_devices (PULL_DOWN);\r
761 \r
762         /* Save context and execute wait instruction.\r
763          *\r
764          * Things that matter here are\r
765          * - Z1VEC, determines where TLB0 will point. TLB0 is written with a\r
766          *   value at startup that 4K aligned to this address.\r
767          * - LowPower_Sleep() will save a interrupt context so we will return\r
768          *   intact.\r
769          * - For devices with little RAM we don't want to impose the alignment\r
770          *   requirements there. Almost as we have to occupy a 4K block for this..\r
771          *   although the code does not take that much space.\r
772          * */\r
773         McuE_EnterLowPower(mcuMode);\r
774 \r
775     /* Clear sleep flags to allow pads to operate */\r
776     CRP.PSCR.B.SLEEPF = 0x1;\r
777 #else\r
778         /* NOT SUPPORTED */\r
779         (void) McuMode;\r
780 #endif\r
781 }\r
782 \r
783 \r
784 void Mcu_SetMode( Mcu_ModeType mcuMode)\r
785 {\r
786         VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
787         // VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
788 \r
789 \r
790 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
791         if( MCU_MODE_RUN == mcuMode ) {\r
792 \r
793         } else if( MCU_MODE_SLEEP == mcuMode ) {\r
794                 /*\r
795                  * Follows the AN3548 from Freescale\r
796                  *\r
797                  */\r
798 #if defined(USE_DMA)\r
799                 Dma_StopAll();\r
800 #endif\r
801 \r
802 \r
803                 /* Set system clock to 16Mhz IRC */\r
804                 SIU.SYSCLK.B.SYSCLKSEL = 0;\r
805 \r
806                 /* Put flash in low-power mode */\r
807                 // TODO\r
808 \r
809                 /* Put QQADC in low-power mode */\r
810                 // TODO\r
811 \r
812                 /* Set us in SLEEP mode */\r
813                 CRP.PSCR.B.SLEEP = 1;\r
814 \r
815 \r
816                 enterLowPower(mcuMode);\r
817         }\r
818 #else\r
819         /* NOT SUPPORTED */\r
820         (void) McuMode;\r
821 #endif\r
822 }\r
823 \r
824 //-------------------------------------------------------------------\r
825 \r
826 /**\r
827  * Get the system clock in Hz. It calculates the clock from the\r
828  * different register settings in HW.\r
829  */\r
830 uint32_t McuE_GetSystemClock(void)\r
831 {\r
832         /*\r
833          * System clock calculation\r
834          *\r
835          * 5516 -  f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));\r
836          * 5567 -  f_sys = extal * (emfd+4) / ( (eprediv+1) * ( 2^erfd ));\r
837          * 563x -  We run in legacy mode = 5567\r
838          * 5606s - f_sys = extal * emfd / ((eprediv+1)*(2<<(erfd)));\r
839          */\r
840 #if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
841         uint32_t eprediv = FMPLL.ESYNCR1.B.EPREDIV;\r
842         uint32_t emfd = FMPLL.ESYNCR1.B.EMFD;\r
843         uint32_t erfd = FMPLL.ESYNCR2.B.ERFD;\r
844 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567) || defined(CFG_MPC5633)\r
845         uint32_t eprediv = FMPLL.SYNCR.B.PREDIV;\r
846         uint32_t emfd = FMPLL.SYNCR.B.MFD;\r
847         uint32_t erfd = FMPLL.SYNCR.B.RFD;\r
848 #elif defined(CFG_MPC560XB)\r
849     uint32_t eprediv = CGM.FMPLL_CR.B.IDF;\r
850     uint32_t emfd = CGM.FMPLL_CR.B.NDIV;\r
851     uint32_t erfd = CGM.FMPLL_CR.B.ODF;\r
852 #elif defined(CFG_MPC5606S)\r
853     uint32_t eprediv = CGM.FMPLL[0].CR.B.IDF;\r
854     uint32_t emfd = CGM.FMPLL[0].CR.B.NDIV;\r
855     uint32_t erfd = CGM.FMPLL[0].CR.B.ODF;\r
856 #endif\r
857 \r
858     uint32_t f_sys;\r
859     uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
860 \r
861     f_sys = CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);\r
862 \r
863     return f_sys;\r
864 }\r
865 \r
866 #if defined(CFG_MPC5668)\r
867 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type) {\r
868         uint32_t sysClock = McuE_GetSystemClock();\r
869         vuint32_t prescaler;\r
870 \r
871         switch (type)\r
872         {\r
873                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
874                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
875                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
876                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
877                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
878                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
879                 case PERIPHERAL_CLOCK_DSPI_A:\r
880                 case PERIPHERAL_CLOCK_DSPI_B:\r
881                 case PERIPHERAL_CLOCK_DSPI_C:\r
882                 case PERIPHERAL_CLOCK_DSPI_D:\r
883                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
884                         break;\r
885                 case PERIPHERAL_CLOCK_ESCI_A:\r
886                 case PERIPHERAL_CLOCK_ESCI_B:\r
887                 case PERIPHERAL_CLOCK_ESCI_C:\r
888                 case PERIPHERAL_CLOCK_ESCI_D:\r
889                 case PERIPHERAL_CLOCK_ESCI_E:\r
890                 case PERIPHERAL_CLOCK_ESCI_F:\r
891                 case PERIPHERAL_CLOCK_IIC_A:\r
892                 case PERIPHERAL_CLOCK_IIC_B:\r
893                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
894                         break;\r
895                 case PERIPHERAL_CLOCK_ADC_A:\r
896                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
897                         break;\r
898                 case PERIPHERAL_CLOCK_EMIOS:\r
899                         prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
900                         break;\r
901                 default:\r
902                         assert(0);\r
903                         break;\r
904         }\r
905 \r
906         return sysClock/(1<<prescaler);\r
907 \r
908 }\r
909 \r
910 #else\r
911 \r
912 /**\r
913  * Get the peripheral clock in Hz for a specific device\r
914  */\r
915 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
916 {\r
917 #if defined(CFG_MPC5567)\r
918         // No peripheral dividers on 5567.\r
919         return McuE_GetSystemClock();\r
920 #else\r
921         uint32_t sysClock = McuE_GetSystemClock();\r
922         vuint32_t prescaler;\r
923 \r
924   // See table 3.1, section 3.4.5 Peripheral Clock dividers\r
925         switch (type)\r
926         {\r
927                 case PERIPHERAL_CLOCK_FLEXCAN_A:\r
928                 case PERIPHERAL_CLOCK_DSPI_A:\r
929 #if defined(CFG_MPC5516)\r
930                         prescaler = SIU.SYSCLK.B.LPCLKDIV0;\r
931                         break;\r
932 #elif defined(CFG_MPC560X)\r
933                         prescaler = CGM.SC_DC[1].B.DIV;\r
934                         break;\r
935 #endif\r
936 \r
937                 case PERIPHERAL_CLOCK_PIT:\r
938                 case PERIPHERAL_CLOCK_ESCI_A:\r
939                 case PERIPHERAL_CLOCK_IIC_A:\r
940 #if defined(CFG_MPC5516)\r
941                         prescaler = SIU.SYSCLK.B.LPCLKDIV1;\r
942                         break;\r
943 #endif\r
944 \r
945                 case PERIPHERAL_CLOCK_FLEXCAN_B:\r
946                 case PERIPHERAL_CLOCK_FLEXCAN_C:\r
947                 case PERIPHERAL_CLOCK_FLEXCAN_D:\r
948                 case PERIPHERAL_CLOCK_FLEXCAN_E:\r
949                 case PERIPHERAL_CLOCK_FLEXCAN_F:\r
950 #if defined(CFG_MPC5516)\r
951                         prescaler = SIU.SYSCLK.B.LPCLKDIV2;\r
952                         break;\r
953 #elif defined(CFG_MPC560X)\r
954                         prescaler = CGM.SC_DC[1].B.DIV;\r
955                         break;\r
956 #endif\r
957 \r
958                 case PERIPHERAL_CLOCK_DSPI_B:\r
959                 case PERIPHERAL_CLOCK_DSPI_C:\r
960                 case PERIPHERAL_CLOCK_DSPI_D:\r
961                 case PERIPHERAL_CLOCK_DSPI_E:\r
962                 case PERIPHERAL_CLOCK_DSPI_F:\r
963 #if defined(CFG_MPC5516)\r
964                 prescaler = SIU.SYSCLK.B.LPCLKDIV3;\r
965                         break;\r
966 #endif\r
967 \r
968                 case PERIPHERAL_CLOCK_ESCI_B:\r
969                 case PERIPHERAL_CLOCK_ESCI_C:\r
970                 case PERIPHERAL_CLOCK_ESCI_D:\r
971                 case PERIPHERAL_CLOCK_ESCI_E:\r
972                 case PERIPHERAL_CLOCK_ESCI_F:\r
973                 case PERIPHERAL_CLOCK_ESCI_G:\r
974                 case PERIPHERAL_CLOCK_ESCI_H:\r
975 #if defined(CFG_MPC5516)\r
976                         prescaler = SIU.SYSCLK.B.LPCLKDIV4;\r
977                         break;\r
978 #endif\r
979 \r
980 #if defined(CFG_MPC560X)\r
981                 case PERIPHERAL_CLOCK_LIN_A:\r
982                 case PERIPHERAL_CLOCK_LIN_B:\r
983 #if defined(CFG_MPC560XB)\r
984                 case PERIPHERAL_CLOCK_LIN_C:\r
985                 case PERIPHERAL_CLOCK_LIN_D:\r
986 #endif\r
987                         prescaler = CGM.SC_DC[0].B.DIV;\r
988                         break;\r
989                 case PERIPHERAL_CLOCK_EMIOS_0:\r
990                         prescaler = CGM.SC_DC[2].B.DIV;\r
991                         break;\r
992                 case PERIPHERAL_CLOCK_EMIOS_1:\r
993                         prescaler = CGM.SC_DC[2].B.DIV;\r
994                         break;\r
995 #else\r
996                 case PERIPHERAL_CLOCK_EMIOS:\r
997 #if defined(CFG_MPC5516)\r
998                         prescaler = SIU.SYSCLK.B.LPCLKDIV5;\r
999                         break;\r
1000 #endif\r
1001 #endif\r
1002 \r
1003                 case PERIPHERAL_CLOCK_MLB:\r
1004 #if defined(CFG_MPC5516)\r
1005                         prescaler = SIU.SYSCLK.B.LPCLKDIV6;\r
1006                         break;\r
1007 #endif\r
1008 \r
1009                 default:\r
1010                         assert(0);\r
1011                         break;\r
1012         }\r
1013 \r
1014         return sysClock/(1<<prescaler);\r
1015 #endif\r
1016 }\r
1017 #endif\r
1018 \r
1019 /**\r
1020  * Function to setup the internal flash for optimal performance\r
1021  */\r
1022 \r
1023 static void Mcu_ConfigureFlash(void)\r
1024 {\r
1025         /* These flash settings increases the CPU performance of 7 times compared\r
1026            to reset default settings!! */\r
1027 \r
1028 #if defined(CFG_MPC5516)\r
1029         /* Disable pipelined reads when flash options are changed. */\r
1030         FLASH.MCR.B.PRD = 1;\r
1031 \r
1032         /* Enable master prefetch for e200z1 and eDMA. */\r
1033         FLASH.PFCRP0.B.M0PFE = 1;\r
1034         FLASH.PFCRP0.B.M2PFE = 1;\r
1035 \r
1036         /* Address pipelining control. Must be set to the same value as RWSC. */\r
1037         FLASH.PFCRP0.B.APC = 2;\r
1038         FLASH.PFCRP0.B.RWSC = 2;\r
1039 \r
1040         /* Write wait states. */\r
1041         FLASH.PFCRP0.B.WWSC = 1;\r
1042 \r
1043         /* Enable data prefetch. */\r
1044         FLASH.PFCRP0.B.DPFEN = 1;\r
1045 \r
1046         /* Enable instruction prefetch. */\r
1047         FLASH.PFCRP0.B.IPFEN = 1;\r
1048 \r
1049         /* Prefetch algorithm. */\r
1050         /* TODO: Ask Freescale about this option. */\r
1051         FLASH.PFCRP0.B.PFLIM = 2;\r
1052 \r
1053         /* Enable line read buffers. */\r
1054         FLASH.PFCRP0.B.BFEN = 1;\r
1055 \r
1056         /* Enable pipelined reads again. */\r
1057         FLASH.MCR.B.PRD = 0;\r
1058 #elif defined(CFG_MPC5668)\r
1059         /* Check values from cookbook and MPC5668x Microcontroller Data Sheet */\r
1060 \r
1061         /* Should probably trim this values */\r
1062         const typeof(FLASH.PFCRP0.B) val = {.M0PFE = 1, .M2PFE=1, .APC=3,\r
1063                                                                  .RWSC=3, .WWSC =1, .DPFEN =1, .IPFEN = 1, .PFLIM =2,\r
1064                                                                  .BFEN  = 1 };\r
1065         FLASH.PFCRP0.B = val;\r
1066 \r
1067         /* Enable pipelined reads again. */\r
1068 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
1069         //TODO: Lägg till flash för mpc5554 &67\r
1070 #endif\r
1071 }\r
1072 \r