xref: /wlan-driver/qca-wifi-host-cmn/hif/src/sdio/hif_bmi_reg_access.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "athdefs.h"
19 #include "a_types.h"
20 #include "a_osapi.h"
21 #define ATH_MODULE_NAME hif
22 #include "a_debug.h"
23 #define ATH_DEBUG_BMI  ATH_DEBUG_MAKE_MODULE_MASK(0)
24 #include "hif.h"
25 #include "bmi.h"
26 #include "htc_api.h"
27 #include "if_sdio.h"
28 #include "regtable_sdio.h"
29 #include "hif_sdio_dev.h"
30 
31 #define BMI_COMMUNICATION_TIMEOUT       100000
32 
33 static bool pending_events_func_check;
34 static uint32_t command_credits;
35 static uint32_t *p_bmi_cmd_credits = &command_credits;
36 
37 /* BMI Access routines */
38 
39 /**
40  * hif_bmi_buffer_send - call to send bmi buffer
41  * @scn: hif context
42  * @device: hif SDIO device
43  * @buffer: buffer
44  * @length: length
45  *
46  * Return: QDF_STATUS_SUCCESS for success.
47  */
48 static QDF_STATUS
hif_bmi_buffer_send(struct hif_sdio_softc * scn,struct hif_sdio_dev * device,char * buffer,uint32_t length)49 hif_bmi_buffer_send(struct hif_sdio_softc *scn, struct hif_sdio_dev *device,
50 		    char *buffer, uint32_t length)
51 {
52 	QDF_STATUS status;
53 	uint32_t timeout;
54 	uint32_t address;
55 	uint32_t mbox_address[HTC_MAILBOX_NUM_MAX];
56 
57 	hif_configure_device(NULL, device, HIF_DEVICE_GET_FIFO_ADDR,
58 			     &mbox_address[0], sizeof(mbox_address));
59 
60 	*p_bmi_cmd_credits = 0;
61 	timeout = BMI_COMMUNICATION_TIMEOUT;
62 
63 	while (timeout-- && !(*p_bmi_cmd_credits)) {
64 		/* Read the counter register to get the command credits */
65 		address =
66 		      COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
67 		/* hit the credit counter with a 4-byte access, the first
68 		 * byte read will hit the counter and cause
69 		 * a decrement, while the remaining 3 bytes has no effect.
70 		 * The rationale behind this is to make all HIF accesses
71 		 * 4-byte aligned
72 		 */
73 		status =
74 			hif_read_write(device, address,
75 				       (uint8_t *) p_bmi_cmd_credits, 4,
76 				       HIF_RD_SYNC_BYTE_INC, NULL);
77 		if (status != QDF_STATUS_SUCCESS) {
78 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
79 			  ("%s:Unable to decrement the credit count register\n",
80 			  __func__));
81 			return QDF_STATUS_E_FAILURE;
82 		}
83 		/* the counter is only 8=bits, ignore anything in the
84 		 * upper 3 bytes
85 		 */
86 		(*p_bmi_cmd_credits) &= 0xFF;
87 	}
88 
89 	if (*p_bmi_cmd_credits) {
90 		address = mbox_address[ENDPOINT1];
91 		status = hif_read_write(device, address, buffer, length,
92 					HIF_WR_SYNC_BYTE_INC, NULL);
93 		if (status != QDF_STATUS_SUCCESS) {
94 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
95 			  ("%s:Unable to send the BMI data to the device\n",
96 			  __func__));
97 			return QDF_STATUS_E_FAILURE;
98 		}
99 	} else {
100 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
101 			("%s:BMI Communication timeout - hif_bmi_buffer_send\n",
102 			__func__));
103 		return QDF_STATUS_E_FAILURE;
104 	}
105 
106 	return status;
107 }
108 
109 #if defined(SDIO_3_0)
110 
111 static QDF_STATUS
hif_bmi_read_write(struct hif_sdio_dev * device,char * buffer,uint32_t length)112 hif_bmi_read_write(struct hif_sdio_dev *device,
113 		   char *buffer, uint32_t length)
114 {
115 	QDF_STATUS status;
116 
117 	status = hif_read_write(device, HOST_INT_STATUS_ADDRESS,
118 				buffer, length,
119 				HIF_RD_SYNC_BYTE_INC, NULL);
120 	if (status != QDF_STATUS_SUCCESS) {
121 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
122 				("%s:Unable to read int status reg\n",
123 				 __func__));
124 		return QDF_STATUS_E_FAILURE;
125 	}
126 	*buffer = (HOST_INT_STATUS_MBOX_DATA_GET(*buffer) & (1 << ENDPOINT1));
127 	return status;
128 }
129 #else
130 
131 static QDF_STATUS
hif_bmi_read_write(struct hif_sdio_dev * device,char * buffer,uint32_t length)132 hif_bmi_read_write(struct hif_sdio_dev *device,
133 		   char *buffer, uint32_t length)
134 {
135 	QDF_STATUS status;
136 
137 	status = hif_read_write(device, RX_LOOKAHEAD_VALID_ADDRESS,
138 				buffer, length,
139 				HIF_RD_SYNC_BYTE_INC, NULL);
140 	if (status != QDF_STATUS_SUCCESS) {
141 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
142 				("%s:Unable to read rx lookahead reg\n",
143 				 __func__));
144 		return QDF_STATUS_E_FAILURE;
145 	}
146 	*buffer &= (1 << ENDPOINT1);
147 	return status;
148 }
149 #endif
150 
151 /**
152  * hif_bmi_buffer_receive - call when bmi buffer is received
153  * @device: hif context
154  * @buffer: buffer
155  * @length: length
156  * @want_timeout: timeout is needed or not
157  *
158  * Return: QDF_STATUS_SUCCESS for success.
159  */
160 static QDF_STATUS
hif_bmi_buffer_receive(struct hif_sdio_dev * device,char * buffer,uint32_t length,bool want_timeout)161 hif_bmi_buffer_receive(struct hif_sdio_dev *device,
162 		       char *buffer, uint32_t length, bool want_timeout)
163 {
164 	QDF_STATUS status;
165 	uint32_t address;
166 	uint32_t mbox_address[HTC_MAILBOX_NUM_MAX];
167 	struct _HIF_PENDING_EVENTS_INFO hif_pending_events;
168 
169 	static HIF_PENDING_EVENTS_FUNC get_pending_events_func;
170 
171 	if (!pending_events_func_check) {
172 		/* see if the HIF layer implements an alternative
173 		 * function to get pending events
174 		 * do this only once!
175 		 */
176 		hif_configure_device(NULL, device,
177 				     HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
178 				     &get_pending_events_func,
179 				     sizeof(get_pending_events_func));
180 		pending_events_func_check = true;
181 	}
182 
183 	hif_configure_device(NULL, device, HIF_DEVICE_GET_FIFO_ADDR,
184 			     &mbox_address[0], sizeof(mbox_address));
185 
186 	/*
187 	 * During normal bootup, small reads may be required.
188 	 * Rather than issue an HIF Read and then wait as the Target
189 	 * adds successive bytes to the FIFO, we wait here until
190 	 * we know that response data is available.
191 	 *
192 	 * This allows us to cleanly timeout on an unexpected
193 	 * Target failure rather than risk problems at the HIF level.  In
194 	 * particular, this avoids SDIO timeouts and possibly garbage
195 	 * data on some host controllers.  And on an interconnect
196 	 * such as Compact Flash (as well as some SDIO masters) which
197 	 * does not provide any indication on data timeout, it avoids
198 	 * a potential hang or garbage response.
199 	 *
200 	 * Synchronization is more difficult for reads larger than the
201 	 * size of the MBOX FIFO (128B), because the Target is unable
202 	 * to push the 129th byte of data until AFTER the Host posts an
203 	 * HIF Read and removes some FIFO data.  So for large reads the
204 	 * Host proceeds to post an HIF Read BEFORE all the data is
205 	 * actually available to read.  Fortunately, large BMI reads do
206 	 * not occur in practice -- they're supported for debug/development.
207 	 *
208 	 * So Host/Target BMI synchronization is divided into these cases:
209 	 *  CASE 1: length < 4
210 	 *        Should not happen
211 	 *
212 	 *  CASE 2: 4 <= length <= 128
213 	 *        Wait for first 4 bytes to be in FIFO
214 	 *        If CONSERVATIVE_BMI_READ is enabled, also wait for
215 	 *        a BMI command credit, which indicates that the ENTIRE
216 	 *        response is available in the the FIFO
217 	 *
218 	 *  CASE 3: length > 128
219 	 *        Wait for the first 4 bytes to be in FIFO
220 	 *
221 	 * For most uses, a small timeout should be sufficient and we will
222 	 * usually see a response quickly; but there may be some unusual
223 	 * (debug) cases of BMI_EXECUTE where we want an larger timeout.
224 	 * For now, we use an unbounded busy loop while waiting for
225 	 * BMI_EXECUTE.
226 	 *
227 	 * If BMI_EXECUTE ever needs to support longer-latency execution,
228 	 * especially in production, this code needs to be enhanced to sleep
229 	 * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
230 	 * a function of Host processor speed.
231 	 */
232 	if (length >= 4) {      /* NB: Currently, always true */
233 		/*
234 		 * NB: word_available is declared static for esoteric reasons
235 		 * having to do with protection on some OSes.
236 		 */
237 		static uint32_t word_available;
238 		uint32_t timeout;
239 
240 		word_available = 0;
241 		timeout = BMI_COMMUNICATION_TIMEOUT;
242 		while ((!want_timeout || timeout--) && !word_available) {
243 
244 			if (get_pending_events_func) {
245 				status = get_pending_events_func(device,
246 							&hif_pending_events,
247 							NULL);
248 				if (status != QDF_STATUS_SUCCESS) {
249 					AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
250 					  ("%s:Failed to get pending events\n",
251 					  __func__));
252 					break;
253 				}
254 
255 				if (hif_pending_events.available_recv_bytes >=
256 							sizeof(uint32_t)) {
257 					word_available = 1;
258 				}
259 				continue;
260 			}
261 			status = hif_bmi_read_write(device,
262 					(uint8_t *) &word_available,
263 					sizeof(word_available));
264 			if (status != QDF_STATUS_SUCCESS)
265 				return QDF_STATUS_E_FAILURE;
266 		}
267 
268 		if (!word_available) {
269 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
270 				("%s:BMI Communication timeout FIFO empty\n",
271 				__func__));
272 			return QDF_STATUS_E_FAILURE;
273 		}
274 	}
275 
276 	address = mbox_address[ENDPOINT1];
277 	status = hif_read_write(device, address, buffer, length,
278 				HIF_RD_SYNC_BYTE_INC, NULL);
279 	if (status != QDF_STATUS_SUCCESS) {
280 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
281 			("%s:Unable to read the BMI data from the device\n",
282 			__func__));
283 		return QDF_STATUS_E_FAILURE;
284 	}
285 
286 	return QDF_STATUS_SUCCESS;
287 }
288 
289 /**
290  * hif_reg_based_get_target_info - to retrieve target info
291  * @hif_ctx: hif context
292  * @targ_info: bmi target info
293  *
294  * Return: QDF_STATUS_SUCCESS for success.
295  */
296 QDF_STATUS
hif_reg_based_get_target_info(struct hif_opaque_softc * hif_ctx,struct bmi_target_info * targ_info)297 hif_reg_based_get_target_info(struct hif_opaque_softc *hif_ctx,
298 			      struct bmi_target_info *targ_info)
299 {
300 	QDF_STATUS status;
301 	uint32_t cid;
302 	struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
303 	struct hif_sdio_dev *device = scn->hif_handle;
304 
305 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
306 			("BMI Get Target Info: Enter (device: 0x%pK)\n",
307 			device));
308 	cid = BMI_GET_TARGET_INFO;
309 	status = hif_bmi_buffer_send(scn, device, (char *)&cid, sizeof(cid));
310 	if (status != QDF_STATUS_SUCCESS) {
311 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
312 				("%s:Unable to write to the device\n",
313 				 __func__));
314 		return QDF_STATUS_E_FAILURE;
315 	}
316 
317 	status = hif_bmi_buffer_receive(device,
318 					(char *) &targ_info->target_ver,
319 					sizeof(targ_info->target_ver), true);
320 	if (status != QDF_STATUS_SUCCESS) {
321 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
322 			("%s:Unable to read Target Version from the device\n",
323 			 __func__));
324 		return QDF_STATUS_E_FAILURE;
325 	}
326 
327 	if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
328 		/* Determine how many bytes are in the Target's targ_info */
329 		status = hif_bmi_buffer_receive(device,
330 						(char *) &targ_info->
331 						target_info_byte_count,
332 						sizeof(targ_info->
333 							target_info_byte_count),
334 						true);
335 		if (status != QDF_STATUS_SUCCESS) {
336 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
337 					("%s:Unable to read target Info\n",
338 					 __func__));
339 			return QDF_STATUS_E_FAILURE;
340 		}
341 
342 		/*
343 		 * The Target's targ_info doesn't match the Host's targ_info.
344 		 * We need to do some backwards compatibility work to make this
345 		 * OK.
346 		 */
347 		QDF_ASSERT(targ_info->target_info_byte_count ==
348 			 sizeof(*targ_info));
349 		/* Read the remainder of the targ_info */
350 		status = hif_bmi_buffer_receive(device,
351 					    ((char *) targ_info) +
352 					    sizeof(targ_info->
353 						   target_info_byte_count),
354 					    sizeof(*targ_info) -
355 					    sizeof(targ_info->
356 						   target_info_byte_count),
357 					    true);
358 		if (status != QDF_STATUS_SUCCESS) {
359 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
360 				("%s:Unable to read Target Info (%d bytes)\n",
361 				__func__, targ_info->target_info_byte_count));
362 			return QDF_STATUS_E_FAILURE;
363 		}
364 	} else {
365 		/*
366 		 * Target must be an AR6001 whose firmware does not
367 		 * support BMI_GET_TARGET_INFO.  Construct the data
368 		 * that it would have sent.
369 		 */
370 		targ_info->target_info_byte_count = sizeof(*targ_info);
371 		targ_info->target_type = TARGET_TYPE_AR6001;
372 	}
373 
374 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
375 			("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
376 			 targ_info->target_ver,
377 			 targ_info->target_type));
378 
379 	return QDF_STATUS_SUCCESS;
380 }
381 
382 /**
383  * hif_exchange_bmi_msg - API to handle HIF-specific BMI message exchanges
384  * @hif_ctx: hif context
385  * @bmi_cmd_da: bmi cmd
386  * @bmi_rsp_da: bmi rsp
387  * @send_message: send message
388  * @length: length
389  * @response_message: response message
390  * @response_length: response length
391  * @timeout_ms: timeout in ms
392  *
393  * This API is synchronous
394  * and only allowed to be called from a context that can block (sleep)
395  *
396  * Return: QDF_STATUS_SUCCESS for success.
397  */
hif_exchange_bmi_msg(struct hif_opaque_softc * hif_ctx,qdf_dma_addr_t bmi_cmd_da,qdf_dma_addr_t bmi_rsp_da,uint8_t * send_message,uint32_t length,uint8_t * response_message,uint32_t * response_length,uint32_t timeout_ms)398 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *hif_ctx,
399 				qdf_dma_addr_t bmi_cmd_da,
400 				qdf_dma_addr_t bmi_rsp_da,
401 				uint8_t *send_message,
402 				uint32_t length,
403 				uint8_t *response_message,
404 				uint32_t *response_length,
405 				uint32_t timeout_ms) {
406 	struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx);
407 	struct hif_sdio_dev *device = scn->hif_handle;
408 	QDF_STATUS status = QDF_STATUS_SUCCESS;
409 
410 	if (!device) {
411 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
412 			("%s:Null device argument\n",
413 			__func__));
414 		return QDF_STATUS_E_INVAL;
415 	}
416 
417 	status = hif_bmi_buffer_send(scn, device, send_message, length);
418 	if (QDF_IS_STATUS_ERROR(status)) {
419 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
420 				("%s:Unable to Send Message to device\n",
421 				 __func__));
422 		return status;
423 	}
424 
425 	if (response_message) {
426 		status = hif_bmi_buffer_receive(device, response_message,
427 						*response_length,
428 						timeout_ms ? true : false);
429 		if (QDF_IS_STATUS_ERROR(status)) {
430 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
431 					("%s:Unable to read response\n",
432 					 __func__));
433 			return status;
434 		}
435 	}
436 
437 	return status;
438 }
439 
hif_register_bmi_callbacks(struct hif_opaque_softc * hif_ctx)440 void hif_register_bmi_callbacks(struct hif_opaque_softc *hif_ctx)
441 {
442 }
443 
444 #ifdef BRINGUP_DEBUG
445 #define SDIO_SCRATCH_1_ADDRESS 0x864
446 /*Functions used for debugging*/
447 /**
448  * hif_bmi_write_scratch_register - API to write scratch register
449  * @device: hif context
450  * @buffer: buffer
451  *
452  * Return: QDF_STATUS_SUCCESS for success.
453  */
hif_bmi_write_scratch_register(struct hif_sdio_dev * device,uint32_t buffer)454 QDF_STATUS hif_bmi_write_scratch_register(struct hif_sdio_dev *device,
455 				    uint32_t buffer) {
456 	QDF_STATUS status = QDF_STATUS_SUCCESS;
457 
458 	status = hif_read_write(device, SDIO_SCRATCH_1_ADDRESS,
459 				(uint8_t *) &buffer, 4,
460 				HIF_WR_SYNC_BYTE_INC, NULL);
461 	if (status != QDF_STATUS_SUCCESS) {
462 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
463 				("%s: Unable to write to 0x%x\n",
464 				 __func__, SDIO_SCRATCH_1_ADDRESS));
465 		return QDF_STATUS_E_FAILURE;
466 	}
467 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wrote 0x%x to 0x%x\n", __func__,
468 			 buffer, SDIO_SCRATCH_1_ADDRESS));
469 
470 	return status;
471 }
472 
473 /**
474  * hif_bmi_read_scratch_register - API to read from scratch register
475  * @device: hif context
476  *
477  * Return: QDF_STATUS_SUCCESS for success.
478  */
hif_bmi_read_scratch_register(struct hif_sdio_dev * device)479 QDF_STATUS hif_bmi_read_scratch_register(struct hif_sdio_dev *device)
480 {
481 	QDF_STATUS status = QDF_STATUS_SUCCESS;
482 	uint32_t buffer = 0;
483 
484 	status = hif_read_write(device, SDIO_SCRATCH_1_ADDRESS,
485 				(uint8_t *) &buffer, 4,
486 				HIF_RD_SYNC_BYTE_INC, NULL);
487 	if (status != QDF_STATUS_SUCCESS) {
488 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
489 				("%s: Unable to read from 0x%x\n",
490 				 __func__, SDIO_SCRATCH_1_ADDRESS));
491 		return QDF_STATUS_E_FAILURE;
492 	}
493 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: read 0x%x from 0x%x\n", __func__,
494 			 buffer, SDIO_SCRATCH_1_ADDRESS));
495 
496 	return status;
497 }
498 #endif
499