/* * Caller:ISR handler... * * This will be called when CPWM interrupt is up. * * using to update cpwn of drv; and drv willl make a decision to up or down pwr level */ void cpwm_int_hdl( PADAPTER padapter, struct reportpwrstate_parm *preportpwrstate) { struct pwrctrl_priv *pwrpriv; pwrpriv = adapter_to_pwrctl(padapter); down(&pwrpriv->lock); if (pwrpriv->rpwm < PS_STATE_S2) { DBG_871X("%s: Redundant CPWM Int. RPWM =0x%02X CPWM =0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); up(&pwrpriv->lock); goto exit; } pwrpriv->cpwm = PS_STATE(preportpwrstate->state); pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE; if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) up(&padapter->cmdpriv.cmd_queue_sema); if (pwrpriv->alives & XMIT_ALIVE) up(&padapter->xmitpriv.xmit_sema); } up(&pwrpriv->lock); exit: RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("cpwm_int_hdl: cpwm =0x%02x\n", pwrpriv->cpwm)); }
/* * * Parameters * rtlpriv * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm(struct rtl_priv *rtlpriv, uint8_t pslv) { uint8_t rpwm; struct pwrctrl_priv *pwrpriv = &rtlpriv->pwrctrlpriv; pslv = PS_STATE(pslv); if (_TRUE == pwrpriv->btcoex_rfon) { if (pslv < PS_STATE_S4) pslv = PS_STATE_S3; } #ifdef CONFIG_LPS_RPWM_TIMER if (pwrpriv->brpwmtimeout == _TRUE) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv); } else #endif // CONFIG_LPS_RPWM_TIMER { if ( (pwrpriv->rpwm == pslv) ) { return; } } if ((rtlpriv->bSurpriseRemoved == _TRUE) || (rtlpriv->hw_init_completed == _FALSE)) { pwrpriv->cpwm = PS_STATE_S4; return; } if (rtlpriv->bDriverStopped == _TRUE) { if (pslv < PS_STATE_S2) { return; } } rpwm = pslv | pwrpriv->tog; pwrpriv->rpwm = pslv; #ifdef CONFIG_LPS_RPWM_TIMER if (rpwm & PS_ACK) _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS); #endif // CONFIG_LPS_RPWM_TIMER pwrpriv->tog += 0x80; { pwrpriv->cpwm = pslv; } }
/* * * Parameters * padapter * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv) { u8 rpwm; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; pslv = PS_STATE(pslv); if (pwrpriv->btcoex_rfon) { if (pslv < PS_STATE_S4) pslv = PS_STATE_S3; } if (pwrpriv->rpwm == pslv) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv)); return; } if (padapter->bSurpriseRemoved == true || padapter->hw_init_completed == false) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); pwrpriv->cpwm = PS_STATE_S4; return; } if (padapter->bDriverStopped == true) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv)); if (pslv < PS_STATE_S2) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Reject to enter PS_STATE(0x%02X) lower " "than S2 when DriverStopped!!\n", __func__, pslv)); return; } } rpwm = pslv | pwrpriv->tog; RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; rtl8723a_set_rpwm(padapter, rpwm); pwrpriv->tog += 0x80; pwrpriv->cpwm = pslv; }
/* * * Parameters * padapter * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm(PADAPTER padapter, u8 pslv) { u8 rpwm; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; _func_enter_; pslv = PS_STATE(pslv); if (pwrpriv->rpwm == pslv) { RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_, ("%s: Already set rpwm[0x%02x]!\n", __FUNCTION__, pslv)); return; } if ((padapter->bDriverStopped == _TRUE) || (padapter->bSurpriseRemoved == _TRUE)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n", __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved)); return; } rpwm = pslv | pwrpriv->tog; #ifdef CONFIG_LPS_LCLK if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2)) rpwm |= PS_ACK; #endif RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); pwrpriv->tog += 0x80; if (!(rpwm & PS_ACK)) pwrpriv->cpwm = pslv; _func_exit_; }
/* * Caller:ISR handler... * * This will be called when CPWM interrupt is up. * * using to update cpwn of drv; and drv willl make a decision to up or down pwr level */ void cpwm_int_hdl(struct rtw_adapter *padapter, struct reportpwrstate_parm *preportpwrstate) { struct pwrctrl_priv *pwrpriv; pwrpriv = &padapter->pwrctrlpriv; pwrpriv->cpwm = PS_STATE(preportpwrstate->state); pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE; if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) _rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema); if (pwrpriv->alives & XMIT_ALIVE) _rtw_up_sema(&padapter->xmitpriv.xmit_sema); } exit: RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("cpwm_int_hdl: cpwm=0x%02x\n", pwrpriv->cpwm)); }
/* * * Parameters * padapter * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm(PADAPTER padapter, u8 pslv) { u8 rpwm; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; _func_enter_; pslv = PS_STATE(pslv); if (_TRUE == pwrpriv->btcoex_rfon) { if (pslv < PS_STATE_S4) pslv = PS_STATE_S3; } #ifdef CONFIG_LPS_RPWM_TIMER if (pwrpriv->brpwmtimeout == _TRUE) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv); } else #endif // CONFIG_LPS_RPWM_TIMER { if ( (pwrpriv->rpwm == pslv) #ifdef CONFIG_LPS_LCLK #ifndef CONFIG_RTL8723A || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2)) #endif #endif ) { RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_, ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv)); return; } } if ((padapter->bSurpriseRemoved == _TRUE) || (padapter->hw_init_completed == _FALSE)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); pwrpriv->cpwm = PS_STATE_S4; return; } if (padapter->bDriverStopped == _TRUE) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv)); if (pslv < PS_STATE_S2) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv)); return; } } rpwm = pslv | pwrpriv->tog; #ifdef CONFIG_LPS_LCLK // only when from PS_STATE S0/S1 to S2 and higher needs ACK if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2)) rpwm |= PS_ACK; #endif RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; #ifdef CONFIG_LPS_RPWM_TIMER if (rpwm & PS_ACK) _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS); #endif // CONFIG_LPS_RPWM_TIMER rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); pwrpriv->tog += 0x80; #ifdef CONFIG_LPS_LCLK // No LPS 32K, No Ack if (!(rpwm & PS_ACK)) #endif { pwrpriv->cpwm = pslv; } _func_exit_; }
/* * Description: * This function MUST be called under power lock protect * * Parameters * padapter * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm(PADAPTER padapter, u8 pslv) { u8 rpwm; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); u8 cpwm_orig; pslv = PS_STATE(pslv); if (pwrpriv->brpwmtimeout == true) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv); } else { if ((pwrpriv->rpwm == pslv) || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2))) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Already set rpwm[0x%02X], new =0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv)); return; } } if ((padapter->bSurpriseRemoved == true) || (padapter->hw_init_completed == false)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); pwrpriv->cpwm = PS_STATE_S4; return; } if (padapter->bDriverStopped == true) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv)); if (pslv < PS_STATE_S2) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv)); return; } } rpwm = pslv | pwrpriv->tog; /* only when from PS_STATE S0/S1 to S2 and higher needs ACK */ if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2)) rpwm |= PS_ACK; RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_set_rpwm: rpwm =0x%02x cpwm =0x%02x\n", rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; cpwm_orig = 0; if (rpwm & PS_ACK) { rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig); } if (rpwm & PS_ACK) _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS); rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); pwrpriv->tog += 0x80; /* No LPS 32K, No Ack */ if (rpwm & PS_ACK) { unsigned long start_time; u8 cpwm_now; u8 poll_cnt =0; start_time = jiffies; /* polling cpwm */ do { mdelay(1); poll_cnt++; rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now); if ((cpwm_orig ^ cpwm_now) & 0x80) { pwrpriv->cpwm = PS_STATE_S4; pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE; break; } if (jiffies_to_msecs(jiffies - start_time) > LPS_RPWM_WAIT_MS) { DBG_871X("%s: polling cpwm timeout! poll_cnt =%d, cpwm_orig =%02x, cpwm_now =%02x \n", __FUNCTION__, poll_cnt, cpwm_orig, cpwm_now); _set_timer(&pwrpriv->pwr_rpwm_timer, 1); break; } } while (1); } else { pwrpriv->cpwm = pslv; } }
/* * * Parameters * padapter * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 * */ void rtw_set_rpwm(PADAPTER padapter, u8 pslv) { u8 rpwm; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); #ifdef CONFIG_DETECT_CPWM_BY_POLLING u8 cpwm_orig = 0; u8 cpwm_now = 0; u32 cpwm_polling_start_time = 0; u8 pollingRes = _FAIL; #endif _func_enter_; pslv = PS_STATE(pslv); if (_TRUE == pwrpriv->btcoex_rfon) { if (pslv < PS_STATE_S4) pslv = PS_STATE_S3; } #ifdef CONFIG_LPS_RPWM_TIMER if (pwrpriv->brpwmtimeout == _TRUE) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv); } else #endif // CONFIG_LPS_RPWM_TIMER { if ( (pwrpriv->rpwm == pslv) #ifdef CONFIG_LPS_LCLK #ifndef CONFIG_RTL8723A || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2)) #endif #endif ) { RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_, ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv)); return; } } if ((padapter->bSurpriseRemoved == _TRUE) || (padapter->hw_init_completed == _FALSE)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); pwrpriv->cpwm = PS_STATE_S4; return; } if (padapter->bDriverStopped == _TRUE) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv)); if (pslv < PS_STATE_S2) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv)); return; } } rpwm = pslv | pwrpriv->tog; #ifdef CONFIG_LPS_LCLK // only when from PS_STATE S0/S1 to S2 and higher needs ACK if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2)) rpwm |= PS_ACK; #endif RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; #ifdef CONFIG_DETECT_CPWM_BY_POLLING if (rpwm & PS_ACK) { //cpwm_orig = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HCPWM1); rtw_hal_get_hwreg(padapter, HW_VAR_GET_CPWM, (u8 *)(&cpwm_orig)); } #endif #if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING) if (rpwm & PS_ACK) _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS); #endif // CONFIG_LPS_RPWM_TIMER && !CONFIG_DETECT_CPWM_BY_POLLING rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); pwrpriv->tog += 0x80; #ifdef CONFIG_LPS_LCLK // No LPS 32K, No Ack if (!(rpwm & PS_ACK)) #endif { pwrpriv->cpwm = pslv; } #ifdef CONFIG_DETECT_CPWM_BY_POLLING if (rpwm & PS_ACK) { cpwm_polling_start_time = rtw_get_current_time(); //polling cpwm do{ rtw_mdelay_os(1); //cpwm_now = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HCPWM1); rtw_hal_get_hwreg(padapter, HW_VAR_GET_CPWM, (u8 *)(&cpwm_now)); if ((cpwm_orig ^ cpwm_now) & 0x80) { #ifdef CONFIG_LPS_LCLK #ifdef CONFIG_RTL8723A pwrpriv->cpwm = PS_STATE(cpwm_now); #else // !CONFIG_RTL8723A pwrpriv->cpwm = PS_STATE_S4; #endif // !CONFIG_RTL8723A pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE; #endif pollingRes = _SUCCESS; break; } }while (rtw_get_passing_time_ms(cpwm_polling_start_time) < LPS_RPWM_WAIT_MS); if (pollingRes == _FAIL) { #ifdef CONFIG_LPS_RPWM_TIMER _set_timer(&pwrpriv->pwr_rpwm_timer, 1); #endif DBG_871X("%s polling cpwm timeout!!!!!!!!!!\n", __FUNCTION__); } } #endif _func_exit_; }