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/dev/ath/ath_hal/ar5416/ar5416_btcoex.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  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2005 Atheros Communications, Inc.
    6  * Copyright (c) 2008-2010, Atheros Communications Inc.
    7  *
    8  * Permission to use, copy, modify, and/or distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  *
   20  * $FreeBSD$
   21  */
   22 
   23 #include "opt_ah.h"
   24 
   25 #include "ah.h"
   26 #include "ah_internal.h"
   27 #include "ah_devid.h"
   28 #ifdef  AH_DEBUG
   29 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
   30 #endif
   31 
   32 #include "ar5416/ar5416.h"
   33 #include "ar5416/ar5416reg.h"
   34 #include "ar5416/ar5416phy.h"
   35 #include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */
   36 #include "ar5416/ar5416_btcoex.h"
   37 
   38 void
   39 ar5416SetBTCoexInfo(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo)
   40 {
   41         struct ath_hal_5416 *ahp = AH5416(ah);
   42 
   43         ahp->ah_btModule = btinfo->bt_module;
   44         ahp->ah_btCoexConfigType = btinfo->bt_coex_config;
   45         ahp->ah_btActiveGpioSelect = btinfo->bt_gpio_bt_active;
   46         ahp->ah_btPriorityGpioSelect = btinfo->bt_gpio_bt_priority;
   47         ahp->ah_wlanActiveGpioSelect = btinfo->bt_gpio_wlan_active;
   48         ahp->ah_btActivePolarity = btinfo->bt_active_polarity;
   49         ahp->ah_btCoexSingleAnt = btinfo->bt_single_ant;
   50         ahp->ah_btWlanIsolation = btinfo->bt_isolation;
   51 }
   52 
   53 void
   54 ar5416BTCoexConfig(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf)
   55 {
   56         struct ath_hal_5416 *ahp = AH5416(ah);
   57         HAL_BOOL rxClearPolarity = btconf->bt_rxclear_polarity;
   58 
   59         /*
   60          * For Kiwi and Osprey, the polarity of rx_clear is active high.
   61          * The bt_rxclear_polarity flag from ath(4) needs to be inverted.
   62          */
   63         if (AR_SREV_KIWI(ah)) {
   64                 rxClearPolarity = !btconf->bt_rxclear_polarity;
   65         }
   66 
   67         ahp->ah_btCoexMode = (ahp->ah_btCoexMode & AR_BT_QCU_THRESH) |
   68             SM(btconf->bt_time_extend, AR_BT_TIME_EXTEND) |
   69             SM(btconf->bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
   70             SM(btconf->bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
   71             SM(btconf->bt_mode, AR_BT_MODE) |
   72             SM(btconf->bt_quiet_collision, AR_BT_QUIET) |
   73             SM(rxClearPolarity, AR_BT_RX_CLEAR_POLARITY) |
   74             SM(btconf->bt_priority_time, AR_BT_PRIORITY_TIME) |
   75             SM(btconf->bt_first_slot_time, AR_BT_FIRST_SLOT_TIME);
   76 
   77         ahp->ah_btCoexMode2 |= SM(btconf->bt_hold_rxclear,
   78             AR_BT_HOLD_RX_CLEAR);
   79 
   80         if (ahp->ah_btCoexSingleAnt == AH_FALSE) {
   81                 /* Enable ACK to go out even though BT has higher priority. */
   82                 ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
   83         }
   84 }
   85 
   86 void
   87 ar5416BTCoexSetQcuThresh(struct ath_hal *ah, int qnum)
   88 {
   89         struct ath_hal_5416 *ahp = AH5416(ah);
   90 
   91         ahp->ah_btCoexMode |= SM(qnum, AR_BT_QCU_THRESH);
   92 }
   93 
   94 void
   95 ar5416BTCoexSetWeights(struct ath_hal *ah, u_int32_t stompType)
   96 {
   97         struct ath_hal_5416 *ahp = AH5416(ah);
   98 
   99         if (AR_SREV_KIWI_10_OR_LATER(ah)) {
  100                 /* TODO: TX RX separate is not enabled. */
  101                 switch (stompType) {
  102                 case HAL_BT_COEX_STOMP_AUDIO:
  103                         /* XXX TODO */
  104                 case HAL_BT_COEX_STOMP_ALL:
  105                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  106                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT;
  107                         break;
  108                 case HAL_BT_COEX_STOMP_LOW:
  109                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  110                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT;
  111                         break;
  112                 case HAL_BT_COEX_STOMP_ALL_FORCE:
  113                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  114                         ahp->ah_btCoexWLANWeight =
  115                             AR5416_STOMP_ALL_FORCE_WLAN_WGHT;
  116                         break;
  117                 case HAL_BT_COEX_STOMP_LOW_FORCE:
  118                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  119                         ahp->ah_btCoexWLANWeight =
  120                             AR5416_STOMP_LOW_FORCE_WLAN_WGHT;
  121                         break;
  122                 case HAL_BT_COEX_STOMP_NONE:
  123                 case HAL_BT_COEX_NO_STOMP:
  124                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  125                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT;
  126                         break;
  127                 default:
  128                         /* There is a forceWeight from registry */
  129                         ahp->ah_btCoexBTWeight = stompType & 0xffff;
  130                         ahp->ah_btCoexWLANWeight = stompType >> 16;
  131                         break;
  132                 }
  133         } else {
  134                 switch (stompType) {
  135                 case HAL_BT_COEX_STOMP_AUDIO:
  136                         /* XXX TODO */
  137                 case HAL_BT_COEX_STOMP_ALL:
  138                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  139                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT;
  140                         break;
  141                 case HAL_BT_COEX_STOMP_LOW:
  142                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  143                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT;
  144                         break;
  145                 case HAL_BT_COEX_STOMP_ALL_FORCE:
  146                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  147                         ahp->ah_btCoexWLANWeight =
  148                             AR5416_STOMP_ALL_FORCE_WLAN_WGHT;
  149                         break;
  150                 case HAL_BT_COEX_STOMP_LOW_FORCE:
  151                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  152                         ahp->ah_btCoexWLANWeight =
  153                             AR5416_STOMP_LOW_FORCE_WLAN_WGHT;
  154                         break;
  155                 case HAL_BT_COEX_STOMP_NONE:
  156                 case HAL_BT_COEX_NO_STOMP:
  157                         ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;
  158                         ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT;
  159                         break;
  160                 default:
  161                         /* There is a forceWeight from registry */
  162                         ahp->ah_btCoexBTWeight = stompType & 0xffff;
  163                         ahp->ah_btCoexWLANWeight = stompType >> 16;
  164                         break;
  165                 }
  166         }
  167 }
  168 
  169 void
  170 ar5416BTCoexSetupBmissThresh(struct ath_hal *ah, u_int32_t thresh)
  171 {
  172         struct ath_hal_5416 *ahp = AH5416(ah);
  173 
  174         ahp->ah_btCoexMode2 |= SM(thresh, AR_BT_BCN_MISS_THRESH);
  175 }
  176 
  177 /*
  178  * There is no antenna diversity for Owl, Kiwi, etc.
  179  *
  180  * Kite will override this particular method.
  181  */
  182 void
  183 ar5416BTCoexAntennaDiversity(struct ath_hal *ah)
  184 {
  185 }
  186 
  187 void
  188 ar5416BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value)
  189 {
  190         struct ath_hal_5416 *ahp = AH5416(ah);
  191 
  192         switch (type) {
  193         case HAL_BT_COEX_SET_ACK_PWR:
  194                 if (value) {
  195                         ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOW_ACK_PWR;
  196                         OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);
  197                 } else {
  198                         ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOW_ACK_PWR;
  199                         OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);
  200                 }
  201                 break;
  202         case HAL_BT_COEX_ANTENNA_DIVERSITY:
  203                 /* This is overridden for Kite */
  204                 break;
  205 #if 0
  206         case HAL_BT_COEX_LOWER_TX_PWR:
  207             if (value) {
  208                 if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) == 0) {
  209                     ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOWER_TX_PWR;
  210                     AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 1;
  211                     ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0);
  212                 }
  213             }
  214             else {
  215                 if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) {
  216                     ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOWER_TX_PWR;
  217                     AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 0;
  218                     ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0);
  219                 }
  220             }
  221             break;
  222 #endif
  223         default:
  224                         break;
  225         }
  226 }
  227 
  228 void
  229 ar5416BTCoexDisable(struct ath_hal *ah)
  230 {
  231         struct ath_hal_5416 *ahp = AH5416(ah);
  232 
  233         /* Always drive rx_clear_external output as 0 */
  234         ar5416GpioSet(ah, ahp->ah_wlanActiveGpioSelect, 0);
  235         ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,
  236             HAL_GPIO_OUTPUT_MUX_AS_OUTPUT);
  237 
  238         if (AR_SREV_9271(ah)) {
  239                 /*
  240                  * Set wlanActiveGpio to input when disabling BT-COEX to
  241                  * reduce power consumption
  242                  */
  243                 ar5416GpioCfgInput(ah, ahp->ah_wlanActiveGpioSelect);
  244         }
  245 
  246         if (ahp->ah_btCoexSingleAnt == AH_TRUE) {
  247                 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE,
  248                     1);
  249                 OS_REG_RMW_FIELD(ah, AR_MISC_MODE, AR_PCU_BT_ANT_PREVENT_RX,
  250                     0);
  251         }
  252 
  253         OS_REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
  254         OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
  255         if (AR_SREV_KIWI_10_OR_LATER(ah))
  256                 OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2, 0);
  257         OS_REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
  258 
  259         ahp->ah_btCoexEnabled = AH_FALSE;
  260 }
  261 
  262 int
  263 ar5416BTCoexEnable(struct ath_hal *ah)
  264 {
  265         struct ath_hal_5416 *ahp = AH5416(ah);
  266 
  267         /* Program coex mode and weight registers to actually enable coex */
  268         OS_REG_WRITE(ah, AR_BT_COEX_MODE, ahp->ah_btCoexMode);
  269         OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT,
  270             SM(ahp->ah_btCoexWLANWeight & 0xFFFF, AR_BT_WL_WGHT) |
  271             SM(ahp->ah_btCoexBTWeight & 0xFFFF, AR_BT_BT_WGHT));
  272         if (AR_SREV_KIWI_10_OR_LATER(ah)) {
  273         OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2,
  274             SM(ahp->ah_btCoexWLANWeight >> 16, AR_BT_WL_WGHT));
  275         }
  276         OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
  277 
  278         /* Added Select GPIO5~8 instaed SPI */
  279         if (AR_SREV_9271(ah)) {
  280                 uint32_t val;
  281 
  282                 val = OS_REG_READ(ah, AR9271_CLOCK_CONTROL);
  283                 val &= 0xFFFFFEFF;
  284                 OS_REG_WRITE(ah, AR9271_CLOCK_CONTROL, val);
  285         }
  286 
  287         if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOW_ACK_PWR)
  288                 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);
  289         else
  290                 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);
  291 
  292         if (ahp->ah_btCoexSingleAnt == AH_TRUE) {
  293                 OS_REG_RMW_FIELD(ah, AR_QUIET1,
  294                     AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
  295                 /* XXX should update miscMode? */
  296                 OS_REG_RMW_FIELD(ah, AR_MISC_MODE,
  297                     AR_PCU_BT_ANT_PREVENT_RX, 1);
  298         } else {
  299                 OS_REG_RMW_FIELD(ah, AR_QUIET1,
  300                     AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
  301                 /* XXX should update miscMode? */
  302                 OS_REG_RMW_FIELD(ah, AR_MISC_MODE,
  303                     AR_PCU_BT_ANT_PREVENT_RX, 0);
  304         }
  305 
  306         if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) {
  307                 /* For 3-wire, configure the desired GPIO port for rx_clear */
  308                 ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,
  309                     HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE);
  310         } else {
  311                 /*
  312                  * For 2-wire, configure the desired GPIO port
  313                  * for TX_FRAME output
  314                  */
  315                 ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,
  316                     HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME);
  317         }
  318 
  319         /*
  320          * Enable a weak pull down on BT_ACTIVE.
  321          * When BT device is disabled, BT_ACTIVE might be floating.
  322          */
  323         OS_REG_RMW(ah, AR_GPIO_PDPU,
  324             (0x2 << (ahp->ah_btActiveGpioSelect * 2)),
  325             (0x3 << (ahp->ah_btActiveGpioSelect * 2)));
  326 
  327         ahp->ah_btCoexEnabled = AH_TRUE;
  328 
  329         return (0);
  330 }
  331 
  332 void
  333 ar5416InitBTCoex(struct ath_hal *ah)
  334 {
  335         struct ath_hal_5416 *ahp = AH5416(ah);
  336 
  337         HALDEBUG(ah, HAL_DEBUG_BT_COEX,
  338             "%s: called; configType=%d\n",
  339             __func__,
  340             ahp->ah_btCoexConfigType);
  341 
  342         if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) {
  343                 OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
  344                     (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
  345                     AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
  346 
  347                 /*
  348                  * Set input mux for bt_prority_async and
  349                  * bt_active_async to GPIO pins
  350                  */
  351                 OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
  352                     AR_GPIO_INPUT_MUX1_BT_ACTIVE,
  353                     ahp->ah_btActiveGpioSelect);
  354                 OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
  355                     AR_GPIO_INPUT_MUX1_BT_PRIORITY,
  356                     ahp->ah_btPriorityGpioSelect);
  357 
  358                 /*
  359                  * Configure the desired GPIO ports for input
  360                  */
  361                 ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect);
  362                 ar5416GpioCfgInput(ah, ahp->ah_btPriorityGpioSelect);
  363 
  364                 /*
  365                  * Configure the antenna diversity setup.
  366                  * It's a no-op for AR9287; AR9285 overrides this
  367                  * as required.
  368                  */
  369                 AH5416(ah)->ah_btCoexSetDiversity(ah);
  370 
  371                 if (ahp->ah_btCoexEnabled)
  372                         ar5416BTCoexEnable(ah);
  373                 else
  374                         ar5416BTCoexDisable(ah);
  375         } else if (ahp->ah_btCoexConfigType != HAL_BT_COEX_CFG_NONE) {
  376                 /* 2-wire */
  377                 if (ahp->ah_btCoexEnabled) {
  378                         /* Connect bt_active_async to baseband */
  379                         OS_REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
  380                             (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
  381                              AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
  382                         OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
  383                             AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
  384 
  385                         /*
  386                          * Set input mux for bt_prority_async and
  387                          * bt_active_async to GPIO pins
  388                          */
  389                         OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
  390                             AR_GPIO_INPUT_MUX1_BT_ACTIVE,
  391                             ahp->ah_btActiveGpioSelect);
  392 
  393                         /* Configure the desired GPIO ports for input */
  394                         ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect);
  395 
  396                         /* Enable coexistence on initialization */
  397                         ar5416BTCoexEnable(ah);
  398                 }
  399         }
  400 }

Cache object: 0197c53136c9ea98d585e04d4e3dc0de


[ 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.