1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 1.1 alc * 5 1.1 alc * Permission to use, copy, modify, and/or distribute this software for any 6 1.1 alc * purpose with or without fee is hereby granted, provided that the above 7 1.1 alc * copyright notice and this permission notice appear in all copies. 8 1.1 alc * 9 1.1 alc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 1.1 alc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 1.1 alc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 1.1 alc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 1.1 alc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 1.1 alc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 1.1 alc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 1.1 alc * 17 1.1 alc * $Id: ar5416_power.c,v 1.1.1.1 2008/12/11 04:46:48 alc Exp $ 18 1.1 alc */ 19 1.1 alc #include "opt_ah.h" 20 1.1 alc 21 1.1 alc #include "ah.h" 22 1.1 alc #include "ah_internal.h" 23 1.1 alc 24 1.1 alc #include "ar5416/ar5416.h" 25 1.1 alc #include "ar5416/ar5416reg.h" 26 1.1 alc 27 1.1 alc /* 28 1.1 alc * Notify Power Mgt is enabled in self-generated frames. 29 1.1 alc * If requested, force chip awake. 30 1.1 alc * 31 1.1 alc * Returns A_OK if chip is awake or successfully forced awake. 32 1.1 alc * 33 1.1 alc * WARNING WARNING WARNING 34 1.1 alc * There is a problem with the chip where sometimes it will not wake up. 35 1.1 alc */ 36 1.1 alc static HAL_BOOL 37 1.1 alc ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip) 38 1.1 alc { 39 1.1 alc #define POWER_UP_TIME 200000 40 1.1 alc uint32_t val; 41 1.1 alc int i = 0; 42 1.1 alc 43 1.1 alc if (setChip) { 44 1.1 alc /* 45 1.1 alc * Do a Power-On-Reset if OWL is shutdown 46 1.1 alc * the NetBSD driver power-cycles the Cardbus slot 47 1.1 alc * as part of the reset procedure. 48 1.1 alc */ 49 1.1 alc if ((OS_REG_READ(ah, AR_RTC_STATUS) 50 1.1 alc & AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { 51 1.1 alc if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) 52 1.1 alc goto bad; 53 1.1 alc } 54 1.1 alc 55 1.1 alc OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); 56 1.1 alc OS_DELAY(50); /* Give chip the chance to awake */ 57 1.1 alc 58 1.1 alc for (i = POWER_UP_TIME / 50; i != 0; i--) { 59 1.1 alc val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; 60 1.1 alc if (val == AR_RTC_STATUS_ON) 61 1.1 alc break; 62 1.1 alc OS_DELAY(50); 63 1.1 alc OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); 64 1.1 alc } 65 1.1 alc bad: 66 1.1 alc if (i == 0) { 67 1.1 alc #ifdef AH_DEBUG 68 1.1 alc ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", 69 1.1 alc __func__, POWER_UP_TIME/1000); 70 1.1 alc #endif 71 1.1 alc return AH_FALSE; 72 1.1 alc } 73 1.1 alc } 74 1.1 alc 75 1.1 alc OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 76 1.1 alc return AH_TRUE; 77 1.1 alc #undef POWER_UP_TIME 78 1.1 alc } 79 1.1 alc 80 1.1 alc /* 81 1.1 alc * Notify Power Mgt is disabled in self-generated frames. 82 1.1 alc * If requested, force chip to sleep. 83 1.1 alc */ 84 1.1 alc static void 85 1.1 alc ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip) 86 1.1 alc { 87 1.1 alc OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 88 1.1 alc if (setChip) { 89 1.1 alc /* Clear the RTC force wake bit to allow the mac to sleep */ 90 1.1 alc OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); 91 1.1 alc OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); 92 1.1 alc /* Shutdown chip. Active low */ 93 1.1 alc OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); 94 1.1 alc } 95 1.1 alc } 96 1.1 alc 97 1.1 alc /* 98 1.1 alc * Notify Power Management is enabled in self-generating 99 1.1 alc * fames. If request, set power mode of chip to 100 1.1 alc * auto/normal. Duration in units of 128us (1/8 TU). 101 1.1 alc */ 102 1.1 alc static void 103 1.1 alc ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) 104 1.1 alc { 105 1.1 alc OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 106 1.1 alc 107 1.1 alc if (setChip) 108 1.1 alc OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); 109 1.1 alc } 110 1.1 alc 111 1.1 alc /* 112 1.1 alc * Set power mgt to the requested mode, and conditionally set 113 1.1 alc * the chip as well 114 1.1 alc */ 115 1.1 alc HAL_BOOL 116 1.1 alc ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) 117 1.1 alc { 118 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 119 1.1 alc #ifdef AH_DEBUG 120 1.1 alc static const char* modes[] = { 121 1.1 alc "AWAKE", 122 1.1 alc "FULL-SLEEP", 123 1.1 alc "NETWORK SLEEP", 124 1.1 alc "UNDEFINED" 125 1.1 alc }; 126 1.1 alc #endif 127 1.1 alc int status = AH_TRUE; 128 1.1 alc if (!setChip) 129 1.1 alc return AH_TRUE; 130 1.1 alc 131 1.1 alc HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, 132 1.1 alc modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); 133 1.1 alc switch (mode) { 134 1.1 alc case HAL_PM_AWAKE: 135 1.1 alc status = ar5416SetPowerModeAwake(ah, setChip); 136 1.1 alc break; 137 1.1 alc case HAL_PM_FULL_SLEEP: 138 1.1 alc ar5416SetPowerModeSleep(ah, setChip); 139 1.1 alc break; 140 1.1 alc case HAL_PM_NETWORK_SLEEP: 141 1.1 alc ar5416SetPowerModeNetworkSleep(ah, setChip); 142 1.1 alc break; 143 1.1 alc default: 144 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n", 145 1.1 alc __func__, mode); 146 1.1 alc return AH_FALSE; 147 1.1 alc } 148 1.1 alc ahp->ah_powerMode = mode; 149 1.1 alc return status; 150 1.1 alc } 151 1.1 alc 152 1.1 alc /* 153 1.1 alc * Return the current sleep mode of the chip 154 1.1 alc */ 155 1.1 alc HAL_POWER_MODE 156 1.1 alc ar5416GetPowerMode(struct ath_hal *ah) 157 1.1 alc { 158 1.1 alc int mode = OS_REG_READ(ah, AR_RTC_STATUS); 159 1.1 alc switch (mode & AR_RTC_PM_STATUS_M) { 160 1.1 alc case AR_RTC_STATUS_ON: 161 1.1 alc case AR_RTC_STATUS_WAKEUP: 162 1.1 alc return HAL_PM_AWAKE; 163 1.1 alc case AR_RTC_STATUS_SLEEP: 164 1.1 alc return HAL_PM_NETWORK_SLEEP; 165 1.1 alc case AR_RTC_STATUS_SHUTDOWN: 166 1.1 alc return HAL_PM_FULL_SLEEP; 167 1.1 alc default: 168 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, 169 1.1 alc "%s: unknown power mode, RTC_STATUS 0x%x\n", 170 1.1 alc __func__, mode); 171 1.1 alc return HAL_PM_UNDEFINED; 172 1.1 alc } 173 1.1 alc } 174