xref: /openbmc/linux/drivers/staging/vt6655/power.c (revision 74ce1896)
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * File: power.c
16  *
17  * Purpose: Handles 802.11 power management  functions
18  *
19  * Author: Lyndon Chen
20  *
21  * Date: July 17, 2002
22  *
23  * Functions:
24  *      PSvEnablePowerSaving - Enable Power Saving Mode
25  *      PSvDiasblePowerSaving - Disable Power Saving Mode
26  *      PSbConsiderPowerDown - Decide if we can Power Down
27  *      PSvSendPSPOLL - Send PS-POLL packet
28  *      PSbSendNullPacket - Send Null packet
29  *      PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
30  *
31  * Revision History:
32  *
33  */
34 
35 #include "mac.h"
36 #include "device.h"
37 #include "power.h"
38 #include "card.h"
39 
40 /*---------------------  Static Definitions -------------------------*/
41 
42 /*---------------------  Static Classes  ----------------------------*/
43 
44 /*---------------------  Static Functions  --------------------------*/
45 
46 /*---------------------  Export Variables  --------------------------*/
47 
48 /*---------------------  Export Functions  --------------------------*/
49 
50 /*
51  *
52  * Routine Description:
53  * Enable hw power saving functions
54  *
55  * Return Value:
56  *    None.
57  *
58  */
59 
60 void
61 PSvEnablePowerSaving(
62 	struct vnt_private *priv,
63 	unsigned short wListenInterval
64 )
65 {
66 	u16 wAID = priv->current_aid | BIT(14) | BIT(15);
67 
68 	/* set period of power up before TBTT */
69 	VNSvOutPortW(priv->PortOffset + MAC_REG_PWBT, C_PWBT);
70 	if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
71 		/* set AID */
72 		VNSvOutPortW(priv->PortOffset + MAC_REG_AIDATIM, wAID);
73 	} else {
74 		/* set ATIM Window */
75 #if 0 /* TODO atim window */
76 		MACvWriteATIMW(priv->PortOffset, pMgmt->wCurrATIMWindow);
77 #endif
78 	}
79 	/* Set AutoSleep */
80 	MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
81 	/* Set HWUTSF */
82 	MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
83 
84 	if (wListenInterval >= 2) {
85 		/* clear always listen beacon */
86 		MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
87 		/* first time set listen next beacon */
88 		MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
89 	} else {
90 		/* always listen beacon */
91 		MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
92 	}
93 
94 	/* enable power saving hw function */
95 	MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
96 	priv->bEnablePSMode = true;
97 
98 	priv->bPWBitOn = true;
99 	pr_debug("PS:Power Saving Mode Enable...\n");
100 }
101 
102 /*
103  *
104  * Routine Description:
105  * Disable hw power saving functions
106  *
107  * Return Value:
108  *    None.
109  *
110  */
111 
112 void
113 PSvDisablePowerSaving(
114 	struct vnt_private *priv
115 )
116 {
117 	/* disable power saving hw function */
118 	MACbPSWakeup(priv);
119 	/* clear AutoSleep */
120 	MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
121 	/* clear HWUTSF */
122 	MACvRegBitsOff(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
123 	/* set always listen beacon */
124 	MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
125 
126 	priv->bEnablePSMode = false;
127 
128 	priv->bPWBitOn = false;
129 }
130 
131 /*
132  *
133  * Routine Description:
134  * Check if Next TBTT must wake up
135  *
136  * Return Value:
137  *    None.
138  *
139  */
140 
141 bool
142 PSbIsNextTBTTWakeUp(
143 	struct vnt_private *priv
144 )
145 {
146 	struct ieee80211_hw *hw = priv->hw;
147 	struct ieee80211_conf *conf = &hw->conf;
148 	bool wake_up = false;
149 
150 	if (conf->listen_interval > 1) {
151 		if (!priv->wake_up_count)
152 			priv->wake_up_count = conf->listen_interval;
153 
154 		--priv->wake_up_count;
155 
156 		if (priv->wake_up_count == 1) {
157 			/* Turn on wake up to listen next beacon */
158 			MACvRegBitsOn(priv->PortOffset,
159 				      MAC_REG_PSCTL, PSCTL_LNBCN);
160 			wake_up = true;
161 		}
162 	}
163 
164 	return wake_up;
165 }
166