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