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