cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtl871x_pwrctrl.c (6669B)


      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
     26void 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
     58void 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 */
     86void 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
    105static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
    106{
    107		pwrctrl->alives |= tag;
    108}
    109
    110static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
    111{
    112	if (pwrctrl->alives & tag)
    113		pwrctrl->alives ^= tag;
    114}
    115
    116static 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
    126static 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
    140static 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
    155static 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
    163void 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 */
    190int 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 */
    211void 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}
    227
    228void r8712_flush_rwctrl_works(struct _adapter *padapter)
    229{
    230	struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
    231
    232	flush_work(&pwrctrl->SetPSModeWorkItem);
    233	flush_work(&pwrctrl->rpwm_workitem);
    234}