3 * Copyright (c) 2004-2010 Atheros Communications Inc.
8 // Permission to use, copy, modify, and/or distribute this software for any
9 // purpose with or without fee is hereby granted, provided that the above
10 // copyright notice and this permission notice appear in all copies.
12 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * Implementation of system power management
28 #include "ar6000_drv.h"
29 #include <linux/inetdevice.h>
30 #include <linux/platform_device.h>
31 #include "wlan_config.h"
33 #define WOW_ENABLE_MAX_INTERVAL 0
34 #define WOW_SET_SCAN_PARAMS 0
36 extern unsigned int wmitimeout
;
37 extern wait_queue_head_t arEvent
;
40 extern void android_ar6k_check_wow_status(AR_SOFTC_T
*ar
, struct sk_buff
*skb
, bool isEvent
);
42 #undef ATH_MODULE_NAME
43 #define ATH_MODULE_NAME pm
44 #define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0)
47 static ATH_DEBUG_MASK_DESCRIPTION pm_debug_desc
[] = {
48 { ATH_DEBUG_PM
, "System power management"},
51 ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm
,
53 "System Power Management",
54 ATH_DEBUG_MASK_DEFAULTS
| ATH_DEBUG_PM
,
55 ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc
),
60 int ar6000_exit_cut_power_state(AR_SOFTC_T
*ar
);
63 static void ar6k_send_asleep_event_to_app(AR_SOFTC_T
*ar
, bool asleep
)
66 union iwreq_data wrqu
;
68 snprintf(buf
, sizeof(buf
), "HOST_ASLEEP=%s", asleep
? "asleep" : "awake");
69 A_MEMZERO(&wrqu
, sizeof(wrqu
));
70 wrqu
.data
.length
= strlen(buf
);
71 wireless_send_event(ar
->arNetDev
, IWEVCUSTOM
, &wrqu
, buf
);
74 static void ar6000_wow_resume(AR_SOFTC_T
*ar
)
76 if (ar
->arWowState
!= WLAN_WOW_STATE_NONE
) {
77 u16 fg_start_period
= (ar
->scParams
.fg_start_period
==0) ? 1 : ar
->scParams
.fg_start_period
;
78 u16 bg_period
= (ar
->scParams
.bg_period
==0) ? 60 : ar
->scParams
.bg_period
;
79 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode
= {true, false};
80 ar
->arWowState
= WLAN_WOW_STATE_NONE
;
81 if (wmi_set_host_sleep_mode_cmd(ar
->arWmi
, &hostSleepMode
)!=A_OK
) {
82 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to setup restore host awake\n"));
84 #if WOW_SET_SCAN_PARAMS
85 wmi_scanparams_cmd(ar
->arWmi
, fg_start_period
,
86 ar
->scParams
.fg_end_period
,
88 ar
->scParams
.minact_chdwell_time
,
89 ar
->scParams
.maxact_chdwell_time
,
90 ar
->scParams
.pas_chdwell_time
,
91 ar
->scParams
.shortScanRatio
,
92 ar
->scParams
.scanCtrlFlags
,
93 ar
->scParams
.max_dfsch_act_time
,
94 ar
->scParams
.maxact_scan_per_ssid
);
96 (void)fg_start_period
;
101 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
102 if (wmi_listeninterval_cmd(ar
->arWmi
, ar
->arListenIntervalT
, ar
->arListenIntervalB
) == A_OK
) {
105 ar6k_send_asleep_event_to_app(ar
, false);
106 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("Resume WoW successfully\n"));
108 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("WoW does not invoked. skip resume"));
110 ar
->arWlanPowerState
= WLAN_POWER_STATE_ON
;
113 static void ar6000_wow_suspend(AR_SOFTC_T
*ar
)
115 #define WOW_LIST_ID 1
116 if (ar
->arNetworkType
!= AP_NETWORK
) {
117 /* Setup WoW for unicast & Arp request for our own IP
118 disable background scan. Set listen interval into 1000 TUs
119 Enable keepliave for 110 seconds
121 struct in_ifaddr
**ifap
= NULL
;
122 struct in_ifaddr
*ifa
= NULL
;
123 struct in_device
*in_dev
;
124 u8 macMask
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
126 WMI_ADD_WOW_PATTERN_CMD addWowCmd
= { .filter
= { 0 } };
127 WMI_DEL_WOW_PATTERN_CMD delWowCmd
;
128 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode
= {false, true};
129 WMI_SET_WOW_MODE_CMD wowMode
= { .enable_wow
= true,
130 .hostReqDelay
= 500 };/*500 ms delay*/
132 if (ar
->arWowState
!= WLAN_WOW_STATE_NONE
) {
133 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("System already go into wow mode!\n"));
137 ar6000_TxDataCleanup(ar
); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/
139 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
140 if (wmi_listeninterval_cmd(ar
->arWmi
, A_MAX_WOW_LISTEN_INTERVAL
, 0) == A_OK
) {
144 #if WOW_SET_SCAN_PARAMS
145 status
= wmi_scanparams_cmd(ar
->arWmi
, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0);
147 /* clear up our WoW pattern first */
148 delWowCmd
.filter_list_id
= WOW_LIST_ID
;
149 delWowCmd
.filter_id
= 0;
150 wmi_del_wow_pattern_cmd(ar
->arWmi
, &delWowCmd
);
152 /* setup unicast packet pattern for WoW */
153 if (ar
->arNetDev
->dev_addr
[1]) {
154 addWowCmd
.filter_list_id
= WOW_LIST_ID
;
155 addWowCmd
.filter_size
= 6; /* MAC address */
156 addWowCmd
.filter_offset
= 0;
157 status
= wmi_add_wow_pattern_cmd(ar
->arWmi
, &addWowCmd
, ar
->arNetDev
->dev_addr
, macMask
, addWowCmd
.filter_size
);
158 if (status
!= A_OK
) {
159 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to add WoW pattern\n"));
162 /* setup ARP request for our own IP */
163 if ((in_dev
= __in_dev_get_rtnl(ar
->arNetDev
)) != NULL
) {
164 for (ifap
= &in_dev
->ifa_list
; (ifa
= *ifap
) != NULL
; ifap
= &ifa
->ifa_next
) {
165 if (!strcmp(ar
->arNetDev
->name
, ifa
->ifa_label
)) {
170 if (ifa
&& ifa
->ifa_local
) {
171 WMI_SET_IP_CMD ipCmd
;
172 memset(&ipCmd
, 0, sizeof(ipCmd
));
173 ipCmd
.ips
[0] = ifa
->ifa_local
;
174 status
= wmi_set_ip_cmd(ar
->arWmi
, &ipCmd
);
175 if (status
!= A_OK
) {
176 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to setup IP for ARP agent\n"));
180 #ifndef ATH6K_CONFIG_OTA_MODE
181 wmi_powermode_cmd(ar
->arWmi
, REC_POWER
);
184 status
= wmi_set_wow_mode_cmd(ar
->arWmi
, &wowMode
);
185 if (status
!= A_OK
) {
186 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to enable wow mode\n"));
188 ar6k_send_asleep_event_to_app(ar
, true);
190 status
= wmi_set_host_sleep_mode_cmd(ar
->arWmi
, &hostSleepMode
);
191 if (status
!= A_OK
) {
192 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to set host asleep\n"));
195 ar
->arWowState
= WLAN_WOW_STATE_SUSPENDING
;
196 if (ar
->arTxPending
[ar
->arControlEp
]) {
197 u32 timeleft
= wait_event_interruptible_timeout(arEvent
,
198 ar
->arTxPending
[ar
->arControlEp
] == 0, wmitimeout
* HZ
);
199 if (!timeleft
|| signal_pending(current
)) {
200 /* what can I do? wow resume at once */
201 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to setup WoW. Pending wmi control data %d\n", ar
->arTxPending
[ar
->arControlEp
]));
205 status
= hifWaitForPendingRecv(ar
->arHifDevice
);
207 ar
->arWowState
= WLAN_WOW_STATE_SUSPENDED
;
208 ar
->arWlanPowerState
= WLAN_POWER_STATE_WOW
;
210 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Not allowed to go to WOW at this moment.\n"));
214 int ar6000_suspend_ev(void *context
)
217 AR_SOFTC_T
*ar
= (AR_SOFTC_T
*)context
;
218 A_INT16 pmmode
= ar
->arSuspendConfig
;
221 case WLAN_SUSPEND_WOW
:
222 if (ar
->arWmiReady
&& ar
->arWlanState
==WLAN_ENABLED
&& ar
->arConnected
) {
223 ar6000_wow_suspend(ar
);
224 AR_DEBUG_PRINTF(ATH_DEBUG_PM
,("%s:Suspend for wow mode %d\n", __func__
, ar
->arWlanPowerState
));
226 pmmode
= ar
->arWow2Config
;
227 goto wow_not_connected
;
230 case WLAN_SUSPEND_CUT_PWR
:
232 case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF
:
234 case WLAN_SUSPEND_DEEP_SLEEP
:
237 status
= ar6000_update_wlan_pwr_state(ar
, WLAN_DISABLED
, true);
238 if (ar
->arWlanPowerState
==WLAN_POWER_STATE_ON
||
239 ar
->arWlanPowerState
==WLAN_POWER_STATE_WOW
) {
240 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("Strange suspend state for not wow mode %d", ar
->arWlanPowerState
));
242 AR_DEBUG_PRINTF(ATH_DEBUG_PM
,("%s:Suspend for %d mode pwr %d status %d\n", __func__
, pmmode
, ar
->arWlanPowerState
, status
));
243 status
= (ar
->arWlanPowerState
== WLAN_POWER_STATE_CUT_PWR
) ? A_OK
: A_EBUSY
;
247 ar
->scan_triggered
= 0;
251 int ar6000_resume_ev(void *context
)
253 AR_SOFTC_T
*ar
= (AR_SOFTC_T
*)context
;
254 u16 powerState
= ar
->arWlanPowerState
;
256 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("%s: enter previous state %d wowState %d\n", __func__
, powerState
, ar
->arWowState
));
257 switch (powerState
) {
258 case WLAN_POWER_STATE_WOW
:
259 ar6000_wow_resume(ar
);
261 case WLAN_POWER_STATE_CUT_PWR
:
263 case WLAN_POWER_STATE_DEEP_SLEEP
:
264 ar6000_update_wlan_pwr_state(ar
, WLAN_ENABLED
, true);
265 AR_DEBUG_PRINTF(ATH_DEBUG_PM
,("%s:Resume for %d mode pwr %d\n", __func__
, powerState
, ar
->arWlanPowerState
));
267 case WLAN_POWER_STATE_ON
:
270 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Strange SDIO bus power mode!!\n"));
276 void ar6000_check_wow_status(AR_SOFTC_T
*ar
, struct sk_buff
*skb
, bool isEvent
)
278 if (ar
->arWowState
!=WLAN_WOW_STATE_NONE
) {
279 if (ar
->arWowState
==WLAN_WOW_STATE_SUSPENDING
) {
280 AR_DEBUG_PRINTF(ATH_DEBUG_PM
,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__
));
283 /* Wow resume from irq interrupt */
284 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("%s: WoW resume from irq thread status %d\n", __func__
, ar
->arWlanPowerState
));
285 ar6000_wow_resume(ar
);
288 android_ar6k_check_wow_status(ar
, skb
, isEvent
);
293 int ar6000_power_change_ev(void *context
, u32 config
)
295 AR_SOFTC_T
*ar
= (AR_SOFTC_T
*)context
;
298 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("%s: power change event callback %d \n", __func__
, config
));
300 case HIF_DEVICE_POWER_UP
:
301 ar6000_restart_endpoint(ar
->arNetDev
);
304 case HIF_DEVICE_POWER_DOWN
:
305 case HIF_DEVICE_POWER_CUT
:
312 static int ar6000_pm_probe(struct platform_device
*pdev
)
314 plat_setup_power(1,1);
318 static int ar6000_pm_remove(struct platform_device
*pdev
)
320 plat_setup_power(0,1);
324 static int ar6000_pm_suspend(struct platform_device
*pdev
, pm_message_t state
)
329 static int ar6000_pm_resume(struct platform_device
*pdev
)
334 static struct platform_driver ar6000_pm_device
= {
335 .probe
= ar6000_pm_probe
,
336 .remove
= ar6000_pm_remove
,
337 .suspend
= ar6000_pm_suspend
,
338 .resume
= ar6000_pm_resume
,
340 .name
= "wlan_ar6000_pm",
343 #endif /* CONFIG_PM */
346 ar6000_setup_cut_power_state(struct ar6_softc
*ar
, AR6000_WLAN_STATE state
)
349 HIF_DEVICE_POWER_CHANGE_TYPE config
;
351 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("%s: Cut power %d %d \n", __func__
,state
, ar
->arWlanPowerState
));
353 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("Wlan OFF %d BT OFf %d \n", ar
->arWlanOff
, ar
->arBTOff
));
356 if (state
== WLAN_ENABLED
) {
357 /* Not in cut power state.. exit */
358 if (ar
->arWlanPowerState
!= WLAN_POWER_STATE_CUT_PWR
) {
362 plat_setup_power(1,0);
364 /* Change the state to ON */
365 ar
->arWlanPowerState
= WLAN_POWER_STATE_ON
;
368 /* Indicate POWER_UP to HIF */
369 config
= HIF_DEVICE_POWER_UP
;
370 status
= HIFConfigureDevice(ar
->arHifDevice
,
371 HIF_DEVICE_POWER_STATE_CHANGE
,
373 sizeof(HIF_DEVICE_POWER_CHANGE_TYPE
));
375 if (status
== A_PENDING
) {
377 /* Wait for WMI ready event */
378 u32 timeleft
= wait_event_interruptible_timeout(arEvent
,
379 (ar
->arWmiReady
== true), wmitimeout
* HZ
);
380 if (!timeleft
|| signal_pending(current
)) {
381 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("ar6000 : Failed to get wmi ready \n"));
387 } else if (status
== A_OK
) {
388 ar6000_restart_endpoint(ar
->arNetDev
);
391 } else if (state
== WLAN_DISABLED
) {
394 /* Already in cut power state.. exit */
395 if (ar
->arWlanPowerState
== WLAN_POWER_STATE_CUT_PWR
) {
398 ar6000_stop_endpoint(ar
->arNetDev
, true, false);
400 config
= HIF_DEVICE_POWER_CUT
;
401 status
= HIFConfigureDevice(ar
->arHifDevice
,
402 HIF_DEVICE_POWER_STATE_CHANGE
,
404 sizeof(HIF_DEVICE_POWER_CHANGE_TYPE
));
406 plat_setup_power(0,0);
408 ar
->arWlanPowerState
= WLAN_POWER_STATE_CUT_PWR
;
416 ar6000_setup_deep_sleep_state(struct ar6_softc
*ar
, AR6000_WLAN_STATE state
)
420 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("%s: Deep sleep %d %d \n", __func__
,state
, ar
->arWlanPowerState
));
422 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("Wlan OFF %d BT OFf %d \n", ar
->arWlanOff
, ar
->arBTOff
));
425 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode
;
427 if (state
== WLAN_ENABLED
) {
430 /* Not in deep sleep state.. exit */
431 if (ar
->arWlanPowerState
!= WLAN_POWER_STATE_DEEP_SLEEP
) {
432 if (ar
->arWlanPowerState
!= WLAN_POWER_STATE_ON
) {
433 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Strange state when we resume from deep sleep %d\n", ar
->arWlanPowerState
));
438 fg_start_period
= (ar
->scParams
.fg_start_period
==0) ? 1 : ar
->scParams
.fg_start_period
;
439 hostSleepMode
.awake
= true;
440 hostSleepMode
.asleep
= false;
442 if ((status
=wmi_set_host_sleep_mode_cmd(ar
->arWmi
, &hostSleepMode
)) != A_OK
) {
446 /* Change the state to ON */
447 ar
->arWlanPowerState
= WLAN_POWER_STATE_ON
;
449 /* Enable foreground scanning */
450 if ((status
=wmi_scanparams_cmd(ar
->arWmi
, fg_start_period
,
451 ar
->scParams
.fg_end_period
,
452 ar
->scParams
.bg_period
,
453 ar
->scParams
.minact_chdwell_time
,
454 ar
->scParams
.maxact_chdwell_time
,
455 ar
->scParams
.pas_chdwell_time
,
456 ar
->scParams
.shortScanRatio
,
457 ar
->scParams
.scanCtrlFlags
,
458 ar
->scParams
.max_dfsch_act_time
,
459 ar
->scParams
.maxact_scan_per_ssid
)) != A_OK
)
464 if (ar
->arNetworkType
!= AP_NETWORK
)
467 if (ar6000_connect_to_ap(ar
) != A_OK
) {
468 /* no need to report error if connection failed */
473 } else if (state
== WLAN_DISABLED
){
474 WMI_SET_WOW_MODE_CMD wowMode
= { .enable_wow
= false };
476 /* Already in deep sleep state.. exit */
477 if (ar
->arWlanPowerState
!= WLAN_POWER_STATE_ON
) {
478 if (ar
->arWlanPowerState
!= WLAN_POWER_STATE_DEEP_SLEEP
) {
479 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Strange state when we suspend for deep sleep %d\n", ar
->arWlanPowerState
));
484 if (ar
->arNetworkType
!= AP_NETWORK
)
486 /* Disconnect from the AP and disable foreground scanning */
487 AR6000_SPIN_LOCK(&ar
->arLock
, 0);
488 if (ar
->arConnected
== true || ar
->arConnectPending
== true) {
489 AR6000_SPIN_UNLOCK(&ar
->arLock
, 0);
490 wmi_disconnect_cmd(ar
->arWmi
);
492 AR6000_SPIN_UNLOCK(&ar
->arLock
, 0);
496 ar
->scan_triggered
= 0;
498 if ((status
=wmi_scanparams_cmd(ar
->arWmi
, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != A_OK
) {
502 /* make sure we disable wow for deep sleep */
503 if ((status
=wmi_set_wow_mode_cmd(ar
->arWmi
, &wowMode
))!=A_OK
)
508 ar6000_TxDataCleanup(ar
);
509 #ifndef ATH6K_CONFIG_OTA_MODE
510 wmi_powermode_cmd(ar
->arWmi
, REC_POWER
);
513 hostSleepMode
.awake
= false;
514 hostSleepMode
.asleep
= true;
515 if ((status
=wmi_set_host_sleep_mode_cmd(ar
->arWmi
, &hostSleepMode
))!=A_OK
) {
518 if (ar
->arTxPending
[ar
->arControlEp
]) {
519 u32 timeleft
= wait_event_interruptible_timeout(arEvent
,
520 ar
->arTxPending
[ar
->arControlEp
] == 0, wmitimeout
* HZ
);
521 if (!timeleft
|| signal_pending(current
)) {
526 status
= hifWaitForPendingRecv(ar
->arHifDevice
);
528 ar
->arWlanPowerState
= WLAN_POWER_STATE_DEEP_SLEEP
;
533 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to enter/exit deep sleep %d\n", state
));
540 ar6000_update_wlan_pwr_state(struct ar6_softc
*ar
, AR6000_WLAN_STATE state
, bool pmEvent
)
543 u16 powerState
, oldPowerState
;
544 AR6000_WLAN_STATE oldstate
= ar
->arWlanState
;
545 bool wlanOff
= ar
->arWlanOff
;
547 bool btOff
= ar
->arBTOff
;
548 #endif /* CONFIG_PM */
550 if ((state
!=WLAN_DISABLED
&& state
!=WLAN_ENABLED
)) {
554 if (ar
->bIsDestroyProgress
) {
558 if (down_interruptible(&ar
->arSem
)) {
562 if (ar
->bIsDestroyProgress
) {
567 ar
->arWlanState
= wlanOff
? WLAN_DISABLED
: state
;
568 oldPowerState
= ar
->arWlanPowerState
;
569 if (state
== WLAN_ENABLED
) {
570 powerState
= ar
->arWlanPowerState
;
571 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("WLAN PWR set to ENABLE^^\n"));
573 if (powerState
== WLAN_POWER_STATE_DEEP_SLEEP
) {
574 status
= ar6000_setup_deep_sleep_state(ar
, WLAN_ENABLED
);
575 } else if (powerState
== WLAN_POWER_STATE_CUT_PWR
) {
576 status
= ar6000_setup_cut_power_state(ar
, WLAN_ENABLED
);
580 else if (pmEvent
&& wlanOff
) {
581 bool allowCutPwr
= ((!ar
->arBTSharing
) || btOff
);
582 if ((powerState
==WLAN_POWER_STATE_CUT_PWR
) && (!allowCutPwr
)) {
583 /* Come out of cut power */
584 ar6000_setup_cut_power_state(ar
, WLAN_ENABLED
);
585 status
= ar6000_setup_deep_sleep_state(ar
, WLAN_DISABLED
);
588 #endif /* CONFIG_PM */
589 } else if (state
== WLAN_DISABLED
) {
590 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("WLAN PWR set to DISABLED~\n"));
591 powerState
= WLAN_POWER_STATE_DEEP_SLEEP
;
593 if (pmEvent
) { /* disable due to suspend */
594 bool suspendCutPwr
= (ar
->arSuspendConfig
== WLAN_SUSPEND_CUT_PWR
||
595 (ar
->arSuspendConfig
== WLAN_SUSPEND_WOW
&&
596 ar
->arWow2Config
==WLAN_SUSPEND_CUT_PWR
));
597 bool suspendCutIfBtOff
= ((ar
->arSuspendConfig
==
598 WLAN_SUSPEND_CUT_PWR_IF_BT_OFF
||
599 (ar
->arSuspendConfig
== WLAN_SUSPEND_WOW
&&
600 ar
->arWow2Config
==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF
)) &&
601 (!ar
->arBTSharing
|| btOff
));
602 if ((suspendCutPwr
) ||
603 (suspendCutIfBtOff
) ||
604 (ar
->arWlanState
==WLAN_POWER_STATE_CUT_PWR
))
606 powerState
= WLAN_POWER_STATE_CUT_PWR
;
610 (ar
->arWlanOffConfig
== WLAN_OFF_CUT_PWR
) &&
611 (!ar
->arBTSharing
|| btOff
))
613 /* For BT clock sharing designs, CUT_POWER depend on BT state */
614 powerState
= WLAN_POWER_STATE_CUT_PWR
;
617 #endif /* CONFIG_PM */
619 if (powerState
== WLAN_POWER_STATE_DEEP_SLEEP
) {
620 if (ar
->arWlanPowerState
== WLAN_POWER_STATE_CUT_PWR
) {
621 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("Load firmware before set to deep sleep\n"));
622 ar6000_setup_cut_power_state(ar
, WLAN_ENABLED
);
624 status
= ar6000_setup_deep_sleep_state(ar
, WLAN_DISABLED
);
625 } else if (powerState
== WLAN_POWER_STATE_CUT_PWR
) {
626 status
= ar6000_setup_cut_power_state(ar
, WLAN_DISABLED
);
632 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Fail to setup WLAN state %d\n", ar
->arWlanState
));
633 ar
->arWlanState
= oldstate
;
634 } else if (status
== A_OK
) {
635 WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent
, *pSleepEvent
= NULL
;
636 if ((ar
->arWlanPowerState
== WLAN_POWER_STATE_ON
) && (oldPowerState
!= WLAN_POWER_STATE_ON
)) {
637 wmiSleepEvent
.sleepState
= WMI_REPORT_SLEEP_STATUS_IS_AWAKE
;
638 pSleepEvent
= &wmiSleepEvent
;
639 } else if ((ar
->arWlanPowerState
!= WLAN_POWER_STATE_ON
) && (oldPowerState
== WLAN_POWER_STATE_ON
)) {
640 wmiSleepEvent
.sleepState
= WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP
;
641 pSleepEvent
= &wmiSleepEvent
;
644 AR_DEBUG_PRINTF(ATH_DEBUG_PM
, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent
.sleepState
));
645 ar6000_send_event_to_app(ar
, WMI_REPORT_SLEEP_STATE_EVENTID
, (u8
*)pSleepEvent
,
646 sizeof(WMI_REPORT_SLEEP_STATE_EVENTID
));
654 ar6000_set_bt_hw_state(struct ar6_softc
*ar
, u32 enable
)
657 bool off
= (enable
== 0);
659 if (ar
->arBTOff
== off
) {
663 status
= ar6000_update_wlan_pwr_state(ar
, ar
->arWlanOff
? WLAN_DISABLED
: WLAN_ENABLED
, false);
671 ar6000_set_wlan_state(struct ar6_softc
*ar
, AR6000_WLAN_STATE state
)
674 bool off
= (state
== WLAN_DISABLED
);
675 if (ar
->arWlanOff
== off
) {
679 status
= ar6000_update_wlan_pwr_state(ar
, state
, false);
683 void ar6000_pm_init()
685 A_REGISTER_MODULE_DEBUG_INFO(pm
);
688 * Register ar6000_pm_device into system.
689 * We should also add platform_device into the first item of array
690 * of devices[] in file arch/xxx/mach-xxx/board-xxxx.c
692 if (platform_driver_register(&ar6000_pm_device
)) {
693 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("ar6000: fail to register the power control driver.\n"));
695 #endif /* CONFIG_PM */
698 void ar6000_pm_exit()
701 platform_driver_unregister(&ar6000_pm_device
);
702 #endif /* CONFIG_PM */