The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 */

Cache object: addcaf37e59446a2fa553f9948dd0868


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.