]> rtime.felk.cvut.cz Git - arc.git/blobdiff - arch/ppc/mpc55xx/drivers/Mcu.c
Mcu ppc, fix for MCUs not supporting sleep mode.
[arc.git] / arch / ppc / mpc55xx / drivers / Mcu.c
index be6d308e45434c2faaef79f2cd1f198935af4698..eee6347ead943b9975f80e8398e99aab91daf518 100644 (file)
 //#define USE_LDEBUG_PRINTF 1\r
 #include "debug.h"\r
 \r
+#if defined(CFG_MPC5668) || defined(CFG_MPC5516)\r
+#define CFG_MCU_SUPPORT_SLEEP_MODE\r
+#endif\r
+\r
+\r
 #define SYSCLOCK_SELECT_PLL    0x2\r
 \r
 #if defined(CFG_MPC5567)\r
@@ -677,13 +682,152 @@ void Mcu_PerformReset(void)
 \r
 //-------------------------------------------------------------------\r
 \r
-void Mcu_SetMode(const Mcu_ModeType McuMode)\r
+/**\r
+ *\r
+ * Application Notes!\r
+ * - AN3584, "MPC5510 Family Low Power Features"\r
+ *   Since it's not complete also check MPC5668\r
+ * - AN4150 , "Using Sleep Mode on the MPC5668x" and it's code\r
+ *\r
+ *\r
+ * @param LPM\r
+ */\r
+static void enterLowPower (Mcu_ModeType mcuMode )\r
+{\r
+#if defined(CFG_MCU_SUPPORT_SLEEP_MODE)\r
+\r
+#if defined(CFG_MPC5668)\r
+       uint32 timeout;\r
+       /* Set the sleep bit; following a WAIT instruction, the device will go to sleep */\r
+       CRP.PSCR.B.SLEEP = 1;\r
+\r
+       /* 0x1 32k, 0x2 64k, 0x3 128k -- RAMs maintain power */\r
+       CRP.PSCR.B.RAMSEL = 0x3;                // Keep all 128K\r
+\r
+       CRP.Z6VEC.R = (uint32)&McuE_LowPowerRecoverFlash;\r
+#if defined(CFG_VLE)\r
+       CRP.Z6VEC.VLE = 1;\r
+#endif\r
+\r
+       /* If we "Mcu_Wakeup()" is located in RAM, set FASTREC */\r
+       CRP.RECPTR.B.FASTREC = 0;\r
+\r
+       /* Halt everything */\r
+    SIU.HLT0.R = 0x037FFF3D;\r
+    SIU.HLT1.R = 0x18000F3C;\r
+    while((SIU.HLTACK0.R != 0x037FFF3D) && (SIU.HLTACK1.R != 0x18000F3C) && (timeout<3000)){}\r
+\r
+       /* put Z0 in reset if not used for wakeup */\r
+       CRP.Z0VEC.B.Z0RST = 1;\r
+\r
+       // TODO: Enable_all_internal_pull_devices (PULL_DOWN);\r
+\r
+       /* Save context and execute wait instruction.\r
+        *\r
+        * Things that matter here are\r
+        * - Z1VEC, determines where TLB0 will point. TLB0 is written with a\r
+        *   value at startup that 4K aligned to this address.\r
+        * - LowPower_Sleep() will save a interrupt context so we will return\r
+        *   intact.\r
+        * - For devices with little RAM we don't want to impose the alignment\r
+        *   requirements there. Almost as we have to occupy a 4K block for this..\r
+        *   although the code does not take that much space.\r
+        * */\r
+       McuE_EnterLowPower(mcuMode);\r
+\r
+    /* Clear sleep flags to allow pads to operate */\r
+       CRP.PSCR.B.SLEEPF = 0x1;\r
+\r
+#elif defined(CFG_MPC5516)\r
+       uint32 timeout;\r
+       /* Set the sleep bit; following a WAIT instruction, the device will go to sleep */\r
+       CRP.PSCR.B.SLEEP = 1;\r
+       /* enable the 1.2V internal regulator when in sleep mode only */\r
+       CRP.PSCR.B.STOP12EN = 1;\r
+       /* 0x1 8k, 0x2 16k, 0x3 32k, 0x6 64k -- RAMs maintain power */\r
+       CRP.PSCR.B.RAMSEL = 0x7;                // Keep all 80K\r
+\r
+       CRP.Z1VEC.R = (uint32)&McuE_LowPowerRecoverFlash;\r
+#if defined(CFG_VLE)\r
+       CRP.VLE = 1;\r
+#endif\r
+\r
+       /* If we "Mcu_Wakeup()" is located in RAM, set FASTREC */\r
+       CRP.RECPRTR.B.FASTREC = 0;\r
+\r
+       /* Halt everything */\r
+       SIU.HLT.R = 0x3FFFFFFF;\r
+       while((SIU.HLTACK.R != 0x3FFFFFFF) && (timeout<3000)) {}\r
+\r
+       /* put Z0 in reset if not used for wakeup */\r
+       CRP.Z0VEC.B.Z0RST = 1;\r
+\r
+       // TODO: Enable_all_internal_pull_devices (PULL_DOWN);\r
+\r
+       /* Save context and execute wait instruction.\r
+        *\r
+        * Things that matter here are\r
+        * - Z1VEC, determines where TLB0 will point. TLB0 is written with a\r
+        *   value at startup that 4K aligned to this address.\r
+        * - LowPower_Sleep() will save a interrupt context so we will return\r
+        *   intact.\r
+        * - For devices with little RAM we don't want to impose the alignment\r
+        *   requirements there. Almost as we have to occupy a 4K block for this..\r
+        *   although the code does not take that much space.\r
+        * */\r
+       McuE_EnterLowPower(mcuMode);\r
+\r
+    /* Clear sleep flags to allow pads to operate */\r
+    CRP.PSCR.B.SLEEPF = 0x1;\r
+#else\r
+       /* NOT SUPPORTED */\r
+       (void) McuMode;\r
+#endif\r
+#endif\r
+}\r
+\r
+\r
+\r
+void Mcu_SetMode( Mcu_ModeType mcuMode)\r
 {\r
+\r
        VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
        // VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
-       (void) McuMode;\r
+#if defined(CFG_MCU_SUPPORT_SLEEP_MODE)\r
+\r
+#if defined(CFG_MPC5516) || defined(CFG_MPC5668)\r
+       if( MCU_MODE_RUN == mcuMode ) {\r
+\r
+       } else if( MCU_MODE_SLEEP == mcuMode ) {\r
+               /*\r
+                * Follows the AN3548 from Freescale\r
+                *\r
+                */\r
+#if defined(USE_DMA)\r
+               Dma_StopAll();\r
+#endif\r
+\r
+\r
+               /* Set system clock to 16Mhz IRC */\r
+               SIU.SYSCLK.B.SYSCLKSEL = 0;\r
+\r
+               /* Put flash in low-power mode */\r
+               // TODO\r
+\r
+               /* Put QQADC in low-power mode */\r
+               // TODO\r
+\r
+               /* Set us in SLEEP mode */\r
+               CRP.PSCR.B.SLEEP = 1;\r
 \r
+\r
+               enterLowPower(mcuMode);\r
+       }\r
+#else\r
        /* NOT SUPPORTED */\r
+       (void) McuMode;\r
+#endif\r
+#endif\r
 }\r
 \r
 //-------------------------------------------------------------------\r