xref: /openbmc/linux/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
173ffcd40SLee Jones /*
2dad0d04fSFariya Fatima  * Copyright (c) 2014 Redpine Signals Inc.
3dad0d04fSFariya Fatima  *
4dad0d04fSFariya Fatima  * Permission to use, copy, modify, and/or distribute this software for any
5dad0d04fSFariya Fatima  * purpose with or without fee is hereby granted, provided that the above
6dad0d04fSFariya Fatima  * copyright notice and this permission notice appear in all copies.
7dad0d04fSFariya Fatima  *
8dad0d04fSFariya Fatima  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9dad0d04fSFariya Fatima  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10dad0d04fSFariya Fatima  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11dad0d04fSFariya Fatima  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12dad0d04fSFariya Fatima  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13dad0d04fSFariya Fatima  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14dad0d04fSFariya Fatima  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15dad0d04fSFariya Fatima  *
16dad0d04fSFariya Fatima  */
17dad0d04fSFariya Fatima 
18dad0d04fSFariya Fatima #include <linux/firmware.h>
19716b840cSSiva Rebbagondla #include <net/rsi_91x.h>
20dad0d04fSFariya Fatima #include "rsi_sdio.h"
21dad0d04fSFariya Fatima #include "rsi_common.h"
22dad0d04fSFariya Fatima 
23dad0d04fSFariya Fatima /**
24dad0d04fSFariya Fatima  * rsi_sdio_master_access_msword() - This function sets the AHB master access
25dad0d04fSFariya Fatima  *				     MS word in the SDIO slave registers.
26dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
27dad0d04fSFariya Fatima  * @ms_word: ms word need to be initialized.
28dad0d04fSFariya Fatima  *
29dad0d04fSFariya Fatima  * Return: status: 0 on success, -1 on failure.
30dad0d04fSFariya Fatima  */
rsi_sdio_master_access_msword(struct rsi_hw * adapter,u16 ms_word)31b97e9b94SPrameela Rani Garnepudi int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
32dad0d04fSFariya Fatima {
33dad0d04fSFariya Fatima 	u8 byte;
34dad0d04fSFariya Fatima 	u8 function = 0;
35dad0d04fSFariya Fatima 	int status = 0;
36dad0d04fSFariya Fatima 
37dad0d04fSFariya Fatima 	byte = (u8)(ms_word & 0x00FF);
38dad0d04fSFariya Fatima 
39dad0d04fSFariya Fatima 	rsi_dbg(INIT_ZONE,
40dad0d04fSFariya Fatima 		"%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte);
41dad0d04fSFariya Fatima 
42dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
43dad0d04fSFariya Fatima 					 function,
44dad0d04fSFariya Fatima 					 SDIO_MASTER_ACCESS_MSBYTE,
45dad0d04fSFariya Fatima 					 &byte);
46dad0d04fSFariya Fatima 	if (status) {
47dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
48dad0d04fSFariya Fatima 			"%s: fail to access MASTER_ACCESS_MSBYTE\n",
49dad0d04fSFariya Fatima 			__func__);
50dad0d04fSFariya Fatima 		return -1;
51dad0d04fSFariya Fatima 	}
52dad0d04fSFariya Fatima 
53dad0d04fSFariya Fatima 	byte = (u8)(ms_word >> 8);
54dad0d04fSFariya Fatima 
55dad0d04fSFariya Fatima 	rsi_dbg(INIT_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);
56dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
57dad0d04fSFariya Fatima 					 function,
58dad0d04fSFariya Fatima 					 SDIO_MASTER_ACCESS_LSBYTE,
59dad0d04fSFariya Fatima 					 &byte);
60dad0d04fSFariya Fatima 	return status;
61dad0d04fSFariya Fatima }
62dad0d04fSFariya Fatima 
6328743146SMarek Vasut static void rsi_rx_handler(struct rsi_hw *adapter);
6428743146SMarek Vasut 
rsi_sdio_rx_thread(struct rsi_common * common)6550117605SPrameela Rani Garnepudi void rsi_sdio_rx_thread(struct rsi_common *common)
6650117605SPrameela Rani Garnepudi {
6750117605SPrameela Rani Garnepudi 	struct rsi_hw *adapter = common->priv;
6850117605SPrameela Rani Garnepudi 	struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
6950117605SPrameela Rani Garnepudi 
7050117605SPrameela Rani Garnepudi 	do {
7150117605SPrameela Rani Garnepudi 		rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
7250117605SPrameela Rani Garnepudi 		rsi_reset_event(&sdev->rx_thread.event);
7328743146SMarek Vasut 		rsi_rx_handler(adapter);
7428743146SMarek Vasut 	} while (!atomic_read(&sdev->rx_thread.thread_done));
7550117605SPrameela Rani Garnepudi 
7650117605SPrameela Rani Garnepudi 	rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
7750117605SPrameela Rani Garnepudi 	atomic_inc(&sdev->rx_thread.thread_done);
78cead1855SEric W. Biederman 	kthread_complete_and_exit(&sdev->rx_thread.completion, 0);
7950117605SPrameela Rani Garnepudi }
8050117605SPrameela Rani Garnepudi 
81dad0d04fSFariya Fatima /**
82dad0d04fSFariya Fatima  * rsi_process_pkt() - This Function reads rx_blocks register and figures out
83dad0d04fSFariya Fatima  *		       the size of the rx pkt.
84dad0d04fSFariya Fatima  * @common: Pointer to the driver private structure.
85dad0d04fSFariya Fatima  *
86dad0d04fSFariya Fatima  * Return: 0 on success, -1 on failure.
87dad0d04fSFariya Fatima  */
rsi_process_pkt(struct rsi_common * common)88dad0d04fSFariya Fatima static int rsi_process_pkt(struct rsi_common *common)
89dad0d04fSFariya Fatima {
90dad0d04fSFariya Fatima 	struct rsi_hw *adapter = common->priv;
91*361beddbSWu Yunchuan 	struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
92dad0d04fSFariya Fatima 	u8 num_blks = 0;
93dad0d04fSFariya Fatima 	u32 rcv_pkt_len = 0;
94dad0d04fSFariya Fatima 	int status = 0;
95ebf084eaSKarun Eagalapati 	u8 value = 0;
96dad0d04fSFariya Fatima 
97ebf084eaSKarun Eagalapati 	num_blks = ((adapter->interrupt_status & 1) |
98ebf084eaSKarun Eagalapati 			((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1));
99ebf084eaSKarun Eagalapati 
100ebf084eaSKarun Eagalapati 	if (!num_blks) {
101dad0d04fSFariya Fatima 		status = rsi_sdio_read_register(adapter,
102dad0d04fSFariya Fatima 						SDIO_RX_NUM_BLOCKS_REG,
103ebf084eaSKarun Eagalapati 						&value);
104dad0d04fSFariya Fatima 		if (status) {
105dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
106dad0d04fSFariya Fatima 				"%s: Failed to read pkt length from the card:\n",
107dad0d04fSFariya Fatima 				__func__);
108dad0d04fSFariya Fatima 			return status;
109dad0d04fSFariya Fatima 		}
110ebf084eaSKarun Eagalapati 		num_blks = value & 0x1f;
111ebf084eaSKarun Eagalapati 	}
112ebf084eaSKarun Eagalapati 
113ebf084eaSKarun Eagalapati 	if (dev->write_fail == 2)
114ebf084eaSKarun Eagalapati 		rsi_sdio_ack_intr(common->priv, (1 << MSDU_PKT_PENDING));
115ebf084eaSKarun Eagalapati 
116ebf084eaSKarun Eagalapati 	if (unlikely(!num_blks)) {
117ebf084eaSKarun Eagalapati 		dev->write_fail = 2;
118ebf084eaSKarun Eagalapati 		return -1;
119ebf084eaSKarun Eagalapati 	}
120ebf084eaSKarun Eagalapati 
121dad0d04fSFariya Fatima 	rcv_pkt_len = (num_blks * 256);
122dad0d04fSFariya Fatima 
12328743146SMarek Vasut 	status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer,
12428743146SMarek Vasut 					     rcv_pkt_len);
125dad0d04fSFariya Fatima 	if (status) {
126dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
127dad0d04fSFariya Fatima 			__func__);
128d50c761aSFariya Fatima 		return status;
129dad0d04fSFariya Fatima 	}
13050117605SPrameela Rani Garnepudi 
13128743146SMarek Vasut 	status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len);
13228743146SMarek Vasut 	if (status) {
13328743146SMarek Vasut 		rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
13428743146SMarek Vasut 		return status;
13528743146SMarek Vasut 	}
13650117605SPrameela Rani Garnepudi 
13750117605SPrameela Rani Garnepudi 	return 0;
13850117605SPrameela Rani Garnepudi }
139dad0d04fSFariya Fatima 
140dad0d04fSFariya Fatima /**
141dad0d04fSFariya Fatima  * rsi_init_sdio_slave_regs() - This function does the actual initialization
142dad0d04fSFariya Fatima  *				of SDBUS slave registers.
143dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
144dad0d04fSFariya Fatima  *
145dad0d04fSFariya Fatima  * Return: status: 0 on success, -1 on failure.
146dad0d04fSFariya Fatima  */
rsi_init_sdio_slave_regs(struct rsi_hw * adapter)147dad0d04fSFariya Fatima int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
148dad0d04fSFariya Fatima {
149*361beddbSWu Yunchuan 	struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
150dad0d04fSFariya Fatima 	u8 function = 0;
151dad0d04fSFariya Fatima 	u8 byte;
152dad0d04fSFariya Fatima 	int status = 0;
153dad0d04fSFariya Fatima 
154dad0d04fSFariya Fatima 	if (dev->next_read_delay) {
155dad0d04fSFariya Fatima 		byte = dev->next_read_delay;
156dad0d04fSFariya Fatima 		status = rsi_sdio_write_register(adapter,
157dad0d04fSFariya Fatima 						 function,
158dad0d04fSFariya Fatima 						 SDIO_NXT_RD_DELAY2,
159dad0d04fSFariya Fatima 						 &byte);
160dad0d04fSFariya Fatima 		if (status) {
161dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
162dad0d04fSFariya Fatima 				"%s: Failed to write SDIO_NXT_RD_DELAY2\n",
163dad0d04fSFariya Fatima 				__func__);
164dad0d04fSFariya Fatima 			return -1;
165dad0d04fSFariya Fatima 		}
166dad0d04fSFariya Fatima 	}
167dad0d04fSFariya Fatima 
168dad0d04fSFariya Fatima 	if (dev->sdio_high_speed_enable) {
169dad0d04fSFariya Fatima 		rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);
170dad0d04fSFariya Fatima 		byte = 0x3;
171dad0d04fSFariya Fatima 
172dad0d04fSFariya Fatima 		status = rsi_sdio_write_register(adapter,
173dad0d04fSFariya Fatima 						 function,
174dad0d04fSFariya Fatima 						 SDIO_REG_HIGH_SPEED,
175dad0d04fSFariya Fatima 						 &byte);
176dad0d04fSFariya Fatima 		if (status) {
177dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
178dad0d04fSFariya Fatima 				"%s: Failed to enable SDIO high speed\n",
179dad0d04fSFariya Fatima 				__func__);
180dad0d04fSFariya Fatima 			return -1;
181dad0d04fSFariya Fatima 		}
182dad0d04fSFariya Fatima 	}
183dad0d04fSFariya Fatima 
184dad0d04fSFariya Fatima 	/* This tells SDIO FIFO when to start read to host */
18555930d2bSColin Ian King 	rsi_dbg(INIT_ZONE, "%s: Initializing SDIO read start level\n", __func__);
186dad0d04fSFariya Fatima 	byte = 0x24;
187dad0d04fSFariya Fatima 
188dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
189dad0d04fSFariya Fatima 					 function,
190dad0d04fSFariya Fatima 					 SDIO_READ_START_LVL,
191dad0d04fSFariya Fatima 					 &byte);
192dad0d04fSFariya Fatima 	if (status) {
193dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
194dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_READ_START_LVL\n", __func__);
195dad0d04fSFariya Fatima 		return -1;
196dad0d04fSFariya Fatima 	}
197dad0d04fSFariya Fatima 
19855930d2bSColin Ian King 	rsi_dbg(INIT_ZONE, "%s: Initializing FIFO ctrl registers\n", __func__);
199dad0d04fSFariya Fatima 	byte = (128 - 32);
200dad0d04fSFariya Fatima 
201dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
202dad0d04fSFariya Fatima 					 function,
203dad0d04fSFariya Fatima 					 SDIO_READ_FIFO_CTL,
204dad0d04fSFariya Fatima 					 &byte);
205dad0d04fSFariya Fatima 	if (status) {
206dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
207dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__);
208dad0d04fSFariya Fatima 		return -1;
209dad0d04fSFariya Fatima 	}
210dad0d04fSFariya Fatima 
211dad0d04fSFariya Fatima 	byte = 32;
212dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
213dad0d04fSFariya Fatima 					 function,
214dad0d04fSFariya Fatima 					 SDIO_WRITE_FIFO_CTL,
215dad0d04fSFariya Fatima 					 &byte);
216dad0d04fSFariya Fatima 	if (status) {
217dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
218dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__);
219dad0d04fSFariya Fatima 		return -1;
220dad0d04fSFariya Fatima 	}
221dad0d04fSFariya Fatima 
222dad0d04fSFariya Fatima 	return 0;
223dad0d04fSFariya Fatima }
224dad0d04fSFariya Fatima 
225dad0d04fSFariya Fatima /**
22628743146SMarek Vasut  * rsi_rx_handler() - Read and process SDIO interrupts.
227dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
228dad0d04fSFariya Fatima  *
229dad0d04fSFariya Fatima  * Return: None.
230dad0d04fSFariya Fatima  */
rsi_rx_handler(struct rsi_hw * adapter)23128743146SMarek Vasut static void rsi_rx_handler(struct rsi_hw *adapter)
232dad0d04fSFariya Fatima {
233dad0d04fSFariya Fatima 	struct rsi_common *common = adapter->priv;
234*361beddbSWu Yunchuan 	struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
235dad0d04fSFariya Fatima 	int status;
236dad0d04fSFariya Fatima 	u8 isr_status = 0;
237dad0d04fSFariya Fatima 	u8 fw_status = 0;
238dad0d04fSFariya Fatima 
239dad0d04fSFariya Fatima 	dev->rx_info.sdio_int_counter++;
240dad0d04fSFariya Fatima 
241dad0d04fSFariya Fatima 	do {
2426c409cadSKarun Eagalapati 		mutex_lock(&common->rx_lock);
243dad0d04fSFariya Fatima 		status = rsi_sdio_read_register(common->priv,
244dad0d04fSFariya Fatima 						RSI_FN1_INT_REGISTER,
245dad0d04fSFariya Fatima 						&isr_status);
246dad0d04fSFariya Fatima 		if (status) {
247dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
248dad0d04fSFariya Fatima 				"%s: Failed to Read Intr Status Register\n",
249dad0d04fSFariya Fatima 				__func__);
2506c409cadSKarun Eagalapati 			mutex_unlock(&common->rx_lock);
251dad0d04fSFariya Fatima 			return;
252dad0d04fSFariya Fatima 		}
253ebf084eaSKarun Eagalapati 		adapter->interrupt_status = isr_status;
254dad0d04fSFariya Fatima 
255dad0d04fSFariya Fatima 		if (isr_status == 0) {
256dad0d04fSFariya Fatima 			rsi_set_event(&common->tx_thread.event);
257dad0d04fSFariya Fatima 			dev->rx_info.sdio_intr_status_zero++;
2586c409cadSKarun Eagalapati 			mutex_unlock(&common->rx_lock);
259dad0d04fSFariya Fatima 			return;
260dad0d04fSFariya Fatima 		}
261dad0d04fSFariya Fatima 
262dad0d04fSFariya Fatima 		rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
263dad0d04fSFariya Fatima 			__func__, isr_status, (1 << MSDU_PKT_PENDING),
264dad0d04fSFariya Fatima 			(1 << FW_ASSERT_IND));
265dad0d04fSFariya Fatima 
266abd131a1SMarek Vasut 		if (isr_status & BIT(PKT_BUFF_AVAILABLE)) {
267abd131a1SMarek Vasut 			status = rsi_sdio_check_buffer_status(adapter, 0);
26867c52a4dSKarun Eagalapati 			if (status < 0)
26967c52a4dSKarun Eagalapati 				rsi_dbg(ERR_ZONE,
27067c52a4dSKarun Eagalapati 					"%s: Failed to check buffer status\n",
27167c52a4dSKarun Eagalapati 					__func__);
272dad0d04fSFariya Fatima 			rsi_sdio_ack_intr(common->priv,
273abd131a1SMarek Vasut 					  BIT(PKT_BUFF_AVAILABLE));
274f75d3419SJahnavi Meher 			rsi_set_event(&common->tx_thread.event);
275f75d3419SJahnavi Meher 
276abd131a1SMarek Vasut 			rsi_dbg(ISR_ZONE, "%s: ==> BUFFER_AVAILABLE <==\n",
277dad0d04fSFariya Fatima 				__func__);
278d64dd2a1SKarun Eagalapati 			dev->buff_status_updated = true;
279dad0d04fSFariya Fatima 
280abd131a1SMarek Vasut 			isr_status &= ~BIT(PKT_BUFF_AVAILABLE);
281abd131a1SMarek Vasut 		}
282abd131a1SMarek Vasut 
283abd131a1SMarek Vasut 		if (isr_status & BIT(FW_ASSERT_IND)) {
284abd131a1SMarek Vasut 			rsi_dbg(ERR_ZONE, "%s: ==> FIRMWARE Assert <==\n",
285dad0d04fSFariya Fatima 				__func__);
286dad0d04fSFariya Fatima 			status = rsi_sdio_read_register(common->priv,
287dad0d04fSFariya Fatima 							SDIO_FW_STATUS_REG,
288dad0d04fSFariya Fatima 							&fw_status);
289dad0d04fSFariya Fatima 			if (status) {
290dad0d04fSFariya Fatima 				rsi_dbg(ERR_ZONE,
291dad0d04fSFariya Fatima 					"%s: Failed to read f/w reg\n",
292dad0d04fSFariya Fatima 					__func__);
293dad0d04fSFariya Fatima 			} else {
294dad0d04fSFariya Fatima 				rsi_dbg(ERR_ZONE,
295dad0d04fSFariya Fatima 					"%s: Firmware Status is 0x%x\n",
296dad0d04fSFariya Fatima 					__func__, fw_status);
297dad0d04fSFariya Fatima 				rsi_sdio_ack_intr(common->priv,
298abd131a1SMarek Vasut 						  BIT(FW_ASSERT_IND));
299dad0d04fSFariya Fatima 			}
300dad0d04fSFariya Fatima 
301dad0d04fSFariya Fatima 			common->fsm_state = FSM_CARD_NOT_READY;
302dad0d04fSFariya Fatima 
303abd131a1SMarek Vasut 			isr_status &= ~BIT(FW_ASSERT_IND);
304abd131a1SMarek Vasut 		}
305abd131a1SMarek Vasut 
306abd131a1SMarek Vasut 		if (isr_status & BIT(MSDU_PKT_PENDING)) {
307dad0d04fSFariya Fatima 			rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
308dad0d04fSFariya Fatima 			dev->rx_info.total_sdio_msdu_pending_intr++;
309dad0d04fSFariya Fatima 
310dad0d04fSFariya Fatima 			status = rsi_process_pkt(common);
311dad0d04fSFariya Fatima 			if (status) {
312abd131a1SMarek Vasut 				rsi_dbg(ERR_ZONE, "%s: Failed to read pkt\n",
313dad0d04fSFariya Fatima 					__func__);
3146c409cadSKarun Eagalapati 				mutex_unlock(&common->rx_lock);
315dad0d04fSFariya Fatima 				return;
316dad0d04fSFariya Fatima 			}
317abd131a1SMarek Vasut 
318abd131a1SMarek Vasut 			isr_status &= ~BIT(MSDU_PKT_PENDING);
319abd131a1SMarek Vasut 		}
320abd131a1SMarek Vasut 
321abd131a1SMarek Vasut 		if (isr_status) {
322dad0d04fSFariya Fatima 			rsi_sdio_ack_intr(common->priv, isr_status);
323dad0d04fSFariya Fatima 			dev->rx_info.total_sdio_unknown_intr++;
324dad0d04fSFariya Fatima 			isr_status = 0;
325abd131a1SMarek Vasut 			rsi_dbg(ISR_ZONE, "Unknown Interrupt %x\n",
326dad0d04fSFariya Fatima 				isr_status);
327dad0d04fSFariya Fatima 		}
328abd131a1SMarek Vasut 
3296c409cadSKarun Eagalapati 		mutex_unlock(&common->rx_lock);
330dad0d04fSFariya Fatima 	} while (1);
331dad0d04fSFariya Fatima }
332dad0d04fSFariya Fatima 
33323e414ccSKarun Eagalapati /* This function is used to read buffer status register and
33423e414ccSKarun Eagalapati  * set relevant fields in rsi_91x_sdiodev struct.
335dad0d04fSFariya Fatima  */
rsi_sdio_check_buffer_status(struct rsi_hw * adapter,u8 q_num)33623e414ccSKarun Eagalapati int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num)
337dad0d04fSFariya Fatima {
338dad0d04fSFariya Fatima 	struct rsi_common *common = adapter->priv;
339*361beddbSWu Yunchuan 	struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
340dad0d04fSFariya Fatima 	u8 buf_status = 0;
341dad0d04fSFariya Fatima 	int status = 0;
342d64dd2a1SKarun Eagalapati 	static int counter = 4;
343dad0d04fSFariya Fatima 
344d64dd2a1SKarun Eagalapati 	if (!dev->buff_status_updated && counter) {
345d64dd2a1SKarun Eagalapati 		counter--;
346d64dd2a1SKarun Eagalapati 		goto out;
347d64dd2a1SKarun Eagalapati 	}
348d64dd2a1SKarun Eagalapati 
349d64dd2a1SKarun Eagalapati 	dev->buff_status_updated = false;
350dad0d04fSFariya Fatima 	status = rsi_sdio_read_register(common->priv,
351dad0d04fSFariya Fatima 					RSI_DEVICE_BUFFER_STATUS_REGISTER,
352dad0d04fSFariya Fatima 					&buf_status);
353dad0d04fSFariya Fatima 
354dad0d04fSFariya Fatima 	if (status) {
355dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
356dad0d04fSFariya Fatima 			"%s: Failed to read status register\n", __func__);
357dad0d04fSFariya Fatima 		return -1;
358dad0d04fSFariya Fatima 	}
359dad0d04fSFariya Fatima 
360dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_MGMT_BUFF_FULL))) {
361dad0d04fSFariya Fatima 		if (!dev->rx_info.mgmt_buffer_full)
362dad0d04fSFariya Fatima 			dev->rx_info.mgmt_buf_full_counter++;
363dad0d04fSFariya Fatima 		dev->rx_info.mgmt_buffer_full = true;
364dad0d04fSFariya Fatima 	} else {
365dad0d04fSFariya Fatima 		dev->rx_info.mgmt_buffer_full = false;
366dad0d04fSFariya Fatima 	}
367dad0d04fSFariya Fatima 
368dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_BUFF_FULL))) {
369dad0d04fSFariya Fatima 		if (!dev->rx_info.buffer_full)
370dad0d04fSFariya Fatima 			dev->rx_info.buf_full_counter++;
371dad0d04fSFariya Fatima 		dev->rx_info.buffer_full = true;
372dad0d04fSFariya Fatima 	} else {
373dad0d04fSFariya Fatima 		dev->rx_info.buffer_full = false;
374dad0d04fSFariya Fatima 	}
375dad0d04fSFariya Fatima 
376dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_BUFF_SEMI_FULL))) {
377dad0d04fSFariya Fatima 		if (!dev->rx_info.semi_buffer_full)
378dad0d04fSFariya Fatima 			dev->rx_info.buf_semi_full_counter++;
379dad0d04fSFariya Fatima 		dev->rx_info.semi_buffer_full = true;
380dad0d04fSFariya Fatima 	} else {
381dad0d04fSFariya Fatima 		dev->rx_info.semi_buffer_full = false;
382dad0d04fSFariya Fatima 	}
383dad0d04fSFariya Fatima 
384d64dd2a1SKarun Eagalapati 	if (dev->rx_info.mgmt_buffer_full || dev->rx_info.buf_full_counter)
385d64dd2a1SKarun Eagalapati 		counter = 1;
386d64dd2a1SKarun Eagalapati 	else
387d64dd2a1SKarun Eagalapati 		counter = 4;
388d64dd2a1SKarun Eagalapati 
389d64dd2a1SKarun Eagalapati out:
390dad0d04fSFariya Fatima 	if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
391dad0d04fSFariya Fatima 		return QUEUE_FULL;
392dad0d04fSFariya Fatima 
393d64dd2a1SKarun Eagalapati 	if ((q_num < MGMT_SOFT_Q) && (dev->rx_info.buffer_full))
394dad0d04fSFariya Fatima 		return QUEUE_FULL;
395dad0d04fSFariya Fatima 
396dad0d04fSFariya Fatima 	return QUEUE_NOT_FULL;
397dad0d04fSFariya Fatima }
398dad0d04fSFariya Fatima 
399dad0d04fSFariya Fatima /**
400dad0d04fSFariya Fatima  * rsi_sdio_determine_event_timeout() - This Function determines the event
401dad0d04fSFariya Fatima  *					timeout duration.
402dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
403dad0d04fSFariya Fatima  *
404dad0d04fSFariya Fatima  * Return: timeout duration is returned.
405dad0d04fSFariya Fatima  */
rsi_sdio_determine_event_timeout(struct rsi_hw * adapter)406dad0d04fSFariya Fatima int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter)
407dad0d04fSFariya Fatima {
408*361beddbSWu Yunchuan 	struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
409dad0d04fSFariya Fatima 
410dad0d04fSFariya Fatima 	/* Once buffer full is seen, event timeout to occur every 2 msecs */
411dad0d04fSFariya Fatima 	if (dev->rx_info.buffer_full)
412dad0d04fSFariya Fatima 		return 2;
413dad0d04fSFariya Fatima 
414dad0d04fSFariya Fatima 	return EVENT_WAIT_FOREVER;
415dad0d04fSFariya Fatima }
416