xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c (revision 02e9120893770924227138ba49df1edb3896112a)
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
26 void 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 
34 void 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 
54 static 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  */
89 void 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  * */
152 void 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 */
173 u_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 
209 void 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 
231 void 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 
277 void 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 
317 void 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 */
360 u_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  */
397 u_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  */
493 HAL_BOOL
494 ar9300_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  */
543 static void
544 ar9300_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  */
595 static void
596 ar9300_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  */
652 HAL_BOOL
653 ar9300_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  */
734 HAL_POWER_MODE
735 ar9300_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  */
760 void
761 ar9300_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  */
801 static void
802 ar9280_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 */
820 static HAL_BOOL
821 ar9300_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 
899 void
900 ar9300_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 
985 HAL_BOOL
986 ar9300_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 
1016 HAL_BOOL
1017 ar9300_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 
1419 u_int32_t
1420 //ar9300_wow_wake_up(struct ath_hal *ah, u_int8_t  *chipPatternBytes)
1421 ar9300_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 
1555 void
1556 ar9300_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