]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Mcu.c
Merge with krn-v2
[arc.git] / arch / arm / arm_cm3 / drivers / Mcu.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23 #include "Std_Types.h"\r
24 #include "Mcu.h"\r
25 #include "Det.h"
26 #if defined(USE_DEM)
27 #include "Dem.h"\r
28 #endif
29 #include <assert.h>\r
30 #include "cpu.h"\r
31 #include <string.h>\r
32 #include "Ramlog.h"\r
33 #include "system_stm32f10x.h"
34 \r
35 //#define USE_TRACE 1\r
36 //#define USE_DEBUG 1\r
37 #include "Trace.h"\r
38 \r
39 typedef struct {\r
40         uint32 lossOfLockCnt;\r
41         uint32 lossOfClockCnt;\r
42 } Mcu_Stats;\r
43 \r
44 void Mcu_ConfigureFlash(void);\r
45 /**\r
46  * Type that holds all global data for Mcu\r
47  */\r
48 typedef struct\r
49 {\r
50   // Set if Mcu_Init() have been called\r
51   boolean initRun;\r
52 \r
53   // Our config\r
54   const Mcu_ConfigType *config;\r
55 \r
56   Mcu_ClockType clockSetting;\r
57 \r
58   Mcu_Stats stats;\r
59 \r
60 } Mcu_GlobalType;\r
61 \r
62 /* Development error macros. */\r
63 #if ( MCU_DEV_ERROR_DETECT == STD_ON )\r
64 #define VALIDATE(_exp,_api,_err ) \\r
65         if( !(_exp) ) { \\r
66           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
67           return; \\r
68         }\r
69 \r
70 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
71         if( !(_exp) ) { \\r
72           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
73           return (_rv); \\r
74         }\r
75 #else\r
76 #define VALIDATE(_exp,_api,_err )\r
77 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
78 #endif\r
79 \r
80 // Global config\r
81 Mcu_GlobalType Mcu_Global =\r
82 {\r
83                 .initRun = 0,\r
84                 .config = &McuConfigData[0],\r
85 };\r
86 \r
87 //-------------------------------------------------------------------\r
88
89 #if 0\r
90 static void Mcu_LossOfLock( void  ) {\r
91 #if defined(USE_DEM)
92         Dem_ReportErrorStatus(MCU_E_CLOCK_FAILURE, DEM_EVENT_STATUS_FAILED);
93 #endif\r
94 \r
95         Mcu_Global.stats.lossOfLockCnt++;\r
96         // Clear interrupt\r
97 //      FMPLL.SYNSR.B.LOLF = 1;\r
98 \r
99 }\r
100 #endif
101 \r
102 #define SPR_PIR 286\r
103 #define SPR_PVR 287\r
104 \r
105 #define CORE_PVR_E200Z1         0x81440000UL\r
106 #define CORE_PVR_E200Z0         0x81710000UL
107 #define CORE_PVR_E200Z3         0x81120000UL\r
108 \r
109 \r
110 typedef struct {\r
111   char *name;\r
112   uint32 pvr;\r
113 } core_info_t;\r
114 \r
115 typedef struct {\r
116   char *name;\r
117   uint32 pvr;\r
118 } cpu_info_t;\r
119 \r
120 cpu_info_t cpu_info_list[] = {\r
121     {\r
122     .name = "MPC5516",\r
123     .pvr = CORE_PVR_E200Z1,\r
124     },\r
125     {\r
126     .name = "MPC5516",\r
127     .pvr = CORE_PVR_E200Z0,\r
128     },
129     {
130     .name = "MPC563X",
131     .pvr = CORE_PVR_E200Z3,
132     },
133 };\r
134 \r
135 core_info_t core_info_list[] = {\r
136     {\r
137     .name = "CORE_E200Z1",\r
138     .pvr = CORE_PVR_E200Z1,\r
139     },\r
140     {\r
141     .name = "CORE_E200Z1",\r
142     .pvr = CORE_PVR_E200Z1,\r
143     },\r
144     {
145     .name = "CORE_E200Z3",
146     .pvr = CORE_PVR_E200Z3,
147     },
148 };\r
149 \r
150 // TODO: move\r
151 #define ARRAY_SIZE(_x)  (sizeof(_x)/sizeof((_x)[0]))\r
152 \r
153 static cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)\r
154 {\r
155   int i;\r
156   for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {\r
157     if (cpu_info_list[i].pvr == pvr) {\r
158       return &cpu_info_list[i];\r
159     }\r
160   }\r
161 \r
162   return NULL;\r
163 }\r
164 \r
165 static core_info_t *Mcu_IdentifyCore(uint32 pvr)\r
166 {\r
167   int i;\r
168   for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {\r
169     if (core_info_list[i].pvr == pvr) {\r
170       return &core_info_list[i];\r
171     }\r
172   }\r
173 \r
174   return NULL;\r
175 }\r
176 \r
177 \r
178 static uint32 Mcu_CheckCpu( void ) {\r
179 \r
180   uint32 pvr;\r
181   //uint32 pir;\r
182   cpu_info_t *cpuType;\r
183   core_info_t *coreType;\r
184 \r
185   // We have to registers to read here, PIR and PVR\r
186 \r
187 #if 0\r
188   pir = get_spr(SPR_PIR);\r
189   pvr = get_spr(SPR_PVR);\r
190 #endif\r
191 \r
192   cpuType = Mcu_IdentifyCpu(pvr);\r
193   coreType = Mcu_IdentifyCore(pvr);\r
194 \r
195   if( (cpuType == NULL) || (coreType == NULL) ) {\r
196     // Just hang\r
197     while(1);\r
198   }\r
199 \r
200   //DEBUG(DEBUG_HIGH,"/drivers/mcu: Cpu:  %s( 0x%08x )\n",cpuType->name,pvr);\r
201   //DEBUG(DEBUG_HIGH,"/drivers/mcu: Core: %s( 0x%08x )\n",coreType->name,pvr);\r
202 \r
203   return 0;\r
204 }\r
205 \r
206 \r
207 //-------------------------------------------------------------------\r
208 \r
209 void Mcu_Init(const Mcu_ConfigType *configPtr)\r
210 {\r
211   VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );\r
212 \r
213   if( !SIMULATOR() ) {\r
214           Mcu_CheckCpu();\r
215   }\r
216 \r
217   memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));\r
218
219
220   SystemInit();\r
221
222   Irq_Enable();\r
223 \r
224   Mcu_Global.config = configPtr;\r
225   Mcu_Global.initRun = 1;\r
226 }\r
227 //-------------------------------------------------------------------\r
228 \r
229 void Mcu_DeInit()\r
230 {\r
231   Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?\r
232 }\r
233 \r
234 //-------------------------------------------------------------------\r
235 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)\r
236 {\r
237   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
238   VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );\r
239 \r
240   /* NOT SUPPORTED, reason: no support for external RAM */\r
241 \r
242   return E_OK;\r
243 }\r
244 \r
245 \r
246 \r
247 //-------------------------------------------------------------------\r
248 \r
249 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)\r
250 {\r
251   Mcu_ClockSettingConfigType *clockSettingsPtr;\r
252   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
253   VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );\r
254 \r
255   Mcu_Global.clockSetting = ClockSetting;\r
256   clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];\r
257 \r
258 \r
259 \r
260 #if 0\r
261   /* 5516clock info:\r
262    * Fsys - System frequency ( CPU + all periperals? )\r
263    *\r
264    *  Fsys = EXTAL_FREQ *(  (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )\r
265    */\r
266   // Check ranges...\r
267   assert((clockSettingsPtr->PllEmfd>=32) && (clockSettingsPtr->PllEmfd<=132));\r
268   assert( (clockSettingsPtr->PllEprediv!=6) &&\r
269           (clockSettingsPtr->PllEprediv!=8) &&\r
270           (clockSettingsPtr->PllEprediv<10) );\r
271   assert( clockSettingsPtr->PllErfd & 1); // Must be odd\r
272 #endif\r
273 \r
274 \r
275 \r
276 #if defined(USE_DEBUG)\r
277   {\r
278     uint32    extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;\r
279     uint32    f_sys;\r
280 \r
281     f_sys = CALC_SYSTEM_CLOCK( extal,\r
282         clockSettingsPtr->PllEmfd,\r
283         clockSettingsPtr->PllEprediv,\r
284         clockSettingsPtr->PllErfd );\r
285 \r
286     //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);\r
287   }\r
288 #endif\r
289 \r
290 #if defined(CFG_MPC5516)\r
291   // External crystal PLL mode.\r
292   FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?\r
293 \r
294   // Write pll parameters.\r
295   FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->PllEprediv;\r
296   FMPLL.ESYNCR1.B.EMFD    = clockSettingsPtr->PllEmfd;\r
297   FMPLL.ESYNCR2.B.ERFD    = clockSettingsPtr->PllErfd;\r
298 \r
299   // Connect SYSCLK to FMPLL\r
300   SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;\r
301 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
302   FMPLL.SYNCR.B.PREDIV  = clockSettingsPtr->PllEprediv;\r
303   FMPLL.SYNCR.B.MFD             = clockSettingsPtr->PllEmfd;\r
304   FMPLL.SYNCR.B.RFD     = clockSettingsPtr->PllErfd;\r
305 #endif\r
306 \r
307   return E_OK;\r
308 }\r
309 \r
310 //-------------------------------------------------------------------\r
311 \r
312 void Mcu_DistributePllClock(void)\r
313 {\r
314   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
315 //  VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
316 \r
317   /* NOT IMPLEMENTED due to pointless function on this hardware */\r
318 \r
319 }\r
320 \r
321 //-------------------------------------------------------------------\r
322 \r
323 Mcu_PllStatusType Mcu_GetPllStatus(void)\r
324 {\r
325   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
326   Mcu_PllStatusType rv;\r
327 \r
328   if( !SIMULATOR() )\r
329   {\r
330 #if 0\r
331     if ( !FMPLL.SYNSR.B.LOCK )\r
332     {\r
333       rv = MCU_PLL_UNLOCKED;\r
334     } else\r
335     {\r
336       rv = MCU_PLL_LOCKED;\r
337     }\r
338 #endif\r
339   }\r
340   else\r
341   {\r
342     /* We are running on instruction set simulator. PLL is then always in sync... */\r
343     rv = MCU_PLL_LOCKED;\r
344   }\r
345 \r
346   return rv;\r
347 }\r
348 \r
349 //-------------------------------------------------------------------\r
350 \r
351 Mcu_ResetType Mcu_GetResetReason(void)\r
352 {\r
353         Mcu_ResetType rv;\r
354 \r
355   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
356 \r
357 #if 0\r
358   if( SIU.RSR.B.SSRS ) {\r
359         rv = MCU_SW_RESET;\r
360   } else if( SIU.RSR.B.WDRS ) {\r
361         rv = MCU_WATCHDOG_RESET;\r
362   } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {\r
363         rv = MCU_POWER_ON_RESET;\r
364   } else {\r
365         rv = MCU_RESET_UNDEFINED;\r
366   }\r
367 #endif\r
368 \r
369   return rv;\r
370 }\r
371 \r
372 //-------------------------------------------------------------------\r
373 \r
374 Mcu_RawResetType Mcu_GetResetRawValue(void)\r
375 {\r
376   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
377 \r
378   if( !Mcu_Global.initRun ) {\r
379         return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
380   }\r
381 \r
382 #if 0\r
383   return SIU.RSR.R;\r
384 #endif\r
385 \r
386   return 0;\r
387 }\r
388 \r
389 //-------------------------------------------------------------------\r
390 \r
391 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
392 void Mcu_PerformReset(void)\r
393 {\r
394   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
395 \r
396   NVIC_SystemReset();\r
397 }\r
398 #endif\r
399 \r
400 //-------------------------------------------------------------------\r
401 \r
402 void Mcu_SetMode(const Mcu_ModeType McuMode)\r
403 {\r
404   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
405   VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
406   (void) McuMode;\r
407 \r
408   /* NOT SUPPORTED */\r
409 }\r
410 \r
411 //-------------------------------------------------------------------\r
412 \r
413 /**\r
414  * Get the system clock in Hz. It calculates the clock from the\r
415  * different register settings in HW.\r
416  */\r
417 uint32_t McuE_GetSystemClock(void)\r
418 {\r
419   /*\r
420    * System clock calculation\r
421    *\r
422    */
423
424   // TODO: This of course wrong....\r
425   uint32_t f_sys = 72000000UL;\r
426 #if 0\r
427   uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;\r
428 \r
429   f_sys =  CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);\r
430 #endif\r
431 \r
432 //  f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));\r
433   return f_sys;\r
434 }\r
435 \r
436 imask_t McuE_EnterCriticalSection()\r
437 {\r
438 #if 0\r
439   uint32_t msr = get_msr();\r
440   Irq_Disable();\r
441   return msr;\r
442 #endif\r
443   return 0;\r
444 }\r
445 \r
446 void McuE_ExitCriticalSection(uint32_t old_state)\r
447 {\r
448 #if 0\r
449   set_msr(old_state);\r
450 #endif\r
451 }\r
452 \r
453 /**\r
454  * Get the peripheral clock in Hz for a specific device\r
455  */\r
456 \r
457 #if 0\r
458 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
459 {\r
460 \r
461         return 0;\r
462 }\r
463 #endif\r
464 \r
465 \r
466 /**\r
467  * Function to setup the internal flash for optimal performance\r
468  */\r
469 \r
470 void Mcu_ConfigureFlash(void)\r
471 {\r
472 \r
473 }\r
474 \r
475 void McuE_EnableInterrupts(void)\r
476 {\r
477   Irq_Enable();\r
478 }\r
479 \r
480 void McuE_DisableInterrupts(void)\r
481 {\r
482   Irq_Disable();\r
483 }\r