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
49void 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	iowrite16(C_PWBT, priv->port_offset + MAC_REG_PWBT);
56	if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
57		/* set AID */
58		iowrite16(wAID, priv->port_offset + MAC_REG_AIDATIM);
59	}
60
61	/* Set AutoSleep */
62	vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
63
64	/* Set HWUTSF */
65	vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
66
67	if (wListenInterval >= 2) {
68		/* clear always listen beacon */
69		vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
70		/* first time set listen next beacon */
71		vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
72	} else {
73		/* always listen beacon */
74		vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
75	}
76
77	/* enable power saving hw function */
78	vt6655_mac_reg_bits_on(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
95void PSvDisablePowerSaving(struct vnt_private *priv)
96{
97	/* disable power saving hw function */
98	MACbPSWakeup(priv);
99
100	/* clear AutoSleep */
101	vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
102
103	/* clear HWUTSF */
104	vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
105
106	/* set always listen beacon */
107	vt6655_mac_reg_bits_on(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
124bool 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			vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
139			wake_up = true;
140		}
141	}
142
143	return wake_up;
144}
145