#ifdef CRANE_MCU_DONGLE /*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====* paltform_pmu.c GENERAL DESCRIPTION This file is for Power management. EXTERNALIZED FUNCTIONS INITIALIZATION AND SEQUENCING REQUIREMENTS Copyright (c) 2019 by ASR, Incorporated. All Rights Reserved. *====*====*====*====*====*====*====*====*====*====*====*====*====*====*====* *=========================================================================== EDIT HISTORY FOR MODULE This section contains comments describing changes made to the module. Notice that changes are listed in reverse chronological order. when who what, where, why -------- ------ ---------------------------------------------------------- 05/30/2013 zhoujin Created module ===========================================================================*/ /*=========================================================================== INCLUDE FILES FOR MODULE ===========================================================================*/ #include "osa.h" #include "utils.h" #include "intc.h" #include "sdio.h" #include "cpmu_def.h" #include "utilities.h" #include "usb_macro.h" #include "platform.h" #include "mvUsbLog.h" #include "qspi_dma.h" #include "cgpio.h" #include "Intc_Hw_TTC.h" #include "quec_cust_feature.h" /*=========================================================================== LOCAL MACRO ===========================================================================*/ /*=========================================================================== LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE This section contains local definitions for constants, macros, types, variables and other items needed by this module. ===========================================================================*/ /* Enter D2 count */ char D2EntryCnt = 0; /* System sleep enable flag */ #if defined(QUEC_POWER_MANAGER_ENABLE) //移远代码禁止默认进休眠 BOOL SystemSleepEnable_flag = FALSE; #else BOOL SystemSleepEnable_flag = TRUE; #endif UINT32 g_TS_last_D2Recover=0; /*=========================================================================== EXTERN DEFINITIONS AND DECLARATIONS FOR MODULE ===========================================================================*/ /* PM usb busy flag */ extern volatile UINT32 pm_usb_busy; /* UART busy flag */ extern unsigned int uart_busy_flag; /* usb suspend flag */ extern volatile BOOL g_flag_usb_suspend; /*=========================================================================== EXTERNAL FUNCTION DEFINITIONS ===========================================================================*/ #if !defined(LTEONLY_THIN_SINGLE_SIM_2MFLASH) extern int psram_fast_refresh_exit(void); extern int psram_fast_refresh_entry(void); #endif #ifdef BT_SUPPORT extern int get_bt2host_gpio_no(void); #endif extern UINT8 GetUsbPmLock(void); extern int bt_wakelock_status(void); extern void USB2ShutdownPhyClock(void); extern UINT8 sdio_work(void); extern BOOL CraneLAdcWork(void); extern int uartdrv_work(void); #ifdef WIFI_FUNCTION_SUPPORT extern int get_sdio2host_gpio_no(void); #endif #ifdef GPS_SUPPORT extern unsigned char get_gps_pm_lock_stub(void); #endif #ifdef SPINOR_SUPPORT extern BOOL spinor_dma_work(void); #endif #ifdef SPIDRV_SUPPORT extern BOOL spidrv_dma_work(void); #endif /*=========================================================================== INTERNAL FUNCTION DEFINITIONS ===========================================================================*/ #if defined(BT_SUPPORT) || defined(WIFI_FUNCTION_SUPPORT) BOOL GPIOWakeupEnable(int pin) { volatile UINT32 temp = 0; unsigned int addr = 0xD401E0DC; // address of GPIO 0 switch(pin) { case 1: addr = 0xD401E0E0; break; case 12: // GPIO 12 addr = 0xD401E10C; break; case 60: // GPIO 60 addr = 0xD401E304; break; case 86: // GPIO 86 addr = 0xD401E1F4; break; case 28: //GPIO 28 addr = 0xD401E14C; break; case 34: //GPIO 34 addr = 0xD401E164; break; default: return FALSE; } temp = BU_REG_READ(addr); temp = (temp | BIT_4 | BIT_5) & (~BIT_6); BU_REG_WRITE(addr, temp); return TRUE; } BOOL GPIOWakeupDisable(int pin) { volatile UINT32 temp = 0; unsigned int addr = 0xD401E0DC; // address of GPIO 0 switch(pin) { case 1: addr = 0xD401E0E0; break; case 12: // GPIO 12 addr = 0xD401E10C; break; case 60: // GPIO 60 addr = 0xD401E304; break; case 86: // GPIO 86 addr = 0xD401E1F4; break; case 28: //GPIO 28 addr = 0xD401E14C; break; case 34: //GPIO 34 addr = 0xD401E164; break; default: return FALSE; } temp = BU_REG_READ(addr); temp = temp | BIT_6; BU_REG_WRITE(addr, temp); return TRUE; } #endif /*FUNCTION*------------------------------------------------------------- * * Function Name : CommPMVbusDetect * Returned Value : None * Comments : * check Vbus detect bit * *END*-----------------------------------------------------------------*/ BOOL CommPMVbusDetect(void) { /* Check Vbus on bit.*/ if((*(volatile UINT32 *)PMUA_SD_ROT_WAKE_CLR) & VBUS_DETECT) { return TRUE; } else { return FALSE; } } /*FUNCTION*------------------------------------------------------------- * * Function Name : CommPMUsbWakeupHandle * Returned Value : None * Comments : * Services transaction complete interrupt * *END*-----------------------------------------------------------------*/ void CommPMUsbWakeupHandle(int state) { volatile UINT32 wakeup_src; /*Management WakeUp Event*/ wakeup_src = BU_REG_READ(PMUM_CWUCRS) & BU_REG_READ(PMUM_CWUCRM); /* Check whether it is USB wakeup source or not.*/ if(wakeup_src&(0x1<<5)) { #ifdef CRANELS_SUPPORT if(IsChipCraneLS()) { volatile UINT32 irqPending = 0, int_number = 0; if( (irqPending = InterruptController.own.ICU_IRQ_PENDING) & ICU_PENDING_INT_VALID_BITS_CRANE) { // identify the SOURCE interrupt int_number = irqPending & ICU_PENDING_INT_NUM_BITS_CRANE; // USB int number: 44, bt ipc int number: 23 if(int_number != (INTC_SRC_USB - INTC_SRC_XIRQ)) { return; } } } #endif #ifdef NO_USB_VBUS pm_usb_busy = 1; if(state) { USB_TRACE("C1WK"); //USB_TRACE("C1: usb wakeup"); } else { USB_TRACE("D2WK"); //USB_TRACE("D2: usb wakeup"); } #else pm_usb_busy = 1; /* Check Vbus on bit.*/ if(CommPMVbusDetect()) { if(state) { USB_TRACE("C1WK"); //USB_TRACE("C1: usb wakeup"); } else { USB_TRACE("D2WK"); //USB_TRACE("D2: usb wakeup"); } } else { //pm_usb_busy = 0; if(state) { USB_TRACE("C1OFF");//USB_TRACE("C1: usb vbus off"); } else { USB_TRACE("D2OFF"); //USB_TRACE("D2: usb vbus off"); } } #endif } } /*FUNCTION*------------------------------------------------------------- * * Function Name : CommPMEnableUsbWakeupSource * Returned Value : None * Comments : * Services transaction complete interrupt * *END*-----------------------------------------------------------------*/ void CommPMEnableUbusWakeupSource(void) { volatile UINT32 temp = 0; /* USB wakeup */ temp = BU_REG_READ(PMUM_CPCR); temp &= ~(PMUM_CPCR_SLPWP5); BU_REG_WRITE(PMUM_CPCR, temp); temp = BU_REG_READ(PMUM_CWUCRM); temp |= PMUM_CWUCRM_WAKEUP5; BU_REG_WRITE(PMUM_CWUCRM, temp); /* Clear USB interrupt */ /* Only clear line status wakeup interrupt, vbus must not */ temp = BU_REG_READ(PMUA_SD_ROT_WAKE_CLR); BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, temp | (USB_LINEST_WK_CLR)); /* Enable line0 status wakeup under C1 only under usb suspend */ #ifdef NO_USB_VBUS if(g_flag_usb_suspend == TRUE) BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN | VBUS_VALID_WK_EN)) | LINEST0_WK_EN); #else /*enable usb wakeup source */ if(CommPMVbusDetect()) { if(g_flag_usb_suspend == TRUE) { /* Enable wakeup source, vbus and line0(only under usb suspend) */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN)) | (LINEST0_WK_EN | VBUS_VALID_WK_EN)); } else { /* Enable wakeup source, vbus only */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST0_WK_EN | LINEST1_WK_EN)) | (VBUS_VALID_WK_EN)); } } else { /* Enable wakeup source, vbus only */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST0_WK_EN | LINEST1_WK_EN)) | (VBUS_VALID_WK_EN)); } #endif } /*FUNCTION*------------------------------------------------------------- * * Function Name : CommPMDisableUbusWakeupSource * Returned Value : None * Comments : * Services transaction complete interrupt * *END*-----------------------------------------------------------------*/ void CommPMDisableUbusWakeupSource(void) { volatile UINT32 temp = 0; temp = BU_REG_READ(PMUA_SD_ROT_WAKE_CLR); #ifdef NO_USB_VBUS /* Disable line status and Vbus wakeup */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN | VBUS_VALID_WK_EN | LINEST0_WK_EN))); #else /* Disable line status wakeup, enable vbus only */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST0_WK_EN | LINEST1_WK_EN)) | (VBUS_VALID_WK_EN)); #endif /* Mask usb wake up source.*/ temp = BU_REG_READ(PMUM_CWUCRM); temp &= ~(PMUM_CWUCRM_WAKEUP5); BU_REG_WRITE(PMUM_CWUCRM, temp); temp = BU_REG_READ(PMUM_CPCR); temp |= (PMUM_CPCR_SLPWP5); BU_REG_WRITE(PMUM_CPCR, temp); } void CommPMEnableUsbWakeupSource(void) { volatile UINT32 temp = 0; /* USB wakeup */ temp = BU_REG_READ(PMUM_CPCR); temp &= ~(PMUM_CPCR_SLPWP5); BU_REG_WRITE(PMUM_CPCR, temp); temp = BU_REG_READ(PMUM_CWUCRM); temp |= PMUM_CWUCRM_WAKEUP5; BU_REG_WRITE(PMUM_CWUCRM, temp); #if (defined(CRANELS_SUPPORT) || defined(CRANELG_SUPPORT)) /* GNSS WAKEUP HOST(WKSRC29) */ temp = BU_REG_READ(PMUM_CPCR); temp &= ~(PMUM_CPCR_SLPWP0); BU_REG_WRITE(PMUM_CPCR, temp); temp = BU_REG_READ(PMUM_CWUCRM); temp |= PMUM_CWUCRM_GSM_WAKEUPWMX; BU_REG_WRITE(PMUM_CWUCRM, temp); #endif /* CRANELS_SUPPORT || CRANELG_SUPPORT*/ #if defined(BT_SUPPORT) || defined(WIFI_FUNCTION_SUPPORT) /* GPIO wakeup */ temp = BU_REG_READ(PMUM_CPCR); temp &= ~(PMUM_CPCR_SLPWP2); BU_REG_WRITE(PMUM_CPCR, temp); temp = BU_REG_READ(PMUM_CWUCRM); temp |= PMUM_CWUCRM_WAKEUP2; BU_REG_WRITE(PMUM_CWUCRM, temp); #endif /* Clear USB interrupt */ temp = BU_REG_READ(PMUA_SD_ROT_WAKE_CLR); BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, temp | (USB_VBUS_WK_CLR | USB_LINEST_WK_CLR)); #ifdef NO_USB_VBUS /* Enable line0 status wakeup under D2 */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN | VBUS_VALID_WK_EN)) | LINEST0_WK_EN); #else if(CommPMVbusDetect()) { /* Enable wakeup source, vbus and line0 under D2 */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN)) | (LINEST0_WK_EN | VBUS_VALID_WK_EN)); } else { /* Enable wakeup source, vbus only */ BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST0_WK_EN | LINEST1_WK_EN)) | (VBUS_VALID_WK_EN)); } #endif #ifdef BT_SUPPORT { int no = get_bt2host_gpio_no(); if(no > 0) { GPIOWakeupEnable(no); } } #endif #ifdef WIFI_FUNCTION_SUPPORT GPIOWakeupEnable(get_sdio2host_gpio_no()); #endif } /*FUNCTION*------------------------------------------------------------- * * Function Name : CommPMDisableUsbWakeupSource * Returned Value : None * Comments : * Services transaction complete interrupt * *END*-----------------------------------------------------------------*/ void CommPMDisableUsbWakeupSource(void) { volatile UINT32 temp = 0; temp = BU_REG_READ(PMUA_SD_ROT_WAKE_CLR); #ifdef NO_USB_VBUS BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST1_WK_EN | VBUS_VALID_WK_EN | LINEST0_WK_EN))); //disable line status wakeup #else BU_REG_WRITE(PMUA_SD_ROT_WAKE_CLR, (temp & ~(LINEST0_WK_EN | LINEST1_WK_EN)) | (VBUS_VALID_WK_EN)); //disable line status wakeup, enable vbus only #endif /* Mask usb wake up source.*/ temp = BU_REG_READ(PMUM_CWUCRM); temp &= ~(PMUM_CWUCRM_WAKEUP5); BU_REG_WRITE(PMUM_CWUCRM, temp); temp = BU_REG_READ(PMUM_CPCR); temp |= (PMUM_CPCR_SLPWP5); BU_REG_WRITE(PMUM_CPCR, temp); #if (defined(CRANELS_SUPPORT) || defined(CRANELG_SUPPORT)) /* Mask GNSS->Host WKSRC29*/ temp = BU_REG_READ(PMUM_CWUCRM); temp &= ~(PMUM_CWUCRM_GSM_WAKEUPWMX); BU_REG_WRITE(PMUM_CWUCRM, temp); temp = BU_REG_READ(PMUM_CPCR); temp |= (PMUM_CPCR_SLPWP0); BU_REG_WRITE(PMUM_CPCR, temp); #endif #if defined(BT_SUPPORT) || defined(WIFI_FUNCTION_SUPPORT) /* Mask GPIO wake up source.*/ temp = BU_REG_READ(PMUM_CWUCRM); temp &= ~(PMUM_CWUCRM_WAKEUP2); BU_REG_WRITE(PMUM_CWUCRM, temp); temp = BU_REG_READ(PMUM_CPCR); temp |= (PMUM_CPCR_SLPWP2); BU_REG_WRITE(PMUM_CPCR, temp); #ifdef BT_SUPPORT { int no = get_bt2host_gpio_no(); if(no > 0) { GPIOWakeupDisable(no); } } #endif #ifdef WIFI_FUNCTION_SUPPORT GPIOWakeupDisable(get_sdio2host_gpio_no()); #endif #endif } /*=========================================================================== FUNCTION PlatformC1Prepare DESCRIPTION This function consists of the platform internal C1 preparations.. DEPENDENCIES None. RETURN VALUE none SIDE EFFECTS none ===========================================================================*/ void PlatformC1Prepare(void) { CommPMEnableUbusWakeupSource(); return; } /*=========================================================================== FUNCTION PlatformC1Recover DESCRIPTION This function consists of the platform internal C1 recovery. DEPENDENCIES None. RETURN VALUE none SIDE EFFECTS none ===========================================================================*/ void PlatformC1Recover(void) { CommPMUsbWakeupHandle(1); CommPMDisableUbusWakeupSource(); return; } /*=========================================================================== FUNCTION PlatformD2Prepare DESCRIPTION This function consists of the platform internal D2 preparations.. DEPENDENCIES None. RETURN VALUE none SIDE EFFECTS none ===========================================================================*/ #ifndef MIN_SYS #ifdef QUEC_QSCLKEX_ENABLE #include "quec_power_manager.h" extern quec_qsclk_ex_s qsclkex_cfg; #endif #endif void PlatformD2Prepare(void) { if(D2EntryCnt == 0) { #ifdef NO_USB_VBUS if(pm_usb_busy == 0) { /* shutdown usb phy clock if system bring up without usb plugin */ USB2ShutdownPhyClock(); } #endif D2EntryCnt = 1; USB_TRACE("->Enter D2"); } if (!IsMiniSystem()) { #ifndef MIN_SYS extern GPIOReturnCode GpioEnableEdgeDetection_wakeup(UINT32 portHandle,GPIOTransitionType edge); extern char quec_uart_get_wakeup_mode_flag(UART_Port port); extern void quec_aotu_flow_Disable(UART_Port portNumber); extern void* quec_get_gpio_wu_hisr(int gpio_num); if(quec_uart_get_wakeup_mode_flag(UART_PORT_STUART)&&(!quec_get_gpio_wu_hisr(51))) { GpioEnableEdgeDetection_wakeup(51,GPIO_TWO_EDGE);//在GpioCommonWakeupCallback关闭边沿检测这里再打开 pony add 2023 11 07 } quec_aotu_flow_Disable(UART_PORT_STUART); #ifdef QUEC_QSCLKEX_ENABLE if(TRUE == qsclkex_cfg.en) { quec_rrc_release_faster_handle(); //sleep not run,punish_remain_time is stop } #endif #endif } CommPMEnableUsbWakeupSource(); #ifndef QUECTEL_PROJECT_CUST /* Enable Edge detect wakeup interrupt. */ INTCEnable(INTC_SRC_ICU_RESERVED9); #endif #if !defined(LTEONLY_THIN_SINGLE_SIM_2MFLASH) psram_fast_refresh_exit(); #endif #ifdef NO_USB_VBUS /* shut down usb phy clk again after usb pluged out*/ if((pm_usb_busy ==0) && (USB2_PHY_PLL_READY())) { USB2ShutdownPhyClock(); } #endif //USB_TRACE("D2P"); return; } /*=========================================================================== FUNCTION PlatformD2Recover DESCRIPTION This function consists of the platform internal D2 recovery. DEPENDENCIES None. RETURN VALUE none SIDE EFFECTS none ===========================================================================*/ void PlatformD2Recover(void) { volatile UINT32 wakeup_src; #if !defined(LTEONLY_THIN_SINGLE_SIM_2MFLASH) psram_fast_refresh_entry(); #endif g_TS_last_D2Recover = get_current_TStimer_tick(); wakeup_src = BU_REG_READ(PMUM_CWUCRS) & BU_REG_READ(PMUM_CWUCRM); USB_TRACE("D2R,Src:%x",wakeup_src); CommPMUsbWakeupHandle(0); CommPMDisableUsbWakeupSource(); return; } /*=========================================================================== FUNCTION PlatformPmLock DESCRIPTION This function get platform work lock flag. DEPENDENCIES None. RETURN VALUE none SIDE EFFECTS none ===========================================================================*/ #if defined(QUEC_POWER_MANAGER_ENABLE) #include "qspi_dma.h" #endif #ifdef QUEC_CAMERA_SUPPORT unsigned int cam_dma_busy_flag = 0; void SleepFlag_CAM_DMA_Set(UINT8 flag) { if(flag) cam_dma_busy_flag= 1; else cam_dma_busy_flag = 0; return; } unsigned int QuecCameraIsWork (void) { return cam_dma_busy_flag; } #endif #if defined(QUEC_GPS_SUPPORT) extern unsigned char get_gps_pm_lock(void); static char get_gps_lock(void) { if(!IsMiniSystem()){ return get_gps_pm_lock(); }else{ return 0; } } #endif BOOL PlatformWorkLock(void) { if (uart_busy_flag || GetUsbPmLock() || SDWork() || sdio_work() #if defined(DM_SOC_ADC_SUPPORT) || CraneLAdcWork() #endif #if defined(QUEC_GPS_SUPPORT) || get_gps_lock() #endif #if defined(QUEC_POWER_MANAGER_ENABLE) || dma_wakelock() #endif #ifdef QUEC_CAMERA_SUPPORT || QuecCameraIsWork() #endif ) { return TRUE; } else { return FALSE; } } #endif void quec_set_sleep_flag(char flag) { SystemSleepEnable_flag = flag; }