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