brintos

brintos / linux-shallow public Read only

0
0
Text · 42.7 KiB · 2b9c079 Raw
1584 lines · c
1/*2 * Copyright (c) 2008-2011 Atheros Communications Inc.3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#include <linux/export.h>18#include "hw.h"19#include "hw-ops.h"20#include "ar9003_phy.h"21#include "ar9003_mci.h"22#include "ar9003_aic.h"23 24static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah)25{26	REG_RMW_FIELD(ah, AR_MCI_COMMAND2,27		      AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);28	udelay(1);29	REG_RMW_FIELD(ah, AR_MCI_COMMAND2,30		      AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);31}32 33static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address,34					u32 bit_position, int time_out)35{36	struct ath_common *common = ath9k_hw_common(ah);37 38	while (time_out) {39		if (!(REG_READ(ah, address) & bit_position)) {40			udelay(10);41			time_out -= 10;42 43			if (time_out < 0)44				break;45			else46				continue;47		}48		REG_WRITE(ah, address, bit_position);49 50		if (address != AR_MCI_INTERRUPT_RX_MSG_RAW)51			break;52 53		if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)54			ar9003_mci_reset_req_wakeup(ah);55 56		if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |57				    AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))58			REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,59				  AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);60 61		REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);62		break;63	}64 65	if (time_out <= 0) {66		ath_dbg(common, MCI,67			"MCI Wait for Reg 0x%08x = 0x%08x timeout\n",68			address, bit_position);69		ath_dbg(common, MCI,70			"MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",71			REG_READ(ah, AR_MCI_INTERRUPT_RAW),72			REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));73		time_out = 0;74	}75 76	return time_out;77}78 79static void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done)80{81	u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};82 83	ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,84				wait_done, false);85	udelay(5);86}87 88static void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done)89{90	u32 payload = 0x00000000;91 92	ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,93				wait_done, false);94}95 96static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done)97{98	ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP,99				NULL, 0, wait_done, false);100	udelay(5);101}102 103static void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)104{105	ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,106				NULL, 0, wait_done, false);107}108 109static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done)110{111	u32 payload = 0x70000000;112 113	ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1,114				wait_done, false);115}116 117static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done)118{119	ar9003_mci_send_message(ah, MCI_SYS_SLEEPING,120				MCI_FLAG_DISABLE_TIMESTAMP,121				NULL, 0, wait_done, false);122}123 124static void ar9003_mci_send_coex_version_query(struct ath_hw *ah,125					       bool wait_done)126{127	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;128	u32 payload[4] = {0, 0, 0, 0};129 130	if (mci->bt_version_known ||131	    (mci->bt_state == MCI_BT_SLEEP))132		return;133 134	MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,135				MCI_GPM_COEX_VERSION_QUERY);136	ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);137}138 139static void ar9003_mci_send_coex_version_response(struct ath_hw *ah,140						  bool wait_done)141{142	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;143	u32 payload[4] = {0, 0, 0, 0};144 145	MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,146				MCI_GPM_COEX_VERSION_RESPONSE);147	*(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =148		mci->wlan_ver_major;149	*(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =150		mci->wlan_ver_minor;151	ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);152}153 154static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah,155					       bool wait_done)156{157	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;158	u32 *payload = &mci->wlan_channels[0];159 160	if (!mci->wlan_channels_update ||161	    (mci->bt_state == MCI_BT_SLEEP))162		return;163 164	MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,165				MCI_GPM_COEX_WLAN_CHANNELS);166	ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);167	MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);168}169 170static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah,171						bool wait_done, u8 query_type)172{173	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;174	u32 payload[4] = {0, 0, 0, 0};175	bool query_btinfo;176 177	if (mci->bt_state == MCI_BT_SLEEP)178		return;179 180	query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO |181					MCI_GPM_COEX_QUERY_BT_TOPOLOGY));182	MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,183				MCI_GPM_COEX_STATUS_QUERY);184 185	*(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;186 187	/*188	 * If bt_status_query message is  not sent successfully,189	 * then need_flush_btinfo should be set again.190	 */191	if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,192				wait_done, true)) {193		if (query_btinfo)194			mci->need_flush_btinfo = true;195	}196 197	if (query_btinfo)198		mci->query_bt = false;199}200 201static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt,202					     bool wait_done)203{204	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;205	u32 payload[4] = {0, 0, 0, 0};206 207	MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,208				MCI_GPM_COEX_HALT_BT_GPM);209 210	if (halt) {211		mci->query_bt = true;212		/* Send next unhalt no matter halt sent or not */213		mci->unhalt_bt_gpm = true;214		mci->need_flush_btinfo = true;215		*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =216			MCI_GPM_COEX_BT_GPM_HALT;217	} else218		*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =219			MCI_GPM_COEX_BT_GPM_UNHALT;220 221	ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);222}223 224static void ar9003_mci_prep_interface(struct ath_hw *ah)225{226	struct ath_common *common = ath9k_hw_common(ah);227	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;228	u32 saved_mci_int_en;229	u32 mci_timeout = 150;230 231	mci->bt_state = MCI_BT_SLEEP;232	saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);233 234	REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);235	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,236		  REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));237	REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,238		  REG_READ(ah, AR_MCI_INTERRUPT_RAW));239 240	ar9003_mci_remote_reset(ah, true);241	ar9003_mci_send_req_wake(ah, true);242 243	if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,244				  AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))245		goto clear_redunt;246 247	mci->bt_state = MCI_BT_AWAKE;248 249	/*250	 * we don't need to send more remote_reset at this moment.251	 * If BT receive first remote_reset, then BT HW will252	 * be cleaned up and will be able to receive req_wake253	 * and BT HW will respond sys_waking.254	 * In this case, WLAN will receive BT's HW sys_waking.255	 * Otherwise, if BT SW missed initial remote_reset,256	 * that remote_reset will still clean up BT MCI RX,257	 * and the req_wake will wake BT up,258	 * and BT SW will respond this req_wake with a remote_reset and259	 * sys_waking. In this case, WLAN will receive BT's SW260	 * sys_waking. In either case, BT's RX is cleaned up. So we261	 * don't need to reply BT's remote_reset now, if any.262	 * Similarly, if in any case, WLAN can receive BT's sys_waking,263	 * that means WLAN's RX is also fine.264	 */265	ar9003_mci_send_sys_waking(ah, true);266	udelay(10);267 268	/*269	 * Set BT priority interrupt value to be 0xff to270	 * avoid having too many BT PRIORITY interrupts.271	 */272	REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);273	REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);274	REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);275	REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);276	REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);277 278	/*279	 * A contention reset will be received after send out280	 * sys_waking. Also BT priority interrupt bits will be set.281	 * Clear those bits before the next step.282	 */283 284	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,285		  AR_MCI_INTERRUPT_RX_MSG_CONT_RST);286	REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);287 288	if (mci->is_2g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {289		ar9003_mci_send_lna_transfer(ah, true);290		udelay(5);291	}292 293	if (mci->is_2g && !mci->update_2g5g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {294		if (ar9003_mci_wait_for_interrupt(ah,295					AR_MCI_INTERRUPT_RX_MSG_RAW,296					AR_MCI_INTERRUPT_RX_MSG_LNA_INFO,297					mci_timeout))298			ath_dbg(common, MCI,299				"MCI WLAN has control over the LNA & BT obeys it\n");300		else301			ath_dbg(common, MCI,302				"MCI BT didn't respond to LNA_TRANS\n");303	}304 305clear_redunt:306	/* Clear the extra redundant SYS_WAKING from BT */307	if ((mci->bt_state == MCI_BT_AWAKE) &&308	    (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,309			    AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&310	    (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,311			    AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) {312		REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,313			  AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);314		REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,315			  AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);316	}317 318	REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);319}320 321void ar9003_mci_set_full_sleep(struct ath_hw *ah)322{323	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;324 325	if (ar9003_mci_state(ah, MCI_STATE_ENABLE) &&326	    (mci->bt_state != MCI_BT_SLEEP) &&327	    !mci->halted_bt_gpm) {328		ar9003_mci_send_coex_halt_bt_gpm(ah, true, true);329	}330 331	mci->ready = false;332}333 334static void ar9003_mci_disable_interrupt(struct ath_hw *ah)335{336	REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);337	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);338}339 340static void ar9003_mci_enable_interrupt(struct ath_hw *ah)341{342	REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);343	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,344		  AR_MCI_INTERRUPT_RX_MSG_DEFAULT);345}346 347static bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints)348{349	u32 intr;350 351	intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);352	return ((intr & ints) == ints);353}354 355void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,356			      u32 *rx_msg_intr)357{358	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;359 360	*raw_intr = mci->raw_intr;361	*rx_msg_intr = mci->rx_msg_intr;362 363	/* Clean int bits after the values are read. */364	mci->raw_intr = 0;365	mci->rx_msg_intr = 0;366}367EXPORT_SYMBOL(ar9003_mci_get_interrupt);368 369void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)370{371	struct ath_common *common = ath9k_hw_common(ah);372	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;373	u32 raw_intr, rx_msg_intr;374 375	rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);376	raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);377 378	if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) {379		ath_dbg(common, MCI,380			"MCI gets 0xdeadbeef during int processing\n");381	} else {382		mci->rx_msg_intr |= rx_msg_intr;383		mci->raw_intr |= raw_intr;384		*masked |= ATH9K_INT_MCI;385 386		if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)387			mci->cont_status = REG_READ(ah, AR_MCI_CONT_STATUS);388 389		REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);390		REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);391	}392}393 394static void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g)395{396	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;397 398	if (!mci->update_2g5g &&399	    (mci->is_2g != is_2g))400		mci->update_2g5g = true;401 402	mci->is_2g = is_2g;403}404 405static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index)406{407	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;408	u32 *payload;409	u32 recv_type, offset;410 411	if (msg_index == MCI_GPM_INVALID)412		return false;413 414	offset = msg_index << 4;415 416	payload = (u32 *)(mci->gpm_buf + offset);417	recv_type = MCI_GPM_TYPE(payload);418 419	if (recv_type == MCI_GPM_RSVD_PATTERN)420		return false;421 422	return true;423}424 425static void ar9003_mci_observation_set_up(struct ath_hw *ah)426{427	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;428 429	if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) {430		ath9k_hw_gpio_request_out(ah, 3, NULL,431					  AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);432		ath9k_hw_gpio_request_out(ah, 2, NULL,433					  AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);434		ath9k_hw_gpio_request_out(ah, 1, NULL,435					  AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);436		ath9k_hw_gpio_request_out(ah, 0, NULL,437					  AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);438	} else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) {439		ath9k_hw_gpio_request_out(ah, 3, NULL,440					  AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);441		ath9k_hw_gpio_request_out(ah, 2, NULL,442					  AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);443		ath9k_hw_gpio_request_out(ah, 1, NULL,444					  AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);445		ath9k_hw_gpio_request_out(ah, 0, NULL,446					  AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);447		ath9k_hw_gpio_request_out(ah, 5, NULL,448					  AR_GPIO_OUTPUT_MUX_AS_OUTPUT);449	} else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) {450		ath9k_hw_gpio_request_out(ah, 3, NULL,451					  AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);452		ath9k_hw_gpio_request_out(ah, 2, NULL,453					  AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);454		ath9k_hw_gpio_request_out(ah, 1, NULL,455					  AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);456		ath9k_hw_gpio_request_out(ah, 0, NULL,457					  AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);458	} else459		return;460 461	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL(ah), AR_GPIO_JTAG_DISABLE);462 463	REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);464	REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);465	REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, ATH_MCI_CONFIG_MCI_OBS_GPIO);466 467	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);468	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);469	REG_WRITE(ah, AR_OBS(ah), 0x4b);470	REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);471	REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);472	REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);473	REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);474	REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah),475		      AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);476}477 478static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done,479					  u8 opcode, u32 bt_flags)480{481	u32 pld[4] = {0, 0, 0, 0};482 483	MCI_GPM_SET_TYPE_OPCODE(pld, MCI_GPM_COEX_AGENT,484				MCI_GPM_COEX_BT_UPDATE_FLAGS);485 486	*(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP)  = opcode;487	*(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;488	*(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF;489	*(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF;490	*(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF;491 492	return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16,493				       wait_done, true);494}495 496static void ar9003_mci_sync_bt_state(struct ath_hw *ah)497{498	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;499	u32 cur_bt_state;500 501	cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP);502 503	if (mci->bt_state != cur_bt_state)504		mci->bt_state = cur_bt_state;505 506	if (mci->bt_state != MCI_BT_SLEEP) {507 508		ar9003_mci_send_coex_version_query(ah, true);509		ar9003_mci_send_coex_wlan_channels(ah, true);510 511		if (mci->unhalt_bt_gpm == true)512			ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);513	}514}515 516void ar9003_mci_check_bt(struct ath_hw *ah)517{518	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;519 520	if (!mci_hw->ready)521		return;522 523	/*524	 * check BT state again to make525	 * sure it's not changed.526	 */527	ar9003_mci_sync_bt_state(ah);528	ar9003_mci_2g5g_switch(ah, true);529 530	if ((mci_hw->bt_state == MCI_BT_AWAKE) &&531	    (mci_hw->query_bt == true)) {532		mci_hw->need_flush_btinfo = true;533	}534}535 536static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type,537					 u8 gpm_opcode, u32 *p_gpm)538{539	struct ath_common *common = ath9k_hw_common(ah);540	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;541	u8 *p_data = (u8 *) p_gpm;542 543	if (gpm_type != MCI_GPM_COEX_AGENT)544		return;545 546	switch (gpm_opcode) {547	case MCI_GPM_COEX_VERSION_QUERY:548		ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n");549		ar9003_mci_send_coex_version_response(ah, true);550		break;551	case MCI_GPM_COEX_VERSION_RESPONSE:552		ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n");553		mci->bt_ver_major =554			*(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);555		mci->bt_ver_minor =556			*(p_data + MCI_GPM_COEX_B_MINOR_VERSION);557		mci->bt_version_known = true;558		ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n",559			mci->bt_ver_major, mci->bt_ver_minor);560		break;561	case MCI_GPM_COEX_STATUS_QUERY:562		ath_dbg(common, MCI,563			"MCI Recv GPM COEX Status Query = 0x%02X\n",564			*(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));565		mci->wlan_channels_update = true;566		ar9003_mci_send_coex_wlan_channels(ah, true);567		break;568	case MCI_GPM_COEX_BT_PROFILE_INFO:569		mci->query_bt = true;570		ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n");571		break;572	case MCI_GPM_COEX_BT_STATUS_UPDATE:573		mci->query_bt = true;574		ath_dbg(common, MCI,575			"MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n",576			*(p_gpm + 3));577		break;578	default:579		break;580	}581}582 583static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,584				   u8 gpm_opcode, int time_out)585{586	struct ath_common *common = ath9k_hw_common(ah);587	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;588	u32 *p_gpm = NULL, more_data;589	u32 offset;590	u8 recv_type = 0, recv_opcode = 0;591	bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);592 593	more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;594 595	while (time_out > 0) {596		if (p_gpm) {597			MCI_GPM_RECYCLE(p_gpm);598			p_gpm = NULL;599		}600 601		if (more_data != MCI_GPM_MORE)602			time_out = ar9003_mci_wait_for_interrupt(ah,603					AR_MCI_INTERRUPT_RX_MSG_RAW,604					AR_MCI_INTERRUPT_RX_MSG_GPM,605					time_out);606 607		if (!time_out)608			break;609 610		offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);611 612		if (offset == MCI_GPM_INVALID)613			continue;614 615		p_gpm = (u32 *) (mci->gpm_buf + offset);616		recv_type = MCI_GPM_TYPE(p_gpm);617		recv_opcode = MCI_GPM_OPCODE(p_gpm);618 619		if (MCI_GPM_IS_CAL_TYPE(recv_type)) {620			if (recv_type == gpm_type) {621				if ((gpm_type == MCI_GPM_BT_CAL_DONE) &&622				    !b_is_bt_cal_done) {623					gpm_type = MCI_GPM_BT_CAL_GRANT;624					continue;625				}626				break;627			}628		} else if ((recv_type == gpm_type) &&629			   (recv_opcode == gpm_opcode))630			break;631 632		/*633		 * check if it's cal_grant634		 *635		 * When we're waiting for cal_grant in reset routine,636		 * it's possible that BT sends out cal_request at the637		 * same time. Since BT's calibration doesn't happen638		 * that often, we'll let BT completes calibration then639		 * we continue to wait for cal_grant from BT.640		 * Orginal: Wait BT_CAL_GRANT.641		 * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait642		 * BT_CAL_DONE -> Wait BT_CAL_GRANT.643		 */644 645		if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&646		    (recv_type == MCI_GPM_BT_CAL_REQ)) {647 648			u32 payload[4] = {0, 0, 0, 0};649 650			gpm_type = MCI_GPM_BT_CAL_DONE;651			MCI_GPM_SET_CAL_TYPE(payload,652					     MCI_GPM_WLAN_CAL_GRANT);653			ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,654						false, false);655			continue;656		} else {657			ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n",658				*(p_gpm + 1));659			ar9003_mci_process_gpm_extra(ah, recv_type,660						     recv_opcode, p_gpm);661		}662	}663 664	if (p_gpm) {665		MCI_GPM_RECYCLE(p_gpm);666		p_gpm = NULL;667	}668 669	if (time_out <= 0)670		time_out = 0;671 672	while (more_data == MCI_GPM_MORE) {673		offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);674		if (offset == MCI_GPM_INVALID)675			break;676 677		p_gpm = (u32 *) (mci->gpm_buf + offset);678		recv_type = MCI_GPM_TYPE(p_gpm);679		recv_opcode = MCI_GPM_OPCODE(p_gpm);680 681		if (!MCI_GPM_IS_CAL_TYPE(recv_type))682			ar9003_mci_process_gpm_extra(ah, recv_type,683						     recv_opcode, p_gpm);684 685		MCI_GPM_RECYCLE(p_gpm);686	}687 688	return time_out;689}690 691bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)692{693	struct ath_common *common = ath9k_hw_common(ah);694	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;695	u32 payload[4] = {0, 0, 0, 0};696 697	ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));698 699	if (mci_hw->bt_state != MCI_BT_CAL_START)700		return false;701 702	mci_hw->bt_state = MCI_BT_CAL;703 704	/*705	 * MCI FIX: disable mci interrupt here. This is to avoid706	 * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and707	 * lead to mci_intr reentry.708	 */709	ar9003_mci_disable_interrupt(ah);710 711	MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);712	ar9003_mci_send_message(ah, MCI_GPM, 0, payload,713				16, true, false);714 715	/* Wait BT calibration to be completed for 25ms */716 717	if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,718				    0, 25000))719		ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n");720	else721		ath_dbg(common, MCI,722			"MCI BT_CAL_DONE not received\n");723 724	mci_hw->bt_state = MCI_BT_AWAKE;725	/* MCI FIX: enable mci interrupt here */726	ar9003_mci_enable_interrupt(ah);727 728	return true;729}730 731int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,732			 struct ath9k_hw_cal_data *caldata)733{734	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;735 736	if (!mci_hw->ready)737		return 0;738 739	if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP))740		goto exit;741 742	if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) &&743	    !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE))744		goto exit;745 746	/*747	 * BT is sleeping. Check if BT wakes up during748	 * WLAN calibration. If BT wakes up during749	 * WLAN calibration, need to go through all750	 * message exchanges again and recal.751	 */752	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,753		  (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |754		   AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE));755 756	ar9003_mci_remote_reset(ah, true);757	ar9003_mci_send_sys_waking(ah, true);758	udelay(1);759 760	if (IS_CHAN_2GHZ(chan))761		ar9003_mci_send_lna_transfer(ah, true);762 763	mci_hw->bt_state = MCI_BT_AWAKE;764 765	REG_CLR_BIT(ah, AR_PHY_TIMING4,766		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);767 768	if (caldata) {769		clear_bit(TXIQCAL_DONE, &caldata->cal_flags);770		clear_bit(TXCLCAL_DONE, &caldata->cal_flags);771		clear_bit(RTT_DONE, &caldata->cal_flags);772	}773 774	if (!ath9k_hw_init_cal(ah, chan))775		return -EIO;776 777	REG_SET_BIT(ah, AR_PHY_TIMING4,778		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);779 780exit:781	ar9003_mci_enable_interrupt(ah);782	return 0;783}784 785static void ar9003_mci_mute_bt(struct ath_hw *ah)786{787	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;788 789	/* disable all MCI messages */790	REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);791	REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);792	REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);793	REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);794	REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);795	REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);796 797	/* wait pending HW messages to flush out */798	udelay(10);799 800	/*801	 * Send LNA_TAKE and SYS_SLEEPING when802	 * 1. reset not after resuming from full sleep803	 * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment804	 */805	if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {806		ar9003_mci_send_lna_take(ah, true);807		udelay(5);808	}809 810	ar9003_mci_send_sys_sleeping(ah, true);811}812 813static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)814{815	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;816	u32 thresh;817 818	if (!enable) {819		REG_CLR_BIT(ah, AR_BTCOEX_CTRL,820			    AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);821		return;822	}823	REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);824	REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,825		      AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);826 827	if (AR_SREV_9565(ah))828		REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);829 830	if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {831		thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);832		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,833			      AR_BTCOEX_CTRL_AGGR_THRESH, thresh);834		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,835			      AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);836	} else837		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,838			      AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);839 840	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,841		      AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);842}843 844static void ar9003_mci_stat_setup(struct ath_hw *ah)845{846	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;847 848	if (!AR_SREV_9565(ah))849		return;850 851	if (mci->config & ATH_MCI_CONFIG_MCI_STAT_DBG) {852		REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,853			      AR_MCI_DBG_CNT_CTRL_ENABLE, 1);854		REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,855			      AR_MCI_DBG_CNT_CTRL_BT_LINKID,856			      MCI_STAT_ALL_BT_LINKID);857	} else {858		REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,859			      AR_MCI_DBG_CNT_CTRL_ENABLE, 0);860	}861}862 863static void ar9003_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hw *ah)864{865	u32 regval;866 867	regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |868		 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |869		 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |870		 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |871		 SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |872		 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |873		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |874		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |875		 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);876 877	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,878		      AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);879	REG_WRITE(ah, AR_BTCOEX_CTRL, regval);880}881 882static void ar9003_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hw *ah)883{884	u32 regval;885 886	regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |887		 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |888		 SM(0, AR_BTCOEX_CTRL_PA_SHARED) |889		 SM(0, AR_BTCOEX_CTRL_LNA_SHARED) |890		 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |891		 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |892		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |893		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |894		 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);895 896	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,897		      AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0);898	REG_WRITE(ah, AR_BTCOEX_CTRL, regval);899}900 901static void ar9003_mci_set_btcoex_ctrl_9462(struct ath_hw *ah)902{903	u32 regval;904 905        regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |906		 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |907		 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |908		 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |909		 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |910		 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |911		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |912		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |913		 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);914 915	REG_WRITE(ah, AR_BTCOEX_CTRL, regval);916}917 918int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,919		     bool is_full_sleep)920{921	struct ath_common *common = ath9k_hw_common(ah);922	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;923	u32 regval, i;924 925	ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",926		is_full_sleep, is_2g);927 928	if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {929		ath_err(common, "BTCOEX control register is dead\n");930		return -EINVAL;931	}932 933	/* Program MCI DMA related registers */934	REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr);935	REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len);936	REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr);937 938	/*939	* To avoid MCI state machine be affected by incoming remote MCI msgs,940	* MCI mode will be enabled later, right before reset the MCI TX and RX.941	*/942	if (AR_SREV_9565(ah)) {943		u8 ant = MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH);944 945		if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED)946			ar9003_mci_set_btcoex_ctrl_9565_1ANT(ah);947		else948			ar9003_mci_set_btcoex_ctrl_9565_2ANT(ah);949	} else {950		ar9003_mci_set_btcoex_ctrl_9462(ah);951	}952 953	if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))954		ar9003_mci_osla_setup(ah, true);955	else956		ar9003_mci_osla_setup(ah, false);957 958	REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,959		    AR_BTCOEX_CTRL_SPDT_ENABLE);960	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,961		      AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);962 963	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);964	REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);965 966	/* Set the time out to 3.125ms (5 BT slots) */967	REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);968 969	/* concurrent tx priority */970	if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) {971		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,972			      AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);973		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,974			      AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);975		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,976			      AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);977		for (i = 0; i < 8; i++)978			REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f);979	}980 981	regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);982	REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);983	REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);984 985	/* Resetting the Rx and Tx paths of MCI */986	regval = REG_READ(ah, AR_MCI_COMMAND2);987	regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);988	REG_WRITE(ah, AR_MCI_COMMAND2, regval);989 990	udelay(1);991 992	regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);993	REG_WRITE(ah, AR_MCI_COMMAND2, regval);994 995	if (is_full_sleep) {996		ar9003_mci_mute_bt(ah);997		udelay(100);998	}999 1000	/* Check pending GPM msg before MCI Reset Rx */1001	ar9003_mci_check_gpm_offset(ah);1002 1003	regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);1004	REG_WRITE(ah, AR_MCI_COMMAND2, regval);1005	udelay(1);1006	regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);1007	REG_WRITE(ah, AR_MCI_COMMAND2, regval);1008 1009	/* Init GPM offset after MCI Reset Rx */1010	ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET);1011 1012	REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,1013		  (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |1014		   SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));1015 1016	if (MCI_ANT_ARCH_PA_LNA_SHARED(mci))1017		REG_CLR_BIT(ah, AR_MCI_TX_CTRL,1018			    AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);1019	else1020		REG_SET_BIT(ah, AR_MCI_TX_CTRL,1021			    AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);1022 1023	ar9003_mci_observation_set_up(ah);1024 1025	mci->ready = true;1026	ar9003_mci_prep_interface(ah);1027	ar9003_mci_stat_setup(ah);1028 1029	if (en_int)1030		ar9003_mci_enable_interrupt(ah);1031 1032	if (ath9k_hw_is_aic_enabled(ah))1033		ar9003_aic_start_normal(ah);1034 1035	return 0;1036}1037 1038void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep)1039{1040	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;1041 1042	ar9003_mci_disable_interrupt(ah);1043 1044	if (mci_hw->ready && !save_fullsleep) {1045		ar9003_mci_mute_bt(ah);1046		udelay(20);1047		REG_WRITE(ah, AR_BTCOEX_CTRL, 0);1048	}1049 1050	mci_hw->bt_state = MCI_BT_SLEEP;1051	mci_hw->ready = false;1052}1053 1054static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done)1055{1056	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1057	u32 to_set, to_clear;1058 1059	if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP))1060		return;1061 1062	if (mci->is_2g) {1063		to_clear = MCI_2G_FLAGS_CLEAR_MASK;1064		to_set = MCI_2G_FLAGS_SET_MASK;1065	} else {1066		to_clear = MCI_5G_FLAGS_CLEAR_MASK;1067		to_set = MCI_5G_FLAGS_SET_MASK;1068	}1069 1070	if (to_clear)1071		ar9003_mci_send_coex_bt_flags(ah, wait_done,1072					      MCI_GPM_COEX_BT_FLAGS_CLEAR,1073					      to_clear);1074	if (to_set)1075		ar9003_mci_send_coex_bt_flags(ah, wait_done,1076					      MCI_GPM_COEX_BT_FLAGS_SET,1077					      to_set);1078}1079 1080static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,1081					u32 *payload, bool queue)1082{1083	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1084	u8 type, opcode;1085 1086	/* check if the message is to be queued */1087	if (header != MCI_GPM)1088		return;1089 1090	type = MCI_GPM_TYPE(payload);1091	opcode = MCI_GPM_OPCODE(payload);1092 1093	if (type != MCI_GPM_COEX_AGENT)1094		return;1095 1096	switch (opcode) {1097	case MCI_GPM_COEX_BT_UPDATE_FLAGS:1098		if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==1099		    MCI_GPM_COEX_BT_FLAGS_READ)1100			break;1101 1102		mci->update_2g5g = queue;1103 1104		break;1105	case MCI_GPM_COEX_WLAN_CHANNELS:1106		mci->wlan_channels_update = queue;1107		break;1108	case MCI_GPM_COEX_HALT_BT_GPM:1109		if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==1110		    MCI_GPM_COEX_BT_GPM_UNHALT) {1111			mci->unhalt_bt_gpm = queue;1112 1113			if (!queue)1114				mci->halted_bt_gpm = false;1115		}1116 1117		if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==1118				MCI_GPM_COEX_BT_GPM_HALT) {1119 1120			mci->halted_bt_gpm = !queue;1121		}1122 1123		break;1124	default:1125		break;1126	}1127}1128 1129void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)1130{1131	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1132 1133	if (!mci->update_2g5g && !force)1134		return;1135 1136	if (mci->is_2g) {1137		ar9003_mci_send_2g5g_status(ah, true);1138		ar9003_mci_send_lna_transfer(ah, true);1139		udelay(5);1140 1141		REG_CLR_BIT(ah, AR_MCI_TX_CTRL,1142			    AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);1143		REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,1144			    AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);1145 1146		if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))1147			ar9003_mci_osla_setup(ah, true);1148 1149		if (AR_SREV_9462(ah))1150			REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);1151	} else {1152		ar9003_mci_send_lna_take(ah, true);1153		udelay(5);1154 1155		REG_SET_BIT(ah, AR_MCI_TX_CTRL,1156			    AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);1157		REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,1158			    AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);1159 1160		ar9003_mci_osla_setup(ah, false);1161		ar9003_mci_send_2g5g_status(ah, true);1162	}1163}1164 1165bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,1166			     u32 *payload, u8 len, bool wait_done,1167			     bool check_bt)1168{1169	struct ath_common *common = ath9k_hw_common(ah);1170	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1171	bool msg_sent = false;1172	u32 regval;1173	u32 saved_mci_int_en;1174	int i;1175 1176	saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);1177	regval = REG_READ(ah, AR_BTCOEX_CTRL);1178 1179	if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {1180		ath_dbg(common, MCI,1181			"MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n",1182			header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0);1183		ar9003_mci_queue_unsent_gpm(ah, header, payload, true);1184		return false;1185	} else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) {1186		ath_dbg(common, MCI,1187			"MCI Don't send message 0x%x. BT is in sleep state\n",1188			header);1189		ar9003_mci_queue_unsent_gpm(ah, header, payload, true);1190		return false;1191	}1192 1193	if (wait_done)1194		REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);1195 1196	/* Need to clear SW_MSG_DONE raw bit before wait */1197 1198	REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,1199		  (AR_MCI_INTERRUPT_SW_MSG_DONE |1200		   AR_MCI_INTERRUPT_MSG_FAIL_MASK));1201 1202	if (payload) {1203		for (i = 0; (i * 4) < len; i++)1204			REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4),1205				  *(payload + i));1206	}1207 1208	REG_WRITE(ah, AR_MCI_COMMAND0,1209		  (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP),1210		      AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |1211		   SM(len, AR_MCI_COMMAND0_LEN) |1212		   SM(header, AR_MCI_COMMAND0_HEADER)));1213 1214	if (wait_done &&1215	    !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,1216					    AR_MCI_INTERRUPT_SW_MSG_DONE, 500)))1217		ar9003_mci_queue_unsent_gpm(ah, header, payload, true);1218	else {1219		ar9003_mci_queue_unsent_gpm(ah, header, payload, false);1220		msg_sent = true;1221	}1222 1223	if (wait_done)1224		REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);1225 1226	return msg_sent;1227}1228EXPORT_SYMBOL(ar9003_mci_send_message);1229 1230void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable)1231{1232	struct ath_common *common = ath9k_hw_common(ah);1233	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;1234	u32 pld[4] = {0, 0, 0, 0};1235 1236	if ((mci_hw->bt_state != MCI_BT_AWAKE) ||1237	    (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))1238		return;1239 1240	MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ);1241	pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++;1242 1243	ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);1244 1245	if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) {1246		ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n");1247	} else {1248		*is_reusable = false;1249		ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n");1250	}1251}1252 1253void ar9003_mci_init_cal_done(struct ath_hw *ah)1254{1255	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;1256	u32 pld[4] = {0, 0, 0, 0};1257 1258	if ((mci_hw->bt_state != MCI_BT_AWAKE) ||1259	    (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))1260		return;1261 1262	MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE);1263	pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++;1264	ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);1265}1266 1267int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,1268		     u16 len, u32 sched_addr)1269{1270	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1271 1272	mci->gpm_addr = gpm_addr;1273	mci->gpm_buf = gpm_buf;1274	mci->gpm_len = len;1275	mci->sched_addr = sched_addr;1276 1277	return ar9003_mci_reset(ah, true, true, true);1278}1279EXPORT_SYMBOL(ar9003_mci_setup);1280 1281void ar9003_mci_cleanup(struct ath_hw *ah)1282{1283	/* Turn off MCI and Jupiter mode. */1284	REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);1285	ar9003_mci_disable_interrupt(ah);1286}1287EXPORT_SYMBOL(ar9003_mci_cleanup);1288 1289u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)1290{1291	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1292	u32 value = 0, tsf;1293	u8 query_type;1294 1295	switch (state_type) {1296	case MCI_STATE_ENABLE:1297		if (mci->ready) {1298			value = REG_READ(ah, AR_BTCOEX_CTRL);1299 1300			if ((value == 0xdeadbeef) || (value == 0xffffffff))1301				value = 0;1302		}1303		value &= AR_BTCOEX_CTRL_MCI_MODE_EN;1304		break;1305	case MCI_STATE_INIT_GPM_OFFSET:1306		value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);1307 1308		if (value < mci->gpm_len)1309			mci->gpm_idx = value;1310		else1311			mci->gpm_idx = 0;1312		break;1313	case MCI_STATE_LAST_SCHD_MSG_OFFSET:1314		value = MS(REG_READ(ah, AR_MCI_RX_STATUS),1315				    AR_MCI_RX_LAST_SCHD_MSG_INDEX);1316		/* Make it in bytes */1317		value <<= 4;1318		break;1319	case MCI_STATE_REMOTE_SLEEP:1320		value = MS(REG_READ(ah, AR_MCI_RX_STATUS),1321			   AR_MCI_RX_REMOTE_SLEEP) ?1322			MCI_BT_SLEEP : MCI_BT_AWAKE;1323		break;1324	case MCI_STATE_SET_BT_AWAKE:1325		mci->bt_state = MCI_BT_AWAKE;1326		ar9003_mci_send_coex_version_query(ah, true);1327		ar9003_mci_send_coex_wlan_channels(ah, true);1328 1329		if (mci->unhalt_bt_gpm)1330			ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);1331 1332		ar9003_mci_2g5g_switch(ah, false);1333		break;1334	case MCI_STATE_RESET_REQ_WAKE:1335		ar9003_mci_reset_req_wakeup(ah);1336		mci->update_2g5g = true;1337 1338		if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) {1339			/* Check if we still have control of the GPIOs */1340			if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) &1341			     ATH_MCI_CONFIG_MCI_OBS_GPIO) !=1342			    ATH_MCI_CONFIG_MCI_OBS_GPIO) {1343				ar9003_mci_observation_set_up(ah);1344			}1345		}1346		break;1347	case MCI_STATE_SEND_WLAN_COEX_VERSION:1348		ar9003_mci_send_coex_version_response(ah, true);1349		break;1350	case MCI_STATE_SEND_VERSION_QUERY:1351		ar9003_mci_send_coex_version_query(ah, true);1352		break;1353	case MCI_STATE_SEND_STATUS_QUERY:1354		query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;1355		ar9003_mci_send_coex_bt_status_query(ah, true, query_type);1356		break;1357	case MCI_STATE_RECOVER_RX:1358		tsf = ath9k_hw_gettsf32(ah);1359		if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) {1360			ath_dbg(ath9k_hw_common(ah), MCI,1361				"(MCI) ignore Rx recovery\n");1362			break;1363		}1364		ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n");1365		mci->last_recovery = tsf;1366		ar9003_mci_prep_interface(ah);1367		mci->query_bt = true;1368		mci->need_flush_btinfo = true;1369		ar9003_mci_send_coex_wlan_channels(ah, true);1370		ar9003_mci_2g5g_switch(ah, false);1371		break;1372	case MCI_STATE_NEED_FTP_STOMP:1373		value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);1374		break;1375	case MCI_STATE_NEED_FLUSH_BT_INFO:1376		value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0;1377		mci->need_flush_btinfo = false;1378		break;1379	case MCI_STATE_AIC_CAL:1380		if (ath9k_hw_is_aic_enabled(ah))1381			value = ar9003_aic_calibration(ah);1382		break;1383	case MCI_STATE_AIC_START:1384		if (ath9k_hw_is_aic_enabled(ah))1385			ar9003_aic_start_normal(ah);1386		break;1387	case MCI_STATE_AIC_CAL_RESET:1388		if (ath9k_hw_is_aic_enabled(ah))1389			value = ar9003_aic_cal_reset(ah);1390		break;1391	case MCI_STATE_AIC_CAL_SINGLE:1392		if (ath9k_hw_is_aic_enabled(ah))1393			value = ar9003_aic_calibration_single(ah);1394		break;1395	default:1396		break;1397	}1398 1399	return value;1400}1401EXPORT_SYMBOL(ar9003_mci_state);1402 1403void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)1404{1405	struct ath_common *common = ath9k_hw_common(ah);1406	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1407 1408	ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");1409 1410	ar9003_mci_send_lna_take(ah, true);1411	udelay(50);1412 1413	REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);1414	mci->is_2g = false;1415	mci->update_2g5g = true;1416	ar9003_mci_send_2g5g_status(ah, true);1417 1418	/* Force another 2g5g update at next scanning */1419	mci->update_2g5g = true;1420}1421 1422void ar9003_mci_set_power_awake(struct ath_hw *ah)1423{1424	u32 btcoex_ctrl2, diag_sw;1425	int i;1426	u8 lna_ctrl, bt_sleep;1427 1428	for (i = 0; i < AH_WAIT_TIMEOUT; i++) {1429		btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);1430		if (btcoex_ctrl2 != 0xdeadbeef)1431			break;1432		udelay(AH_TIME_QUANTUM);1433	}1434	REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));1435 1436	for (i = 0; i < AH_WAIT_TIMEOUT; i++) {1437		diag_sw = REG_READ(ah, AR_DIAG_SW);1438		if (diag_sw != 0xdeadbeef)1439			break;1440		udelay(AH_TIME_QUANTUM);1441	}1442	REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));1443	lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;1444	bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP);1445 1446	REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);1447	REG_WRITE(ah, AR_DIAG_SW, diag_sw);1448 1449	if (bt_sleep && (lna_ctrl == 2)) {1450		REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);1451		REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);1452		udelay(50);1453	}1454}1455 1456void ar9003_mci_check_gpm_offset(struct ath_hw *ah)1457{1458	struct ath_common *common = ath9k_hw_common(ah);1459	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1460	u32 offset;1461 1462	/*1463	 * This should only be called before "MAC Warm Reset" or "MCI Reset Rx".1464	 */1465	offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);1466	if (mci->gpm_idx == offset)1467		return;1468	ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",1469		mci->gpm_idx, offset);1470	mci->query_bt = true;1471	mci->need_flush_btinfo = true;1472	mci->gpm_idx = 0;1473}1474 1475u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more)1476{1477	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1478	u32 offset, more_gpm = 0, gpm_ptr;1479 1480	/*1481	 * This could be useful to avoid new GPM message interrupt which1482	 * may lead to spurious interrupt after power sleep, or multiple1483	 * entry of ath_mci_intr().1484	 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can1485	 * alleviate this effect, but clearing GPM RX interrupt bit is1486	 * safe, because whether this is called from hw or driver code1487	 * there must be an interrupt bit set/triggered initially1488	 */1489	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,1490			AR_MCI_INTERRUPT_RX_MSG_GPM);1491 1492	gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);1493	offset = gpm_ptr;1494 1495	if (!offset)1496		offset = mci->gpm_len - 1;1497	else if (offset >= mci->gpm_len) {1498		if (offset != 0xFFFF)1499			offset = 0;1500	} else {1501		offset--;1502	}1503 1504	if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {1505		offset = MCI_GPM_INVALID;1506		more_gpm = MCI_GPM_NOMORE;1507		goto out;1508	}1509	for (;;) {1510		u32 temp_index;1511 1512		/* skip reserved GPM if any */1513 1514		if (offset != mci->gpm_idx)1515			more_gpm = MCI_GPM_MORE;1516		else1517			more_gpm = MCI_GPM_NOMORE;1518 1519		temp_index = mci->gpm_idx;1520 1521		if (temp_index >= mci->gpm_len)1522			temp_index = 0;1523 1524		mci->gpm_idx++;1525 1526		if (mci->gpm_idx >= mci->gpm_len)1527			mci->gpm_idx = 0;1528 1529		if (ar9003_mci_is_gpm_valid(ah, temp_index)) {1530			offset = temp_index;1531			break;1532		}1533 1534		if (more_gpm == MCI_GPM_NOMORE) {1535			offset = MCI_GPM_INVALID;1536			break;1537		}1538	}1539 1540	if (offset != MCI_GPM_INVALID)1541		offset <<= 4;1542out:1543	if (more)1544		*more = more_gpm;1545 1546	return offset;1547}1548EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);1549 1550void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)1551{1552	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1553 1554	mci->bt_ver_major = major;1555	mci->bt_ver_minor = minor;1556	mci->bt_version_known = true;1557	ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",1558		mci->bt_ver_major, mci->bt_ver_minor);1559}1560EXPORT_SYMBOL(ar9003_mci_set_bt_version);1561 1562void ar9003_mci_send_wlan_channels(struct ath_hw *ah)1563{1564	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;1565 1566	mci->wlan_channels_update = true;1567	ar9003_mci_send_coex_wlan_channels(ah, true);1568}1569EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);1570 1571u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)1572{1573	if (!ah->btcoex_hw.mci.concur_tx)1574		goto out;1575 1576	if (ctlmode == CTL_2GHT20)1577		return ATH_BTCOEX_HT20_MAX_TXPOWER;1578	else if (ctlmode == CTL_2GHT40)1579		return ATH_BTCOEX_HT40_MAX_TXPOWER;1580 1581out:1582	return -1;1583}1584