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