PWRBTN_PCF.c
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:16k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. //
  2. // Copyright (c) Microsoft Corporation.  All rights reserved.
  3. //
  4. //
  5. // Use of this source code is subject to the terms of the Microsoft end-user
  6. // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
  7. // If you did not accept the terms of the EULA, you are not authorized to use
  8. // this source code. For a copy of the EULA, please see the LICENSE.RTF on your
  9. // install media.
  10. //
  11. /* ++
  12.     PCF50606 Power Supply Controller & Battery Management
  13.     Notes:
  14.     ======
  15.     o) I2c client
  16. -- */
  17. #include <windows.h>
  18. #include <nkintr.h>
  19. #include <windev.h>
  20. #include <winbase.h>
  21. #include "oalintr.h"
  22. #include "pwr.h"
  23. static DWORD PWR_IST(LPVOID Context);
  24. // Make sure the driver builds OK in tinykern configuration
  25. HMODULE g_hMod = NULL;
  26. typedef void (*PFN_GwesPowerOffSystem)(void);
  27. PFN_GwesPowerOffSystem g_pfnGwesPowerOffSystem = NULL;
  28. // 
  29. // Write PCF50606 registers directly from our cache
  30. //
  31. DWORD
  32. HW_WriteRegisters(
  33.     PPWR_CONTEXT pPWR,
  34.     PUCHAR pBuff,   // Optional buffer
  35.     UCHAR StartReg, // start register
  36.     DWORD nRegs     // number of registers
  37.     )
  38. {
  39.     return 1;
  40. }
  41. /* ++
  42. Setup the regulators/converters.
  43. Currenly uses default settings.
  44. TODO: determine if we can lower anything.
  45. -- */
  46. DWORD
  47. HW_InitRegulators(
  48.     PPWR_CONTEXT    pPWR
  49.     )
  50. {
  51.     return 1;
  52. }
  53. #define ENABLE  TRUE
  54. #define DISABLE FALSE
  55. DWORD
  56. HW_InitCharger(
  57.     PPWR_CONTEXT    pPWR,
  58.     UCHAR           ucMode,
  59.     UCHAR           ucFlags,
  60.     BOOL            bEnable
  61.     )
  62. {
  63.     return 1;
  64. }
  65. DWORD
  66. HW_InitRegisters(
  67.     PPWR_CONTEXT pPWR
  68.     )
  69. {
  70.     DWORD retry = 0;
  71. // EINT0, GPF0 Port Init
  72. IOPreg * v_pIOPregs;
  73. v_pIOPregs = (volatile IOPreg *)VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
  74. VirtualCopy((PVOID)v_pIOPregs, (PVOID)(IOP_BASE), sizeof(IOPreg), PAGE_READWRITE | PAGE_NOCACHE);
  75. v_pIOPregs->rGPFCON  &= ~(0x3 << 0); /* Set EINT0(GPF0) as EINT0 */
  76. v_pIOPregs->rGPFCON  |=  (0x2 << 0);
  77.     v_pIOPregs->rEXTINT0 &= ~(0x7 << 0); /* Configure EINT0 as Falling Edge Mode */
  78.     v_pIOPregs->rEXTINT0 |=  (0x4 << 0);
  79. VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
  80. // EINT0, GPF0 Port Init Done
  81.     EnterCriticalSection(&pPWR->RegCS);
  82.     // init DRV_GLOBAL
  83.     pPWR->pDriverGlobals->power.State   = PCF50606_STATE_IDLE;
  84.     pPWR->pDriverGlobals->power.Error   = ERROR_SUCCESS;
  85.     pPWR->pDriverGlobals->power.ACLineStatus = 0;
  86. pPWR->pDriverGlobals->power.ACLineStatus |= AC_LINE_BACKUP_POWER;
  87. pPWR->pDriverGlobals->power.ACLineStatus |= AC_LINE_ONLINE;
  88.     pPWR->pDriverGlobals->power.BatteryFlag  = 0;
  89. pPWR->pDriverGlobals->power.BatteryFlag |=  BATTERY_FLAG_CHARGING;
  90.     
  91.     pPWR->pDriverGlobals->power.bADCC1   = 0;
  92.     pPWR->pDriverGlobals->power.bADCC2   = 0;
  93.     pPWR->pDriverGlobals->power.bADCDAT1 = 0;
  94.     pPWR->pDriverGlobals->power.bADCDAT2 = 0;
  95.     pPWR->pDriverGlobals->power.bADCDAT3 = 0;
  96.     LeaveCriticalSection(&pPWR->RegCS);
  97.         
  98.     return 0;
  99. }
  100. /* ++
  101.     The reset value of the PCF50606 INTxM registers is 0: Interrupt enabled.
  102.     Once we enable the interrupt they start firing unless we mask them _before_
  103.     enabeling the interrupt(s).
  104.     
  105. -- */
  106. DWORD
  107. HW_Init(
  108.     PPWR_CONTEXT pPWR
  109.     )
  110. {
  111.     DWORD dwErr = ERROR_SUCCESS;
  112.     BOOL    Ret;
  113. pPWR->pDriverGlobals = NULL;
  114. RETAILMSG(1, (TEXT("HW_Init : GetProcAddress rn"), dwErr));
  115.     //  Load GwesPowerOffSystem from coredll
  116.     g_hMod = LoadLibraryEx(L"coredll.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
  117.     if(g_hMod) {
  118.         g_pfnGwesPowerOffSystem = (PFN_GwesPowerOffSystem) GetProcAddress(g_hMod, L"GwesPowerOffSystem");
  119.         if(!g_pfnGwesPowerOffSystem) {
  120.             FreeLibrary(g_hMod);
  121.             g_hMod = NULL;
  122.         }
  123.     }
  124.     
  125. RETAILMSG(1, (TEXT("HW_Init : ERROR_INVALID_PARAMETER rn")));
  126.     if ( !pPWR )
  127.         return ERROR_INVALID_PARAMETER;
  128.         
  129. RETAILMSG(1, (TEXT("HW_Init : InitializeCriticalSection rn")));
  130.     InitializeCriticalSection(&pPWR->RegCS);
  131. RETAILMSG(1, (TEXT("HW_Init : VirtualAlloc rn")));
  132.     // map in DRV_GLOB
  133.     if ( pPWR->pDriverGlobals == NULL )
  134.     {
  135.         pPWR->pDriverGlobals =
  136.             (PDRIVER_GLOBALS)
  137.                   VirtualAlloc( 0,
  138.                                 DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
  139.                                 MEM_RESERVE,
  140.                                 PAGE_NOACCESS
  141.                               );
  142.         if ( pPWR->pDriverGlobals == NULL )
  143.         {
  144.             RETAILMSG( 1, (TEXT( "pPWR->pDriverGlobals: VirtualAlloc failed!rn")) );
  145.         goto _error_exit;
  146.         }
  147.         Ret = VirtualCopy( (LPVOID)pPWR->pDriverGlobals,
  148.                            (LPVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
  149.                            DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
  150.                            PAGE_READWRITE | PAGE_NOCACHE
  151.                            );
  152.         if ( Ret == FALSE )
  153.         {
  154.             RETAILMSG( 1, (TEXT( "pPWR->pDriverGlobals: VirtualCopy failed!rn")) );
  155.         goto _error_exit;
  156.         }
  157.     }
  158. RETAILMSG(1, (TEXT("HW_Init : pPWR->State rn")));
  159.     // Init H/W
  160.     pPWR->State = INITIALIZE;
  161.     
  162.     RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters rn"), dwErr));
  163. dwErr = HW_InitRegisters(pPWR);
  164.     if ( dwErr ) {
  165.     RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters  Error rn"), dwErr));
  166.         goto _error_exit;
  167.     }
  168.     //
  169.     // create PWR_IST
  170.     //
  171.     RETAILMSG(1, (TEXT("HW_Init : CreateEvent rn"), dwErr));
  172.     if ( (pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
  173.         dwErr = GetLastError();
  174.         RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST event: %u rn"), dwErr));
  175.         goto _error_exit;
  176.     }
  177.     RETAILMSG(1, (TEXT("HW_Init : InterruptInitialize rn"), dwErr));
  178.     if( !InterruptInitialize(SYSINTR_POWER, pPWR->ISTEvent, NULL, 0) ) {
  179.         dwErr = GetLastError();
  180.         RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to initialize interrupt: %urn"), dwErr));
  181.         goto _error_exit;
  182.     }
  183.     RETAILMSG(1, (TEXT("HW_Init : CreateThread rn"), dwErr));
  184.     if ( (pPWR->IST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PWR_IST, pPWR, 0, NULL)) == NULL) {
  185.         dwErr = GetLastError();
  186.         RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST: %urn"), dwErr));
  187.         goto _error_exit;
  188.     }
  189.     
  190.     RETAILMSG(1, (TEXT("HW_Init : CeSetThreadPriority rn"), dwErr));
  191.     // TODO: registry override
  192.     if ( !CeSetThreadPriority(pPWR->IST, POWER_THREAD_PRIORITY)) {
  193.         dwErr = GetLastError();
  194.         RETAILMSG(1, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d rn"), dwErr));
  195.         goto _error_exit;
  196.     }
  197.     pPWR->State = RUN;
  198.     // Finally, after we are initialized dispatch any unmasked interrupts 
  199.     // we may have missed during system start up. We do this because the INTx
  200.     // registers are cleared on read.
  201.     if ( !dwErr ) 
  202.     {
  203.         RETAILMSG(1,(TEXT("HW_Init OOCS: 0x%.2xrn"), pPWR->ResetReg[0] ));
  204.         RETAILMSG(1,(TEXT("HW_Init INT1: 0x%.2xrn"), pPWR->ResetReg[1]));
  205.         RETAILMSG(1,(TEXT("HW_Init INT2: 0x%.2xrn"), pPWR->ResetReg[2]));
  206.         RETAILMSG(1,(TEXT("HW_Init INT3: 0x%.2xrn"), pPWR->ResetReg[3]));
  207. //        pPWR->ResetRegReady = TRUE;
  208. //        SetEvent(pPWR->ISTEvent);
  209.     }
  210.     RETAILMSG(1, (TEXT("HW_Init : Donw rn"), dwErr));
  211. _error_exit:
  212.     return dwErr;
  213. }
  214. DWORD
  215. HW_Deinit(
  216.     PPWR_CONTEXT pPWR
  217.     )
  218. {
  219.     if ( !pPWR )
  220.         return ERROR_INVALID_PARAMETER;
  221.     
  222.     RETAILMSG(1,(TEXT("+PWR_Deinit rn")));
  223.     pPWR->State = UNINITIALIZED;
  224.     if (pPWR->hADC && CloseHandle(pPWR->hADC))
  225.         pPWR->hADC = NULL;
  226.     if (pPWR->hTSCPRES && CloseHandle(pPWR->hTSCPRES))
  227.         pPWR->hTSCPRES = NULL;
  228.     if (pPWR->hI2C && pPWR->hI2C != INVALID_HANDLE_VALUE && CloseHandle(pPWR->hI2C))
  229.         pPWR->hI2C = INVALID_HANDLE_VALUE;
  230.     
  231.     InterruptDisable(SYSINTR_POWER);
  232.     if (pPWR->ISTEvent && CloseHandle(pPWR->ISTEvent))
  233.         pPWR->ISTEvent = NULL;
  234.     
  235.     if (pPWR->IST && CloseHandle(pPWR->IST))
  236.         pPWR->IST = NULL;  
  237.     if (pPWR->pDriverGlobals) {
  238.         VirtualFree( pPWR->pDriverGlobals,
  239.                      DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE ,
  240.                      MEM_RELEASE
  241.                     );
  242.         pPWR->pDriverGlobals = NULL;
  243.     }        
  244.     //  Free the coredll instance if we have allocated one
  245.     if(g_hMod) {
  246.         FreeLibrary(g_hMod);
  247.         g_hMod = NULL;
  248.     }
  249.     DeleteCriticalSection(&pPWR->RegCS);
  250.     RETAILMSG(1,(TEXT("-PWR_Deinit rn")));
  251.     return ERROR_SUCCESS;
  252. }
  253. DWORD 
  254. HW_Open(
  255.     PPWR_CONTEXT pPWR
  256.     )
  257. {
  258.     return ERROR_SUCCESS;
  259. }
  260. DWORD 
  261. HW_Close(
  262.     PPWR_CONTEXT pPWR
  263.     )
  264. {
  265.     return ERROR_SUCCESS;
  266. }
  267. BOOL
  268. HW_PowerUp(
  269.     PPWR_CONTEXT pPWR
  270.    )
  271. {
  272.     RETAILMSG(1, (TEXT("PCF: HW_PowerUp rn")));
  273.     pPWR->State = RESUME;
  274.     SetInterruptEvent(SYSINTR_POWER);
  275.     return TRUE;
  276. }
  277. BOOL
  278. HW_PowerDown(
  279.     PPWR_CONTEXT pPWR
  280.    )
  281. {
  282.     pPWR->State = SUSPEND;
  283.     return TRUE;
  284. }
  285. BOOL
  286. HW_PowerCapabilities(
  287.     PPWR_CONTEXT pPWR,
  288.     PPOWER_CAPABILITIES ppc
  289.     )
  290. {
  291.     return TRUE;
  292. }
  293. BOOL
  294. HW_PowerSet(
  295.     PPWR_CONTEXT pPWR,
  296.     PCEDEVICE_POWER_STATE pDx   // IN, OUT
  297.    )
  298. {   
  299.     CEDEVICE_POWER_STATE NewDx = *pDx;
  300.     if ( VALID_DX(NewDx) ) 
  301.     {
  302.         // We only support D0, so do nothing.
  303.         // Just return current state.
  304.         pPWR->Dx = *pDx = D0;
  305.         RETAILMSG(1, (TEXT("PCF: IOCTL_POWER_SET: D%u => D%u rn"), NewDx, pPWR->Dx));
  306.         return TRUE;
  307.     }
  308.     return FALSE;
  309. }
  310. BOOL
  311. HW_PowerGet(
  312.     PPWR_CONTEXT pPWR,
  313.     PCEDEVICE_POWER_STATE pDx
  314.    )
  315. {   
  316.     // return our Current Dx value
  317.     *pDx = pPWR->Dx;
  318.     RETAILMSG(1, (TEXT("PCF: IOCTL_POWER_GET: D%u rn"), pPWR->Dx));
  319.     return TRUE;
  320. }
  321. static DWORD 
  322. PWR_IST(
  323.     PPWR_CONTEXT pPWR
  324.     )
  325. {
  326. int CurrStatus = RUN;
  327.     DWORD we;
  328. WCHAR  state[1024] = {0};
  329. LPWSTR pState = &state[0];
  330. DWORD dwBufChars = (sizeof(state) / sizeof(state[0]));
  331. DWORD  dwStateFlags = 0;
  332. DWORD dwErr;
  333.     
  334.     if (!pPWR)
  335.         return ERROR_INVALID_PARAMETER;
  336.     while (1) {
  337.         __try {
  338.             we = WaitForSingleObject(pPWR->ISTEvent, INFINITE);
  339. RETAILMSG(1,(TEXT("rnPWR_IST: pPWR->State = 0x%x rn"), pPWR->State));
  340. dwErr = GetSystemPowerState(pState, dwBufChars, &dwStateFlags);
  341. if (ERROR_SUCCESS != dwErr) {
  342. RETAILMSG(1, (TEXT("PMGET!GetSystemPowerState:ERROR:%dn"), dwErr));
  343. } else {
  344. RETAILMSG(1, (TEXT("PMGET! System Power state is '%s', flags 0x%08xn"), state, dwStateFlags));
  345. switch (POWER_STATE(dwStateFlags)) {
  346. case POWER_STATE_ON:
  347. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_ONn")));
  348. break;
  349. case POWER_STATE_OFF:
  350. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_OFFn")));
  351. break;
  352. case POWER_STATE_CRITICAL:
  353. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_CRITICALn")));
  354. break;
  355. case POWER_STATE_BOOT:
  356. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_BOOTn")));
  357. break;
  358. case POWER_STATE_IDLE:
  359. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_IDLEn")));
  360. break;
  361. case POWER_STATE_SUSPEND:
  362. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_SUSPENDn")));
  363. break;
  364. case POWER_STATE_RESET:
  365. RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_RESETn")));
  366. break;
  367. case 0:
  368. break;
  369. default:
  370. RETAILMSG(1,(TEXT("PMGET!tUnknown Power State Flags:0x%xn"),dwStateFlags));
  371. ASSERT(0);
  372. break;
  373. }
  374. }
  375.             
  376. switch (pPWR->State) {
  377.                 
  378.                 case RUN:
  379.                     RETAILMSG(1, (TEXT("PWR_IST: RUNrn")));
  380. if (CurrStatus == SUSPEND)
  381. {
  382.                     RETAILMSG(1, (TEXT("CurrStatus == SUSPENDrn")));
  383. pPWR->State = RUN;
  384. CurrStatus = RUN;
  385. // clear any potential pending ADC interrupt
  386. InterruptDone(SYSINTR_POWER);
  387. SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
  388. continue;
  389. }
  390. else if (CurrStatus == RESUME)
  391. {
  392. RETAILMSG(1, (TEXT("CurrStatus == RESUMErn")));
  393. if ( wcscmp(state,TEXT("unattended")) == 0 )
  394. {
  395.                     RETAILMSG(1, (TEXT("Unattended Power Off Modern")));
  396. pPWR->State = RUN;
  397. CurrStatus = SUSPEND;
  398. continue;
  399. }
  400. // else if ( wcscmp(state,TEXT("resuming")) == 0 )
  401. // {
  402. //                     RETAILMSG(1, (TEXT("Still resuming...rn")));
  403. // Sleep(1000);
  404. // SetEvent(pPWR->ISTEvent);
  405. // continue;
  406. // }
  407. else
  408. {
  409.                     RETAILMSG(1, (TEXT("Power Onrn")));
  410. pPWR->State = RUN;
  411. CurrStatus = RUN;
  412. // clear any potential pending ADC interrupt
  413. InterruptDone(SYSINTR_POWER);
  414. SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
  415. continue;
  416. }
  417. }
  418.                     break;
  419.                 case INITIALIZE:
  420.                     // Keep from reading our clear on read INTx registers
  421.                     // during init.
  422.                     RETAILMSG(1, (TEXT("PWR_IST: INITIALIZErn")));
  423.                     Sleep(10);
  424.                     continue;
  425.                     break;
  426.                 case SUSPEND:
  427.                     RETAILMSG(1, (TEXT("PWR_IST: SUSPENDrn")));
  428. //                    continue;
  429.                     break;
  430.                     
  431.                 case RESUME:
  432.                 case ADC_ERROR:
  433.                     RETAILMSG(1,(TEXT("PWR_IST: %s rn"), pPWR->State == RESUME ? L"RESUME" : L"ADC_ERROR" ));
  434.                     pPWR->State = RUN;
  435. CurrStatus = RESUME;
  436.                     // clear any potential pending ADC interrupt
  437. InterruptDone(SYSINTR_POWER);
  438. Sleep(200);
  439. SetEvent(pPWR->ISTEvent);
  440. //                 SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
  441.                     continue;
  442.                     break;
  443.                     
  444.                 case UNINITIALIZED:
  445.                     RETAILMSG(1,(TEXT("PWR_IST: ExitThread rn")));
  446.                     ExitThread(ERROR_SUCCESS);
  447.                     return ERROR_SUCCESS;
  448.                 default:
  449.                     RETAILMSG(1,(TEXT("PWR_IST: unknown state: %urn"), pPWR->State));
  450.                     TEST_TRAP;
  451.                     continue;
  452.                     break;
  453.             }
  454.             //
  455.             // get status
  456.             //
  457. // EnterCriticalSection(&pPWR->RegCS);
  458. //
  459. // if ( !pPWR->ResetRegReady ) {
  460. // } else {
  461. // // get & restore the cleared registers
  462. // pPWR->ResetRegReady = FALSE;
  463. // }
  464.             LeaveCriticalSection(&pPWR->RegCS);
  465.             
  466.             // clear the interrupt before power off
  467.             InterruptDone(SYSINTR_POWER);
  468. CurrStatus = SUSPEND;
  469.             SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE );
  470.         } _except(EXCEPTION_EXECUTE_HANDLER) {
  471.             
  472.             RETAILMSG(1,(TEXT("!!! PWR_IST EXCEPTION: 0x%X !!!rn"), GetExceptionCode() ));
  473.         }
  474. }
  475. }
  476. /* ++
  477.  Get/Set the PCF RTC.
  478.  
  479.  One neat PCF feature is the stand alone RTC.
  480.  You could power the ARM core to full off and maintin the RTC & ALARM on the PCF.
  481.  This is not a required feature for PPC2002 release, but OEMs are 
  482.  free to add this as desired. You should sync the ARM & PCF RTC
  483.  and update as appropriate. If you choose to implement this it would
  484.  be good to power as much of the PCF off as possible to maintin it's RTC
  485.  for much longer time.
  486. -- */
  487. BOOL 
  488. PWR_GetRealTime(
  489.     PPWR_CONTEXT pPWR,
  490.     LPSYSTEMTIME lpst
  491.     )
  492. {
  493.     return TRUE;
  494. }
  495. BOOL
  496. PWR_SetRealTime(
  497.     PPWR_CONTEXT pPWR,
  498.     LPSYSTEMTIME lpst
  499.     ) 
  500. {
  501.     return TRUE;
  502. }
  503. BOOL
  504. HW_IOControl(
  505.     PPWR_CONTEXT pPWR,
  506.     DWORD dwCode,
  507.     PBYTE pBufIn,
  508.     DWORD dwLenIn,
  509.     PBYTE pBufOut,
  510.     DWORD dwLenOut,
  511.     PDWORD pdwActualOut
  512.    )
  513. {
  514. return FALSE;
  515. }