1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian
18250003Sadrian#include "opt_ah.h"
19250003Sadrian
20250003Sadrian#include "ah.h"
21250003Sadrian#include "ah_internal.h"
22250003Sadrian
23250003Sadrian#include "ar9300/ar9300.h"
24250003Sadrian#include "ar9300/ar9300reg.h"
25250003Sadrian#include "ar9300/ar9300phy.h"
26250003Sadrian
27250003Sadrian#if ATH_SUPPORT_MCI
28250003Sadrian
29250003Sadrian#define AH_MCI_REMOTE_RESET_INTERVAL_US     500
30250003Sadrian#define AH_MCI_DEBUG_PRINT_SCHED    0
31250003Sadrian
32250003Sadrianstatic void ar9300_mci_print_msg(struct ath_hal *ah, HAL_BOOL send,u_int8_t hdr,
33250003Sadrian                                 int len, u_int32_t *pl)
34250003Sadrian{
35250008Sadrian#if 0
36250003Sadrian    char s[128];
37250003Sadrian    char *p = s;
38250003Sadrian    int i;
39250003Sadrian    u_int8_t *p_data = (u_int8_t *) pl;
40250003Sadrian
41250003Sadrian    if (send) {
42250003Sadrian        p += snprintf(s, 60,
43250003Sadrian                      "(MCI) >>>>> Hdr: %02X, Len: %d, Payload:", hdr, len);
44250003Sadrian    }
45250003Sadrian    else {
46250003Sadrian        p += snprintf(s, 60,
47250003Sadrian                      "(MCI) <<<<< Hdr: %02X, Len: %d, Payload:", hdr, len);
48250003Sadrian    }
49250003Sadrian    for ( i=0; i<len; i++)
50250003Sadrian    {
51250003Sadrian        p += snprintf(p, 60, " %02x", *(p_data + i));
52250003Sadrian    }
53250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s\n", s);
54250003Sadrian/*
55250003Sadrian    for ( i=0; i<(len + 3)/4; i++)
56250003Sadrian    {
57250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI)   0x%08x\n", *(pl + i));
58250003Sadrian    }
59250003Sadrian*/
60250003Sadrian#endif
61250003Sadrian}
62250003Sadrian
63250003Sadrianstatic
64250003Sadrianvoid ar9300_mci_osla_setup(struct ath_hal *ah, HAL_BOOL enable)
65250003Sadrian{
66250008Sadrian//    struct ath_hal_9300 *ahp = AH9300(ah);
67250003Sadrian    u_int32_t thresh;
68250003Sadrian
69250003Sadrian    if (enable) {
70250003Sadrian        OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);
71250003Sadrian        OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
72250003Sadrian
73250008Sadrian        if (!(ah->ah_config.ath_hal_mci_config &
74250003Sadrian            ATH_MCI_CONFIG_DISABLE_AGGR_THRESH))
75250003Sadrian        {
76250008Sadrian            thresh = MS(ah->ah_config.ath_hal_mci_config,
77250003Sadrian                        ATH_MCI_CONFIG_AGGR_THRESH);
78250003Sadrian            OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
79250003Sadrian                             AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
80250003Sadrian            OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
81250003Sadrian                             AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
82250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
83250003Sadrian                "(MCI) SCHED aggr thresh: on, thresh=%d (%d.%d%%)\n",
84250003Sadrian                thresh, (thresh + 1)*125/10, (thresh + 1)*125%10);
85250003Sadrian
86250003Sadrian        }
87250003Sadrian        else {
88250003Sadrian            OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
89250003Sadrian                             AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
90250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED aggr thresh: off\n");
91250003Sadrian        }
92250003Sadrian        OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
93250003Sadrian                         AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
94250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: on\n");
95250003Sadrian    }
96250003Sadrian    else {
97250003Sadrian        OS_REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
98250003Sadrian            AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
99250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: off\n");
100250003Sadrian    }
101250003Sadrian}
102250003Sadrian
103250003Sadrianstatic void ar9300_mci_reset_req_wakeup(struct ath_hal *ah)
104250003Sadrian{
105250003Sadrian    /* to be tested in emulation */
106250003Sadrian    if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
107250003Sadrian        OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
108250003Sadrian            AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);
109250003Sadrian        OS_DELAY(1);
110250003Sadrian        OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
111250003Sadrian            AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);
112250003Sadrian    }
113250003Sadrian}
114250003Sadrian
115250003Sadrianstatic int32_t ar9300_mci_wait_for_interrupt(struct ath_hal *ah,
116250003Sadrian                                             u_int32_t address,
117250003Sadrian                                             u_int32_t bit_position,
118250003Sadrian                                             int32_t time_out)
119250003Sadrian{
120250008Sadrian    int data; //, loop;
121250003Sadrian
122250003Sadrian    while (time_out) {
123250003Sadrian        data = OS_REG_READ(ah, address);
124250003Sadrian
125250003Sadrian        if (data & bit_position) {
126250003Sadrian            OS_REG_WRITE(ah, address, bit_position);
127250003Sadrian            if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) {
128250003Sadrian                if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
129250003Sadrian                    ar9300_mci_reset_req_wakeup(ah);
130250003Sadrian                }
131250003Sadrian                if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |
132250003Sadrian                                    AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))
133250003Sadrian                {
134250003Sadrian                    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
135250003Sadrian                        AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
136250003Sadrian                }
137250003Sadrian                OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);
138250003Sadrian            }
139250003Sadrian            break;
140250003Sadrian        }
141250003Sadrian
142250003Sadrian        OS_DELAY(10);
143250003Sadrian        time_out -= 10;
144250003Sadrian        if (time_out < 0) {
145250003Sadrian            break;
146250003Sadrian        }
147250003Sadrian    }
148250003Sadrian
149250003Sadrian    if (time_out <= 0) {
150250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
151250003Sadrian            "(MCI) %s: Wait for Reg0x%08x = 0x%08x timeout.\n",
152250003Sadrian            __func__, address, bit_position);
153250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
154250003Sadrian            "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x",
155250003Sadrian            OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW),
156250003Sadrian            OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
157250003Sadrian        time_out = 0;
158250003Sadrian    }
159250003Sadrian    return time_out;
160250003Sadrian}
161250003Sadrian
162250003Sadrianvoid ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done)
163250003Sadrian{
164250003Sadrian    u_int32_t payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
165250003Sadrian
166250003Sadrian    ar9300_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
167250003Sadrian        wait_done, AH_FALSE);
168250003Sadrian
169250003Sadrian    OS_DELAY(5);
170250003Sadrian}
171250003Sadrian
172250003Sadrianvoid ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done)
173250003Sadrian{
174250003Sadrian    u_int32_t payload = 0x00000000;
175250003Sadrian
176250003Sadrian    ar9300_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
177250003Sadrian        wait_done, AH_FALSE);
178250003Sadrian}
179250003Sadrian
180250003Sadrianstatic void ar9300_mci_send_req_wake(struct ath_hal *ah, HAL_BOOL wait_done)
181250003Sadrian{
182250003Sadrian    ar9300_mci_send_message(ah, MCI_REQ_WAKE,
183250003Sadrian        HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
184250003Sadrian
185250003Sadrian    OS_DELAY(5);
186250003Sadrian}
187250003Sadrian
188250003Sadrianvoid ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done)
189250003Sadrian{
190250003Sadrian    ar9300_mci_send_message(ah, MCI_SYS_WAKING,
191250003Sadrian        HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
192250003Sadrian}
193250003Sadrian
194250003Sadrianstatic void ar9300_mci_send_lna_take(struct ath_hal *ah, HAL_BOOL wait_done)
195250003Sadrian{
196250003Sadrian    u_int32_t payload = 0x70000000;
197250003Sadrian
198250003Sadrian    /* LNA gain index is set to 7. */
199250003Sadrian    ar9300_mci_send_message(ah, MCI_LNA_TAKE,
200250003Sadrian        HAL_MCI_FLAG_DISABLE_TIMESTAMP, &payload, 1, wait_done, AH_FALSE);
201250003Sadrian}
202250003Sadrian
203250003Sadrianstatic void ar9300_mci_send_sys_sleeping(struct ath_hal *ah, HAL_BOOL wait_done)
204250003Sadrian{
205250003Sadrian    ar9300_mci_send_message(ah, MCI_SYS_SLEEPING,
206250003Sadrian        HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
207250003Sadrian}
208250003Sadrian
209250003Sadrianstatic void
210250003Sadrianar9300_mci_send_coex_version_query(struct ath_hal *ah, HAL_BOOL wait_done)
211250003Sadrian{
212250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
213250003Sadrian    u_int32_t payload[4] = {0, 0, 0, 0};
214250003Sadrian
215250003Sadrian    if ((ahp->ah_mci_coex_bt_version_known == AH_FALSE) &&
216250003Sadrian        (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
217250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version query.\n");
218250003Sadrian        MCI_GPM_SET_TYPE_OPCODE(payload,
219250003Sadrian            MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY);
220250003Sadrian        ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
221250003Sadrian    }
222250003Sadrian}
223250003Sadrian
224250003Sadrianstatic void
225250003Sadrianar9300_mci_send_coex_version_response(struct ath_hal *ah, HAL_BOOL wait_done)
226250003Sadrian{
227250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
228250003Sadrian    u_int32_t payload[4] = {0, 0, 0, 0};
229250003Sadrian
230250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version response.\n");
231250003Sadrian    MCI_GPM_SET_TYPE_OPCODE(payload,
232250003Sadrian        MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_RESPONSE);
233250003Sadrian    *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
234250003Sadrian        ahp->ah_mci_coex_major_version_wlan;
235250003Sadrian    *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =
236250003Sadrian        ahp->ah_mci_coex_minor_version_wlan;
237250003Sadrian    ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
238250003Sadrian}
239250003Sadrian
240250003Sadrianstatic void
241250003Sadrianar9300_mci_send_coex_wlan_channels(struct ath_hal *ah, HAL_BOOL wait_done)
242250003Sadrian{
243250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
244250003Sadrian    u_int32_t *payload = &ahp->ah_mci_coex_wlan_channels[0];
245250003Sadrian
246250003Sadrian    if ((ahp->ah_mci_coex_wlan_channels_update == AH_TRUE) &&
247250003Sadrian        (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
248250003Sadrian    {
249250003Sadrian        MCI_GPM_SET_TYPE_OPCODE(payload,
250250003Sadrian            MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS);
251250003Sadrian        ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
252250003Sadrian        MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);
253250003Sadrian    }
254250003Sadrian}
255250003Sadrian
256250003Sadrianstatic void ar9300_mci_send_coex_bt_status_query(struct ath_hal *ah,
257250003Sadrian                                    HAL_BOOL wait_done, u_int8_t query_type)
258250003Sadrian{
259250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
260250003Sadrian    u_int32_t pld[4] = {0, 0, 0, 0};
261250003Sadrian    HAL_BOOL query_btinfo = query_type &
262250003Sadrian            (MCI_GPM_COEX_QUERY_BT_ALL_INFO | MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
263250003Sadrian
264250003Sadrian    if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
265250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
266250003Sadrian            "(MCI) Send Coex BT Status Query 0x%02X\n", query_type);
267250003Sadrian        MCI_GPM_SET_TYPE_OPCODE(pld,
268250003Sadrian            MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY);
269250003Sadrian        *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;
270250003Sadrian        /*
271250003Sadrian         * If bt_status_query message is thought not sent successfully,
272250003Sadrian         * then ah_mci_need_flush_btinfo should be set again.
273250003Sadrian         */
274250003Sadrian        if (!ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE))
275250003Sadrian        {
276250003Sadrian            if (query_btinfo) {
277250003Sadrian                ahp->ah_mci_need_flush_btinfo = AH_TRUE;
278250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
279250003Sadrian                    "(MCI) send bt_status_query fail, set flush flag again\n");
280250003Sadrian            }
281250003Sadrian        }
282250003Sadrian        if (query_btinfo) {
283250003Sadrian            ahp->ah_mci_query_bt = AH_FALSE;
284250003Sadrian        }
285250003Sadrian    }
286250003Sadrian}
287250003Sadrian
288250003Sadrianvoid ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah,
289250003Sadrian                                      HAL_BOOL halt, HAL_BOOL wait_done)
290250003Sadrian{
291250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
292250003Sadrian    u_int32_t payload[4] = {0, 0, 0, 0};
293250003Sadrian
294250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
295250003Sadrian        "(MCI) Send Coex %s BT GPM.\n", (halt == AH_TRUE)?"HALT":"UNHALT");
296250003Sadrian
297250003Sadrian    MCI_GPM_SET_TYPE_OPCODE(payload,
298250003Sadrian        MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM);
299250003Sadrian    if (halt == AH_TRUE) {
300250003Sadrian        ahp->ah_mci_query_bt = AH_TRUE;
301250003Sadrian        /* Send next UNHALT no matter HALT sent or not */
302250003Sadrian        ahp->ah_mci_unhalt_bt_gpm = AH_TRUE;
303250003Sadrian        ahp->ah_mci_need_flush_btinfo = AH_TRUE;
304250003Sadrian        *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
305250003Sadrian            MCI_GPM_COEX_BT_GPM_HALT;
306250003Sadrian    }
307250003Sadrian    else {
308250003Sadrian        *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
309250003Sadrian            MCI_GPM_COEX_BT_GPM_UNHALT;
310250003Sadrian    }
311250003Sadrian    ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
312250003Sadrian}
313250003Sadrian
314250003Sadrianstatic HAL_BOOL ar9300_mci_send_coex_bt_flags(struct ath_hal *ah, HAL_BOOL wait_done,
315250003Sadrian                                          u_int8_t opcode, u_int32_t bt_flags)
316250003Sadrian{
317250008Sadrian//    struct ath_hal_9300 *ahp = AH9300(ah);
318250003Sadrian    u_int32_t pld[4] = {0, 0, 0, 0};
319250003Sadrian
320250003Sadrian    MCI_GPM_SET_TYPE_OPCODE(pld,
321250003Sadrian        MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS);
322250003Sadrian
323250003Sadrian    *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP)  = opcode;
324250003Sadrian    *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;
325250003Sadrian    *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) =
326250003Sadrian        (bt_flags >> 8) & 0xFF;
327250003Sadrian    *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) =
328250003Sadrian        (bt_flags >> 16) & 0xFF;
329250003Sadrian    *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) =
330250003Sadrian        (bt_flags >> 24) & 0xFF;
331250003Sadrian
332250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
333250003Sadrian        "(MCI) BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n",
334250003Sadrian            (opcode == MCI_GPM_COEX_BT_FLAGS_READ)?"READ":
335250003Sadrian            ((opcode == MCI_GPM_COEX_BT_FLAGS_SET)?"SET":"CLEAR"),
336250003Sadrian            bt_flags);
337250003Sadrian
338250003Sadrian    return ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE);
339250003Sadrian}
340250003Sadrian
341250003Sadrianvoid ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g)
342250003Sadrian{
343250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
344250003Sadrian
345250003Sadrian    if (ahp->ah_mci_coex_2g5g_update == AH_FALSE) {
346250003Sadrian        if (ahp->ah_mci_coex_is_2g == is_2g) {
347250003Sadrian            //HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: not changed\n");
348250003Sadrian        } else {
349250003Sadrian            ahp->ah_mci_coex_2g5g_update = AH_TRUE;
350250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: changed\n");
351250003Sadrian        }
352250003Sadrian    } else {
353250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: force send\n");
354250003Sadrian    }
355250003Sadrian    ahp->ah_mci_coex_is_2g = is_2g;
356250003Sadrian}
357250003Sadrian
358250003Sadrianstatic void ar9300_mci_send_2g5g_status(struct ath_hal *ah, HAL_BOOL wait_done)
359250003Sadrian{
360250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
361250003Sadrian    u_int32_t new_flags, to_set, to_clear;
362250003Sadrian
363250003Sadrian    if ((AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) &&
364250003Sadrian        (ahp->ah_mci_coex_2g5g_update == AH_TRUE) &&
365250003Sadrian        (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
366250003Sadrian    {
367250003Sadrian        if (ahp->ah_mci_coex_is_2g) {
368250003Sadrian            new_flags = HAL_MCI_2G_FLAGS;
369250003Sadrian            to_clear = HAL_MCI_2G_FLAGS_CLEAR_MASK;
370250003Sadrian            to_set = HAL_MCI_2G_FLAGS_SET_MASK;
371250003Sadrian        } else {
372250003Sadrian            new_flags = HAL_MCI_5G_FLAGS;
373250003Sadrian            to_clear = HAL_MCI_5G_FLAGS_CLEAR_MASK;
374250003Sadrian            to_set = HAL_MCI_5G_FLAGS_SET_MASK;
375250003Sadrian        }
376250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
377250003Sadrian            "(MCI) BT_MCI_FLAGS: %s (0x%08x) clr=0x%08x, set=0x%08x\n",
378250003Sadrian            ahp->ah_mci_coex_is_2g?"2G":"5G", new_flags, to_clear, to_set);
379250003Sadrian        if (to_clear) {
380250003Sadrian            ar9300_mci_send_coex_bt_flags(ah, wait_done,
381250003Sadrian                MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear);
382250003Sadrian        }
383250003Sadrian        if (to_set) {
384250003Sadrian            ar9300_mci_send_coex_bt_flags(ah, wait_done,
385250003Sadrian                MCI_GPM_COEX_BT_FLAGS_SET, to_set);
386250003Sadrian        }
387250003Sadrian    }
388250003Sadrian    if (AR_SREV_JUPITER_10(ah) && (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
389250003Sadrian        ahp->ah_mci_coex_2g5g_update = AH_FALSE;
390250003Sadrian    }
391250003Sadrian}
392250003Sadrian
393250003Sadrianvoid ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done)
394250003Sadrian{
395250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
396250003Sadrian
397250003Sadrian    if (ahp->ah_mci_coex_2g5g_update)
398250003Sadrian    {
399250003Sadrian        if (ahp->ah_mci_coex_is_2g) {
400250003Sadrian            ar9300_mci_send_2g5g_status(ah, AH_TRUE);
401250003Sadrian
402250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA trans\n");
403250003Sadrian            ar9300_mci_send_lna_transfer(ah, AH_TRUE);
404250003Sadrian            OS_DELAY(5);
405250003Sadrian
406250003Sadrian            OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
407250003Sadrian                AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
408250003Sadrian            if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
409250003Sadrian                OS_REG_CLR_BIT(ah, AR_GLB_CONTROL,
410250003Sadrian                    AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
411250008Sadrian                if (!(ah->ah_config.ath_hal_mci_config &
412250003Sadrian                    ATH_MCI_CONFIG_DISABLE_OSLA))
413250003Sadrian                {
414250003Sadrian                    ar9300_mci_osla_setup(ah, AH_TRUE);
415250003Sadrian                }
416250003Sadrian            }
417250003Sadrian        } else {
418250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
419250003Sadrian            ar9300_mci_send_lna_take(ah, AH_TRUE);
420250003Sadrian            OS_DELAY(5);
421250003Sadrian
422250003Sadrian            OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL,
423250003Sadrian                AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
424250003Sadrian            if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
425250003Sadrian                OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
426250003Sadrian                    AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
427250003Sadrian                ar9300_mci_osla_setup(ah, AH_FALSE);
428250003Sadrian            }
429250003Sadrian
430250003Sadrian            ar9300_mci_send_2g5g_status(ah, AH_TRUE);
431250003Sadrian        }
432250003Sadrian    }
433250003Sadrian
434250003Sadrian    /*
435250003Sadrian     * Update self gen chain mask. Also set basic set for
436250003Sadrian     * txbf.
437250003Sadrian     */
438250003Sadrian    if (AR_SREV_JUPITER(ah)) {
439250003Sadrian        if (ahp->ah_mci_coex_is_2g) {
440250003Sadrian            ahp->ah_reduced_self_gen_mask = AH_TRUE;
441250003Sadrian            OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
442250003Sadrian            ar9300_txbf_set_basic_set(ah);
443250003Sadrian        }
444250003Sadrian        else {
445250003Sadrian            ahp->ah_reduced_self_gen_mask = AH_FALSE;
446250003Sadrian            ar9300_txbf_set_basic_set(ah);
447250003Sadrian        }
448250003Sadrian    }
449250003Sadrian}
450250003Sadrian
451250003Sadrianvoid ar9300_mci_mute_bt(struct ath_hal *ah)
452250003Sadrian{
453250003Sadrian    /* disable all MCI messages */
454250003Sadrian    OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xFFFF0000);
455250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xFFFFFFFF);
456250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xFFFFFFFF);
457250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xFFFFFFFF);
458250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xFFFFFFFF);
459250003Sadrian    OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
460250003Sadrian    /* wait pending HW messages to flush out */
461250003Sadrian    OS_DELAY(10);
462250003Sadrian
463250003Sadrian    /*
464250003Sadrian     * Send LNA_TAKE and SYS_SLEEPING when
465250003Sadrian     * 1. reset not after resuming from full sleep
466250003Sadrian     * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
467250003Sadrian     */
468250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
469250003Sadrian    ar9300_mci_send_lna_take(ah, AH_TRUE);
470250003Sadrian    OS_DELAY(5);
471250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send sys sleeping\n");
472250003Sadrian    ar9300_mci_send_sys_sleeping(ah, AH_TRUE);
473250003Sadrian}
474250003Sadrian
475250003Sadrianstatic void ar9300_mci_observation_set_up(struct ath_hal *ah)
476250003Sadrian{
477250003Sadrian    /*
478250003Sadrian     * Set up the observation bus in order to monitor MCI bus
479250003Sadrian     * through GPIOs (0, 1, 2, and 3).
480250003Sadrian     */
481250003Sadrian    /*
482250003Sadrian    OS_REG_WRITE(ah, AR_GPIO_INTR_POL, 0x00420000);
483250003Sadrian    OS_REG_WRITE(ah, AR_GPIO_OE_OUT, 0x000000ff); // 4050
484250003Sadrian    OS_REG_WRITE(ah, AR_GPIO_OUTPUT_MUX1, 0x000bdab4); // 4068
485250003Sadrian    OS_REG_WRITE(ah, AR_OBS, 0x0000004b); // 4088
486250003Sadrian    OS_REG_WRITE(ah, AR_DIAG_SW, 0x080c0000);
487250003Sadrian    OS_REG_WRITE(ah, AR_MACMISC, 0x0001a000);
488250003Sadrian    OS_REG_WRITE(ah, AR_PHY_TEST, 0x00080000); // a360
489250003Sadrian    OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0xe0000000); // a364
490250003Sadrian    */
491250003Sadrian
492250008Sadrian    if (ah->ah_config.ath_hal_mci_config &
493250003Sadrian        ATH_MCI_CONFIG_MCI_OBS_MCI)
494250003Sadrian    {
495250003Sadrian        ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
496250003Sadrian        ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
497250003Sadrian        ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
498250003Sadrian        ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
499250003Sadrian    }
500250008Sadrian    else if (ah->ah_config.ath_hal_mci_config &
501250003Sadrian        ATH_MCI_CONFIG_MCI_OBS_TXRX)
502250003Sadrian    {
503250003Sadrian        ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
504250003Sadrian        ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
505250003Sadrian        ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
506250003Sadrian        ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
507250003Sadrian        ar9300_gpio_cfg_output(ah, 5, HAL_GPIO_OUTPUT_MUX_AS_OUTPUT);
508250003Sadrian    }
509250008Sadrian    else if (ah->ah_config.ath_hal_mci_config &
510250003Sadrian        ATH_MCI_CONFIG_MCI_OBS_BT)
511250003Sadrian    {
512250003Sadrian        ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
513250003Sadrian        ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
514250003Sadrian        ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
515250003Sadrian        ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
516250003Sadrian    }
517250003Sadrian    else {
518250003Sadrian        return;
519250003Sadrian    }
520250003Sadrian
521250003Sadrian    OS_REG_SET_BIT(ah,
522250003Sadrian        AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
523250003Sadrian
524250003Sadrian    if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
525250003Sadrian        OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);
526250003Sadrian        OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);
527250003Sadrian        OS_REG_WRITE(ah, AR_GLB_GPIO_CONTROL,
528250003Sadrian                     (OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) |
529250003Sadrian                      ATH_MCI_CONFIG_MCI_OBS_GPIO));
530250003Sadrian    }
531250003Sadrian
532250003Sadrian    OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);
533250003Sadrian    OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);
534250003Sadrian    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 0x4b);
535250003Sadrian    OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);
536250003Sadrian    OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);
537250003Sadrian    OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);
538250003Sadrian    OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);
539250003Sadrian    //OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 0x01);
540250003Sadrian    OS_REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS,
541250003Sadrian        AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);
542250003Sadrian}
543250003Sadrian
544250003Sadrianstatic void ar9300_mci_process_gpm_extra(struct ath_hal *ah,
545250003Sadrian                    u_int8_t gpm_type, u_int8_t gpm_opcode, u_int32_t *p_gpm)
546250003Sadrian{
547250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
548250003Sadrian    u_int8_t *p_data = (u_int8_t *) p_gpm;
549250003Sadrian
550250003Sadrian    switch (gpm_type)
551250003Sadrian    {
552250003Sadrian        case MCI_GPM_COEX_AGENT:
553250003Sadrian            switch (gpm_opcode)
554250003Sadrian            {
555250003Sadrian                case MCI_GPM_COEX_VERSION_QUERY:
556250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
557250003Sadrian                        "(MCI) Recv GPM COEX Version Query.\n");
558250003Sadrian                    ar9300_mci_send_coex_version_response(ah, AH_TRUE);
559250003Sadrian                    break;
560250003Sadrian
561250003Sadrian                case MCI_GPM_COEX_VERSION_RESPONSE:
562250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
563250003Sadrian                        "(MCI) Recv GPM COEX Version Response.\n");
564250003Sadrian                    ahp->ah_mci_coex_major_version_bt =
565250003Sadrian                        *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
566250003Sadrian                    ahp->ah_mci_coex_minor_version_bt =
567250003Sadrian                        *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
568250003Sadrian                    ahp->ah_mci_coex_bt_version_known = AH_TRUE;
569250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
570250003Sadrian                        "(MCI) BT Coex version: %d.%d\n",
571250003Sadrian                        ahp->ah_mci_coex_major_version_bt,
572250003Sadrian                        ahp->ah_mci_coex_minor_version_bt);
573250003Sadrian                    break;
574250003Sadrian
575250003Sadrian                case MCI_GPM_COEX_STATUS_QUERY:
576250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
577250003Sadrian                        "(MCI) Recv GPM COEX Status Query = 0x%02X.\n",
578250003Sadrian                        *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
579250003Sadrian                    //if ((*(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)) &
580250003Sadrian                    //    MCI_GPM_COEX_QUERY_WLAN_ALL_INFO)
581250003Sadrian                    {
582250003Sadrian                        ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
583250003Sadrian                        ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
584250003Sadrian                    }
585250003Sadrian                    break;
586250003Sadrian
587250003Sadrian                case MCI_GPM_COEX_BT_PROFILE_INFO:
588250003Sadrian                    ahp->ah_mci_query_bt = AH_TRUE;
589250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
590250003Sadrian                        "(MCI) Recv GPM COEX BT_Profile_Info (drop&query)\n");
591250003Sadrian                    break;
592250003Sadrian
593250003Sadrian                case MCI_GPM_COEX_BT_STATUS_UPDATE:
594250003Sadrian                    ahp->ah_mci_query_bt = AH_TRUE;
595250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
596250003Sadrian                        "(MCI) Recv GPM COEX BT_Status_Update "
597250003Sadrian                        "SEQ=%d (drop&query)\n",
598250003Sadrian                        *(p_gpm + 3));
599250003Sadrian                    break;
600250003Sadrian
601250003Sadrian                default:
602250003Sadrian                    break;
603250003Sadrian            }
604250003Sadrian        default:
605250003Sadrian            break;
606250003Sadrian    }
607250003Sadrian}
608250003Sadrian
609250003Sadrianu_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type,
610250003Sadrian                                  u_int8_t gpm_opcode, int32_t time_out)
611250003Sadrian{
612250003Sadrian    u_int32_t *p_gpm = NULL, mismatch = 0, more_data = HAL_MCI_GPM_NOMORE;
613250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
614250003Sadrian    HAL_BOOL b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
615250003Sadrian    u_int32_t offset;
616250003Sadrian    u_int8_t recv_type = 0, recv_opcode = 0;
617250003Sadrian
618250003Sadrian    if (time_out == 0) {
619250003Sadrian        more_data = HAL_MCI_GPM_MORE;
620250003Sadrian    }
621250003Sadrian
622250003Sadrian    while (time_out > 0)
623250003Sadrian    {
624250003Sadrian        if (p_gpm != NULL) {
625250003Sadrian            MCI_GPM_RECYCLE(p_gpm);
626250003Sadrian            p_gpm = NULL;
627250003Sadrian        }
628250003Sadrian
629250003Sadrian        if (more_data != HAL_MCI_GPM_MORE) {
630250003Sadrian            time_out = ar9300_mci_wait_for_interrupt(ah,
631250003Sadrian                AR_MCI_INTERRUPT_RX_MSG_RAW,
632250003Sadrian                AR_MCI_INTERRUPT_RX_MSG_GPM,
633250003Sadrian                time_out);
634250003Sadrian        }
635250003Sadrian
636250003Sadrian        if (time_out) {
637250003Sadrian            offset = ar9300_mci_state(ah,
638250003Sadrian                HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
639250003Sadrian
640250003Sadrian            if (offset == HAL_MCI_GPM_INVALID) {
641250003Sadrian                continue;
642250003Sadrian            }
643250003Sadrian            p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
644250003Sadrian            ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
645250003Sadrian
646250003Sadrian            recv_type = MCI_GPM_TYPE(p_gpm);
647250003Sadrian            recv_opcode = MCI_GPM_OPCODE(p_gpm);
648250003Sadrian
649250003Sadrian            if (MCI_GPM_IS_CAL_TYPE(recv_type)) {
650250003Sadrian                if (recv_type == gpm_type) {
651250003Sadrian                    if ((gpm_type == MCI_GPM_BT_CAL_DONE) && !b_is_bt_cal_done)
652250003Sadrian                    {
653250003Sadrian                        gpm_type = MCI_GPM_BT_CAL_GRANT;
654250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
655250003Sadrian                            "(MCI) Rcv BT_CAL_DONE. Now Wait BT_CAL_GRANT\n");
656250003Sadrian                        continue;
657250003Sadrian                    }
658250003Sadrian                    if (gpm_type == MCI_GPM_BT_CAL_GRANT) {
659250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
660250003Sadrian                            "(MCI) BT_CAL_GRANT seq=%d, req_count=%d\n",
661250003Sadrian                            *(p_gpm + 2), *(p_gpm + 3));
662250003Sadrian                    }
663250003Sadrian                    break;
664250003Sadrian                }
665250003Sadrian            }
666250003Sadrian            else {
667250003Sadrian                if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) {
668250003Sadrian                    break;
669250003Sadrian                }
670250003Sadrian            }
671250003Sadrian
672250003Sadrian            /* not expected message */
673250003Sadrian
674250003Sadrian            /*
675250003Sadrian             * Check if it's cal_grant
676250003Sadrian             *
677250003Sadrian             * When we're waiting for cal_grant in reset routine, it's
678250003Sadrian             * possible that BT sends out cal_request at the same time.
679250003Sadrian             * Since BT's calibration doesn't happen that often, we'll
680250003Sadrian             * let BT completes calibration then we continue to wait
681250003Sadrian             * for cal_grant from BT.
682250003Sadrian             * Orginal: Wait BT_CAL_GRANT.
683250003Sadrian             * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT -> wait
684250003Sadrian             * BT_CAL_DONE -> Wait BT_CAL_GRANT.
685250003Sadrian             */
686250003Sadrian            if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&
687250003Sadrian                (recv_type == MCI_GPM_BT_CAL_REQ))
688250003Sadrian            {
689250003Sadrian                u_int32_t payload[4] = {0, 0, 0, 0};
690250003Sadrian
691250003Sadrian                gpm_type = MCI_GPM_BT_CAL_DONE;
692250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
693250003Sadrian                    "(MCI) Rcv BT_CAL_REQ. Send WLAN_CAL_GRANT.\n");
694250003Sadrian
695250003Sadrian                MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
696250003Sadrian                ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16,
697250003Sadrian                    AH_FALSE, AH_FALSE);
698250003Sadrian
699250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
700250003Sadrian                    "(MCI) Now wait for BT_CAL_DONE.\n");
701250003Sadrian                continue;
702250003Sadrian            }
703250003Sadrian            else {
704250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
705250003Sadrian                    "(MCI) GPM subtype not match 0x%x\n", *(p_gpm + 1));
706250003Sadrian                mismatch++;
707250003Sadrian                ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
708250003Sadrian            }
709250003Sadrian        }
710250003Sadrian    }
711250003Sadrian    if (p_gpm != NULL) {
712250003Sadrian        MCI_GPM_RECYCLE(p_gpm);
713250003Sadrian        p_gpm = NULL;
714250003Sadrian    }
715250003Sadrian
716250003Sadrian    if (time_out <= 0) {
717250003Sadrian        time_out = 0;
718250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
719250003Sadrian            "(MCI) GPM receiving timeout, mismatch = %d\n", mismatch);
720250003Sadrian    } else {
721250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
722250003Sadrian            "(MCI) Receive GPM type=0x%x, code=0x%x\n", gpm_type, gpm_opcode);
723250003Sadrian    }
724250003Sadrian
725250003Sadrian    while (more_data == HAL_MCI_GPM_MORE) {
726250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) discard remaining GPM\n");
727250003Sadrian        offset = ar9300_mci_state(ah,
728250003Sadrian            HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
729250003Sadrian
730250003Sadrian        if (offset == HAL_MCI_GPM_INVALID) {
731250003Sadrian            break;
732250003Sadrian        }
733250003Sadrian        p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
734250003Sadrian        ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
735250003Sadrian        recv_type = MCI_GPM_TYPE(p_gpm);
736250003Sadrian        recv_opcode = MCI_GPM_OPCODE(p_gpm);
737250003Sadrian        if (!MCI_GPM_IS_CAL_TYPE(recv_type)) {
738250003Sadrian            ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
739250003Sadrian        }
740250003Sadrian        MCI_GPM_RECYCLE(p_gpm);
741250003Sadrian    }
742250003Sadrian
743250003Sadrian    return time_out;
744250003Sadrian}
745250003Sadrian
746250003Sadrianstatic void ar9300_mci_prep_interface(struct ath_hal *ah)
747250003Sadrian{
748250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
749250003Sadrian    u_int32_t saved_mci_int_en;
750250003Sadrian    u_int32_t mci_timeout = 150;
751250003Sadrian
752250003Sadrian    ahp->ah_mci_bt_state = MCI_BT_SLEEP;
753250003Sadrian
754250003Sadrian    saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
755250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
756250003Sadrian
757250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
758250003Sadrian        OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
759250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
760250003Sadrian        OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW));
761250003Sadrian
762250003Sadrian    /* Remote Reset */
763250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Reset sequence start\n", __func__);
764250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n");
765250003Sadrian    ar9300_mci_remote_reset(ah, AH_TRUE);
766250003Sadrian
767250003Sadrian    /*
768250003Sadrian     * This delay is required for the reset delay worst case value 255 in
769250003Sadrian     * MCI_COMMAND2 register
770250003Sadrian     */
771250003Sadrian    if (AR_SREV_JUPITER_10(ah)) {
772250003Sadrian        OS_DELAY(252);
773250003Sadrian    }
774250003Sadrian
775250003Sadrian    /* Send REQ_WAKE to BT */
776250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send REQ_WAKE to remote(BT)\n",
777250003Sadrian        __func__);
778250003Sadrian
779250003Sadrian    ar9300_mci_send_req_wake(ah, AH_TRUE);
780250003Sadrian
781250003Sadrian    if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
782250003Sadrian        AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))
783250003Sadrian    {
784250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
785250003Sadrian            "(MCI) %s: Saw SYS_WAKING from remote(BT)\n", __func__);
786250003Sadrian        ahp->ah_mci_bt_state = MCI_BT_AWAKE;
787250003Sadrian
788250003Sadrian        if (AR_SREV_JUPITER_10(ah)) {
789250003Sadrian            OS_DELAY(10);
790250003Sadrian        }
791250003Sadrian        /*
792250003Sadrian         * We don't need to send more remote_reset at this moment.
793250003Sadrian         *
794250003Sadrian         * If BT receive first remote_reset, then BT HW will be cleaned up and
795250003Sadrian         * will be able to receive req_wake and BT HW will respond sys_waking.
796250003Sadrian         * In this case, WLAN will receive BT's HW sys_waking.
797250003Sadrian         *
798250003Sadrian         * Otherwise, if BT SW missed initial remote_reset, that remote_reset
799250003Sadrian         * will still clean up BT MCI RX, and the req_wake will wake BT up,
800250003Sadrian         * and BT SW will respond this req_wake with a remote_reset and
801250003Sadrian         * sys_waking. In this case, WLAN will receive BT's SW sys_waking.
802250003Sadrian         *
803250003Sadrian         * In either case, BT's RX is cleaned up. So we don't need to reply
804250003Sadrian         * BT's remote_reset now, if any.
805250003Sadrian         *
806250003Sadrian         * Similarly, if in any case, WLAN can receive BT's sys_waking, that
807250003Sadrian         * means WLAN's RX is also fine.
808250003Sadrian         */
809250003Sadrian
810250003Sadrian        /* Send SYS_WAKING to BT */
811250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
812250003Sadrian            "(MCI) %s: Send SW SYS_WAKING to remot(BT)\n", __func__);
813250003Sadrian        ar9300_mci_send_sys_waking(ah, AH_TRUE);
814250003Sadrian
815250003Sadrian        OS_DELAY(10);
816250003Sadrian
817250003Sadrian        /*
818250003Sadrian         * Set BT priority interrupt value to be 0xff to
819250003Sadrian         * avoid having too many BT PRIORITY interrupts.
820250003Sadrian         */
821250003Sadrian
822250003Sadrian        OS_REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);
823250003Sadrian        OS_REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);
824250003Sadrian        OS_REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);
825250003Sadrian        OS_REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);
826250003Sadrian        OS_REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);
827250003Sadrian
828250003Sadrian        /*
829250003Sadrian         * A contention reset will be received after send out sys_waking.
830250003Sadrian         * Also BT priority interrupt bits will be set. Clear those bits
831250003Sadrian         * before the next step.
832250003Sadrian         */
833250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
834250003Sadrian            AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
835250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
836250003Sadrian
837250003Sadrian        if (AR_SREV_JUPITER_10(ah) || ahp->ah_mci_coex_is_2g) {
838250003Sadrian            /* Send LNA_TRANS */
839250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send LNA_TRANS to BT\n",
840250003Sadrian                __func__);
841250003Sadrian            ar9300_mci_send_lna_transfer(ah, AH_TRUE);
842250003Sadrian
843250003Sadrian            OS_DELAY(5);
844250003Sadrian        }
845250003Sadrian
846250003Sadrian        if (AR_SREV_JUPITER_10(ah) ||
847250003Sadrian            (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update))
848250003Sadrian        {
849250003Sadrian            if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
850250003Sadrian                AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) {
851250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
852250003Sadrian                    "(MCI) %s: WLAN has control over the LNA & BT obeys it\n",
853250003Sadrian                    __func__);
854250003Sadrian            } else {
855250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
856250003Sadrian                    "(MCI) %s: BT did not respond to LNA_TRANS!\n", __func__);
857250003Sadrian                //ahp->ah_mci_bt_state = MCI_BT_SLEEP;
858250003Sadrian            }
859250003Sadrian        }
860250003Sadrian
861250003Sadrian        if (AR_SREV_JUPITER_10(ah)) {
862250003Sadrian            /* Send another remote_reset to deassert BT clk_req. */
863250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
864250003Sadrian                "(MCI) %s: Another remote_reset to deassert clk_req.\n",
865250003Sadrian                __func__);
866250003Sadrian            ar9300_mci_remote_reset(ah, AH_TRUE);
867250003Sadrian            OS_DELAY(252);
868250003Sadrian        }
869250003Sadrian    }
870250003Sadrian
871250003Sadrian    /* Clear the extra redundant SYS_WAKING from BT */
872250003Sadrian    if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
873250003Sadrian        (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
874250003Sadrian            AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&
875250003Sadrian        (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
876250003Sadrian            AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0))
877250003Sadrian    {
878250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
879250003Sadrian            AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);
880250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
881250003Sadrian            AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
882250003Sadrian    }
883250003Sadrian
884250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
885250003Sadrian}
886250003Sadrian
887250003Sadrianvoid ar9300_mci_setup(struct ath_hal *ah, u_int32_t gpm_addr,
888250003Sadrian                      void *gpm_buf, u_int16_t len,
889250003Sadrian                      u_int32_t sched_addr)
890250003Sadrian{
891250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
892250003Sadrian    void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
893250003Sadrian
894250003Sadrian    ahp->ah_mci_gpm_addr = gpm_addr;
895250003Sadrian    ahp->ah_mci_gpm_buf = gpm_buf;
896250003Sadrian    ahp->ah_mci_gpm_len = len;
897250003Sadrian    ahp->ah_mci_sched_addr = sched_addr;
898250003Sadrian    ahp->ah_mci_sched_buf = sched_buf;
899250003Sadrian
900250003Sadrian    ar9300_mci_reset(ah, AH_TRUE, AH_TRUE, AH_TRUE);
901250003Sadrian}
902250003Sadrian
903250003Sadrianvoid ar9300_mci_disable_interrupt(struct ath_hal *ah)
904250003Sadrian{
905250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
906250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
907250003Sadrian}
908250003Sadrian
909250003Sadrianvoid ar9300_mci_enable_interrupt(struct ath_hal *ah)
910250003Sadrian{
911250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
912250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
913250003Sadrian        AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
914250003Sadrian}
915250003Sadrian
916250003Sadrianvoid ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
917250003Sadrian                      HAL_BOOL is_full_sleep)
918250003Sadrian{
919250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
920250008Sadrian//    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
921250003Sadrian    u_int32_t regval;
922250003Sadrian
923250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: full_sleep = %d, is_2g = %d\n",
924250003Sadrian        __func__, is_full_sleep, is_2g);
925250003Sadrian
926250003Sadrian    if (!ahp->ah_mci_gpm_addr && !ahp->ah_mci_sched_addr) {
927250003Sadrian        /* GPM buffer and scheduling message buffer are not allocated */
928250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
929250003Sadrian            "(MCI) GPM and SCHEDULE buffers not allocated\n");
930250003Sadrian        return;
931250003Sadrian    }
932250003Sadrian
933250003Sadrian    if (OS_REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
934250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
935250003Sadrian            "(MCI) %s: ### It's deadbeef, quit mcireset()\n", __func__);
936250003Sadrian        return;
937250003Sadrian    }
938250003Sadrian
939250003Sadrian    /* Program MCI DMA related registers */
940250003Sadrian    OS_REG_WRITE(ah, AR_MCI_GPM_0, ahp->ah_mci_gpm_addr);
941250003Sadrian    OS_REG_WRITE(ah, AR_MCI_GPM_1, ahp->ah_mci_gpm_len);
942250003Sadrian    OS_REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, ahp->ah_mci_sched_addr);
943250003Sadrian
944250003Sadrian    /*
945250003Sadrian     * To avoid MCI state machine be affected by incoming remote MCI messages,
946250003Sadrian     * MCI mode will be enabled later, right before reset the MCI TX and RX.
947250003Sadrian     */
948250003Sadrian    regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
949250003Sadrian             SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
950250003Sadrian             SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
951250003Sadrian             SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
952250003Sadrian             SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
953250003Sadrian             SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
954250003Sadrian             SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
955250003Sadrian             SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
956250003Sadrian             SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
957250003Sadrian
958250003Sadrian    if (AR_SREV_JUPITER_10(ah)) {
959250003Sadrian        regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
960250003Sadrian    }
961250003Sadrian
962250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
963250003Sadrian
964250003Sadrian    if (is_2g && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) &&
965250008Sadrian         !(ah->ah_config.ath_hal_mci_config &
966250003Sadrian           ATH_MCI_CONFIG_DISABLE_OSLA))
967250003Sadrian    {
968250003Sadrian        ar9300_mci_osla_setup(ah, AH_TRUE);
969250003Sadrian    }
970250003Sadrian    else {
971250003Sadrian        ar9300_mci_osla_setup(ah, AH_FALSE);
972250003Sadrian    }
973250003Sadrian
974250003Sadrian    if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
975250003Sadrian        OS_REG_SET_BIT(ah, AR_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE);
976250003Sadrian
977250003Sadrian        OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
978250003Sadrian                         AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
979250003Sadrian    }
980250003Sadrian
981250003Sadrian    OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
982250003Sadrian
983250003Sadrian    OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
984250003Sadrian
985250008Sadrian    if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) {
986250003Sadrian        u_int8_t i;
987250003Sadrian        u_int32_t const *pmax_tx_pwr;
988250003Sadrian
989250008Sadrian        if ((ah->ah_config.ath_hal_mci_config &
990250003Sadrian             ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_SHARED_CHN)
991250003Sadrian        {
992250003Sadrian            ahp->ah_mci_concur_tx_en = (ahp->ah_bt_coex_flag &
993250003Sadrian                HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) ? AH_TRUE : AH_FALSE;
994250003Sadrian
995250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) concur_tx_en = %d\n",
996250003Sadrian                     ahp->ah_mci_concur_tx_en);
997250003Sadrian            /*
998250003Sadrian             * We're not relying on HW to reduce WLAN tx power.
999250003Sadrian             * Set the max tx power table to 0x7f for all.
1000250003Sadrian             */
1001250003Sadrian#if 0
1002250003Sadrian            if (AH_PRIVATE(ah)->ah_curchan) {
1003250003Sadrian                chan_flags = AH_PRIVATE(ah)->ah_curchan->channel_flags;
1004250003Sadrian            }
1005250003Sadrian            if (chan_flags == CHANNEL_G_HT20) {
1006250003Sadrian                pmax_tx_pwr = &mci_concur_tx_max_pwr[2][0];
1007250003Sadrian            }
1008250003Sadrian            else if (chan_flags == CHANNEL_G) {
1009250003Sadrian                pmax_tx_pwr = &mci_concur_tx_max_pwr[1][0];
1010250003Sadrian            }
1011250003Sadrian            else if ((chan_flags == CHANNEL_G_HT40PLUS) ||
1012250003Sadrian                     (chan_flags == CHANNEL_G_HT40MINUS))
1013250003Sadrian            {
1014250003Sadrian                pmax_tx_pwr = &mci_concur_tx_max_pwr[3][0];
1015250003Sadrian            }
1016250003Sadrian            else {
1017250003Sadrian                pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1018250003Sadrian            }
1019250003Sadrian
1020250003Sadrian            if (ahp->ah_mci_concur_tx_en) {
1021250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1022250003Sadrian                        "(MCI) chan flags = 0x%x, max_tx_pwr = %d dBm\n",
1023250003Sadrian                        chan_flags,
1024250003Sadrian                        (MS(pmax_tx_pwr[2],
1025250003Sadrian                         ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK) >> 1));
1026250003Sadrian            }
1027250003Sadrian#else
1028250003Sadrian            pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1029250003Sadrian#endif
1030250003Sadrian        }
1031250008Sadrian        else if ((ah->ah_config.ath_hal_mci_config &
1032250003Sadrian                  ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_UNSHARED_CHN)
1033250003Sadrian        {
1034250003Sadrian            pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1035250003Sadrian            ahp->ah_mci_concur_tx_en = AH_TRUE;
1036250003Sadrian        }
1037250003Sadrian        else {
1038250003Sadrian            pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1039250003Sadrian            ahp->ah_mci_concur_tx_en = AH_TRUE;
1040250003Sadrian        }
1041250003Sadrian
1042250003Sadrian    	/* Default is using rate based TPC. */
1043250003Sadrian        OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1044250003Sadrian                         AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
1045250003Sadrian        OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1046250003Sadrian                         AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
1047250003Sadrian        OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
1048250003Sadrian                         AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
1049250003Sadrian        for (i = 0; i < 8; i++) {
1050250003Sadrian            OS_REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), pmax_tx_pwr[i]);
1051250003Sadrian        }
1052250003Sadrian    }
1053250003Sadrian
1054250008Sadrian    regval = MS(ah->ah_config.ath_hal_mci_config,
1055250003Sadrian                ATH_MCI_CONFIG_CLK_DIV);
1056250003Sadrian    OS_REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
1057250003Sadrian
1058250003Sadrian    OS_REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
1059250003Sadrian
1060250003Sadrian    /* Resetting the Rx and Tx paths of MCI */
1061250003Sadrian    regval = OS_REG_READ(ah, AR_MCI_COMMAND2);
1062250003Sadrian    regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
1063250003Sadrian    OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1064250003Sadrian    OS_DELAY(1);
1065250003Sadrian    regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
1066250003Sadrian    OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1067250003Sadrian
1068250003Sadrian    if (is_full_sleep) {
1069250003Sadrian        ar9300_mci_mute_bt(ah);
1070250003Sadrian        OS_DELAY(100);
1071250003Sadrian    }
1072250003Sadrian
1073250003Sadrian    regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
1074250003Sadrian    OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1075250003Sadrian    OS_DELAY(1);
1076250003Sadrian    regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
1077250003Sadrian    OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1078250003Sadrian
1079250003Sadrian    ar9300_mci_state(ah, HAL_MCI_STATE_INIT_GPM_OFFSET, NULL);
1080250003Sadrian    OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
1081250003Sadrian             (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
1082250003Sadrian              SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
1083250003Sadrian    OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1084250003Sadrian
1085250003Sadrian    if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1086250003Sadrian        ar9300_mci_observation_set_up(ah);
1087250003Sadrian    }
1088250003Sadrian
1089250003Sadrian    ahp->ah_mci_ready = AH_TRUE;
1090250003Sadrian    ar9300_mci_prep_interface(ah);
1091250003Sadrian
1092250003Sadrian    if (en_int) {
1093250003Sadrian        ar9300_mci_enable_interrupt(ah);
1094250003Sadrian    }
1095250003Sadrian
1096250003Sadrian#if ATH_SUPPORT_AIC
1097250003Sadrian    if (ahp->ah_aic_enabled) {
1098250003Sadrian        ar9300_aic_start_normal(ah);
1099250003Sadrian    }
1100250003Sadrian#endif
1101250003Sadrian}
1102250003Sadrian
1103250003Sadrianstatic void ar9300_mci_queue_unsent_gpm(struct ath_hal *ah, u_int8_t header,
1104250003Sadrian                                        u_int32_t *payload, HAL_BOOL queue)
1105250003Sadrian{
1106250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1107250003Sadrian    u_int8_t type, opcode;
1108250003Sadrian
1109250003Sadrian    if (queue == AH_TRUE) {
1110250003Sadrian        if (payload != NULL) {
1111250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1112250003Sadrian                "(MCI) ERROR: Send fail: %02x: %02x %02x %02x\n",
1113250003Sadrian                header,
1114250003Sadrian                *(((u_int8_t *)payload) + 4),
1115250003Sadrian                *(((u_int8_t *)payload) + 5),
1116250003Sadrian                *(((u_int8_t *)payload) + 6));
1117250003Sadrian        } else {
1118250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1119250003Sadrian                "(MCI) ERROR: Send fail: %02x\n", header);
1120250003Sadrian        }
1121250003Sadrian    }
1122250003Sadrian    /* check if the message is to be queued */
1123250003Sadrian    if (header == MCI_GPM) {
1124250003Sadrian        type = MCI_GPM_TYPE(payload);
1125250003Sadrian        opcode = MCI_GPM_OPCODE(payload);
1126250003Sadrian
1127250003Sadrian        if (type == MCI_GPM_COEX_AGENT) {
1128250003Sadrian            switch (opcode)
1129250003Sadrian            {
1130250003Sadrian                case MCI_GPM_COEX_BT_UPDATE_FLAGS:
1131250003Sadrian                    if (AR_SREV_JUPITER_10(ah)) {
1132250003Sadrian                        break;
1133250003Sadrian                    }
1134250003Sadrian                    if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
1135250003Sadrian                        MCI_GPM_COEX_BT_FLAGS_READ)
1136250003Sadrian                    {
1137250003Sadrian                        break;
1138250003Sadrian                    }
1139250003Sadrian                    ahp->ah_mci_coex_2g5g_update = queue;
1140250003Sadrian                    if (queue == AH_TRUE) {
1141250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1142250003Sadrian                            "(MCI) BT_MCI_FLAGS: 2G5G status <queued> %s.\n",
1143250003Sadrian                            ahp->ah_mci_coex_is_2g?"2G":"5G");
1144250003Sadrian                    }
1145250003Sadrian                    else {
1146250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1147250003Sadrian                            "(MCI) BT_MCI_FLAGS: 2G5G status <sent> %s.\n",
1148250003Sadrian                            ahp->ah_mci_coex_is_2g?"2G":"5G");
1149250003Sadrian                    }
1150250003Sadrian                    break;
1151250003Sadrian
1152250003Sadrian                case MCI_GPM_COEX_WLAN_CHANNELS:
1153250003Sadrian                    ahp->ah_mci_coex_wlan_channels_update = queue;
1154250003Sadrian                    if (queue == AH_TRUE) {
1155250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1156250003Sadrian                            "(MCI) WLAN channel map <queued>.\n");
1157250003Sadrian                    }
1158250003Sadrian                    else {
1159250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1160250003Sadrian                            "(MCI) WLAN channel map <sent>.\n");
1161250003Sadrian                    }
1162250003Sadrian                    break;
1163250003Sadrian
1164250003Sadrian                case MCI_GPM_COEX_HALT_BT_GPM:
1165250003Sadrian                    if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1166250003Sadrian                        MCI_GPM_COEX_BT_GPM_UNHALT)
1167250003Sadrian                    {
1168250003Sadrian                        ahp->ah_mci_unhalt_bt_gpm = queue;
1169250003Sadrian                        if (queue == AH_TRUE) {
1170250003Sadrian                            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1171250003Sadrian                                "(MCI) UNHALT BT GPM <queued>.\n");
1172250003Sadrian                        }
1173250003Sadrian                        else {
1174250003Sadrian                            ahp->ah_mci_halted_bt_gpm = AH_FALSE;
1175250003Sadrian                            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1176250003Sadrian                                "(MCI) UNHALT BT GPM <sent>.\n");
1177250003Sadrian                        }
1178250003Sadrian                    }
1179250003Sadrian                    if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1180250003Sadrian                        MCI_GPM_COEX_BT_GPM_HALT)
1181250003Sadrian                    {
1182250003Sadrian                        ahp->ah_mci_halted_bt_gpm = !queue;
1183250003Sadrian                        if (queue == AH_TRUE) {
1184250003Sadrian                            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1185250003Sadrian                                "(MCI) HALT BT GPM <not sent>.\n");
1186250003Sadrian                        }
1187250003Sadrian                        else {
1188250003Sadrian                            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1189250003Sadrian                                "(MCI) HALT BT GPM <sent>.\n");
1190250003Sadrian                        }
1191250003Sadrian                    }
1192250003Sadrian                    break;
1193250003Sadrian
1194250003Sadrian                default:
1195250003Sadrian                    break;
1196250003Sadrian            }
1197250003Sadrian        }
1198250003Sadrian    }
1199250003Sadrian}
1200250003Sadrian
1201250003SadrianHAL_BOOL ar9300_mci_send_message(struct ath_hal *ah, u_int8_t header,
1202250003Sadrian                              u_int32_t flag, u_int32_t *payload,
1203250003Sadrian                              u_int8_t len, HAL_BOOL wait_done, HAL_BOOL check_bt)
1204250003Sadrian{
1205250003Sadrian    int i;
1206250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1207250003Sadrian    HAL_BOOL msg_sent = AH_FALSE;
1208250003Sadrian    u_int32_t regval;
1209250003Sadrian    u_int32_t saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
1210250003Sadrian
1211250003Sadrian    regval = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1212250003Sadrian    if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
1213250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1214250003Sadrian            "(MCI) %s: Not send 0x%x. MCI is not enabled. full_sleep = %d\n",
1215250003Sadrian            __func__, header, ahp->ah_chip_full_sleep);
1216250003Sadrian        ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1217250003Sadrian        return AH_FALSE;
1218250003Sadrian    }
1219250003Sadrian    else if (check_bt && (ahp->ah_mci_bt_state == MCI_BT_SLEEP)) {
1220250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1221250003Sadrian            "(MCI) %s: Don't send message(0x%x). BT is in sleep state\n",
1222250003Sadrian            __func__, header);
1223250003Sadrian        ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1224250003Sadrian        return AH_FALSE;
1225250003Sadrian    }
1226250003Sadrian
1227250003Sadrian    if (wait_done) {
1228250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
1229250003Sadrian    }
1230250003Sadrian
1231250003Sadrian    /* Need to clear SW_MSG_DONE raw bit before wait */
1232250003Sadrian    OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
1233250003Sadrian        AR_MCI_INTERRUPT_SW_MSG_DONE | AR_MCI_INTERRUPT_MSG_FAIL_MASK);
1234250003Sadrian
1235250003Sadrian    if (payload != AH_NULL) {
1236250003Sadrian        for (i = 0; (i*4) < len; i++) {
1237250003Sadrian            OS_REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i*4), *(payload + i));
1238250003Sadrian        }
1239250003Sadrian    }
1240250003Sadrian    ar9300_mci_print_msg(ah, AH_TRUE, header, len, payload);
1241250003Sadrian
1242250003Sadrian    OS_REG_WRITE(ah, AR_MCI_COMMAND0,
1243250003Sadrian                (SM((flag & HAL_MCI_FLAG_DISABLE_TIMESTAMP),
1244250003Sadrian                 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
1245250003Sadrian                 SM(len, AR_MCI_COMMAND0_LEN) |
1246250003Sadrian                 SM(header, AR_MCI_COMMAND0_HEADER)));
1247250003Sadrian
1248250003Sadrian    if (wait_done &&
1249250003Sadrian        ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
1250250003Sadrian                                    AR_MCI_INTERRUPT_SW_MSG_DONE, 500) == 0)
1251250003Sadrian    {
1252250003Sadrian        ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1253250003Sadrian    }
1254250003Sadrian    else {
1255250003Sadrian        ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_FALSE);
1256250003Sadrian        msg_sent = AH_TRUE;
1257250003Sadrian    }
1258250003Sadrian
1259250003Sadrian    if (wait_done) {
1260250003Sadrian        OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
1261250003Sadrian    }
1262250003Sadrian
1263250003Sadrian    return msg_sent;
1264250003Sadrian}
1265250003Sadrian
1266250003Sadrianu_int32_t ar9300_mci_get_interrupt(struct ath_hal *ah, u_int32_t *mci_int,
1267250003Sadrian                                   u_int32_t *mci_int_rx_msg)
1268250003Sadrian{
1269250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1270250003Sadrian
1271250003Sadrian    *mci_int = ahp->ah_mci_int_raw;
1272250003Sadrian    *mci_int_rx_msg = ahp->ah_mci_int_rx_msg;
1273250003Sadrian
1274250003Sadrian    /* Clean int bits after the values are read. */
1275250003Sadrian    ahp->ah_mci_int_raw = 0;
1276250003Sadrian    ahp->ah_mci_int_rx_msg = 0;
1277250003Sadrian
1278250003Sadrian    return 0;
1279250003Sadrian}
1280250003Sadrian
1281250003Sadrianu_int32_t ar9300_mci_check_int(struct ath_hal *ah, u_int32_t ints)
1282250003Sadrian{
1283250003Sadrian    u_int32_t reg;
1284250003Sadrian
1285250003Sadrian    reg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
1286250003Sadrian    return ((reg & ints) == ints);
1287250003Sadrian}
1288250003Sadrian
1289250003Sadrianvoid ar9300_mci_sync_bt_state(struct ath_hal *ah)
1290250003Sadrian{
1291250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1292250003Sadrian    u_int32_t cur_bt_state;
1293250003Sadrian
1294250003Sadrian    cur_bt_state = ar9300_mci_state(ah, HAL_MCI_STATE_REMOTE_SLEEP, NULL);
1295250003Sadrian    if (ahp->ah_mci_bt_state != cur_bt_state) {
1296250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1297250003Sadrian            "(MCI) %s: BT state mismatches. old: %d, new: %d\n",
1298250003Sadrian            __func__, ahp->ah_mci_bt_state, cur_bt_state);
1299250003Sadrian        ahp->ah_mci_bt_state = cur_bt_state;
1300250003Sadrian    }
1301250003Sadrian    if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
1302250003Sadrian#if MCI_QUERY_BT_VERSION_VERBOSE
1303250003Sadrian        ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1304250003Sadrian#endif
1305250003Sadrian        ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1306250003Sadrian        if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1307250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: UNHALT BT GPM\n", __func__);
1308250003Sadrian            ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1309250003Sadrian        }
1310250003Sadrian    }
1311250003Sadrian}
1312250003Sadrian
1313250003Sadrianstatic HAL_BOOL ar9300_mci_is_gpm_valid(struct ath_hal *ah, u_int32_t msg_index)
1314250003Sadrian{
1315250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1316250003Sadrian    u_int32_t *payload;
1317250003Sadrian    u_int32_t recv_type, offset = msg_index << 4;
1318250003Sadrian
1319250003Sadrian    if (msg_index == HAL_MCI_GPM_INVALID) {
1320250003Sadrian        return AH_FALSE;
1321250003Sadrian    }
1322250003Sadrian
1323250003Sadrian    payload = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
1324250003Sadrian    recv_type = MCI_GPM_TYPE(payload);
1325250003Sadrian
1326250003Sadrian    if (recv_type == MCI_GPM_RSVD_PATTERN) {
1327250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Skip RSVD GPM\n");
1328250003Sadrian        return AH_FALSE;
1329250003Sadrian    }
1330250003Sadrian
1331250003Sadrian    return AH_TRUE;
1332250003Sadrian}
1333250003Sadrian
1334250003Sadrianu_int32_t
1335250003Sadrianar9300_mci_state(struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data)
1336250003Sadrian{
1337250003Sadrian    u_int32_t   value = 0, more_gpm = 0, gpm_ptr;
1338250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1339250003Sadrian
1340250003Sadrian    switch (state_type) {
1341250003Sadrian        case HAL_MCI_STATE_ENABLE:
1342250008Sadrian            if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
1343250003Sadrian                value = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1344250003Sadrian                if ((value == 0xdeadbeef) || (value == 0xffffffff)) {
1345250003Sadrian                    //    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1346250003Sadrian                    //        "(MCI) BTCOEX_CTRL = 0xdeadbeef\n");
1347250003Sadrian                    value = 0;
1348250003Sadrian                }
1349250003Sadrian            }
1350250003Sadrian            value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
1351250003Sadrian            break;
1352250003Sadrian
1353250003Sadrian        case HAL_MCI_STATE_INIT_GPM_OFFSET:
1354250003Sadrian            value = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1355250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1356250003Sadrian                    "(MCI) %s: GPM initial WRITE_PTR=%d.\n", __func__, value);
1357250003Sadrian            ahp->ah_mci_gpm_idx = value;
1358250003Sadrian            break;
1359250003Sadrian
1360250003Sadrian        case HAL_MCI_STATE_NEXT_GPM_OFFSET:
1361250003Sadrian        case HAL_MCI_STATE_LAST_GPM_OFFSET:
1362250003Sadrian            /*
1363250003Sadrian             * This could be useful to avoid new GPM message interrupt which
1364250003Sadrian             * may lead to spurious interrupt after power sleep, or multiple
1365250003Sadrian             * entry of ath_coex_mci_intr().
1366250003Sadrian             * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
1367250003Sadrian             * alleviate this effect, but clearing GPM RX interrupt bit is
1368250003Sadrian             * safe, because whether this is called from HAL or LMAC, there
1369250003Sadrian             * must be an interrupt bit set/triggered initially.
1370250003Sadrian             */
1371250003Sadrian            OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
1372250003Sadrian                         AR_MCI_INTERRUPT_RX_MSG_GPM);
1373250003Sadrian
1374250003Sadrian            gpm_ptr = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1375250003Sadrian            value = gpm_ptr;
1376250003Sadrian
1377250003Sadrian            if (value == 0) {
1378250003Sadrian                value = ahp->ah_mci_gpm_len - 1;
1379250003Sadrian            }
1380250003Sadrian            else if (value >= ahp->ah_mci_gpm_len) {
1381250003Sadrian                if (value != 0xFFFF) {
1382250003Sadrian                    value = 0;
1383250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1384250003Sadrian                        "(MCI) %s: GPM offset out of range.\n", __func__);
1385250003Sadrian                }
1386250003Sadrian            }
1387250003Sadrian            else {
1388250003Sadrian                value--;
1389250003Sadrian            }
1390250003Sadrian
1391250003Sadrian            if (value == 0xFFFF) {
1392250003Sadrian                value = HAL_MCI_GPM_INVALID;
1393250003Sadrian                more_gpm = HAL_MCI_GPM_NOMORE;
1394250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1395250003Sadrian                        "(MCI) %s: GPM ptr invalid "
1396250003Sadrian                        "@ptr=%d, @offset=%d, more=NOMORE.\n",
1397250003Sadrian                        __func__, gpm_ptr, value);
1398250003Sadrian            }
1399250003Sadrian            else if (state_type == HAL_MCI_STATE_NEXT_GPM_OFFSET) {
1400250003Sadrian                if (gpm_ptr == ahp->ah_mci_gpm_idx) {
1401250003Sadrian                    value = HAL_MCI_GPM_INVALID;
1402250003Sadrian                    more_gpm = HAL_MCI_GPM_NOMORE;
1403250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1404250003Sadrian                            "(MCI) %s: GPM message not available "
1405250003Sadrian                            "@ptr=%d, @offset=%d, more=NOMORE.\n",
1406250003Sadrian                            __func__, gpm_ptr, value);
1407250003Sadrian                }
1408250003Sadrian                else {
1409250003Sadrian                    while (1) {
1410250003Sadrian                        u_int32_t temp_index;
1411250003Sadrian
1412250003Sadrian                        /* skip reserved GPM if any */
1413250003Sadrian                        if (value != ahp->ah_mci_gpm_idx) {
1414250003Sadrian                            more_gpm = HAL_MCI_GPM_MORE;
1415250003Sadrian                        }
1416250003Sadrian                        else {
1417250003Sadrian                            more_gpm = HAL_MCI_GPM_NOMORE;
1418250003Sadrian                        }
1419250003Sadrian                        temp_index = ahp->ah_mci_gpm_idx;
1420250003Sadrian                        ahp->ah_mci_gpm_idx++;
1421250003Sadrian                        if (ahp->ah_mci_gpm_idx >= ahp->ah_mci_gpm_len) {
1422250003Sadrian                            ahp->ah_mci_gpm_idx = 0;
1423250003Sadrian                        }
1424250003Sadrian                        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1425250003Sadrian                                "(MCI) %s: GPM message got "
1426250003Sadrian                                "@ptr=%d, @offset=%d, more=%s.\n",
1427250003Sadrian                                __func__, gpm_ptr, temp_index,
1428250003Sadrian                                (more_gpm == HAL_MCI_GPM_MORE)?"MORE":"NOMORE");
1429250003Sadrian                        if (ar9300_mci_is_gpm_valid(ah, temp_index)) {
1430250003Sadrian                            value = temp_index;
1431250003Sadrian                            break;
1432250003Sadrian                        }
1433250003Sadrian                        if (more_gpm == HAL_MCI_GPM_NOMORE) {
1434250003Sadrian                            value = HAL_MCI_GPM_INVALID;
1435250003Sadrian                            break;
1436250003Sadrian                        }
1437250003Sadrian                    }
1438250003Sadrian                }
1439250003Sadrian                if (p_data != NULL) {
1440250003Sadrian                    *p_data = more_gpm;
1441250003Sadrian                }
1442250003Sadrian            }
1443250003Sadrian            if (value != HAL_MCI_GPM_INVALID) {
1444250003Sadrian                value <<= 4;
1445250003Sadrian            }
1446250003Sadrian            break;
1447250003Sadrian
1448250003Sadrian    case HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET:
1449250003Sadrian        value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1450250003Sadrian            AR_MCI_RX_LAST_SCHD_MSG_INDEX);
1451250003Sadrian
1452250003Sadrian#if AH_MCI_DEBUG_PRINT_SCHED
1453250003Sadrian        {
1454250003Sadrian            u_int32_t index = value;
1455250003Sadrian            u_int32_t prev_index, sched_idx;
1456250003Sadrian            u_int32_t *pld;
1457250003Sadrian            u_int8_t  *pld8;
1458250003Sadrian            u_int32_t wbtimer = OS_REG_READ(ah, AR_BTCOEX_WBTIMER);
1459250003Sadrian            u_int32_t schd_ctl = OS_REG_READ(ah, AR_MCI_HW_SCHD_TBL_CTL);
1460250003Sadrian
1461250003Sadrian            if (index > 0) {
1462250003Sadrian                prev_index = index - 1;
1463250003Sadrian            } else {
1464250003Sadrian                prev_index = index;
1465250003Sadrian            }
1466250003Sadrian
1467250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED\n");
1468250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1469250003Sadrian                "(MCI) SCHED SCHD_TBL_CTRL=0x%08x, WBTIMER=0x%08x (%d)\n",
1470250003Sadrian                schd_ctl, wbtimer, wbtimer);
1471250003Sadrian            for (sched_idx = prev_index; sched_idx <= index; sched_idx++) {
1472250003Sadrian                pld = (u_int32_t *) (ahp->ah_mci_sched_buf + (sched_idx << 4));
1473250003Sadrian                pld8 = (u_int8_t *) pld;
1474250003Sadrian
1475250003Sadrian                ar9300_mci_print_msg(ah, AH_FALSE, MCI_SCHD_INFO, 16, pld);
1476250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1477250003Sadrian                    "(MCI) SCHED    idx=%d, T1=0x%08x (%d), T2=0x%08x (%d)\n",
1478250003Sadrian                    sched_idx,
1479250003Sadrian                    pld[0], pld[0], pld[1], pld[1]);
1480250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1481250003Sadrian                    "(MCI) SCHED    addr=%d %s pwr=%d prio=%d %s link=%d\n",
1482250003Sadrian                    pld8[11] >> 4,
1483250003Sadrian                    (pld8[11] & 0x08)?"TX":"RX",
1484250003Sadrian                    (int8_t) (((pld8[11] & 0x07) << 5) | (pld8[10] >> 3)),
1485250003Sadrian                    (((pld8[10] & 0x07) << 5) | (pld8[9] >> 3)),
1486250003Sadrian                    (pld8[9] & 0x04)?"LE":"BR/EDR",
1487250003Sadrian                    (((pld8[9] & 0x03) << 2) | (pld8[8] >> 6)));
1488250003Sadrian            }
1489250003Sadrian        }
1490250003Sadrian#endif /* AH_MCI_DEBUG_PRINT_SCHED */
1491250003Sadrian
1492250003Sadrian        /* Make it in bytes */
1493250003Sadrian        value <<= 4;
1494250003Sadrian        break;
1495250003Sadrian
1496250003Sadrian    case HAL_MCI_STATE_REMOTE_SLEEP:
1497250003Sadrian        value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1498250003Sadrian            AR_MCI_RX_REMOTE_SLEEP) ? MCI_BT_SLEEP : MCI_BT_AWAKE;
1499250003Sadrian        break;
1500250003Sadrian
1501250003Sadrian        case HAL_MCI_STATE_CONT_RSSI_POWER:
1502250003Sadrian            value = MS(ahp->ah_mci_cont_status,
1503250003Sadrian                AR_MCI_CONT_RSSI_POWER);
1504250003Sadrian            break;
1505250003Sadrian
1506250003Sadrian        case HAL_MCI_STATE_CONT_PRIORITY:
1507250003Sadrian            value = MS(ahp->ah_mci_cont_status,
1508250003Sadrian                AR_MCI_CONT_RRIORITY);
1509250003Sadrian            break;
1510250003Sadrian
1511250003Sadrian        case HAL_MCI_STATE_CONT_TXRX:
1512250003Sadrian            value = MS(ahp->ah_mci_cont_status,
1513250003Sadrian                AR_MCI_CONT_TXRX);
1514250003Sadrian            break;
1515250003Sadrian
1516250003Sadrian        case HAL_MCI_STATE_BT:
1517250003Sadrian            value = ahp->ah_mci_bt_state;
1518250003Sadrian            break;
1519250003Sadrian
1520250003Sadrian        case HAL_MCI_STATE_SET_BT_SLEEP:
1521250003Sadrian            ahp->ah_mci_bt_state = MCI_BT_SLEEP;
1522250003Sadrian            break;
1523250003Sadrian
1524250003Sadrian        case HAL_MCI_STATE_SET_BT_AWAKE:
1525250003Sadrian            ahp->ah_mci_bt_state = MCI_BT_AWAKE;
1526250003Sadrian            ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1527250003Sadrian            ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1528250003Sadrian            if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1529250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1530250003Sadrian                    "(MCI) %s: UNHALT BT GPM\n", __func__);
1531250003Sadrian                ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1532250003Sadrian            }
1533250003Sadrian            ar9300_mci_2g5g_switch(ah, AH_TRUE);
1534250003Sadrian            break;
1535250003Sadrian
1536250003Sadrian        case HAL_MCI_STATE_SET_BT_CAL_START:
1537250003Sadrian            ahp->ah_mci_bt_state = MCI_BT_CAL_START;
1538250003Sadrian            break;
1539250003Sadrian
1540250003Sadrian        case HAL_MCI_STATE_SET_BT_CAL:
1541250003Sadrian            ahp->ah_mci_bt_state = MCI_BT_CAL;
1542250003Sadrian            break;
1543250003Sadrian
1544250003Sadrian        case HAL_MCI_STATE_RESET_REQ_WAKE:
1545250003Sadrian            ar9300_mci_reset_req_wakeup(ah);
1546250003Sadrian            ahp->ah_mci_coex_2g5g_update = AH_TRUE;
1547250003Sadrian
1548250003Sadrian            if ((AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) &&
1549250008Sadrian                (ah->ah_config.ath_hal_mci_config &
1550250003Sadrian                 ATH_MCI_CONFIG_MCI_OBS_MASK))
1551250003Sadrian            {
1552250003Sadrian                /* Check if we still have control of the GPIOs */
1553250003Sadrian                if ((OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) &
1554250003Sadrian                     ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
1555250003Sadrian                     ATH_MCI_CONFIG_MCI_OBS_GPIO)
1556250003Sadrian                 {
1557250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1558250003Sadrian                        "(MCI) Reconfigure observation\n");
1559250003Sadrian                    ar9300_mci_observation_set_up(ah);
1560250003Sadrian                 }
1561250003Sadrian            }
1562250003Sadrian
1563250003Sadrian            break;
1564250003Sadrian
1565250003Sadrian        case HAL_MCI_STATE_SEND_WLAN_COEX_VERSION:
1566250003Sadrian            ar9300_mci_send_coex_version_response(ah, AH_TRUE);
1567250003Sadrian            break;
1568250003Sadrian
1569250003Sadrian        case HAL_MCI_STATE_SET_BT_COEX_VERSION:
1570250003Sadrian            if (p_data == NULL) {
1571250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1572250003Sadrian                    "(MCI) Error: Set BT Coex version with NULL data !!!\n");
1573250003Sadrian            }
1574250003Sadrian            else {
1575250003Sadrian                ahp->ah_mci_coex_major_version_bt = (*p_data >> 8) & 0xff;
1576250003Sadrian                ahp->ah_mci_coex_minor_version_bt = (*p_data) & 0xff;
1577250003Sadrian                ahp->ah_mci_coex_bt_version_known = AH_TRUE;
1578250003Sadrian                HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT version set: %d.%d\n",
1579250003Sadrian                        ahp->ah_mci_coex_major_version_bt,
1580250003Sadrian                        ahp->ah_mci_coex_minor_version_bt);
1581250003Sadrian            }
1582250003Sadrian            break;
1583250003Sadrian
1584250003Sadrian        case HAL_MCI_STATE_SEND_WLAN_CHANNELS:
1585250003Sadrian            if (p_data != NULL)
1586250003Sadrian            {
1587250003Sadrian                if (((ahp->ah_mci_coex_wlan_channels[1] & 0xffff0000) ==
1588250003Sadrian                    (*(p_data + 1) & 0xffff0000)) &&
1589250003Sadrian                    (ahp->ah_mci_coex_wlan_channels[2] == *(p_data + 2)) &&
1590250003Sadrian                    (ahp->ah_mci_coex_wlan_channels[3] == *(p_data + 3)))
1591250003Sadrian                {
1592250003Sadrian                    break;
1593250003Sadrian                }
1594250003Sadrian                ahp->ah_mci_coex_wlan_channels[0] = *p_data++;
1595250003Sadrian                ahp->ah_mci_coex_wlan_channels[1] = *p_data++;
1596250003Sadrian                ahp->ah_mci_coex_wlan_channels[2] = *p_data++;
1597250003Sadrian                ahp->ah_mci_coex_wlan_channels[3] = *p_data++;
1598250003Sadrian            }
1599250003Sadrian            ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
1600250003Sadrian            ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1601250003Sadrian            break;
1602250003Sadrian
1603250003Sadrian        case HAL_MCI_STATE_SEND_VERSION_QUERY:
1604250003Sadrian            ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1605250003Sadrian            break;
1606250003Sadrian
1607250003Sadrian        case HAL_MCI_STATE_SEND_STATUS_QUERY:
1608250003Sadrian            if (AR_SREV_JUPITER_10(ah)) {
1609250003Sadrian                ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1610250003Sadrian                        MCI_GPM_COEX_QUERY_BT_ALL_INFO);
1611250003Sadrian            } else {
1612250003Sadrian                ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1613250003Sadrian                        MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
1614250003Sadrian            }
1615250003Sadrian            break;
1616250003Sadrian
1617250003Sadrian        case HAL_MCI_STATE_NEED_FLUSH_BT_INFO:
1618250003Sadrian            /*
1619250003Sadrian             * ah_mci_unhalt_bt_gpm means whether it's needed to send
1620250003Sadrian             * UNHALT message. It's set whenever there's a request to send HALT
1621250003Sadrian             * message. ah_mci_halted_bt_gpm means whether HALT message is sent
1622250003Sadrian             * out successfully.
1623250003Sadrian             *
1624250003Sadrian             * Checking (ah_mci_unhalt_bt_gpm == AH_FALSE) instead of checking
1625250003Sadrian             * (ahp->ah_mci_halted_bt_gpm == AH_FALSE) will make sure currently is
1626250003Sadrian             * in UNHALT-ed mode and BT can respond to status query.
1627250003Sadrian             */
1628250003Sadrian            if ((ahp->ah_mci_unhalt_bt_gpm == AH_FALSE) &&
1629250003Sadrian                (ahp->ah_mci_need_flush_btinfo == AH_TRUE))
1630250003Sadrian            {
1631250003Sadrian                value = 1;
1632250003Sadrian            }
1633250003Sadrian            else {
1634250003Sadrian                value = 0;
1635250003Sadrian            }
1636250003Sadrian            if (p_data != NULL) {
1637250008Sadrian                ahp->ah_mci_need_flush_btinfo = (*p_data != 0)? AH_TRUE : AH_FALSE;
1638250003Sadrian            }
1639250003Sadrian            break;
1640250003Sadrian
1641250003Sadrian        case HAL_MCI_STATE_SET_CONCUR_TX_PRI:
1642250003Sadrian            if (p_data) {
1643250003Sadrian                ahp->ah_mci_stomp_none_tx_pri = *p_data & 0xff;
1644250003Sadrian                ahp->ah_mci_stomp_low_tx_pri = (*p_data >> 8) & 0xff;
1645250003Sadrian                ahp->ah_mci_stomp_all_tx_pri = (*p_data >> 16) & 0xff;
1646250003Sadrian            }
1647250003Sadrian            break;
1648250003Sadrian
1649250003Sadrian        case HAL_MCI_STATE_RECOVER_RX:
1650250003Sadrian            HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) hal RECOVER_RX\n");
1651250003Sadrian            ar9300_mci_prep_interface(ah);
1652250003Sadrian            ahp->ah_mci_query_bt = AH_TRUE;
1653250003Sadrian            ahp->ah_mci_need_flush_btinfo = AH_TRUE;
1654250003Sadrian            ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1655250003Sadrian            ar9300_mci_2g5g_switch(ah, AH_TRUE);
1656250003Sadrian            break;
1657250003Sadrian
1658250003Sadrian        case HAL_MCI_STATE_DEBUG:
1659250003Sadrian            if (p_data != NULL) {
1660250003Sadrian                if (*p_data == HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG) {
1661250003Sadrian                    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) QUERY_BT_DEBUG\n");
1662250003Sadrian                    ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1663250003Sadrian                        MCI_GPM_COEX_QUERY_BT_DEBUG);
1664250003Sadrian                    OS_DELAY(10);
1665250003Sadrian                    if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
1666250003Sadrian                        ar9300_mci_send_coex_bt_flags(ah, AH_TRUE,
1667250003Sadrian                            MCI_GPM_COEX_BT_FLAGS_READ, 0);
1668250003Sadrian                    }
1669250003Sadrian                }
1670250003Sadrian            }
1671250003Sadrian            break;
1672250003Sadrian
1673250003Sadrian        case HAL_MCI_STATE_NEED_FTP_STOMP:
1674250008Sadrian            value = (ah->ah_config.ath_hal_mci_config &
1675250003Sadrian                     ATH_MCI_CONFIG_DISABLE_FTP_STOMP) ? 0 : 1;
1676250003Sadrian            break;
1677250003Sadrian
1678250003Sadrian        case HAL_MCI_STATE_NEED_TUNING:
1679250008Sadrian            value = (ah->ah_config.ath_hal_mci_config &
1680250003Sadrian                     ATH_MCI_CONFIG_DISABLE_TUNING) ? 0 : 1;
1681250003Sadrian            break;
1682250003Sadrian
1683250003Sadrian        case HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX:
1684250008Sadrian            value = ((ah->ah_config.ath_hal_mci_config &
1685250003Sadrian                     ATH_MCI_CONFIG_CONCUR_TX) ==
1686250003Sadrian                     ATH_MCI_CONCUR_TX_SHARED_CHN)? 1 : 0;
1687250003Sadrian            break;
1688250003Sadrian
1689250003Sadrian        default:
1690250003Sadrian            break;
1691250003Sadrian    }
1692250003Sadrian    return value;
1693250003Sadrian}
1694250003Sadrian
1695250003Sadrianvoid ar9300_mci_detach(struct ath_hal *ah)
1696250003Sadrian{
1697250003Sadrian    /* Turn off MCI and Jupiter mode. */
1698250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
1699250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) ar9300_mci_detach\n");
1700250003Sadrian    ar9300_mci_disable_interrupt(ah);
1701250003Sadrian}
1702250003Sadrian
1703250003Sadrian/*
1704250003Sadrian * Low priority BT: 0 - 59(0x3b)
1705250003Sadrian * High priority BT: 60 - 125(0x7d)
1706250003Sadrian * Critical BT: 126 - 255
1707250003Sadrian
1708250003Sadrian    BTCOEX_WL_WEIGHTS0_VALUE0 ; // wl_idle
1709250003Sadrian    BTCOEX_WL_WEIGHTS0_VALUE1 ; // sw_ctrl[3] - all_stomp
1710250003Sadrian    BTCOEX_WL_WEIGHTS0_VALUE2 ; // sw_ctrl[2] - all_not_stomp
1711250003Sadrian    BTCOEX_WL_WEIGHTS0_VALUE3 ; // sw_ctrl[1] - pa_pre_distortion
1712250003Sadrian    BTCOEX_WL_WEIGHTS1_VALUE0 ; // sw_ctrl[0] - general purpose
1713250003Sadrian    BTCOEX_WL_WEIGHTS1_VALUE1 ; // tm_wl_wait_beacon
1714250003Sadrian    BTCOEX_WL_WEIGHTS1_VALUE2 ; // ts_state_wait_ack_cts
1715250003Sadrian    BTCOEX_WL_WEIGHTS1_VALUE3 ; // self_gen
1716250003Sadrian    BTCOEX_WL_WEIGHTS2_VALUE0 ; // idle
1717250003Sadrian    BTCOEX_WL_WEIGHTS2_VALUE1 ; // rx
1718250003Sadrian    BTCOEX_WL_WEIGHTS2_VALUE2 ; // tx
1719250003Sadrian    BTCOEX_WL_WEIGHTS2_VALUE3 ; // rx + tx
1720250003Sadrian    BTCOEX_WL_WEIGHTS3_VALUE0 ; // tx
1721250003Sadrian    BTCOEX_WL_WEIGHTS3_VALUE1 ; // rx
1722250003Sadrian    BTCOEX_WL_WEIGHTS3_VALUE2 ; // tx
1723250003Sadrian    BTCOEX_WL_WEIGHTS3_VALUE3 ; // rx + tx
1724250003Sadrian
1725250003Sadrian    Stomp all:
1726250003Sadrian    ah_bt_coex_wlan_weight[0] = 0x00007d00
1727250003Sadrian    ah_bt_coex_wlan_weight[1] = 0x7d7d7d00
1728250003Sadrian    ah_bt_coex_wlan_weight[2] = 0x7d7d7d00
1729250003Sadrian    ah_bt_coex_wlan_weight[3] = 0x7d7d7d7d
1730250003Sadrian    Stomp low:
1731250003Sadrian    ah_bt_coex_wlan_weight[0] = 0x00007d00
1732250003Sadrian    ah_bt_coex_wlan_weight[1] = 0x7d3b3b00
1733250003Sadrian    ah_bt_coex_wlan_weight[2] = 0x3b3b3b00
1734250003Sadrian    ah_bt_coex_wlan_weight[3] = 0x3b3b3b3b
1735250003Sadrian    Stomp none:
1736250003Sadrian    ah_bt_coex_wlan_weight[0] = 0x00007d00
1737250003Sadrian    ah_bt_coex_wlan_weight[1] = 0x7d000000
1738250003Sadrian    ah_bt_coex_wlan_weight[2] = 0x00000000
1739250003Sadrian    ah_bt_coex_wlan_weight[3] = 0x00000000
1740250003Sadrian*/
1741250003Sadrian
1742250003Sadrianvoid ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type)
1743250003Sadrian{
1744250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1745250008Sadrian//    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
1746250003Sadrian    u_int32_t tx_priority = 0;
1747250003Sadrian
1748250003Sadrian    switch (stomp_type) {
1749250003Sadrian    case HAL_BT_COEX_STOMP_ALL:
1750250003Sadrian        ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_WLAN_WGHT0;
1751250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_WLAN_WGHT1;
1752250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_WLAN_WGHT2;
1753250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_WLAN_WGHT3;
1754250003Sadrian        if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_all_tx_pri) {
1755250003Sadrian            tx_priority = ahp->ah_mci_stomp_all_tx_pri;
1756250003Sadrian        }
1757250003Sadrian        break;
1758250003Sadrian    case HAL_BT_COEX_STOMP_LOW:
1759250003Sadrian        if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX) {
1760250003Sadrian            ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT0;
1761250003Sadrian            ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT1;
1762250003Sadrian            ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT2;
1763250003Sadrian            ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT3;
1764250003Sadrian        }
1765250003Sadrian        else {
1766250003Sadrian            ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_WLAN_WGHT0;
1767250003Sadrian            ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_WLAN_WGHT1;
1768250003Sadrian            ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_WLAN_WGHT2;
1769250003Sadrian            ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_WLAN_WGHT3;
1770250003Sadrian        }
1771250003Sadrian        if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1772250003Sadrian            tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1773250003Sadrian        }
1774250008Sadrian        if (ah->ah_config.ath_hal_mci_config &
1775250003Sadrian            ATH_MCI_CONFIG_MCI_OBS_TXRX)
1776250003Sadrian        {
1777250003Sadrian            ar9300_gpio_set(ah, 5, 1);
1778250003Sadrian        }
1779250003Sadrian        break;
1780250003Sadrian    case HAL_BT_COEX_STOMP_ALL_FORCE:
1781250003Sadrian        ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0;
1782250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1;
1783250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2;
1784250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3;
1785250003Sadrian        break;
1786250003Sadrian    case HAL_BT_COEX_STOMP_LOW_FORCE:
1787250003Sadrian        ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0;
1788250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1;
1789250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2;
1790250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3;
1791250003Sadrian        if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1792250003Sadrian            tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1793250003Sadrian        }
1794250003Sadrian        break;
1795250003Sadrian    case HAL_BT_COEX_STOMP_NONE:
1796250003Sadrian    case HAL_BT_COEX_NO_STOMP:
1797250003Sadrian        ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_NONE_WLAN_WGHT0;
1798250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_NONE_WLAN_WGHT1;
1799250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_NONE_WLAN_WGHT2;
1800250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_NONE_WLAN_WGHT3;
1801250003Sadrian        if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_none_tx_pri) {
1802250003Sadrian            tx_priority = ahp->ah_mci_stomp_none_tx_pri;
1803250003Sadrian        }
1804250008Sadrian        if (ah->ah_config.ath_hal_mci_config &
1805250003Sadrian            ATH_MCI_CONFIG_MCI_OBS_TXRX)
1806250003Sadrian        {
1807250003Sadrian            ar9300_gpio_set(ah, 5, 0);
1808250003Sadrian        }
1809250003Sadrian        break;
1810250003Sadrian    default:
1811250003Sadrian        /* There is a forceWeight from registry */
1812250003Sadrian        ahp->ah_bt_coex_wlan_weight[0] = stomp_type;
1813250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] = stomp_type;
1814250003Sadrian        break;
1815250003Sadrian    }
1816250003Sadrian
1817250003Sadrian    if (ahp->ah_mci_concur_tx_en && tx_priority) {
1818250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] &= ~MCI_CONCUR_TX_WLAN_WGHT1_MASK;
1819250003Sadrian        ahp->ah_bt_coex_wlan_weight[1] |=
1820250003Sadrian            SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT1_MASK);
1821250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] &= ~MCI_CONCUR_TX_WLAN_WGHT2_MASK;
1822250003Sadrian        ahp->ah_bt_coex_wlan_weight[2] |=
1823250003Sadrian            SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT2_MASK);
1824250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK;
1825250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] |=
1826250003Sadrian            SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK);
1827250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK2;
1828250003Sadrian        ahp->ah_bt_coex_wlan_weight[3] |=
1829250003Sadrian            SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK2);
1830250003Sadrian    }
1831250008Sadrian    if (ah->ah_config.ath_hal_mci_config &
1832250003Sadrian        ATH_MCI_CONFIG_MCI_WEIGHT_DBG)
1833250003Sadrian    {
1834250003Sadrian        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1835250003Sadrian                "(MCI) Set weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
1836250003Sadrian                ahp->ah_bt_coex_wlan_weight[0],
1837250003Sadrian                ahp->ah_bt_coex_wlan_weight[1],
1838250003Sadrian                ahp->ah_bt_coex_wlan_weight[2],
1839250003Sadrian                ahp->ah_bt_coex_wlan_weight[3]);
1840250003Sadrian    }
1841250003Sadrian}
1842250003Sadrian
1843250003Sadrianvoid ar9300_mci_bt_coex_disable(struct ath_hal *ah)
1844250003Sadrian{
1845250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1846250003Sadrian
1847250003Sadrian    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1848250003Sadrian        "(MCI) %s: Set weight to stomp none.\n", __func__);
1849250003Sadrian
1850250003Sadrian    ar9300_mci_bt_coex_set_weights(ah, HAL_BT_COEX_STOMP_NONE);
1851250003Sadrian
1852250003Sadrian    /*
1853250003Sadrian     * In Jupiter, when coex is disabled, we just set weight
1854250003Sadrian     * table to be in favor of WLAN.
1855250003Sadrian     */
1856250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1857250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1858250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1859250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1860250003Sadrian
1861250003Sadrian    ahp->ah_bt_coex_enabled = AH_FALSE;
1862250003Sadrian}
1863250003Sadrian
1864250003Sadrianint ar9300_mci_bt_coex_enable(struct ath_hal *ah)
1865250003Sadrian{
1866250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
1867250003Sadrian
1868250003Sadrian    /* Mainly change the WLAN weight table */
1869250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1870250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1871250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1872250003Sadrian    OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1873250003Sadrian
1874250003Sadrian    /* Send ACK even when BT has higher priority. */
1875250003Sadrian    OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
1876250003Sadrian
1877250003Sadrian    if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) {
1878250003Sadrian        OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);
1879250003Sadrian    }
1880250003Sadrian    else {
1881250003Sadrian        OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);
1882250003Sadrian    }
1883250003Sadrian
1884250003Sadrian    ahp->ah_bt_coex_enabled = AH_TRUE;
1885250003Sadrian
1886250003Sadrian    return 0;
1887250003Sadrian}
1888250003Sadrian
1889250003Sadrian#endif /* ATH_SUPPORT_MCI */
1890