Path: blob/main/sys/dev/ath/ath_hal/ar5210/ar5210_power.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2004 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"2223#include "ar5210/ar5210.h"24#include "ar5210/ar5210reg.h"2526/*27* Notify Power Mgt is disabled in self-generated frames.28* If requested, set Power Mode of chip to auto/normal.29*/30static void31ar5210SetPowerModeAuto(struct ath_hal *ah, int setChip)32{33OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);34if (setChip)35OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_ALLOW);36}3738/*39* Notify Power Mgt is enabled in self-generated frames.40* If requested, force chip awake.41*42* Returns A_OK if chip is awake or successfully forced awake.43*44* WARNING WARNING WARNING45* There is a problem with the chip where sometimes it will not wake up.46*/47static HAL_BOOL48ar5210SetPowerModeAwake(struct ath_hal *ah, int setChip)49{50#define POWER_UP_TIME 200051uint32_t val;52int i;5354if (setChip) {55OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE);56OS_DELAY(2000); /* Give chip the chance to awake */5758for (i = POWER_UP_TIME / 200; i != 0; i--) {59val = OS_REG_READ(ah, AR_PCICFG);60if ((val & AR_PCICFG_SPWR_DN) == 0)61break;62OS_DELAY(200);63OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE,64AR_SCR_SLE_WAKE);65}66if (i == 0) {67#ifdef AH_DEBUG68ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",69__func__, POWER_UP_TIME/20);70#endif71return AH_FALSE;72}73}7475OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);76return AH_TRUE;77#undef POWER_UP_TIME78}7980/*81* Notify Power Mgt is disabled in self-generated frames.82* If requested, force chip to sleep.83*/84static void85ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip)86{87OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);88if (setChip)89OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP);90}9192HAL_BOOL93ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)94{95#ifdef AH_DEBUG96static const char* modes[] = {97"AWAKE",98"FULL-SLEEP",99"NETWORK SLEEP",100"UNDEFINED"101};102#endif103int status = AH_TRUE;104105HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,106modes[ah->ah_powerMode], modes[mode],107setChip ? "set chip " : "");108switch (mode) {109case HAL_PM_AWAKE:110if (setChip)111ah->ah_powerMode = mode;112status = ar5210SetPowerModeAwake(ah, setChip);113break;114case HAL_PM_FULL_SLEEP:115ar5210SetPowerModeSleep(ah, setChip);116if (setChip)117ah->ah_powerMode = mode;118break;119case HAL_PM_NETWORK_SLEEP:120ar5210SetPowerModeAuto(ah, setChip);121if (setChip)122ah->ah_powerMode = mode;123break;124default:125HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",126__func__, mode);127return AH_FALSE;128}129return status;130}131132HAL_POWER_MODE133ar5210GetPowerMode(struct ath_hal *ah)134{135/* Just so happens the h/w maps directly to the abstracted value */136return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE);137}138139140