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 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 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 95 void 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 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 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