ar9300_power.c revision 250003
1/*
2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "opt_ah.h"
18
19#ifdef AH_SUPPORT_AR9300
20
21#include "ah.h"
22#include "ah_internal.h"
23
24#include "ar9300/ar9300.h"
25#include "ar9300/ar9300reg.h"
26
27#if ATH_WOW_OFFLOAD
28void ar9300_wowoffload_prep(struct ath_hal *ah)
29{
30    struct ath_hal_9300 *ahp = AH9300(ah);
31
32    ahp->ah_mcast_filter_l32_set = 0;
33    ahp->ah_mcast_filter_u32_set = 0;
34}
35
36void ar9300_wowoffload_post(struct ath_hal *ah)
37{
38    struct ath_hal_9300 *ahp = AH9300(ah);
39    u_int32_t val;
40
41    if (ahp->ah_mcast_filter_l32_set != 0) {
42        val = OS_REG_READ(ah, AR_MCAST_FIL0);
43        val &= ~ahp->ah_mcast_filter_l32_set;
44        OS_REG_WRITE(ah, AR_MCAST_FIL0, val);
45    }
46    if (ahp->ah_mcast_filter_u32_set != 0) {
47        val = OS_REG_READ(ah, AR_MCAST_FIL1);
48        val &= ~ahp->ah_mcast_filter_u32_set;
49        OS_REG_WRITE(ah, AR_MCAST_FIL1, val);
50    }
51
52    ahp->ah_mcast_filter_l32_set = 0;
53    ahp->ah_mcast_filter_u32_set = 0;
54}
55
56static void ar9300_wowoffload_add_mcast_filter(struct ath_hal *ah, u_int8_t *mc_addr)
57{
58    struct ath_hal_9300 *ahp = AH9300(ah);
59    u_int32_t reg, val;
60    u_int8_t  pos, high32;
61
62    memcpy((u_int8_t *) &val, &mc_addr[0], 3);
63    pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
64    memcpy((u_int8_t *) &val, &mc_addr[3], 3);
65    pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
66    high32 = pos & 0x20;
67    reg = high32 ? AR_MCAST_FIL1 : AR_MCAST_FIL0;
68    pos &= 0x1F;
69
70    val = OS_REG_READ(ah, reg);
71    if ((val & (1 << pos)) == 0) {
72        val |= (1 << pos);
73        if (high32) {
74            ahp->ah_mcast_filter_u32_set |= (1 << pos);
75        } else {
76            ahp->ah_mcast_filter_l32_set |= (1 << pos);
77        }
78        OS_REG_WRITE(ah, reg, val);
79    }
80}
81
82/*
83 * DeviceID SWAR - EV91928
84 *
85 * During SW WOW, 0x4004[13] is set to allow BT eCPU to access WLAN MAC
86 * registers. Setting 00x4004[13] will prevent eeprom state machine to
87 * load customizable PCIE configuration registers, which lead to the PCIE
88 * device id stay as default 0xABCD. The SWAR to have BT eCPU to write
89 * to PCIE registers as soon as it detects PCIE reset is deasserted.
90 */
91void ar9300_wowoffload_download_devid_swar(struct ath_hal *ah)
92{
93    u_int32_t addr = AR_WOW_OFFLOAD_WLAN_REGSET_NUM;
94
95    OS_REG_WRITE(ah, addr, 8);
96    addr += 4;
97    OS_REG_WRITE(ah, addr, 0x5000);
98    addr += 4;
99    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_000 = %08x\n",
100             AH_PRIVATE(ah)->ah_config.ath_hal_pcie_000);
101    OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_000);
102    addr += 4;
103    OS_REG_WRITE(ah, addr, 0x5008);
104    addr += 4;
105    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_008 = %08x\n",
106             AH_PRIVATE(ah)->ah_config.ath_hal_pcie_008);
107    OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_008);
108    addr += 4;
109    OS_REG_WRITE(ah, addr, 0x502c);
110    addr += 4;
111    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_02c = %08x\n",
112             AH_PRIVATE(ah)->ah_config.ath_hal_pcie_02c);
113    OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_02c);
114    addr += 4;
115    OS_REG_WRITE(ah, addr, 0x18c00);
116    addr += 4;
117    OS_REG_WRITE(ah, addr, 0x18212ede);
118    addr += 4;
119    OS_REG_WRITE(ah, addr, 0x18c04);
120    addr += 4;
121    OS_REG_WRITE(ah, addr, 0x008001d8);
122    addr += 4;
123    OS_REG_WRITE(ah, addr, 0x18c08);
124    addr += 4;
125    OS_REG_WRITE(ah, addr, 0x0003580c);
126    addr += 4;
127    OS_REG_WRITE(ah, addr, 0x570c);
128    addr += 4;
129    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_70c = %08x\n",
130             AH_PRIVATE(ah)->ah_config.ath_hal_pcie_70c);
131    OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_70c);
132    addr += 4;
133    OS_REG_WRITE(ah, addr, 0x5040);
134    addr += 4;
135    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_040 = %08x\n",
136             AH_PRIVATE(ah)->ah_config.ath_hal_pcie_040);
137    OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_040);
138    addr += 4;
139/*
140    A_SOC_REG_WRITE(0x45000, 0x0034168c);
141    A_SOC_REG_WRITE(0x45008, 0x02800001);
142    A_SOC_REG_WRITE(0x4502c, 0x3117168c);
143    A_SOC_REG_WRITE(0x58c00, 0x18212ede);
144    A_SOC_REG_WRITE(0x58c04, 0x000801d8);
145    A_SOC_REG_WRITE(0x58c08, 0x0003580c);
146    A_SOC_REG_WRITE(0x4570c, 0x275f3f01);
147    A_SOC_REG_WRITE(0x45040, 0xffc25001);
148*/
149}
150
151/* Retrieve updated information from MAC PCU buffer.
152 * Embedded CPU would have written the value before exiting WoW
153 * */
154void ar9300_wowoffload_retrieve_data(struct ath_hal *ah, void *buf, u_int32_t param)
155{
156    u_int32_t rc_lower, rc_upper;
157
158    if (param == WOW_PARAM_REPLAY_CNTR) {
159        rc_lower = OS_REG_READ(ah, AR_WOW_TXBUF(0));
160        rc_upper = OS_REG_READ(ah, AR_WOW_TXBUF(1));
161        *(u_int64_t *)buf = rc_lower + (rc_upper << 32);
162    }
163    else if (param == WOW_PARAM_KEY_TSC) {
164        rc_lower = OS_REG_READ(ah, AR_WOW_TXBUF(2));
165        rc_upper = OS_REG_READ(ah, AR_WOW_TXBUF(3));
166        *(u_int64_t *)buf = rc_lower + (rc_upper << 32);
167    }
168    else if (param == WOW_PARAM_TX_SEQNUM) {
169        *(u_int32_t *)buf = OS_REG_READ(ah, AR_WOW_TXBUF(4));
170    }
171
172}
173
174/* Download GTK rekey related information to the embedded CPU */
175u_int32_t ar9300_wowoffload_download_rekey_data(struct ath_hal *ah, u_int32_t *data, u_int32_t bytes)
176{
177    int i;
178    int mbox_status = OS_REG_READ(ah, AR_MBOX_CTRL_STATUS);
179    u_int32_t gtk_data_start;
180
181    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) %s, bytes=%d\n", __func__, bytes);
182    if (AR_SREV_JUPITER(ah) &&
183        (bytes > (AR_WOW_OFFLOAD_GTK_DATA_WORDS_JUPITER * 4)))
184    {
185        bytes = AR_WOW_OFFLOAD_GTK_DATA_WORDS_JUPITER * 4;
186        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) bytes truncated to %d\n", bytes);
187    }
188    /* Check if mailbox is busy */
189    if (mbox_status != 0) {
190        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: Mailbox register busy! Reg = 0x%x", __func__, mbox_status);
191        return 1;
192    }
193
194    /* Clear status */
195    OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0);
196    OS_REG_WRITE(ah, AR_WLAN_WOW_ENABLE, 0);
197    OS_REG_WRITE(ah, AR_WLAN_WOW_STATUS, 0xFFFFFFFF);
198
199    if (AR_SREV_JUPITER(ah)) {
200        gtk_data_start = AR_WOW_OFFLOAD_GTK_DATA_START_JUPITER;
201    } else {
202        gtk_data_start = AR_WOW_OFFLOAD_GTK_DATA_START;
203    }
204    for (i = 0;i < bytes/4; i++) {
205        OS_REG_WRITE(ah, gtk_data_start + i * 4, data[i]);
206    }
207
208    return 0;
209}
210
211void ar9300_wowoffload_download_acer_magic( struct ath_hal *ah,
212                                            HAL_BOOL      valid,
213                                            u_int8_t* datap,
214                                            u_int32_t bytes)
215{
216    u_int32_t *p32 = (u_int32_t *) datap;
217    u_int32_t l = 0, u = 0;
218
219    if (valid) {
220        l = *p32;
221        p32++;
222        u = *(u_int16_t *) p32;
223    }
224
225    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_ACER_MAGIC_START, l);
226    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_ACER_MAGIC_START + 4, u);
227
228    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
229        "%s: Aer Magic: %02x-%02x-%02x-%02x-%02x-%02x\n", __func__,
230        datap[0], datap[1], datap[2], datap[3], datap[4], datap[5]);
231}
232
233void ar9300_wowoffload_download_acer_swka(  struct ath_hal *ah,
234                                            u_int32_t  id,
235                                            HAL_BOOL       valid,
236                                            u_int32_t  period,
237                                            u_int32_t  size,
238                                            u_int32_t* datap)
239{
240    u_int32_t ka_period[2] = {
241        AR_WOW_OFFLOAD_ACER_KA0_PERIOD_MS,
242        AR_WOW_OFFLOAD_ACER_KA1_PERIOD_MS
243    };
244    u_int32_t ka_size[2] = {
245        AR_WOW_OFFLOAD_ACER_KA0_SIZE,
246        AR_WOW_OFFLOAD_ACER_KA1_SIZE
247    };
248    u_int32_t ka_data[2] = {
249        AR_WOW_OFFLOAD_ACER_KA0_DATA,
250        AR_WOW_OFFLOAD_ACER_KA1_DATA
251    };
252    u_int32_t n_data = AR_WOW_OFFLOAD_ACER_KA0_DATA_WORDS;
253    int i;
254
255    if (id >= 2) {
256        return;
257    }
258
259    if (valid) {
260        OS_REG_WRITE(ah, ka_period[id], period);
261        OS_REG_WRITE(ah, ka_size[id], size);
262    } else {
263        OS_REG_WRITE(ah, ka_period[id], 0);
264        OS_REG_WRITE(ah, ka_size[id], 0);
265    }
266    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: id=%d, period=%d ms, size=%d bytes\n",
267            __func__, id, period, size);
268
269    if (size < (n_data * 4)) {
270        n_data = (size + 3) / 4;
271    }
272    for (i=0; i<n_data * 4; i+=4) {
273        OS_REG_WRITE(ah, ka_data[id] + i, *datap);
274        /*HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) %08x\n", *datap);*/
275        datap++;
276    }
277}
278
279void ar9300_wowoffload_download_arp_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data)
280{
281    u_int32_t addr;
282    struct hal_wow_offload_arp_info *p_info = (struct hal_wow_offload_arp_info *) data;
283
284    if (id == 0) {
285        addr = AR_WOW_OFFLOAD_ARP0_VALID;
286    } else if (id == 1) {
287        addr = AR_WOW_OFFLOAD_ARP1_VALID;
288    } else {
289        return;
290    }
291
292    if (p_info->valid) {
293        OS_REG_WRITE(ah, addr, 0x1);
294        addr += 4;
295        OS_REG_WRITE(ah, addr, p_info->RemoteIPv4Address.u32);
296        addr += 4;
297        OS_REG_WRITE(ah, addr, p_info->HostIPv4Address.u32);
298        addr += 4;
299        OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[0]);
300        addr += 4;
301        OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[1]);
302    } else {
303        OS_REG_WRITE(ah, addr, 0x0);
304    }
305}
306
307#define WOW_WRITE_NS_IPV6_ADDRESS(_ah, _buf_addr, _p_ipv6_addr) \
308    {                                                           \
309        u_int32_t   offset = (_buf_addr);                       \
310        u_int32_t  *p_ipv6_addr = (u_int32_t *) (_p_ipv6_addr); \
311        int i;                                                  \
312        for (i = 0; i < 4; i++) {                               \
313            OS_REG_WRITE((_ah), offset, *p_ipv6_addr);          \
314            offset += 4;                                        \
315            p_ipv6_addr ++;                                     \
316        }                                                       \
317    }
318
319void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data)
320{
321    u_int32_t addr;
322    struct hal_wow_offload_ns_info *p_info = (struct hal_wow_offload_ns_info *) data;
323    u_int8_t mc_addr[6];
324
325    if (id == 0) {
326        addr = AR_WOW_OFFLOAD_NS0_VALID;
327    } else if (id == 1) {
328        addr = AR_WOW_OFFLOAD_NS1_VALID;
329    } else {
330        return;
331    }
332
333    if (p_info->valid) {
334        OS_REG_WRITE(ah, addr, 0x1);
335        addr += 4;
336        WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->RemoteIPv6Address.u32[0]);
337        addr += 4 * 4;
338        WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->SolicitedNodeIPv6Address.u32[0]);
339        addr += 4 * 4;
340        OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[0]);
341        addr += 4;
342        OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[1]);
343        addr += 4;
344        WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->TargetIPv6Addresses[0].u32[0]);
345        addr += 4 * 4;
346        WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->TargetIPv6Addresses[1].u32[0]);
347
348        mc_addr[0] = 0x33;
349        mc_addr[1] = 0x33;
350        mc_addr[2] = 0xFF;
351        mc_addr[3] = p_info->SolicitedNodeIPv6Address.u8[13];
352        mc_addr[4] = p_info->SolicitedNodeIPv6Address.u8[14];
353        mc_addr[5] = p_info->SolicitedNodeIPv6Address.u8[15];
354        ar9300_wowoffload_add_mcast_filter(ah, mc_addr);
355    } else {
356        OS_REG_WRITE(ah, addr, 0x0);
357    }
358}
359
360/* Download transmit parameters for GTK response frame during WoW
361 * offload */
362u_int32_t ar9300_wow_offload_download_hal_params(struct ath_hal *ah)
363{
364    u_int32_t tpc = 0x3f; /* Transmit Power Control */
365    u_int32_t tx_tries_series = 7;
366    u_int32_t tx_rate_series, transmit_rate;
367    u_int32_t gtk_txdesc_param_start;
368
369    if (AH_PRIVATE(ah)->ah_curchan->channel_flags & CHANNEL_CCK) {
370        transmit_rate = 0x1B;    /* CCK_1M */
371    } else {
372        transmit_rate = 0xB;     /* OFDM_6M */
373    }
374
375    /* Use single rate for now. Change later as need be */
376    tx_rate_series  = transmit_rate;
377    tx_tries_series = 7;
378
379    if (AR_SREV_JUPITER(ah)) {
380        gtk_txdesc_param_start = AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START_JUPITER;
381    } else {
382        gtk_txdesc_param_start = AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START;
383    }
384#define AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(x) (gtk_txdesc_param_start + ((x) * 4))
385
386    /* Do not change the data order unless firmware code on embedded
387     * CPU is changed correspondingly */
388    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(0), tx_rate_series);
389    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(1), tx_tries_series);
390    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(2), AH9300(ah)->ah_tx_chainmask);
391    OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(3), tpc);
392
393    return 0;
394}
395
396/* Indicate to the embedded CPU that host is ready to enter WoW mode.
397 * Embedded CPU will copy relevant information from the MAC PCU buffer
398 */
399u_int32_t ar9300_wow_offload_handshake(struct ath_hal *ah, u_int32_t pattern_enable)
400{
401    int val;
402    int mbox_status = OS_REG_READ(ah, AR_MBOX_CTRL_STATUS);
403#if ATH_WOW_OFFLOAD
404    u_int32_t bt_handshake_timeout_us = HAL_WOW_CTRL_WAIT_BT_TO(ah) * 100000;
405
406#define AH_DEFAULT_BT_WAIT_TIMEOUT  3000000; /* 3 sec */
407    if (bt_handshake_timeout_us == 0) {
408        bt_handshake_timeout_us = AH_DEFAULT_BT_WAIT_TIMEOUT;
409    }
410    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) TIMEOUT: %d us\n", bt_handshake_timeout_us);
411#endif /* ATH_WOW_OFFLOAD */
412
413    if (mbox_status & AR_MBOX_WOW_REQ) {
414        /* WOW mode request handshake is already in progress.
415         * Do nothing */
416        return 0;
417    }
418
419    /* Clear status */
420    OS_REG_WRITE(ah, AR_MBOX_CTRL_STATUS, 0);
421    OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0);
422    OS_REG_WRITE(ah, AR_WLAN_WOW_ENABLE, 0);
423    OS_REG_WRITE(ah, AR_WLAN_WOW_STATUS, 0xFFFFFFFF);
424
425    OS_REG_WRITE(ah, AR_RIMT, 0);
426    OS_REG_WRITE(ah, AR_TIMT, 0);
427
428    val = 0;
429    if (pattern_enable & AH_WOW_USER_PATTERN_EN) {
430        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - User pattern\n");
431        val |= AR_EMB_CPU_WOW_ENABLE_PATTERN_MATCH;
432    }
433    else {
434        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - User pattern\n");
435    }
436    if ((pattern_enable & AH_WOW_MAGIC_PATTERN_EN)
437#if ATH_WOW_OFFLOAD
438        || (pattern_enable & AH_WOW_ACER_MAGIC_EN)
439#endif
440        )
441    {
442        val |= AR_EMB_CPU_WOW_ENABLE_MAGIC_PATTERN;
443        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Magic pattern\n");
444    }
445    else {
446        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Magic pattern\n");
447    }
448    if ((pattern_enable & AH_WOW_LINK_CHANGE)
449#if ATH_WOW_OFFLOAD
450        || HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_KAFAIL_ENABLE)
451#endif
452        )
453    {
454        val |= AR_EMB_CPU_WOW_ENABLE_KEEP_ALIVE_FAIL;
455        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Kepp alive fail\n");
456    }
457    else {
458        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Kepp alive fail\n");
459    }
460    if (pattern_enable & AH_WOW_BEACON_MISS) {
461        val |= AR_EMB_CPU_WOW_ENABLE_BEACON_MISS;
462        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Becon Miss\n");
463    }
464    else {
465        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Becon Miss\n");
466    }
467
468    OS_REG_WRITE(ah, AR_EMB_CPU_WOW_ENABLE, val);
469
470    OS_REG_CLR_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF);
471    OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_REQ);
472    OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_INT_EMB_CPU);
473
474    if (!ath_hal_wait(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
475        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: WoW offload handshake failed", __func__);
476        return 0;
477    }
478    else {
479        OS_REG_CLR_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF);
480        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: WoW offload handshake successful",__func__);
481    }
482    return 1;
483}
484#endif /* ATH_WOW_OFFLOAD */
485
486/*
487 * Notify Power Mgt is enabled in self-generated frames.
488 * If requested, force chip awake.
489 *
490 * Returns A_OK if chip is awake or successfully forced awake.
491 *
492 * WARNING WARNING WARNING
493 * There is a problem with the chip where sometimes it will not wake up.
494 */
495HAL_BOOL
496ar9300_set_power_mode_awake(struct ath_hal *ah, int set_chip)
497{
498    struct ath_hal_9300 *ahp = AH9300(ah);
499#define POWER_UP_TIME   10000
500    u_int32_t val;
501    int i;
502
503    /* Set Bits 14 and 17 of AR_WA before powering on the chip. */
504    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val);
505    OS_DELAY(10); /* delay to allow the write to take effect. */
506
507    if (set_chip) {
508        /* Do a Power-On-Reset if MAC is shutdown */
509        if ((OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_SHUTDOWN)) {
510            if (ar9300_set_reset_reg(ah, HAL_RESET_POWER_ON) != AH_TRUE) {
511                HALASSERT(0);
512                return AH_FALSE;
513            }
514        }
515
516        OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
517
518        OS_DELAY(50);
519
520        for (i = POWER_UP_TIME / 50; i > 0; i--) {
521            val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
522            if (val == AR_RTC_STATUS_ON) {
523                break;
524            }
525            OS_DELAY(50);
526            OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
527        }
528        if (i == 0) {
529            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: Failed to wakeup in %uus\n",
530                     __func__, POWER_UP_TIME / 20);
531            return AH_FALSE;
532        }
533
534    }
535
536    OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
537    return AH_TRUE;
538#undef POWER_UP_TIME
539}
540
541/*
542 * Notify Power Mgt is disabled in self-generated frames.
543 * If requested, force chip to sleep.
544 */
545static void
546ar9300_set_power_mode_sleep(struct ath_hal *ah, int set_chip)
547{
548    struct ath_hal_9300 *ahp = AH9300(ah);
549
550    OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
551    if (set_chip ) {
552        if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
553            OS_REG_WRITE(ah, AR_TIMER_MODE,
554                    OS_REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
555            OS_REG_WRITE(ah, AR_GEN_TIMERS2_MODE,
556                    OS_REG_READ(ah, AR_GEN_TIMERS2_MODE) & 0xFFFFFF00);
557            OS_REG_WRITE(ah, AR_SLP32_INC,
558                    OS_REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
559            OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
560            OS_DELAY(100);
561        }
562        /* Clear the RTC force wake bit to allow the mac to go to sleep */
563        OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
564
565        if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
566            /*
567             * In Jupiter, after enter sleep mode, hardware will send
568             * a SYS_SLEEPING message through MCI interface. Add a
569             * few us delay to make sure the message can reach BT side.
570             */
571            OS_DELAY(100);
572        }
573
574        if (!AR_SREV_JUPITER_10(ah)) {
575            /* Shutdown chip. Active low */
576            OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
577            /* Settle time */
578            OS_DELAY(2);
579        }
580    }
581
582#if ATH_WOW_OFFLOAD
583    if (!AR_SREV_JUPITER(ah) || !HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SET_4004_BIT14))
584#endif /* ATH_WOW_OFFLOAD */
585    {
586        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
587        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA),
588               ahp->ah_wa_reg_val & ~AR_WA_D3_TO_L1_DISABLE);
589    }
590}
591
592/*
593 * Notify Power Management is enabled in self-generating
594 * frames. If request, set power mode of chip to
595 * auto/normal.  Duration in units of 128us (1/8 TU).
596 */
597static void
598ar9300_set_power_mode_network_sleep(struct ath_hal *ah, int set_chip)
599{
600    struct ath_hal_9300 *ahp = AH9300(ah);
601
602    OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
603    if (set_chip) {
604        HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
605
606        if (! p_cap->hal_auto_sleep_support) {
607            /* Set wake_on_interrupt bit; clear force_wake bit */
608            OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
609        }
610        else {
611            /*
612             * When chip goes into network sleep, it could be waken up by
613             * MCI_INT interrupt caused by BT's HW messages (LNA_xxx, CONT_xxx)
614             * which chould be in a very fast rate (~100us). This will cause
615             * chip to leave and re-enter network sleep mode frequently, which
616             * in consequence will have WLAN MCI HW to generate lots of
617             * SYS_WAKING and SYS_SLEEPING messages which will make BT CPU
618             * to busy to process.
619             */
620            if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
621                OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
622                        OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
623                                    ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK);
624            }
625
626            /* Clear the RTC force wake bit to allow the mac to go to sleep */
627            OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
628
629            if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
630                /*
631                 * In Jupiter, after enter sleep mode, hardware will send
632                 * a SYS_SLEEPING message through MCI interface. Add a
633                 * few us delay to make sure the message can reach BT side.
634                 */
635                OS_DELAY(30);
636            }
637        }
638    }
639
640#if ATH_WOW_OFFLOAD
641    if (!AR_SREV_JUPITER(ah) || !HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SET_4004_BIT14))
642#endif /* ATH_WOW_OFFLOAD */
643    {
644        /* Clear Bit 14 of AR_WA after putting chip into Sleep mode. */
645        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA),
646               ahp->ah_wa_reg_val & ~AR_WA_D3_TO_L1_DISABLE);
647    }
648}
649
650/*
651 * Set power mgt to the requested mode, and conditionally set
652 * the chip as well
653 */
654HAL_BOOL
655ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip)
656{
657    struct ath_hal_9300 *ahp = AH9300(ah);
658#if AH_DEBUG || AH_PRINT_FILTER
659    static const char* modes[] = {
660        "AWAKE",
661        "FULL-SLEEP",
662        "NETWORK SLEEP",
663        "UNDEFINED"
664    };
665#endif
666    int status = AH_TRUE;
667
668    HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
669        modes[ar9300_get_power_mode(ah)], modes[mode],
670        set_chip ? "set chip " : "");
671
672    switch (mode) {
673    case HAL_PM_AWAKE:
674        status = ar9300_set_power_mode_awake(ah, set_chip);
675#if ATH_SUPPORT_MCI
676        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
677            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
678        }
679#endif
680        break;
681    case HAL_PM_FULL_SLEEP:
682#if ATH_SUPPORT_MCI
683        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
684            if (ar9300_get_power_mode(ah) == HAL_PM_AWAKE) {
685                if ((ar9300_mci_state(ah, HAL_MCI_STATE_ENABLE, NULL) != 0) &&
686                    (ahp->ah_mci_bt_state != MCI_BT_SLEEP) &&
687                    !ahp->ah_mci_halted_bt_gpm)
688                {
689                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
690                        "(MCI) %s: HALT BT GPM (full_sleep)\n", __func__);
691                    ar9300_mci_send_coex_halt_bt_gpm(ah, AH_TRUE, AH_TRUE);
692                }
693            }
694            ahp->ah_mci_ready = AH_FALSE;
695        }
696#endif
697#if ATH_SUPPORT_MCI
698        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
699            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
700        }
701#endif
702        ar9300_set_power_mode_sleep(ah, set_chip);
703        ahp->ah_chip_full_sleep = AH_TRUE;
704        break;
705    case HAL_PM_NETWORK_SLEEP:
706#if ATH_SUPPORT_MCI
707        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
708            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
709        }
710#endif
711        ar9300_set_power_mode_network_sleep(ah, set_chip);
712        break;
713    default:
714        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
715            "%s: unknown power mode %u\n", __func__, mode);
716        return AH_FALSE;
717    }
718    return status;
719}
720
721/*
722 * Return the current sleep mode of the chip
723 */
724HAL_POWER_MODE
725ar9300_get_power_mode(struct ath_hal *ah)
726{
727    int mode = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
728
729    switch (mode) {
730    case AR_RTC_STATUS_ON:
731    case AR_RTC_STATUS_WAKEUP:
732        return HAL_PM_AWAKE;
733        break;
734    case AR_RTC_STATUS_SLEEP:
735        return HAL_PM_NETWORK_SLEEP;
736        break;
737    case AR_RTC_STATUS_SHUTDOWN:
738        return HAL_PM_FULL_SLEEP;
739        break;
740    default:
741        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
742            "%s: unknown power mode 0x%x\n", __func__, mode);
743        return HAL_PM_UNDEFINED;
744    }
745}
746
747/*
748 * Set SM power save mode
749 */
750void
751ar9300_set_sm_power_mode(struct ath_hal *ah, HAL_SMPS_MODE mode)
752{
753    int regval;
754    struct ath_hal_9300 *ahp = AH9300(ah);
755
756    if (ar9300_get_capability(ah, HAL_CAP_DYNAMIC_SMPS, 0, AH_NULL) != HAL_OK) {
757        return;
758    }
759
760    /* Program low & high power chainmask settings and enable MAC control */
761    regval = SM(AR_PCU_SMPS_LPWR_CHNMSK_VAL, AR_PCU_SMPS_LPWR_CHNMSK) |
762             SM(ahp->ah_rx_chainmask, AR_PCU_SMPS_HPWR_CHNMSK) |
763             AR_PCU_SMPS_MAC_CHAINMASK;
764
765    /* Program registers according to required SM power mode.*/
766    switch (mode) {
767    case HAL_SMPS_SW_CTRL_LOW_PWR:
768        OS_REG_WRITE(ah, AR_PCU_SMPS, regval);
769        break;
770    case HAL_SMPS_SW_CTRL_HIGH_PWR:
771        OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_SW_CTRL_HPWR);
772        break;
773    case HAL_SMPS_HW_CTRL:
774        OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_HW_CTRL_EN);
775        break;
776    case HAL_SMPS_DEFAULT:
777        OS_REG_WRITE(ah, AR_PCU_SMPS, 0);
778        break;
779    default:
780        break;
781    }
782    ahp->ah_sm_power_mode = mode;
783}
784
785#if ATH_WOW
786#if NOT_NEEDED_FOR_OSPREY /* not compiled for darwin */
787/*
788 * This routine is called to configure the SerDes register for the
789 * Merlin 2.0 and above chip during WOW sleep.
790 */
791static void
792ar9280_config_ser_des__wow_sleep(struct ath_hal *ah)
793{
794    int i;
795    struct ath_hal_9300 *ahp = AH9300(ah);
796
797    /*
798     * For WOW sleep, we reprogram the SerDes so that the PLL and CHK REQ
799     * are both enabled. This uses more power but the Maverick team reported
800     * that otherwise, WOW sleep is unstable and chip may disappears.
801     */
802    for (i = 0; i < ahp->ah_ini_pcie_serdes_wow.ia_rows; i++) {
803        OS_REG_WRITE(ah,
804            INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 0),
805            INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 1));
806    }
807    OS_DELAY(1000);
808}
809#endif /* if NOT_NEEDED_FOR_OSPREY */
810static HAL_BOOL
811ar9300_wow_create_keep_alive_pattern(struct ath_hal *ah)
812{
813    struct ath_hal_9300 *ahp = AH9300(ah);
814    u_int32_t  frame_len = 28;
815    u_int32_t  tpc = 0x3f;
816    u_int32_t  transmit_rate;
817    u_int32_t  frame_type = 0x2;    /* Frame Type -> Data; */
818    u_int32_t  sub_type = 0x4;      /* Subtype -> Null Data */
819    u_int32_t  to_ds = 1;
820    u_int32_t  duration_id = 0x3d;
821    u_int8_t   *sta_mac_addr, *ap_mac_addr;
822    u_int8_t   *addr1, *addr2, *addr3;
823    u_int32_t  ctl[13] = { 0, };
824#define NUM_KA_DATA_WORDS 6
825    u_int32_t  data_word[NUM_KA_DATA_WORDS];
826    u_int32_t  i;
827    u_int32_t wow_ka_dataword0;
828
829    sta_mac_addr = (u_int8_t *)ahp->ah_macaddr;
830    ap_mac_addr = (u_int8_t *)ahp->ah_bssid;
831    addr2 = sta_mac_addr;
832    addr1 = addr3 = ap_mac_addr;
833
834    if (AH_PRIVATE(ah)->ah_curchan->channel_flags & CHANNEL_CCK) {
835        transmit_rate = 0x1B;    /* CCK_1M */
836    } else {
837        transmit_rate = 0xB;     /* OFDM_6M */
838    }
839
840    /* Set the Transmit Buffer. */
841    ctl[0] = (frame_len | (tpc << 16));
842    ctl[1] = 0;
843    ctl[2] = (0x7 << 16);  /* tx_tries0 */
844    ctl[3] = transmit_rate;
845    ctl[4] = 0;
846    ctl[7] = ahp->ah_tx_chainmask << 2;
847
848    for (i = 0; i < 13; i++) {
849        OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
850    }
851
852    data_word[0] =
853        (frame_type  <<  2) |
854        (sub_type    <<  4) |
855        (to_ds       <<  8) |
856        (duration_id << 16);
857    data_word[1] = (((u_int32_t)addr1[3] << 24) | ((u_int32_t)addr1[2] << 16) |
858                  ((u_int32_t)addr1[1]) << 8 | ((u_int32_t)addr1[0]));
859    data_word[2] = (((u_int32_t)addr2[1] << 24) | ((u_int32_t)addr2[0] << 16) |
860                  ((u_int32_t)addr1[5]) << 8 | ((u_int32_t)addr1[4]));
861    data_word[3] = (((u_int32_t)addr2[5] << 24) | ((u_int32_t)addr2[4] << 16) |
862                  ((u_int32_t)addr2[3]) << 8 | ((u_int32_t)addr2[2]));
863    data_word[4] = (((u_int32_t)addr3[3] << 24) | ((u_int32_t)addr3[2] << 16) |
864                  ((u_int32_t)addr3[1]) << 8 | (u_int32_t)addr3[0]);
865    data_word[5] = (((u_int32_t)addr3[5]) << 8 | ((u_int32_t)addr3[4]));
866
867    if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
868        /* Jupiter 2.0 has an extra descriptor word (Time based
869         * discard) compared to other chips */
870        OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + 12 * 4), 0);
871        wow_ka_dataword0 = AR_WOW_TXBUF(13);
872    }
873    else {
874        wow_ka_dataword0 = AR_WOW_TXBUF(12);
875    }
876
877    for (i = 0; i < NUM_KA_DATA_WORDS; i++) {
878        OS_REG_WRITE(ah, (wow_ka_dataword0 + i * 4), data_word[i]);
879    }
880
881    return AH_TRUE;
882}
883
884/* TBD: Should querying hal for hardware capability */
885#define MAX_PATTERN_SIZE      256
886#define MAX_PATTERN_MASK_SIZE  32
887#define MAX_NUM_USER_PATTERN    6 /* Deducting the disassoc/deauth packets */
888
889void
890ar9300_wow_apply_pattern(
891    struct ath_hal *ah,
892    u_int8_t *p_ath_pattern,
893    u_int8_t *p_ath_mask,
894    int32_t pattern_count,
895    u_int32_t ath_pattern_len)
896{
897    int i;
898    u_int32_t    reg_pat[] = {
899                  AR_WOW_TB_PATTERN0,
900                  AR_WOW_TB_PATTERN1,
901                  AR_WOW_TB_PATTERN2,
902                  AR_WOW_TB_PATTERN3,
903                  AR_WOW_TB_PATTERN4,
904                  AR_WOW_TB_PATTERN5,
905                  AR_WOW_TB_PATTERN6,
906                  AR_WOW_TB_PATTERN7
907                 };
908    u_int32_t    reg_mask[] = {
909                  AR_WOW_TB_MASK0,
910                  AR_WOW_TB_MASK1,
911                  AR_WOW_TB_MASK2,
912                  AR_WOW_TB_MASK3,
913                  AR_WOW_TB_MASK4,
914                  AR_WOW_TB_MASK5,
915                  AR_WOW_TB_MASK6,
916                  AR_WOW_TB_MASK7
917                 };
918    u_int32_t   pattern_val;
919    u_int32_t   mask_val;
920    u_int32_t   val;
921    u_int8_t    mask_bit = 0x1;
922    u_int8_t    pattern;
923
924    /* TBD: should check count by querying the hardware capability */
925    if (pattern_count >= MAX_NUM_USER_PATTERN) {
926        return;
927    }
928
929    pattern = (u_int8_t)OS_REG_READ(ah, AR_WOW_PATTERN_REG);
930    pattern = pattern | (mask_bit << pattern_count);
931    OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, pattern);
932
933    /* Set the registers for pattern */
934    for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
935        pattern_val = (((u_int32_t)p_ath_pattern[i + 0]) |
936                       ((u_int32_t)p_ath_pattern[i + 1] << 8) |
937                       ((u_int32_t)p_ath_pattern[i + 2] << 16) |
938                       ((u_int32_t)p_ath_pattern[i + 3] << 24));
939        OS_REG_WRITE(ah, (reg_pat[pattern_count] + i), pattern_val);
940    }
941
942    /* Set the registers for mask */
943    for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
944        mask_val = (((u_int32_t)p_ath_mask[i + 0]) |
945                    ((u_int32_t)p_ath_mask[i + 1] << 8) |
946                    ((u_int32_t)p_ath_mask[i + 2] << 16) |
947                    ((u_int32_t)p_ath_mask[i + 3] << 24));
948        OS_REG_WRITE(ah, (reg_mask[pattern_count] + i), mask_val);
949    }
950
951    /* XXX */
952    /* Set the pattern length to be matched */
953    if (pattern_count < 4) {
954        /* Pattern 0-3 uses AR_WOW_LENGTH1_REG register */
955        val = OS_REG_READ(ah, AR_WOW_LENGTH1_REG);
956        val = ((val & (~AR_WOW_LENGTH1_MASK(pattern_count))) |
957               ((ath_pattern_len & AR_WOW_LENGTH_MAX) <<
958                AR_WOW_LENGTH1_SHIFT(pattern_count)));
959        OS_REG_WRITE(ah, AR_WOW_LENGTH1_REG, val);
960    } else {
961        /* Pattern 4-7 uses AR_WOW_LENGTH2_REG register */
962        val = OS_REG_READ(ah, AR_WOW_LENGTH2_REG);
963        val = ((val & (~AR_WOW_LENGTH2_MASK(pattern_count))) |
964               ((ath_pattern_len & AR_WOW_LENGTH_MAX) <<
965                AR_WOW_LENGTH2_SHIFT(pattern_count)));
966        OS_REG_WRITE(ah, AR_WOW_LENGTH2_REG, val);
967    }
968
969    AH_PRIVATE(ah)->ah_wow_event_mask |=
970        (1 << (pattern_count + AR_WOW_PATTERN_FOUND_SHIFT));
971
972    return;
973}
974
975HAL_BOOL
976ar9300_set_power_mode_wow_sleep(struct ath_hal *ah)
977{
978    OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
979
980    OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);    /* Set receive disable bit */
981    if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
982        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: dma failed to stop in 10ms\n"
983                 "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__,
984                 OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW));
985        return AH_FALSE;
986    } else {
987#if 0
988        OS_REG_WRITE(ah, AR_RXDP, 0x0);
989#endif
990
991        HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
992            "%s: TODO How to disable RXDP!!\n", __func__);
993
994#if ATH_SUPPORT_MCI
995        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
996            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
997        }
998#endif
999        OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
1000
1001        return AH_TRUE;
1002    }
1003}
1004
1005
1006HAL_BOOL
1007ar9300_wow_enable(
1008    struct ath_hal *ah,
1009    u_int32_t pattern_enable,
1010    u_int32_t timeout_in_seconds,
1011    int clearbssid,
1012    HAL_BOOL offloadEnable)
1013{
1014    uint32_t init_val, val, rval = 0;
1015    const int ka_delay = 4; /* Delay of 4 millisec between two keep_alive's */
1016    uint32_t wow_event_mask;
1017#if ATH_WOW_OFFLOAD
1018    uint32_t wow_feature_enable =
1019            //AR_WOW_OFFLOAD_ENA_GTK            |
1020            //AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD    |
1021            //AR_WOW_OFFLOAD_ENA_NS_OFFLOAD     |
1022            //AR_WOW_OFFLOAD_ENA_ACER_MAGIC     |
1023            //AR_WOW_OFFLOAD_ENA_STD_MAGIC      |
1024            //AR_WOW_OFFLOAD_ENA_4WAY_WAKE      |
1025            //AR_WOW_OFFLOAD_ENA_SWKA           |
1026            //AR_WOW_OFFLOAD_ENA_BT_SLEEP       |
1027            AR_WOW_OFFLOAD_ENA_SW_NULL;
1028#endif
1029
1030    /*
1031     * ah_wow_event_mask is a mask to the AR_WOW_PATTERN_REG register to
1032     * indicate which WOW events that we have enabled. The WOW Events are
1033     * from the pattern_enable in this function and pattern_count of
1034     * ar9300_wow_apply_pattern()
1035     */
1036    wow_event_mask = AH_PRIVATE(ah)->ah_wow_event_mask;
1037
1038    HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1039        "%s: offload: %d, pattern: %08x, event_mask: %08x\n",
1040        __func__, offloadEnable, pattern_enable, wow_event_mask);
1041
1042    /*
1043     * Untie Power-On-Reset from the PCI-E Reset. When we are in WOW sleep,
1044     * we do not want the Reset from the PCI-E to disturb our hw state.
1045     */
1046    if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) {
1047
1048        u_int32_t wa_reg_val;
1049        /*
1050         * We need to untie the internal POR (power-on-reset) to the external
1051         * PCI-E reset. We also need to tie the PCI-E Phy reset to the PCI-E
1052         * reset.
1053         */
1054        HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1055            "%s: Untie POR and PCIE reset\n", __func__);
1056        wa_reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_WA));
1057        wa_reg_val = wa_reg_val & ~(AR_WA_UNTIE_RESET_EN);
1058        wa_reg_val = wa_reg_val | AR_WA_RESET_EN | AR_WA_POR_SHORT;
1059        /*
1060         * This bit is to bypass the EEPROM/OTP state machine, (by clearing its
1061         * busy state while PCIE_rst is asserted), to allow BT embedded CPU
1062         * be able to access WLAN registers. Otherwise the eCPU access will be
1063         * stalled as eeprom_sm is held in busy state.
1064         *
1065         * EV91928 is that when this bit is set, after host wakeup and PCIE_rst
1066         * deasserted, PCIE configuration registers will be reset and DeviceID
1067         * SubsystemID etc. registers will be different from values before
1068         * entering sleep. This will cause Windows to detect a device removal.
1069         *
1070         * For HW WOW, this bit should keep as cleared.
1071         */
1072        if (offloadEnable) {
1073            HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1074                "%s: Set AR_WA.13 COLD_RESET_OVERRIDE\n", __func__);
1075            wa_reg_val = wa_reg_val | AR_WA_COLD_RESET_OVERRIDE;
1076
1077#if ATH_WOW_OFFLOAD
1078            if (AR_SREV_JUPITER(ah)) {
1079                wa_reg_val = wa_reg_val | AR_WA_D3_TO_L1_DISABLE;
1080            }
1081#endif
1082        }
1083        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), wa_reg_val);
1084    }
1085
1086    /*
1087     * Set the power states appropriately and enable pme.
1088     */
1089    val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1090    val |=
1091        AR_PMCTRL_HOST_PME_EN     |
1092        AR_PMCTRL_PWR_PM_CTRL_ENA |
1093        AR_PMCTRL_AUX_PWR_DET;
1094
1095    /*
1096     * Set and clear WOW_PME_CLEAR registers for the chip to generate next
1097     * wow signal.
1098     */
1099    val |= AR_PMCTRL_WOW_PME_CLR;
1100    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1101    val &= ~AR_PMCTRL_WOW_PME_CLR;
1102    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1103
1104    /*
1105     * Setup for for:
1106     *     - beacon misses
1107     *     - magic pattern
1108     *     - keep alive timeout
1109     *     - pattern matching
1110     */
1111
1112    /*
1113     * Program some default values for keep-alives, beacon misses, etc.
1114     */
1115    init_val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1116    val = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF) | init_val;
1117    OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val);
1118    rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1119
1120    val =
1121        AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
1122        AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
1123        AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
1124    OS_REG_WRITE(ah, AR_WOW_COUNT_REG, val);
1125    rval = OS_REG_READ(ah, AR_WOW_COUNT_REG);
1126
1127    if (pattern_enable & AH_WOW_BEACON_MISS) {
1128        val = AR_WOW_BEACON_TIMO;
1129    } else {
1130        /* We are not using the beacon miss. Program a large value. */
1131        val = AR_WOW_BEACON_TIMO_MAX;
1132    }
1133    OS_REG_WRITE(ah, AR_WOW_BCN_TIMO_REG, val);
1134    rval = OS_REG_READ(ah, AR_WOW_BCN_TIMO_REG);
1135
1136    /*
1137     * Keep Alive Timo in ms.
1138     */
1139    if (pattern_enable == 0) {
1140        val =  AR_WOW_KEEP_ALIVE_NEVER;
1141    } else {
1142        val =  AH_PRIVATE(ah)->ah_config.ath_hal_keep_alive_timeout * 32;
1143    }
1144    OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO_REG, val);
1145    rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_TIMO_REG);
1146
1147    /*
1148     * Keep Alive delay in us.
1149     */
1150    val = ka_delay * 1000;
1151    OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY_REG, val);
1152    rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_DELAY_REG);
1153
1154    /*
1155     * Create keep_alive Pattern to respond to beacons.
1156     */
1157    ar9300_wow_create_keep_alive_pattern(ah);
1158
1159    /*
1160     * Configure Mac Wow Registers.
1161     */
1162
1163    val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG);
1164
1165    /*
1166     * Send keep alive timeouts anyway.
1167     */
1168    val &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS;
1169
1170    if (pattern_enable & AH_WOW_LINK_CHANGE) {
1171        val &= ~ AR_WOW_KEEP_ALIVE_FAIL_DIS;
1172        wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
1173    } else {
1174        val |=  AR_WOW_KEEP_ALIVE_FAIL_DIS;
1175    }
1176#if ATH_WOW_OFFLOAD
1177    if (offloadEnable) {
1178        /* Don't enable KA frames yet. BT CPU is not
1179         * yet ready. */
1180    }
1181    else
1182#endif /* ATH_WOW_OFFLOAD */
1183    {
1184        OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_REG, val);
1185        val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG);
1186    }
1187
1188
1189    /*
1190     * We are relying on a bmiss failure. Ensure we have enough
1191     * threshold to prevent AH_FALSE positives.
1192     */
1193    OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
1194        AR_WOW_BMISSTHRESHOLD);
1195
1196    val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG);
1197    if (pattern_enable & AH_WOW_BEACON_MISS) {
1198        val |= AR_WOW_BEACON_FAIL_EN;
1199        wow_event_mask |= AR_WOW_BEACON_FAIL;
1200    } else {
1201        val &= ~AR_WOW_BEACON_FAIL_EN;
1202    }
1203    OS_REG_WRITE(ah, AR_WOW_BCN_EN_REG, val);
1204    val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG);
1205
1206    /*
1207     * Enable the magic packet registers.
1208     */
1209    val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1210    if ((pattern_enable & AH_WOW_MAGIC_PATTERN_EN)
1211#if ATH_WOW_OFFLOAD
1212        || (pattern_enable & AH_WOW_ACER_MAGIC_EN)
1213#endif
1214        )
1215    {
1216        val |= AR_WOW_MAGIC_EN;
1217        wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
1218    } else {
1219        val &= ~AR_WOW_MAGIC_EN;
1220    }
1221    val |= AR_WOW_MAC_INTR_EN;
1222    OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val);
1223    val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1224
1225#if ATH_WOW_OFFLOAD
1226    if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_BT_SLEEP)) {
1227        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_BT_SLEEP;
1228        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - BT SLEEP\n");
1229    } else {
1230        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_BT_SLEEP;
1231        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - BT SLEEP\n");
1232    }
1233
1234    if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SW_NULL_DISABLE)) {
1235        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - SW NULL\n");
1236        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SW_NULL;
1237    } else {
1238        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - SW NULL\n");
1239        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SW_NULL;
1240    }
1241
1242    if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_DEVID_SWAR_DISABLE)) {
1243        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - DevID SWAR\n");
1244        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_DEVID_SWAR;
1245    } else {
1246        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - DevID SWAR\n");
1247        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_DEVID_SWAR;
1248    }
1249
1250    if (pattern_enable & AH_WOW_ACER_KEEP_ALIVE_EN) {
1251        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer SWKA\n");
1252        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SWKA;
1253    } else {
1254        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer SWKA\n");
1255        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SWKA;
1256    }
1257
1258    if (pattern_enable & AH_WOW_ACER_MAGIC_EN) {
1259        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Standard Magic\n");
1260        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_STD_MAGIC;
1261        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer Magic\n");
1262        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ACER_MAGIC;
1263    } else {
1264        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Standard Magic\n");
1265        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_STD_MAGIC;
1266        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer Magic\n");
1267        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ACER_MAGIC;
1268    }
1269
1270    if ((pattern_enable & AH_WOW_4WAY_HANDSHAKE_EN) ||
1271        HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_4WAY_HS_WAKE)) {
1272        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - 4Way Handshake\n");
1273        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_4WAY_WAKE;
1274    } else {
1275        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - 4Way Handshake\n");
1276        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_4WAY_WAKE;
1277    }
1278
1279    if((pattern_enable & AH_WOW_AP_ASSOCIATION_LOST_EN) ||
1280        HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_AP_LOSS_WAKE))
1281    {
1282        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - AP loss wake\n");
1283        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE;
1284    } else {
1285        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - AP loss wake\n");
1286        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE;
1287    }
1288
1289    if((pattern_enable & AH_WOW_GTK_HANDSHAKE_ERROR_EN) ||
1290        HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_GTK_ERR_WAKE))
1291    {
1292        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK error wake\n");
1293        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE;
1294    } else {
1295        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK error wake\n");
1296        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE;
1297    }
1298
1299    if (pattern_enable & AH_WOW_GTK_OFFLOAD_EN) {
1300        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK offload\n");
1301        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK;
1302    } else {
1303        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK offload\n");
1304        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK;
1305    }
1306
1307    if (pattern_enable & AH_WOW_ARP_OFFLOAD_EN) {
1308        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - ARP offload\n");
1309        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD;
1310    } else {
1311        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - ARP offload\n");
1312        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD;
1313    }
1314
1315    if (pattern_enable & AH_WOW_NS_OFFLOAD_EN) {
1316        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - NS offload\n");
1317        wow_feature_enable |= AR_WOW_OFFLOAD_ENA_NS_OFFLOAD;
1318    } else {
1319        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - NS offload\n");
1320        wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_NS_OFFLOAD;
1321    }
1322
1323#endif /* ATH_WOW_OFFLOAD */
1324
1325    /* For Kite and later version of the chips
1326     * enable wow pattern match for packets less than
1327     * 256 bytes for all patterns.
1328     */
1329    /* XXX */
1330    OS_REG_WRITE(
1331        ah, AR_WOW_PATTERN_MATCH_LT_256B_REG, AR_WOW_PATTERN_SUPPORTED);
1332
1333    /*
1334     * Set the power states appropriately and enable PME.
1335     */
1336    val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1337    val |=
1338        AR_PMCTRL_PWR_STATE_D1D3 |
1339        AR_PMCTRL_HOST_PME_EN    |
1340        AR_PMCTRL_PWR_PM_CTRL_ENA;
1341    val &= ~AR_PCIE_PM_CTRL_ENA;
1342    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1343
1344    /* Wake on Timer Interrupt. Test mode only. Used in Manufacturing line. */
1345    if (timeout_in_seconds) {
1346        /* convert Timeout to u_secs */
1347        OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER,
1348            OS_REG_READ(ah, AR_TSF_L32) + timeout_in_seconds * 1000000 );
1349        /* timer_period = 30 seconds always */
1350        OS_REG_WRITE(ah, AR_NDP_PERIOD, 30 * 1000000);
1351        OS_REG_WRITE(ah, AR_TIMER_MODE, OS_REG_READ(ah, AR_TIMER_MODE) | 0x80);
1352        OS_REG_WRITE(ah, AR_IMR_S5, OS_REG_READ(ah, AR_IMR_S5) | 0x80);
1353        OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_GENTMR);
1354        if (clearbssid) {
1355            OS_REG_WRITE(ah, AR_BSS_ID0, 0);
1356            OS_REG_WRITE(ah, AR_BSS_ID1, 0);
1357        }
1358    }
1359
1360    /* Enable Seq# generation when asleep. */
1361    OS_REG_WRITE(ah, AR_STA_ID1,
1362                     OS_REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_PRESERVE_SEQNUM);
1363
1364
1365    AH_PRIVATE(ah)->ah_wow_event_mask = wow_event_mask;
1366
1367#if ATH_WOW_OFFLOAD
1368    if (offloadEnable) {
1369        /* Force MAC awake before entering SW WoW mode */
1370        OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
1371#if ATH_SUPPORT_MCI
1372        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
1373            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1374        }
1375#endif
1376
1377        OS_REG_WRITE(ah, AR_WOW_OFFLOAD_COMMAND_JUPITER, wow_feature_enable);
1378        OS_REG_WRITE(ah, AR_WOW_OFFLOAD_STATUS_JUPITER, 0x0);
1379        if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_SW_NULL) {
1380            OS_REG_WRITE(ah, AR_WOW_SW_NULL_PARAMETER,
1381                ((1000) |
1382                (4 << AR_WOW_SW_NULL_SHORT_PERIOD_MASK_S)));
1383        }
1384
1385        if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_DEVID_SWAR) {
1386            ar9300_wowoffload_download_devid_swar(ah);
1387        }
1388
1389        ar9300_wow_offload_download_hal_params(ah);
1390        ar9300_wow_offload_handshake(ah, pattern_enable);
1391        AH9300(ah)->ah_chip_full_sleep = AH_FALSE;
1392
1393        //OS_REG_SET_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE);
1394    }
1395    else
1396#endif /* ATH_WOW_OFFLOAD */
1397    {
1398#if ATH_SUPPORT_MCI
1399        if (AH_PRIVATE(ah)->ah_caps.hal_mci_support) {
1400            OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1401        }
1402#endif
1403        ar9300_set_power_mode_wow_sleep(ah);
1404        AH9300(ah)->ah_chip_full_sleep = AH_TRUE;
1405    }
1406
1407    return (AH_TRUE);
1408}
1409
1410u_int32_t
1411//ar9300_wow_wake_up(struct ath_hal *ah, u_int8_t  *chipPatternBytes)
1412ar9300_wow_wake_up(struct ath_hal *ah, HAL_BOOL offloadEnabled)
1413{
1414    uint32_t wow_status = 0;
1415    uint32_t val = 0, rval;
1416
1417    OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE);
1418    OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_SW_WOW_ENABLE);
1419
1420#if ATH_WOW_OFFLOAD
1421    /* If WoW was offloaded to embedded CPU, use the global
1422     * shared register to know the wakeup reason */
1423    if (offloadEnabled) {
1424        val = OS_REG_READ(ah, AR_EMB_CPU_WOW_STATUS);
1425        if (val) {
1426            if (val & AR_EMB_CPU_WOW_STATUS_MAGIC_PATTERN) {
1427                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW MAGIC_PATTERN\n");
1428                wow_status |= AH_WOW_MAGIC_PATTERN_EN;
1429            }
1430            if (val & AR_EMB_CPU_WOW_STATUS_PATTERN_MATCH) {
1431                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW USER_PATTERN\n");
1432                wow_status |= AH_WOW_USER_PATTERN_EN;
1433            }
1434            if (val & AR_EMB_CPU_WOW_STATUS_KEEP_ALIVE_FAIL) {
1435                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW KEEP_ALIVE_FAIL\n");
1436                wow_status |= AH_WOW_LINK_CHANGE;
1437            }
1438            if (val & AR_EMB_CPU_WOW_STATUS_BEACON_MISS) {
1439                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW BEACON_FAIL\n");
1440                wow_status |= AH_WOW_BEACON_MISS;
1441            }
1442        }
1443
1444        /* Clear status and mask registers */
1445        OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0);
1446        OS_REG_WRITE(ah, AR_EMB_CPU_WOW_ENABLE, 0);
1447        OS_REG_WRITE(ah, AR_MBOX_CTRL_STATUS, 0);
1448
1449    }
1450    else
1451#endif /* ATH_WOW_OFFLOAD */
1452    {
1453        /*
1454         * Read the WOW Status register to know the wakeup reason.
1455         */
1456        rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1457        val = AR_WOW_STATUS(rval);
1458
1459        /*
1460         * Mask only the WOW events that we have enabled.
1461         * Sometimes we have spurious WOW events from the AR_WOW_PATTERN_REG
1462         * register. This mask will clean it up.
1463         */
1464        val &= AH_PRIVATE(ah)->ah_wow_event_mask;
1465
1466        if (val) {
1467            if (val & AR_WOW_MAGIC_PAT_FOUND) {
1468                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW MAGIC_PATTERN\n");
1469                wow_status |= AH_WOW_MAGIC_PATTERN_EN;
1470            }
1471            if (AR_WOW_PATTERN_FOUND(val)) {
1472                //int  i, offset;
1473                //offset = OS_REG_READ(ah, AR_WOW_RXBUF_START_ADDR);
1474                //// Read matched pattern for wake packet detection indication.
1475                //for( i = 0; i< MAX_PATTERN_SIZE/4; i+=4)
1476                //{
1477                //    // RX FIFO is only 8K wrapping.
1478                //    if(offset >= 8 * 1024 / 4) offset = 0;
1479                //    *(u_int32_t*)(chipPatternBytes + i) = OS_REG_READ( ah,offset );
1480                //    offset++;
1481                //}
1482                wow_status |= AH_WOW_USER_PATTERN_EN;
1483                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW USER_PATTERN\n");
1484            }
1485            if (val & AR_WOW_KEEP_ALIVE_FAIL) {
1486                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW KEEP_ALIVE_FAIL\n");
1487                wow_status |= AH_WOW_LINK_CHANGE;
1488            }
1489            if (val & AR_WOW_BEACON_FAIL) {
1490                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW BEACON_FAIL\n");
1491                wow_status |= AH_WOW_BEACON_MISS;
1492            }
1493        }
1494    }
1495
1496    /*
1497     * Set and clear WOW_PME_CLEAR registers for the chip to generate next
1498     * wow signal.
1499     * Disable D3 before accessing other registers ?
1500     */
1501    val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1502    /* Check the bit value 0x01000000 (7-10)? */
1503    val &= ~AR_PMCTRL_PWR_STATE_D1D3;
1504    val |= AR_PMCTRL_WOW_PME_CLR;
1505    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1506
1507    /*
1508     * Clear all events.
1509     */
1510    OS_REG_WRITE(ah, AR_WOW_PATTERN_REG,
1511        AR_WOW_CLEAR_EVENTS(OS_REG_READ(ah, AR_WOW_PATTERN_REG)));
1512
1513    //HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1514    //    "%s: Skip PCIE WA programming\n", __func__);
1515#if 0
1516    /*
1517     * Tie reset register.
1518     * FIXME: Per David Quan not tieing it back might have some repurcussions.
1519     */
1520    /* XXX */
1521    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), OS_REG_READ(ah, AR_WA) |
1522            AR_WA_UNTIE_RESET_EN | AR_WA_POR_SHORT | AR_WA_RESET_EN);
1523#endif
1524
1525    /* Restore the Beacon Threshold to init value */
1526    OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, INIT_RSSI_THR);
1527
1528    /*
1529     * Restore the way the PCI-E Reset, Power-On-Reset, external PCIE_POR_SHORT
1530     * pins are tied to its original value. Previously just before WOW sleep,
1531     * we untie the PCI-E Reset to our Chip's Power On Reset so that
1532     * any PCI-E reset from the bus will not reset our chip.
1533     */
1534    HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: restore AR_WA\n", __func__);
1535    if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) {
1536        ar9300_config_pci_power_save(ah, 0, 0);
1537    }
1538
1539    AH_PRIVATE(ah)->ah_wow_event_mask = 0;
1540    HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1541        "(WOW) wow_status=%08x\n", wow_status);
1542
1543    return (wow_status);
1544}
1545
1546void
1547ar9300_wow_set_gpio_reset_low(struct ath_hal *ah)
1548{
1549    uint32_t val;
1550
1551    val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT));
1552    val |= (1 << (2 * 2));
1553    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), val);
1554    val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT));
1555    /* val = OS_REG_READ(ah,AR_GPIO_IN_OUT ); */
1556}
1557#endif /* ATH_WOW */
1558
1559#endif /* AH_SUPPORT_AR9300 */
1560