root/drivers/staging/rtl8712/rtl871x_pwrctrl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. r8712_set_rpwm
  2. r8712_set_ps_mode
  3. r8712_cpwm_int_hdl
  4. register_task_alive
  5. unregister_task_alive
  6. _rpwm_check_handler
  7. SetPSModeWorkItemCallback
  8. rpwm_workitem_callback
  9. rpwm_check_handler
  10. r8712_init_pwrctrl_priv
  11. r8712_register_cmd_alive
  12. r8712_unregister_cmd_alive

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  * rtl871x_pwrctrl.c
   4  *
   5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6  * Linux device driver for RTL8192SU
   7  *
   8  * Modifications for inclusion into the Linux staging tree are
   9  * Copyright(c) 2010 Larry Finger. All rights reserved.
  10  *
  11  * Contact information:
  12  * WLAN FAE <wlanfae@realtek.com>
  13  * Larry Finger <Larry.Finger@lwfinger.net>
  14  *
  15  ******************************************************************************/
  16 
  17 #define _RTL871X_PWRCTRL_C_
  18 
  19 #include "osdep_service.h"
  20 #include "drv_types.h"
  21 #include "osdep_intf.h"
  22 
  23 #define RTL8712_SDIO_LOCAL_BASE 0X10100000
  24 #define SDIO_HCPWM (RTL8712_SDIO_LOCAL_BASE + 0x0081)
  25 
  26 void r8712_set_rpwm(struct _adapter *padapter, u8 val8)
  27 {
  28         u8      rpwm;
  29         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
  30 
  31         if (pwrpriv->rpwm == val8) {
  32                 if (pwrpriv->rpwm_retry == 0)
  33                         return;
  34         }
  35         if (padapter->driver_stopped || padapter->surprise_removed)
  36                 return;
  37         rpwm = val8 | pwrpriv->tog;
  38         switch (val8) {
  39         case PS_STATE_S1:
  40                 pwrpriv->cpwm = val8;
  41                 break;
  42         case PS_STATE_S2:/* only for USB normal powersave mode use,
  43                           * temp mark some code.
  44                           */
  45         case PS_STATE_S3:
  46         case PS_STATE_S4:
  47                 pwrpriv->cpwm = val8;
  48                 break;
  49         default:
  50                 break;
  51         }
  52         pwrpriv->rpwm_retry = 0;
  53         pwrpriv->rpwm = val8;
  54         r8712_write8(padapter, 0x1025FE58, rpwm);
  55         pwrpriv->tog += 0x80;
  56 }
  57 
  58 void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, uint smart_ps)
  59 {
  60         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
  61 
  62         if (ps_mode > PM_Card_Disable)
  63                 return;
  64         /* if driver is in active state, we dont need set smart_ps.*/
  65         if (ps_mode == PS_MODE_ACTIVE)
  66                 smart_ps = 0;
  67         if ((pwrpriv->pwr_mode != ps_mode) || (pwrpriv->smart_ps != smart_ps)) {
  68                 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
  69                         pwrpriv->bSleep = true;
  70                 else
  71                         pwrpriv->bSleep = false;
  72                 pwrpriv->pwr_mode = ps_mode;
  73                 pwrpriv->smart_ps = smart_ps;
  74                 schedule_work(&pwrpriv->SetPSModeWorkItem);
  75         }
  76 }
  77 
  78 /*
  79  * Caller:ISR handler...
  80  *
  81  * This will be called when CPWM interrupt is up.
  82  *
  83  * using to update cpwn of drv; and drv will make a decision to up or
  84  * down pwr level
  85  */
  86 void r8712_cpwm_int_hdl(struct _adapter *padapter,
  87                         struct reportpwrstate_parm *preportpwrstate)
  88 {
  89         struct pwrctrl_priv *pwrpriv = &(padapter->pwrctrlpriv);
  90         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
  91 
  92         if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80))
  93                 return;
  94         del_timer(&padapter->pwrctrlpriv.rpwm_check_timer);
  95         mutex_lock(&pwrpriv->mutex_lock);
  96         pwrpriv->cpwm = (preportpwrstate->state) & 0xf;
  97         if (pwrpriv->cpwm >= PS_STATE_S2) {
  98                 if (pwrpriv->alives & CMD_ALIVE)
  99                         complete(&(pcmdpriv->cmd_queue_comp));
 100         }
 101         pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80;
 102         mutex_unlock(&pwrpriv->mutex_lock);
 103 }
 104 
 105 static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
 106 {
 107                 pwrctrl->alives |= tag;
 108 }
 109 
 110 static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
 111 {
 112         if (pwrctrl->alives & tag)
 113                 pwrctrl->alives ^= tag;
 114 }
 115 
 116 static void _rpwm_check_handler (struct _adapter *padapter)
 117 {
 118         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 119 
 120         if (padapter->driver_stopped || padapter->surprise_removed)
 121                 return;
 122         if (pwrpriv->cpwm != pwrpriv->rpwm)
 123                 schedule_work(&pwrpriv->rpwm_workitem);
 124 }
 125 
 126 static void SetPSModeWorkItemCallback(struct work_struct *work)
 127 {
 128         struct pwrctrl_priv *pwrpriv = container_of(work,
 129                                        struct pwrctrl_priv, SetPSModeWorkItem);
 130         struct _adapter *padapter = container_of(pwrpriv,
 131                                     struct _adapter, pwrctrlpriv);
 132         if (!pwrpriv->bSleep) {
 133                 mutex_lock(&pwrpriv->mutex_lock);
 134                 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
 135                         r8712_set_rpwm(padapter, PS_STATE_S4);
 136                 mutex_unlock(&pwrpriv->mutex_lock);
 137         }
 138 }
 139 
 140 static void rpwm_workitem_callback(struct work_struct *work)
 141 {
 142         struct pwrctrl_priv *pwrpriv = container_of(work,
 143                                        struct pwrctrl_priv, rpwm_workitem);
 144         struct _adapter *padapter = container_of(pwrpriv,
 145                                     struct _adapter, pwrctrlpriv);
 146         if (pwrpriv->cpwm != pwrpriv->rpwm) {
 147                 mutex_lock(&pwrpriv->mutex_lock);
 148                 r8712_read8(padapter, SDIO_HCPWM);
 149                 pwrpriv->rpwm_retry = 1;
 150                 r8712_set_rpwm(padapter, pwrpriv->rpwm);
 151                 mutex_unlock(&pwrpriv->mutex_lock);
 152         }
 153 }
 154 
 155 static void rpwm_check_handler (struct timer_list *t)
 156 {
 157         struct _adapter *adapter =
 158                 from_timer(adapter, t, pwrctrlpriv.rpwm_check_timer);
 159 
 160         _rpwm_check_handler(adapter);
 161 }
 162 
 163 void r8712_init_pwrctrl_priv(struct _adapter *padapter)
 164 {
 165         struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
 166 
 167         memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
 168         mutex_init(&pwrctrlpriv->mutex_lock);
 169         pwrctrlpriv->cpwm = PS_STATE_S4;
 170         pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
 171         pwrctrlpriv->smart_ps = 0;
 172         pwrctrlpriv->tog = 0x80;
 173 /* clear RPWM to ensure driver and fw back to initial state. */
 174         r8712_write8(padapter, 0x1025FE58, 0);
 175         INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback);
 176         INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback);
 177         timer_setup(&pwrctrlpriv->rpwm_check_timer, rpwm_check_handler, 0);
 178 }
 179 
 180 /*
 181  * Caller: r8712_cmd_thread
 182  * Check if the fw_pwrstate is okay for issuing cmd.
 183  * If not (cpwm should be is less than P2 state), then the sub-routine
 184  * will raise the cpwm to be greater than or equal to P2.
 185  * Calling Context: Passive
 186  * Return Value:
 187  * 0:       r8712_cmd_thread can issue cmds to firmware afterwards.
 188  * -EINVAL: r8712_cmd_thread can not do anything.
 189  */
 190 int r8712_register_cmd_alive(struct _adapter *padapter)
 191 {
 192         int res = 0;
 193         struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
 194 
 195         mutex_lock(&pwrctrl->mutex_lock);
 196         register_task_alive(pwrctrl, CMD_ALIVE);
 197         if (pwrctrl->cpwm < PS_STATE_S2) {
 198                 r8712_set_rpwm(padapter, PS_STATE_S3);
 199                 res = -EINVAL;
 200         }
 201         mutex_unlock(&pwrctrl->mutex_lock);
 202         return res;
 203 }
 204 
 205 /*
 206  * Caller: ISR
 207  * If ISR's txdone,
 208  * No more pkts for TX,
 209  * Then driver shall call this fun. to power down firmware again.
 210  */
 211 void r8712_unregister_cmd_alive(struct _adapter *padapter)
 212 {
 213         struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
 214 
 215         mutex_lock(&pwrctrl->mutex_lock);
 216         unregister_task_alive(pwrctrl, CMD_ALIVE);
 217         if ((pwrctrl->cpwm > PS_STATE_S2) &&
 218            (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) {
 219                 if ((pwrctrl->alives == 0) &&
 220                     (check_fwstate(&padapter->mlmepriv,
 221                      _FW_UNDER_LINKING) != true)) {
 222                         r8712_set_rpwm(padapter, PS_STATE_S0);
 223                 }
 224         }
 225         mutex_unlock(&pwrctrl->mutex_lock);
 226 }

/* [<][>][^][v][top][bottom][index][help] */