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