GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / staging / vt6655 / power.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
4  * All rights reserved.
5  *
6  * File: power.c
7  *
8  * Purpose: Handles 802.11 power management  functions
9  *
10  * Author: Lyndon Chen
11  *
12  * Date: July 17, 2002
13  *
14  * Functions:
15  *      PSvEnablePowerSaving - Enable Power Saving Mode
16  *      PSvDiasblePowerSaving - Disable Power Saving Mode
17  *      PSbConsiderPowerDown - Decide if we can Power Down
18  *      PSvSendPSPOLL - Send PS-POLL packet
19  *      PSbSendNullPacket - Send Null packet
20  *      PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
21  *
22  * Revision History:
23  *
24  */
25
26 #include "mac.h"
27 #include "device.h"
28 #include "power.h"
29 #include "card.h"
30
31 /*---------------------  Static Definitions -------------------------*/
32
33 /*---------------------  Static Classes  ----------------------------*/
34
35 /*---------------------  Static Functions  --------------------------*/
36
37 /*---------------------  Export Variables  --------------------------*/
38
39 /*---------------------  Export Functions  --------------------------*/
40
41 /*
42  *
43  * Routine Description:
44  * Enable hw power saving functions
45  *
46  * Return Value:
47  *    None.
48  *
49  */
50
51 void PSvEnablePowerSaving(struct vnt_private *priv,
52                           unsigned short wListenInterval)
53 {
54         u16 wAID = priv->current_aid | BIT(14) | BIT(15);
55
56         /* set period of power up before TBTT */
57         VNSvOutPortW(priv->PortOffset + MAC_REG_PWBT, C_PWBT);
58         if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
59                 /* set AID */
60                 VNSvOutPortW(priv->PortOffset + MAC_REG_AIDATIM, wAID);
61         }
62
63         /* Set AutoSleep */
64         MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
65
66         /* Set HWUTSF */
67         MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
68
69         if (wListenInterval >= 2) {
70                 /* clear always listen beacon */
71                 MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
72                 /* first time set listen next beacon */
73                 MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
74         } else {
75                 /* always listen beacon */
76                 MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
77         }
78
79         /* enable power saving hw function */
80         MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
81         priv->bEnablePSMode = true;
82
83         priv->bPWBitOn = true;
84         pr_debug("PS:Power Saving Mode Enable...\n");
85 }
86
87 /*
88  *
89  * Routine Description:
90  * Disable hw power saving functions
91  *
92  * Return Value:
93  *    None.
94  *
95  */
96
97 void PSvDisablePowerSaving(struct vnt_private *priv)
98 {
99         /* disable power saving hw function */
100         MACbPSWakeup(priv);
101
102         /* clear AutoSleep */
103         MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
104
105         /* clear HWUTSF */
106         MACvRegBitsOff(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
107
108         /* set always listen beacon */
109         MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
110
111         priv->bEnablePSMode = false;
112
113         priv->bPWBitOn = false;
114 }
115
116 /*
117  *
118  * Routine Description:
119  * Check if Next TBTT must wake up
120  *
121  * Return Value:
122  *    None.
123  *
124  */
125
126 bool PSbIsNextTBTTWakeUp(struct vnt_private *priv)
127 {
128         struct ieee80211_hw *hw = priv->hw;
129         struct ieee80211_conf *conf = &hw->conf;
130         bool wake_up = false;
131
132         if (conf->listen_interval > 1) {
133                 if (!priv->wake_up_count)
134                         priv->wake_up_count = conf->listen_interval;
135
136                 --priv->wake_up_count;
137
138                 if (priv->wake_up_count == 1) {
139                         /* Turn on wake up to listen next beacon */
140                         MACvRegBitsOn(priv->PortOffset,
141                                       MAC_REG_PSCTL, PSCTL_LNBCN);
142                         wake_up = true;
143                 }
144         }
145
146         return wake_up;
147 }