iwl-power.c revision 298df1f62aa69881528bf0f1c3c14395bc447846
15da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/******************************************************************************
25da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
35da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
45da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
55da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Portions of this file are derived from the ipw3945 project, as well
65da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * as portions of the ieee80211 subsystem header files.
75da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
85da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * This program is free software; you can redistribute it and/or modify it
95da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * under the terms of version 2 of the GNU General Public License as
105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * published by the Free Software Foundation.
115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * This program is distributed in the hope that it will be useful, but WITHOUT
135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * more details.
165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * You should have received a copy of the GNU General Public License along with
185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this program; if not, write to the Free Software Foundation, Inc.,
195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * The full GNU General Public License is included in this distribution in the
225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * file called LICENSE.
235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Contact Information:
255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * James P. Ketrenos <ipw2100-admin@linux.intel.com>
265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *****************************************************************************/
285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/kernel.h>
315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/module.h>
325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/version.h>
335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/init.h>
345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <net/mac80211.h>
365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-eeprom.h"
383e0d4cb12f6fd97193a455b49125398b2231c87cTomas Winkler#include "iwl-dev.h"
395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-core.h"
405a36ba0e412a0e12a8bf2648a075226c1dd7870dTomas Winkler#include "iwl-commands.h"
415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-debug.h"
425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-power.h"
435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-helpers.h"
445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/*
465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Setting power level allow the card to go to sleep when not busy
475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * there are three factor that decide the power level to go to, they
485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * are list here with its priority
495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *  1- critical_power_setting this will be set according to card temperature.
505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *  2- system_power_setting this will be set by system PM manager.
515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *  3- user_power_setting this will be set by user either by writing to sys or
525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *  	mac80211
535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * if system_power_setting and user_power_setting is set to auto
555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * the power level will be decided according to association status and battery
565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * status.
575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *
585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define MSEC_TO_USEC 1024
615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_0_MAX  (2)
625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_1_MAX  (10)
635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define NOSLP __constant_cpu_to_le16(0), 0, 0
665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				     __constant_cpu_to_le32(X1), \
705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				     __constant_cpu_to_le32(X2), \
715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				     __constant_cpu_to_le32(X3), \
725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				     __constant_cpu_to_le32(X4)}
735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_BATTERY		IWL_POWER_INDEX_5
755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_DISASSOC	IWL_POWER_MODE_CAM
765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_ASSOC		IWL_POWER_MODE_CAM
775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_CT_KILL_TEMPERATURE		110
805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_MIN_POWER_TEMPERATURE	100
815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_REDUCED_POWER_TEMPERATURE	95
825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* default power management (not Tx power) table values */
845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim  0-10 */
85298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2}
925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas};
935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim = 3-10 */
96298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
1005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
1015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
1025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
1035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas};
1045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim > 11 */
106298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
1075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
1085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
1095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
1105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
1115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
1125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
1135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas};
1145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
115ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas/* set card power command */
116ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbasstatic int iwl_set_power(struct iwl_priv *priv, void *cmd)
117ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas{
118ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas	return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD,
119ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas				      sizeof(struct iwl_powertable_cmd),
120ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas				      cmd, NULL);
121ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas}
1225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* decide the right power level according to association status
1235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * and battery status
1245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
1255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
1265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
127298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	u16 mode;
1285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	switch (priv->power_data.user_power_setting) {
1305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	case IWL_POWER_AUTO:
1315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		/* if running on battery */
1325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (priv->power_data.is_battery_active)
1335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			mode = IWL_POWER_ON_BATTERY;
1345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		else if (iwl_is_associated(priv))
1355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			mode = IWL_POWER_ON_AC_ASSOC;
1365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		else
1375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			mode = IWL_POWER_ON_AC_DISASSOC;
1385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
139298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	/* FIXME: remove battery and ac from here */
1405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	case IWL_POWER_BATTERY:
1415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		mode = IWL_POWER_INDEX_3;
1425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
1435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	case IWL_POWER_AC:
1445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		mode = IWL_POWER_MODE_CAM;
1455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
146298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	default:
147298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer		mode = priv->power_data.user_power_setting;
148298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer		break;
1495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
1505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return mode;
1515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
1525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* initialize to default */
1545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_power_init_handle(struct iwl_priv *priv)
1555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
1565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0, i;
1575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	struct iwl_power_mgr *pow_data;
158298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
1595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u16 pci_pm;
1605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	IWL_DEBUG_POWER("Initialize power \n");
1625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	pow_data = &(priv->power_data);
1645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	memset(pow_data, 0, sizeof(*pow_data));
1665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
1685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
1695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
1705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	ret = pci_read_config_word(priv->pci_dev,
1725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				  PCI_LINK_CTRL, &pci_pm);
1735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (ret != 0)
1745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return 0;
1755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else {
176ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas		struct iwl_powertable_cmd *cmd;
1775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		IWL_DEBUG_POWER("adjust power command flags\n");
1795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
180298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer		for (i = 0; i < IWL_POWER_MAX; i++) {
1815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			cmd = &pow_data->pwr_range_0[i].cmd;
1825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			if (pci_pm & 0x1)
1845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
1855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			else
1865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				cmd->flags |= IWL_POWER_PCI_PM_MSK;
1875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		}
1885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
1895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
1905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
1915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
1925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* adjust power command according to dtim period and power level*/
1935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_update_power_command(struct iwl_priv *priv,
194ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas				    struct iwl_powertable_cmd *cmd,
1955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				    u16 mode)
1965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
1975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0, i;
1985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u8 skip;
1995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u32 max_sleep = 0;
2005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	struct iwl_power_vec_entry *range;
2015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u8 period = 0;
2025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	struct iwl_power_mgr *pow_data;
2035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (mode > IWL_POWER_INDEX_5) {
2055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		IWL_DEBUG_POWER("Error invalid power mode \n");
2065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return -1;
2075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
2085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	pow_data = &(priv->power_data);
2095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX)
2115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		range = &pow_data->pwr_range_0[0];
2125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
2135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		range = &pow_data->pwr_range_1[0];
2145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else
2155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		range = &pow_data->pwr_range_2[0];
2165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	period = pow_data->dtim_period;
218ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas	memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
2195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (period == 0) {
2215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		period = 1;
2225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		skip = 0;
2235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	} else
2245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		skip = range[mode].no_dtim;
2255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (skip == 0) {
2275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		max_sleep = period;
2285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
2295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	} else {
2305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
2315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		max_sleep = le32_to_cpu(slp_itrvl);
2325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (max_sleep == 0xFF)
2335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			max_sleep = period * (skip + 1);
2345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		else if (max_sleep >  period)
2355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
2365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
2375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
2385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
2405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
2415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
2425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
2435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
2455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
2465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
2475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n",
2485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			le32_to_cpu(cmd->sleep_interval[0]),
2495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			le32_to_cpu(cmd->sleep_interval[1]),
2505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			le32_to_cpu(cmd->sleep_interval[2]),
2515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			le32_to_cpu(cmd->sleep_interval[3]),
2525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			le32_to_cpu(cmd->sleep_interval[4]));
2535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
2555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
2565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/*
2595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * calucaute the final power mode index
2605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
2615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
2625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
2635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	struct iwl_power_mgr *setting = &(priv->power_data);
2645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
2655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u16 uninitialized_var(final_mode);
2665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas       /* If on battery, set to 3,
2685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	* if plugged into AC power, set to CAM ("continuously aware mode"),
2695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	* else user level */
2705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	switch (setting->system_power_setting) {
272298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	case IWL_POWER_SYS_AUTO:
2735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		final_mode = iwl_get_auto_power_mode(priv);
2745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
275298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	case IWL_POWER_SYS_BATTERY:
2765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		final_mode = IWL_POWER_INDEX_3;
2775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
278298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	case IWL_POWER_SYS_AC:
2795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		final_mode = IWL_POWER_MODE_CAM;
2805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		break;
2815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	default:
282298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer		final_mode = IWL_POWER_INDEX_3;
283298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer		WARN_ON(1);
2845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
2855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (setting->critical_power_setting > final_mode)
2875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		final_mode = setting->critical_power_setting;
2885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	/* driver only support CAM for non STA network */
2905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (priv->iw_mode != IEEE80211_IF_TYPE_STA)
2915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		final_mode = IWL_POWER_MODE_CAM;
2925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (!iwl_is_rfkill(priv) && !setting->power_disabled &&
2945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	    ((setting->power_mode != final_mode) || refresh)) {
295ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas		struct iwl_powertable_cmd cmd;
2965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
2975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (final_mode != IWL_POWER_MODE_CAM)
2985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			set_bit(STATUS_POWER_PMI, &priv->status);
2995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		iwl_update_power_command(priv, &cmd, final_mode);
3015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		cmd.keep_alive_beacons = 0;
3025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (final_mode == IWL_POWER_INDEX_5)
3045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			cmd.flags |= IWL_POWER_FAST_PD;
3055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
306ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas		ret = iwl_set_power(priv, &cmd);
3075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (final_mode == IWL_POWER_MODE_CAM)
3095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			clear_bit(STATUS_POWER_PMI, &priv->status);
3105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		else
3115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			set_bit(STATUS_POWER_PMI, &priv->status);
3125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (priv->cfg->ops->lib->update_chain_flags)
3145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			priv->cfg->ops->lib->update_chain_flags(priv);
3155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		if (!ret)
3175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas			setting->power_mode = final_mode;
3185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	}
3195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
3215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
3225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_update_mode);
3235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active
3255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this will be usefull for rate scale to disable PM during heavy
3265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Tx/Rx activities
3275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
3285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_disable_management(struct iwl_priv *priv)
3295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
3305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u16 prev_mode;
3315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
3325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (priv->power_data.power_disabled)
3345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return -EBUSY;
3355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	prev_mode = priv->power_data.user_power_setting;
3375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.user_power_setting = IWL_POWER_MODE_CAM;
3385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	ret = iwl_power_update_mode(priv, 0);
3395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.power_disabled = 1;
3405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.user_power_setting = prev_mode;
3415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
3435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
3445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_disable_management);
3455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active
3475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this will be usefull for rate scale to disable PM during hight
3485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * valume activities
3495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
3505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_enable_management(struct iwl_priv *priv)
3515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
3525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
3535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.power_disabled = 0;
3555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	ret = iwl_power_update_mode(priv, 0);
3565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
3575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
3585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_enable_management);
3595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set user_power_setting */
3615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
3625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
3635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
3645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (mode > IWL_POWER_LIMIT)
3665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return -EINVAL;
3675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.user_power_setting = mode;
3695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	ret = iwl_power_update_mode(priv, 0);
3715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
3735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
3745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_user_mode);
3755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set system_power_setting. This should be set by over all
3785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * PM application.
3795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */
3805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
3815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
3825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
3835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (mode > IWL_POWER_LIMIT)
3855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return -EINVAL;
3865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.system_power_setting = mode;
3885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	ret = iwl_power_update_mode(priv, 0);
3905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
3925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
3935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_system_mode);
3945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* initilize to default */
3965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasvoid iwl_power_initialize(struct iwl_priv *priv)
3975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
3985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
3995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	iwl_power_init_handle(priv);
4005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.user_power_setting = IWL_POWER_AUTO;
4015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.power_disabled = 0;
402298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer	priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO;
4035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.is_battery_active = 0;
4045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.power_disabled = 0;
4055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	priv->power_data.critical_power_setting = 0;
4065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
4075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_initialize);
4085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
4095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set critical_power_setting according to temperature value */
4105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_temperature_change(struct iwl_priv *priv)
4115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{
4125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	int ret = 0;
4135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	u16 new_critical = priv->power_data.critical_power_setting;
4145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature);
4155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
4165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (temperature > IWL_CT_KILL_TEMPERATURE)
4175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		return 0;
4185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else if (temperature > IWL_MIN_POWER_TEMPERATURE)
4195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		new_critical = IWL_POWER_INDEX_5;
4205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else if (temperature > IWL_REDUCED_POWER_TEMPERATURE)
4215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		new_critical = IWL_POWER_INDEX_3;
4225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	else
4235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		new_critical = IWL_POWER_MODE_CAM;
4245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
4255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (new_critical != priv->power_data.critical_power_setting)
4265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		priv->power_data.critical_power_setting = new_critical;
4275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
4285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	if (priv->power_data.critical_power_setting >
4295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas				priv->power_data.power_mode)
4305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas		ret = iwl_power_update_mode(priv, 0);
4315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas
4325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas	return ret;
4335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}
4345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_temperature_change);
435