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