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