Deleted Added
full compact
ar9300_power.c (269793) ar9300_power.c (278741)
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
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_wait(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
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
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;
681 break;
682 case HAL_PM_FULL_SLEEP:
683#if ATH_SUPPORT_MCI
684 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
685 if (ar9300_get_power_mode(ah) == HAL_PM_AWAKE) {
686 if ((ar9300_mci_state(ah, HAL_MCI_STATE_ENABLE, NULL) != 0) &&
687 (ahp->ah_mci_bt_state != MCI_BT_SLEEP) &&
688 !ahp->ah_mci_halted_bt_gpm)
689 {
690 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
691 "(MCI) %s: HALT BT GPM (full_sleep)\n", __func__);
692 ar9300_mci_send_coex_halt_bt_gpm(ah, AH_TRUE, AH_TRUE);
693 }
694 }
695 ahp->ah_mci_ready = AH_FALSE;
696 }
697#endif
698#if ATH_SUPPORT_MCI
699 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
700 OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
701 }
702#endif
703 ar9300_set_power_mode_sleep(ah, set_chip);
704 if (set_chip) {
705 ahp->ah_chip_full_sleep = AH_TRUE;
706 ah->ah_powerMode = mode;
707 }
708 break;
709 case HAL_PM_NETWORK_SLEEP:
710#if ATH_SUPPORT_MCI
711 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
712 OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
713 }
714#endif
715 ar9300_set_power_mode_network_sleep(ah, set_chip);
716 if (set_chip) {
717 ah->ah_powerMode = mode;
718 }
719 break;
720 default:
721 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
722 "%s: unknown power mode %u\n", __func__, mode);
723 OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, -1);
724 return AH_FALSE;
725 }
726 OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, status);
727 return status;
728}
729
730/*
731 * Return the current sleep mode of the chip
732 */
733HAL_POWER_MODE
734ar9300_get_power_mode(struct ath_hal *ah)
735{
736 int mode = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
737
738 switch (mode) {
739 case AR_RTC_STATUS_ON:
740 case AR_RTC_STATUS_WAKEUP:
741 return HAL_PM_AWAKE;
742 break;
743 case AR_RTC_STATUS_SLEEP:
744 return HAL_PM_NETWORK_SLEEP;
745 break;
746 case AR_RTC_STATUS_SHUTDOWN:
747 return HAL_PM_FULL_SLEEP;
748 break;
749 default:
750 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
751 "%s: unknown power mode 0x%x\n", __func__, mode);
752 return HAL_PM_UNDEFINED;
753 }
754}
755
756/*
757 * Set SM power save mode
758 */
759void
760ar9300_set_sm_power_mode(struct ath_hal *ah, HAL_SMPS_MODE mode)
761{
762 int regval;
763 struct ath_hal_9300 *ahp = AH9300(ah);
764
765 if (ar9300_get_capability(ah, HAL_CAP_DYNAMIC_SMPS, 0, AH_NULL) != HAL_OK) {
766 return;
767 }
768
769 /* Program low & high power chainmask settings and enable MAC control */
770 regval = SM(AR_PCU_SMPS_LPWR_CHNMSK_VAL, AR_PCU_SMPS_LPWR_CHNMSK) |
771 SM(ahp->ah_rx_chainmask, AR_PCU_SMPS_HPWR_CHNMSK) |
772 AR_PCU_SMPS_MAC_CHAINMASK;
773
774 /* Program registers according to required SM power mode.*/
775 switch (mode) {
776 case HAL_SMPS_SW_CTRL_LOW_PWR:
777 OS_REG_WRITE(ah, AR_PCU_SMPS, regval);
778 break;
779 case HAL_SMPS_SW_CTRL_HIGH_PWR:
780 OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_SW_CTRL_HPWR);
781 break;
782 case HAL_SMPS_HW_CTRL:
783 OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_HW_CTRL_EN);
784 break;
785 case HAL_SMPS_DEFAULT:
786 OS_REG_WRITE(ah, AR_PCU_SMPS, 0);
787 break;
788 default:
789 break;
790 }
791 ahp->ah_sm_power_mode = mode;
792}
793
794#if ATH_WOW
795#if NOT_NEEDED_FOR_OSPREY /* not compiled for darwin */
796/*
797 * This routine is called to configure the SerDes register for the
798 * Merlin 2.0 and above chip during WOW sleep.
799 */
800static void
801ar9280_config_ser_des__wow_sleep(struct ath_hal *ah)
802{
803 int i;
804 struct ath_hal_9300 *ahp = AH9300(ah);
805
806 /*
807 * For WOW sleep, we reprogram the SerDes so that the PLL and CHK REQ
808 * are both enabled. This uses more power but the Maverick team reported
809 * that otherwise, WOW sleep is unstable and chip may disappears.
810 */
811 for (i = 0; i < ahp->ah_ini_pcie_serdes_wow.ia_rows; i++) {
812 OS_REG_WRITE(ah,
813 INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 0),
814 INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 1));
815 }
816 OS_DELAY(1000);
817}
818#endif /* if NOT_NEEDED_FOR_OSPREY */
819static HAL_BOOL
820ar9300_wow_create_keep_alive_pattern(struct ath_hal *ah)
821{
822 struct ath_hal_9300 *ahp = AH9300(ah);
823 u_int32_t frame_len = 28;
824 u_int32_t tpc = 0x3f;
825 u_int32_t transmit_rate;
826 u_int32_t frame_type = 0x2; /* Frame Type -> Data; */
827 u_int32_t sub_type = 0x4; /* Subtype -> Null Data */
828 u_int32_t to_ds = 1;
829 u_int32_t duration_id = 0x3d;
830 u_int8_t *sta_mac_addr, *ap_mac_addr;
831 u_int8_t *addr1, *addr2, *addr3;
832 u_int32_t ctl[13] = { 0, };
833#define NUM_KA_DATA_WORDS 6
834 u_int32_t data_word[NUM_KA_DATA_WORDS];
835 u_int32_t i;
836 u_int32_t wow_ka_dataword0;
837
838 sta_mac_addr = (u_int8_t *)ahp->ah_macaddr;
839 ap_mac_addr = (u_int8_t *)ahp->ah_bssid;
840 addr2 = sta_mac_addr;
841 addr1 = addr3 = ap_mac_addr;
842
843 if (AH_PRIVATE(ah)->ah_curchan->channel_flags & CHANNEL_CCK) {
844 transmit_rate = 0x1B; /* CCK_1M */
845 } else {
846 transmit_rate = 0xB; /* OFDM_6M */
847 }
848
849 /* Set the Transmit Buffer. */
850 ctl[0] = (frame_len | (tpc << 16));
851 ctl[1] = 0;
852 ctl[2] = (0x7 << 16); /* tx_tries0 */
853 ctl[3] = transmit_rate;
854 ctl[4] = 0;
855 ctl[7] = ahp->ah_tx_chainmask << 2;
856
857 for (i = 0; i < 13; i++) {
858 OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
859 }
860
861 data_word[0] =
862 (frame_type << 2) |
863 (sub_type << 4) |
864 (to_ds << 8) |
865 (duration_id << 16);
866 data_word[1] = (((u_int32_t)addr1[3] << 24) | ((u_int32_t)addr1[2] << 16) |
867 ((u_int32_t)addr1[1]) << 8 | ((u_int32_t)addr1[0]));
868 data_word[2] = (((u_int32_t)addr2[1] << 24) | ((u_int32_t)addr2[0] << 16) |
869 ((u_int32_t)addr1[5]) << 8 | ((u_int32_t)addr1[4]));
870 data_word[3] = (((u_int32_t)addr2[5] << 24) | ((u_int32_t)addr2[4] << 16) |
871 ((u_int32_t)addr2[3]) << 8 | ((u_int32_t)addr2[2]));
872 data_word[4] = (((u_int32_t)addr3[3] << 24) | ((u_int32_t)addr3[2] << 16) |
873 ((u_int32_t)addr3[1]) << 8 | (u_int32_t)addr3[0]);
874 data_word[5] = (((u_int32_t)addr3[5]) << 8 | ((u_int32_t)addr3[4]));
875
876 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
877 /* Jupiter 2.0 has an extra descriptor word (Time based
878 * discard) compared to other chips */
879 OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + 12 * 4), 0);
880 wow_ka_dataword0 = AR_WOW_TXBUF(13);
881 }
882 else {
883 wow_ka_dataword0 = AR_WOW_TXBUF(12);
884 }
885
886 for (i = 0; i < NUM_KA_DATA_WORDS; i++) {
887 OS_REG_WRITE(ah, (wow_ka_dataword0 + i * 4), data_word[i]);
888 }
889
890 return AH_TRUE;
891}
892
893/* TBD: Should querying hal for hardware capability */
894#define MAX_PATTERN_SIZE 256
895#define MAX_PATTERN_MASK_SIZE 32
896#define MAX_NUM_USER_PATTERN 6 /* Deducting the disassoc/deauth packets */
897
898void
899ar9300_wow_apply_pattern(
900 struct ath_hal *ah,
901 u_int8_t *p_ath_pattern,
902 u_int8_t *p_ath_mask,
903 int32_t pattern_count,
904 u_int32_t ath_pattern_len)
905{
906 int i;
907 u_int32_t reg_pat[] = {
908 AR_WOW_TB_PATTERN0,
909 AR_WOW_TB_PATTERN1,
910 AR_WOW_TB_PATTERN2,
911 AR_WOW_TB_PATTERN3,
912 AR_WOW_TB_PATTERN4,
913 AR_WOW_TB_PATTERN5,
914 AR_WOW_TB_PATTERN6,
915 AR_WOW_TB_PATTERN7
916 };
917 u_int32_t reg_mask[] = {
918 AR_WOW_TB_MASK0,
919 AR_WOW_TB_MASK1,
920 AR_WOW_TB_MASK2,
921 AR_WOW_TB_MASK3,
922 AR_WOW_TB_MASK4,
923 AR_WOW_TB_MASK5,
924 AR_WOW_TB_MASK6,
925 AR_WOW_TB_MASK7
926 };
927 u_int32_t pattern_val;
928 u_int32_t mask_val;
929 u_int32_t val;
930 u_int8_t mask_bit = 0x1;
931 u_int8_t pattern;
932
933 /* TBD: should check count by querying the hardware capability */
934 if (pattern_count >= MAX_NUM_USER_PATTERN) {
935 return;
936 }
937
938 pattern = (u_int8_t)OS_REG_READ(ah, AR_WOW_PATTERN_REG);
939 pattern = pattern | (mask_bit << pattern_count);
940 OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, pattern);
941
942 /* Set the registers for pattern */
943 for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
944 pattern_val = (((u_int32_t)p_ath_pattern[i + 0]) |
945 ((u_int32_t)p_ath_pattern[i + 1] << 8) |
946 ((u_int32_t)p_ath_pattern[i + 2] << 16) |
947 ((u_int32_t)p_ath_pattern[i + 3] << 24));
948 OS_REG_WRITE(ah, (reg_pat[pattern_count] + i), pattern_val);
949 }
950
951 /* Set the registers for mask */
952 for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
953 mask_val = (((u_int32_t)p_ath_mask[i + 0]) |
954 ((u_int32_t)p_ath_mask[i + 1] << 8) |
955 ((u_int32_t)p_ath_mask[i + 2] << 16) |
956 ((u_int32_t)p_ath_mask[i + 3] << 24));
957 OS_REG_WRITE(ah, (reg_mask[pattern_count] + i), mask_val);
958 }
959
960 /* XXX */
961 /* Set the pattern length to be matched */
962 if (pattern_count < 4) {
963 /* Pattern 0-3 uses AR_WOW_LENGTH1_REG register */
964 val = OS_REG_READ(ah, AR_WOW_LENGTH1_REG);
965 val = ((val & (~AR_WOW_LENGTH1_MASK(pattern_count))) |
966 ((ath_pattern_len & AR_WOW_LENGTH_MAX) <<
967 AR_WOW_LENGTH1_SHIFT(pattern_count)));
968 OS_REG_WRITE(ah, AR_WOW_LENGTH1_REG, val);
969 } else {
970 /* Pattern 4-7 uses AR_WOW_LENGTH2_REG register */
971 val = OS_REG_READ(ah, AR_WOW_LENGTH2_REG);
972 val = ((val & (~AR_WOW_LENGTH2_MASK(pattern_count))) |
973 ((ath_pattern_len & AR_WOW_LENGTH_MAX) <<
974 AR_WOW_LENGTH2_SHIFT(pattern_count)));
975 OS_REG_WRITE(ah, AR_WOW_LENGTH2_REG, val);
976 }
977
978 AH_PRIVATE(ah)->ah_wow_event_mask |=
979 (1 << (pattern_count + AR_WOW_PATTERN_FOUND_SHIFT));
980
981 return;
982}
983
984HAL_BOOL
985ar9300_set_power_mode_wow_sleep(struct ath_hal *ah)
986{
987 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
988
989 OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */
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 */
990 if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
991 if (!ath_hal_waitfor(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
991 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: dma failed to stop in 10ms\n"
992 "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__,
993 OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW));
994 return AH_FALSE;
995 } else {
996#if 0
997 OS_REG_WRITE(ah, AR_RXDP, 0x0);
998#endif
999
1000 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1001 "%s: TODO How to disable RXDP!!\n", __func__);
1002
1003#if ATH_SUPPORT_MCI
1004 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
1005 OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1006 }
1007#endif
1008 OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
1009
1010 return AH_TRUE;
1011 }
1012}
1013
1014
1015HAL_BOOL
1016ar9300_wow_enable(
1017 struct ath_hal *ah,
1018 u_int32_t pattern_enable,
1019 u_int32_t timeout_in_seconds,
1020 int clearbssid,
1021 HAL_BOOL offloadEnable)
1022{
1023 uint32_t init_val, val, rval = 0;
1024 const int ka_delay = 4; /* Delay of 4 millisec between two keep_alive's */
1025 uint32_t wow_event_mask;
1026#if ATH_WOW_OFFLOAD
1027 uint32_t wow_feature_enable =
1028 //AR_WOW_OFFLOAD_ENA_GTK |
1029 //AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD |
1030 //AR_WOW_OFFLOAD_ENA_NS_OFFLOAD |
1031 //AR_WOW_OFFLOAD_ENA_ACER_MAGIC |
1032 //AR_WOW_OFFLOAD_ENA_STD_MAGIC |
1033 //AR_WOW_OFFLOAD_ENA_4WAY_WAKE |
1034 //AR_WOW_OFFLOAD_ENA_SWKA |
1035 //AR_WOW_OFFLOAD_ENA_BT_SLEEP |
1036 AR_WOW_OFFLOAD_ENA_SW_NULL;
1037#endif
1038
1039 /*
1040 * ah_wow_event_mask is a mask to the AR_WOW_PATTERN_REG register to
1041 * indicate which WOW events that we have enabled. The WOW Events are
1042 * from the pattern_enable in this function and pattern_count of
1043 * ar9300_wow_apply_pattern()
1044 */
1045 wow_event_mask = AH_PRIVATE(ah)->ah_wow_event_mask;
1046
1047 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1048 "%s: offload: %d, pattern: %08x, event_mask: %08x\n",
1049 __func__, offloadEnable, pattern_enable, wow_event_mask);
1050
1051 /*
1052 * Untie Power-On-Reset from the PCI-E Reset. When we are in WOW sleep,
1053 * we do not want the Reset from the PCI-E to disturb our hw state.
1054 */
1055 if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) {
1056
1057 u_int32_t wa_reg_val;
1058 /*
1059 * We need to untie the internal POR (power-on-reset) to the external
1060 * PCI-E reset. We also need to tie the PCI-E Phy reset to the PCI-E
1061 * reset.
1062 */
1063 HAL_DEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1064 "%s: Untie POR and PCIE reset\n", __func__);
1065 wa_reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_WA));
1066 wa_reg_val = wa_reg_val & ~(AR_WA_UNTIE_RESET_EN);
1067 wa_reg_val = wa_reg_val | AR_WA_RESET_EN | AR_WA_POR_SHORT;
1068 /*
1069 * This bit is to bypass the EEPROM/OTP state machine, (by clearing its
1070 * busy state while PCIE_rst is asserted), to allow BT embedded CPU
1071 * be able to access WLAN registers. Otherwise the eCPU access will be
1072 * stalled as eeprom_sm is held in busy state.
1073 *
1074 * EV91928 is that when this bit is set, after host wakeup and PCIE_rst
1075 * deasserted, PCIE configuration registers will be reset and DeviceID
1076 * SubsystemID etc. registers will be different from values before
1077 * entering sleep. This will cause Windows to detect a device removal.
1078 *
1079 * For HW WOW, this bit should keep as cleared.
1080 */
1081 if (offloadEnable) {
1082 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1083 "%s: Set AR_WA.13 COLD_RESET_OVERRIDE\n", __func__);
1084 wa_reg_val = wa_reg_val | AR_WA_COLD_RESET_OVERRIDE;
1085
1086#if ATH_WOW_OFFLOAD
1087 if (AR_SREV_JUPITER(ah)) {
1088 wa_reg_val = wa_reg_val | AR_WA_D3_TO_L1_DISABLE;
1089 }
1090#endif
1091 }
1092 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), wa_reg_val);
1093 }
1094
1095 /*
1096 * Set the power states appropriately and enable pme.
1097 */
1098 val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1099 val |=
1100 AR_PMCTRL_HOST_PME_EN |
1101 AR_PMCTRL_PWR_PM_CTRL_ENA |
1102 AR_PMCTRL_AUX_PWR_DET;
1103
1104 /*
1105 * Set and clear WOW_PME_CLEAR registers for the chip to generate next
1106 * wow signal.
1107 */
1108 val |= AR_PMCTRL_WOW_PME_CLR;
1109 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1110 val &= ~AR_PMCTRL_WOW_PME_CLR;
1111 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1112
1113 /*
1114 * Setup for for:
1115 * - beacon misses
1116 * - magic pattern
1117 * - keep alive timeout
1118 * - pattern matching
1119 */
1120
1121 /*
1122 * Program some default values for keep-alives, beacon misses, etc.
1123 */
1124 init_val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1125 val = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF) | init_val;
1126 OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val);
1127 rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1128
1129 val =
1130 AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
1131 AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
1132 AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
1133 OS_REG_WRITE(ah, AR_WOW_COUNT_REG, val);
1134 rval = OS_REG_READ(ah, AR_WOW_COUNT_REG);
1135
1136 if (pattern_enable & AH_WOW_BEACON_MISS) {
1137 val = AR_WOW_BEACON_TIMO;
1138 } else {
1139 /* We are not using the beacon miss. Program a large value. */
1140 val = AR_WOW_BEACON_TIMO_MAX;
1141 }
1142 OS_REG_WRITE(ah, AR_WOW_BCN_TIMO_REG, val);
1143 rval = OS_REG_READ(ah, AR_WOW_BCN_TIMO_REG);
1144
1145 /*
1146 * Keep Alive Timo in ms.
1147 */
1148 if (pattern_enable == 0) {
1149 val = AR_WOW_KEEP_ALIVE_NEVER;
1150 } else {
1151 val = AH_PRIVATE(ah)->ah_config.ath_hal_keep_alive_timeout * 32;
1152 }
1153 OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO_REG, val);
1154 rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_TIMO_REG);
1155
1156 /*
1157 * Keep Alive delay in us.
1158 */
1159 val = ka_delay * 1000;
1160 OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY_REG, val);
1161 rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_DELAY_REG);
1162
1163 /*
1164 * Create keep_alive Pattern to respond to beacons.
1165 */
1166 ar9300_wow_create_keep_alive_pattern(ah);
1167
1168 /*
1169 * Configure Mac Wow Registers.
1170 */
1171
1172 val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG);
1173
1174 /*
1175 * Send keep alive timeouts anyway.
1176 */
1177 val &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS;
1178
1179 if (pattern_enable & AH_WOW_LINK_CHANGE) {
1180 val &= ~ AR_WOW_KEEP_ALIVE_FAIL_DIS;
1181 wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
1182 } else {
1183 val |= AR_WOW_KEEP_ALIVE_FAIL_DIS;
1184 }
1185#if ATH_WOW_OFFLOAD
1186 if (offloadEnable) {
1187 /* Don't enable KA frames yet. BT CPU is not
1188 * yet ready. */
1189 }
1190 else
1191#endif /* ATH_WOW_OFFLOAD */
1192 {
1193 OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_REG, val);
1194 val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG);
1195 }
1196
1197
1198 /*
1199 * We are relying on a bmiss failure. Ensure we have enough
1200 * threshold to prevent AH_FALSE positives.
1201 */
1202 OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
1203 AR_WOW_BMISSTHRESHOLD);
1204
1205 val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG);
1206 if (pattern_enable & AH_WOW_BEACON_MISS) {
1207 val |= AR_WOW_BEACON_FAIL_EN;
1208 wow_event_mask |= AR_WOW_BEACON_FAIL;
1209 } else {
1210 val &= ~AR_WOW_BEACON_FAIL_EN;
1211 }
1212 OS_REG_WRITE(ah, AR_WOW_BCN_EN_REG, val);
1213 val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG);
1214
1215 /*
1216 * Enable the magic packet registers.
1217 */
1218 val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1219 if ((pattern_enable & AH_WOW_MAGIC_PATTERN_EN)
1220#if ATH_WOW_OFFLOAD
1221 || (pattern_enable & AH_WOW_ACER_MAGIC_EN)
1222#endif
1223 )
1224 {
1225 val |= AR_WOW_MAGIC_EN;
1226 wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
1227 } else {
1228 val &= ~AR_WOW_MAGIC_EN;
1229 }
1230 val |= AR_WOW_MAC_INTR_EN;
1231 OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val);
1232 val = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1233
1234#if ATH_WOW_OFFLOAD
1235 if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_BT_SLEEP)) {
1236 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_BT_SLEEP;
1237 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - BT SLEEP\n");
1238 } else {
1239 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_BT_SLEEP;
1240 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - BT SLEEP\n");
1241 }
1242
1243 if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SW_NULL_DISABLE)) {
1244 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - SW NULL\n");
1245 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SW_NULL;
1246 } else {
1247 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - SW NULL\n");
1248 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SW_NULL;
1249 }
1250
1251 if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_DEVID_SWAR_DISABLE)) {
1252 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - DevID SWAR\n");
1253 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_DEVID_SWAR;
1254 } else {
1255 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - DevID SWAR\n");
1256 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_DEVID_SWAR;
1257 }
1258
1259 if (pattern_enable & AH_WOW_ACER_KEEP_ALIVE_EN) {
1260 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer SWKA\n");
1261 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SWKA;
1262 } else {
1263 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer SWKA\n");
1264 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SWKA;
1265 }
1266
1267 if (pattern_enable & AH_WOW_ACER_MAGIC_EN) {
1268 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Standard Magic\n");
1269 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_STD_MAGIC;
1270 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer Magic\n");
1271 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ACER_MAGIC;
1272 } else {
1273 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Standard Magic\n");
1274 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_STD_MAGIC;
1275 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer Magic\n");
1276 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ACER_MAGIC;
1277 }
1278
1279 if ((pattern_enable & AH_WOW_4WAY_HANDSHAKE_EN) ||
1280 HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_4WAY_HS_WAKE)) {
1281 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - 4Way Handshake\n");
1282 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_4WAY_WAKE;
1283 } else {
1284 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - 4Way Handshake\n");
1285 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_4WAY_WAKE;
1286 }
1287
1288 if((pattern_enable & AH_WOW_AP_ASSOCIATION_LOST_EN) ||
1289 HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_AP_LOSS_WAKE))
1290 {
1291 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - AP loss wake\n");
1292 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE;
1293 } else {
1294 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - AP loss wake\n");
1295 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE;
1296 }
1297
1298 if((pattern_enable & AH_WOW_GTK_HANDSHAKE_ERROR_EN) ||
1299 HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_GTK_ERR_WAKE))
1300 {
1301 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK error wake\n");
1302 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE;
1303 } else {
1304 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK error wake\n");
1305 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE;
1306 }
1307
1308 if (pattern_enable & AH_WOW_GTK_OFFLOAD_EN) {
1309 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK offload\n");
1310 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK;
1311 } else {
1312 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK offload\n");
1313 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK;
1314 }
1315
1316 if (pattern_enable & AH_WOW_ARP_OFFLOAD_EN) {
1317 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - ARP offload\n");
1318 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD;
1319 } else {
1320 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - ARP offload\n");
1321 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD;
1322 }
1323
1324 if (pattern_enable & AH_WOW_NS_OFFLOAD_EN) {
1325 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - NS offload\n");
1326 wow_feature_enable |= AR_WOW_OFFLOAD_ENA_NS_OFFLOAD;
1327 } else {
1328 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - NS offload\n");
1329 wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_NS_OFFLOAD;
1330 }
1331
1332#endif /* ATH_WOW_OFFLOAD */
1333
1334 /* For Kite and later version of the chips
1335 * enable wow pattern match for packets less than
1336 * 256 bytes for all patterns.
1337 */
1338 /* XXX */
1339 OS_REG_WRITE(
1340 ah, AR_WOW_PATTERN_MATCH_LT_256B_REG, AR_WOW_PATTERN_SUPPORTED);
1341
1342 /*
1343 * Set the power states appropriately and enable PME.
1344 */
1345 val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1346 val |=
1347 AR_PMCTRL_PWR_STATE_D1D3 |
1348 AR_PMCTRL_HOST_PME_EN |
1349 AR_PMCTRL_PWR_PM_CTRL_ENA;
1350 val &= ~AR_PCIE_PM_CTRL_ENA;
1351 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1352
1353 /* Wake on Timer Interrupt. Test mode only. Used in Manufacturing line. */
1354 if (timeout_in_seconds) {
1355 /* convert Timeout to u_secs */
1356 OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER,
1357 OS_REG_READ(ah, AR_TSF_L32) + timeout_in_seconds * 1000000 );
1358 /* timer_period = 30 seconds always */
1359 OS_REG_WRITE(ah, AR_NDP_PERIOD, 30 * 1000000);
1360 OS_REG_WRITE(ah, AR_TIMER_MODE, OS_REG_READ(ah, AR_TIMER_MODE) | 0x80);
1361 OS_REG_WRITE(ah, AR_IMR_S5, OS_REG_READ(ah, AR_IMR_S5) | 0x80);
1362 OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_GENTMR);
1363 if (clearbssid) {
1364 OS_REG_WRITE(ah, AR_BSS_ID0, 0);
1365 OS_REG_WRITE(ah, AR_BSS_ID1, 0);
1366 }
1367 }
1368
1369 /* Enable Seq# generation when asleep. */
1370 OS_REG_WRITE(ah, AR_STA_ID1,
1371 OS_REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_PRESERVE_SEQNUM);
1372
1373 AH_PRIVATE(ah)->ah_wow_event_mask = wow_event_mask;
1374
1375#if ATH_WOW_OFFLOAD
1376 if (offloadEnable) {
1377 /* Force MAC awake before entering SW WoW mode */
1378 OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
1379#if ATH_SUPPORT_MCI
1380 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
1381 OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1382 }
1383#endif
1384
1385 OS_REG_WRITE(ah, AR_WOW_OFFLOAD_COMMAND_JUPITER, wow_feature_enable);
1386 OS_REG_WRITE(ah, AR_WOW_OFFLOAD_STATUS_JUPITER, 0x0);
1387 if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_SW_NULL) {
1388 OS_REG_WRITE(ah, AR_WOW_SW_NULL_PARAMETER,
1389 ((1000) |
1390 (4 << AR_WOW_SW_NULL_SHORT_PERIOD_MASK_S)));
1391 }
1392
1393 if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_DEVID_SWAR) {
1394 ar9300_wowoffload_download_devid_swar(ah);
1395 }
1396
1397 ar9300_wow_offload_download_hal_params(ah);
1398 ar9300_wow_offload_handshake(ah, pattern_enable);
1399 AH9300(ah)->ah_chip_full_sleep = AH_FALSE;
1400
1401 //OS_REG_SET_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE);
1402 }
1403 else
1404#endif /* ATH_WOW_OFFLOAD */
1405 {
1406#if ATH_SUPPORT_MCI
1407 if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
1408 OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1409 }
1410#endif
1411 ar9300_set_power_mode_wow_sleep(ah);
1412 AH9300(ah)->ah_chip_full_sleep = AH_TRUE;
1413 }
1414
1415 return (AH_TRUE);
1416}
1417
1418u_int32_t
1419//ar9300_wow_wake_up(struct ath_hal *ah, u_int8_t *chipPatternBytes)
1420ar9300_wow_wake_up(struct ath_hal *ah, HAL_BOOL offloadEnabled)
1421{
1422 uint32_t wow_status = 0;
1423 uint32_t val = 0, rval;
1424
1425 OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE);
1426 OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_SW_WOW_ENABLE);
1427
1428#if ATH_WOW_OFFLOAD
1429 /* If WoW was offloaded to embedded CPU, use the global
1430 * shared register to know the wakeup reason */
1431 if (offloadEnabled) {
1432 val = OS_REG_READ(ah, AR_EMB_CPU_WOW_STATUS);
1433 if (val) {
1434 if (val & AR_EMB_CPU_WOW_STATUS_MAGIC_PATTERN) {
1435 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW MAGIC_PATTERN\n");
1436 wow_status |= AH_WOW_MAGIC_PATTERN_EN;
1437 }
1438 if (val & AR_EMB_CPU_WOW_STATUS_PATTERN_MATCH) {
1439 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW USER_PATTERN\n");
1440 wow_status |= AH_WOW_USER_PATTERN_EN;
1441 }
1442 if (val & AR_EMB_CPU_WOW_STATUS_KEEP_ALIVE_FAIL) {
1443 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW KEEP_ALIVE_FAIL\n");
1444 wow_status |= AH_WOW_LINK_CHANGE;
1445 }
1446 if (val & AR_EMB_CPU_WOW_STATUS_BEACON_MISS) {
1447 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW BEACON_FAIL\n");
1448 wow_status |= AH_WOW_BEACON_MISS;
1449 }
1450 }
1451
1452 /* Clear status and mask registers */
1453 OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0);
1454 OS_REG_WRITE(ah, AR_EMB_CPU_WOW_ENABLE, 0);
1455 OS_REG_WRITE(ah, AR_MBOX_CTRL_STATUS, 0);
1456
1457 }
1458 else
1459#endif /* ATH_WOW_OFFLOAD */
1460 {
1461 /*
1462 * Read the WOW Status register to know the wakeup reason.
1463 */
1464 rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
1465 val = AR_WOW_STATUS(rval);
1466
1467 /*
1468 * Mask only the WOW events that we have enabled.
1469 * Sometimes we have spurious WOW events from the AR_WOW_PATTERN_REG
1470 * register. This mask will clean it up.
1471 */
1472 val &= AH_PRIVATE(ah)->ah_wow_event_mask;
1473
1474 if (val) {
1475 if (val & AR_WOW_MAGIC_PAT_FOUND) {
1476 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW MAGIC_PATTERN\n");
1477 wow_status |= AH_WOW_MAGIC_PATTERN_EN;
1478 }
1479 if (AR_WOW_PATTERN_FOUND(val)) {
1480 //int i, offset;
1481 //offset = OS_REG_READ(ah, AR_WOW_RXBUF_START_ADDR);
1482 //// Read matched pattern for wake packet detection indication.
1483 //for( i = 0; i< MAX_PATTERN_SIZE/4; i+=4)
1484 //{
1485 // // RX FIFO is only 8K wrapping.
1486 // if(offset >= 8 * 1024 / 4) offset = 0;
1487 // *(u_int32_t*)(chipPatternBytes + i) = OS_REG_READ( ah,offset );
1488 // offset++;
1489 //}
1490 wow_status |= AH_WOW_USER_PATTERN_EN;
1491 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW USER_PATTERN\n");
1492 }
1493 if (val & AR_WOW_KEEP_ALIVE_FAIL) {
1494 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW KEEP_ALIVE_FAIL\n");
1495 wow_status |= AH_WOW_LINK_CHANGE;
1496 }
1497 if (val & AR_WOW_BEACON_FAIL) {
1498 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW BEACON_FAIL\n");
1499 wow_status |= AH_WOW_BEACON_MISS;
1500 }
1501 }
1502 }
1503
1504 /*
1505 * Set and clear WOW_PME_CLEAR registers for the chip to generate next
1506 * wow signal.
1507 * Disable D3 before accessing other registers ?
1508 */
1509 val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL));
1510 /* Check the bit value 0x01000000 (7-10)? */
1511 val &= ~AR_PMCTRL_PWR_STATE_D1D3;
1512 val |= AR_PMCTRL_WOW_PME_CLR;
1513 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val);
1514
1515 /*
1516 * Clear all events.
1517 */
1518 OS_REG_WRITE(ah, AR_WOW_PATTERN_REG,
1519 AR_WOW_CLEAR_EVENTS(OS_REG_READ(ah, AR_WOW_PATTERN_REG)));
1520
1521 //HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1522 // "%s: Skip PCIE WA programming\n", __func__);
1523#if 0
1524 /*
1525 * Tie reset register.
1526 * FIXME: Per David Quan not tieing it back might have some repurcussions.
1527 */
1528 /* XXX */
1529 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), OS_REG_READ(ah, AR_WA) |
1530 AR_WA_UNTIE_RESET_EN | AR_WA_POR_SHORT | AR_WA_RESET_EN);
1531#endif
1532
1533 /* Restore the Beacon Threshold to init value */
1534 OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, INIT_RSSI_THR);
1535
1536 /*
1537 * Restore the way the PCI-E Reset, Power-On-Reset, external PCIE_POR_SHORT
1538 * pins are tied to its original value. Previously just before WOW sleep,
1539 * we untie the PCI-E Reset to our Chip's Power On Reset so that
1540 * any PCI-E reset from the bus will not reset our chip.
1541 */
1542 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: restore AR_WA\n", __func__);
1543 if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) {
1544 ar9300_config_pci_power_save(ah, 0, 0);
1545 }
1546
1547 AH_PRIVATE(ah)->ah_wow_event_mask = 0;
1548 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
1549 "(WOW) wow_status=%08x\n", wow_status);
1550
1551 return (wow_status);
1552}
1553
1554void
1555ar9300_wow_set_gpio_reset_low(struct ath_hal *ah)
1556{
1557 uint32_t val;
1558
1559 val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT));
1560 val |= (1 << (2 * 2));
1561 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), val);
1562 val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT));
1563 /* val = OS_REG_READ(ah,AR_GPIO_IN_OUT ); */
1564}
1565#endif /* ATH_WOW */
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 */