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