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  *      vnt_enable_power_saving - Enable Power Saving Mode
16  *      PSvDiasblePowerSaving - Disable Power Saving Mode
17  *      vnt_next_tbtt_wakeup - Decide if we need to wake up at next Beacon
18  *
19  * Revision History:
20  *
21  */
22 
23 #include "mac.h"
24 #include "device.h"
25 #include "power.h"
26 #include "wcmd.h"
27 #include "rxtx.h"
28 #include "card.h"
29 #include "usbpipe.h"
30 
31 /*
32  *
33  * Routine Description:
34  * Enable hw power saving functions
35  *
36  * Return Value:
37  *    None.
38  *
39  */
40 
vnt_enable_power_saving(struct vnt_private * priv,u16 listen_interval)41 void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval)
42 {
43 	u16 aid = priv->current_aid | BIT(14) | BIT(15);
44 
45 	/* set period of power up before TBTT */
46 	vnt_mac_write_word(priv, MAC_REG_PWBT, C_PWBT);
47 
48 	if (priv->op_mode != NL80211_IFTYPE_ADHOC)
49 		/* set AID */
50 		vnt_mac_write_word(priv, MAC_REG_AIDATIM, aid);
51 
52 	/* Warren:06-18-2004,the sequence must follow
53 	 * PSEN->AUTOSLEEP->GO2DOZE
54 	 */
55 	/* enable power saving hw function */
56 	vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_PSEN);
57 
58 	/* Set AutoSleep */
59 	vnt_mac_reg_bits_on(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
60 
61 	/* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the
62 	 * AUTOSLEEP doesn't work
63 	 */
64 	vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_GO2DOZE);
65 
66 	if (listen_interval >= 2) {
67 		/* clear always listen beacon */
68 		vnt_mac_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
69 
70 		/* first time set listen next beacon */
71 		vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN);
72 	} else {
73 		/* always listen beacon */
74 		vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
75 	}
76 
77 	dev_dbg(&priv->usb->dev,  "PS:Power Saving Mode Enable...\n");
78 }
79 
80 /*
81  *
82  * Routine Description:
83  * Disable hw power saving functions
84  *
85  * Return Value:
86  *    None.
87  *
88  */
89 
vnt_disable_power_saving(struct vnt_private * priv)90 void vnt_disable_power_saving(struct vnt_private *priv)
91 {
92 	/* disable power saving hw function */
93 	vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0,
94 			0, 0, NULL);
95 
96 	/* clear AutoSleep */
97 	vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
98 
99 	/* set always listen beacon */
100 	vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
101 }
102 
103 /*
104  *
105  * Routine Description:
106  * Check if Next TBTT must wake up
107  *
108  * Return Value:
109  *    None.
110  *
111  */
112 
vnt_next_tbtt_wakeup(struct vnt_private * priv)113 int vnt_next_tbtt_wakeup(struct vnt_private *priv)
114 {
115 	struct ieee80211_hw *hw = priv->hw;
116 	struct ieee80211_conf *conf = &hw->conf;
117 	int wake_up = false;
118 
119 	if (conf->listen_interval > 1) {
120 		/* Turn on wake up to listen next beacon */
121 		vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN);
122 		wake_up = true;
123 	}
124 
125 	return wake_up;
126 }
127