xref: /wlan-driver/qcacld-3.0/core/bmi/src/ol_fw.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <linux/firmware.h>
21 #include "ol_if_athvar.h"
22 #include "qdf_time.h"
23 #include "targaddrs.h"
24 #include "ol_cfg.h"
25 #include "cds_api.h"
26 #include "wma_api.h"
27 #include "wma.h"
28 #include "bin_sig.h"
29 #include "i_ar6320v2_regtable.h"
30 #include "epping_main.h"
31 #ifdef HIF_PCI
32 #include "ce_reg.h"
33 #endif
34 #if defined(HIF_SDIO)
35 #include "if_sdio.h"
36 #include "regtable_sdio.h"
37 #endif
38 #if defined(HIF_USB)
39 #include "if_usb.h"
40 #include "regtable_usb.h"
41 #endif
42 #include "pld_common.h"
43 #include "hif_main.h"
44 
45 #include "i_bmi.h"
46 #include "qwlan_version.h"
47 #include "wlan_policy_mgr_api.h"
48 #include "dbglog_host.h"
49 
50 #ifdef FEATURE_SECURE_FIRMWARE
51 static struct hash_fw fw_hash;
52 #endif
53 
54 static uint32_t refclk_speed_to_hz[] = {
55 	48000000,               /* SOC_REFCLK_48_MHZ */
56 	19200000,               /* SOC_REFCLK_19_2_MHZ */
57 	24000000,               /* SOC_REFCLK_24_MHZ */
58 	26000000,               /* SOC_REFCLK_26_MHZ */
59 	37400000,               /* SOC_REFCLK_37_4_MHZ */
60 	38400000,               /* SOC_REFCLK_38_4_MHZ */
61 	40000000,               /* SOC_REFCLK_40_MHZ */
62 	52000000,               /* SOC_REFCLK_52_MHZ */
63 };
64 
65 static int ol_target_coredump(void *inst, void *memory_block,
66 					uint32_t block_len);
67 
68 #ifdef FEATURE_SECURE_FIRMWARE
ol_check_fw_hash(struct device * dev,const u8 * data,u32 fw_size,enum ATH_BIN_FILE file)69 static int ol_check_fw_hash(struct device *dev, const u8 *data,
70 			    u32 fw_size, enum ATH_BIN_FILE file)
71 {
72 	u8 *hash = NULL;
73 	u8 *fw_mem = NULL;
74 	u8 digest[SHA256_DIGEST_SIZE];
75 	u8 temp[SHA256_DIGEST_SIZE] = { };
76 	int ret = 0;
77 
78 	switch (file) {
79 	case ATH_BOARD_DATA_FILE:
80 		hash = fw_hash.bdwlan;
81 		break;
82 	case ATH_OTP_FILE:
83 		hash = fw_hash.otp;
84 		break;
85 	case ATH_FIRMWARE_FILE:
86 #ifdef QCA_WIFI_FTM
87 		if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) {
88 			hash = fw_hash.utf;
89 			break;
90 		}
91 #endif
92 		hash = fw_hash.qwlan;
93 	default:
94 		break;
95 	}
96 
97 	if (!hash) {
98 		BMI_INFO("No entry for file:%d Download FW in non-secure mode",
99 									file);
100 		goto end;
101 	}
102 
103 	if (qdf_mem_cmp(hash, temp, SHA256_DIGEST_SIZE)) {
104 		BMI_INFO("Download FW in non-secure mode:%d", file);
105 		goto end;
106 	}
107 
108 	fw_mem = pld_get_fw_ptr(dev);
109 	if (!fw_mem || (fw_size > MAX_FIRMWARE_SIZE)) {
110 		BMI_ERR("No Memory to copy FW data");
111 		ret = -1;
112 		goto end;
113 	}
114 	qdf_mem_copy(fw_mem, data, fw_size);
115 
116 	ret = pld_get_sha_hash(dev, fw_mem, fw_size, "sha256", digest);
117 
118 	if (ret) {
119 		BMI_ERR("Sha256 Hash computation failed err:%d", ret);
120 		goto end;
121 	}
122 
123 	if (qdf_mem_cmp(hash, digest, SHA256_DIGEST_SIZE)) {
124 		BMI_ERR("Hash Mismatch");
125 		qdf_trace_hex_dump(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
126 				   digest, SHA256_DIGEST_SIZE);
127 		qdf_trace_hex_dump(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
128 				   hash, SHA256_DIGEST_SIZE);
129 		ret = QDF_STATUS_E_FAILURE;
130 	}
131 end:
132 	return ret;
133 }
134 #endif
135 
136 /**
137  * ol_board_id_to_filename() - Auto BDF board_id to filename conversion
138  * @old_name: name of the default board data file
139  * @board_id: board ID
140  *
141  * The API return board filename based on the board_id and chip_id.
142  * eg: input = "bdwlan30.bin", board_id = 0x01, board_file = "bdwlan30.b01"
143  * Return: The buffer with the formatted board filename.
144  */
ol_board_id_to_filename(const char * old_name,uint16_t board_id)145 static char *ol_board_id_to_filename(const char *old_name,
146 				     uint16_t board_id)
147 {
148 	int name_len;
149 	char *new_name;
150 
151 	name_len = strlen(old_name);
152 	new_name = qdf_mem_malloc(name_len + 1);
153 
154 	if (!new_name)
155 		goto out;
156 
157 	if (board_id > 0xFF)
158 		board_id = 0x0;
159 
160 	qdf_mem_copy(new_name, old_name, name_len);
161 	snprintf(&new_name[name_len - 2], 3, "%.2x", board_id);
162 out:
163 	return new_name;
164 }
165 
166 #ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT
167 #define SIGNED_SPLIT_BINARY_VALUE true
168 #else
169 #define SIGNED_SPLIT_BINARY_VALUE false
170 #endif
171 
172 static int
__ol_transfer_bin_file(struct ol_context * ol_ctx,enum ATH_BIN_FILE file,uint32_t address,bool compressed)173 __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
174 		       uint32_t address, bool compressed)
175 {
176 	struct hif_opaque_softc *scn = ol_ctx->scn;
177 	int status = 0;
178 	const char *filename;
179 	const struct firmware *fw_entry;
180 	uint32_t fw_entry_size;
181 	uint8_t *temp_eeprom;
182 	uint32_t board_data_size;
183 	bool bin_sign = false;
184 	int bin_off, bin_len;
185 	SIGN_HEADER_T *sign_header;
186 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
187 	uint32_t target_type = tgt_info->target_type;
188 	struct bmi_info *bmi_ctx = GET_BMI_CONTEXT(ol_ctx);
189 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
190 	int i;
191 
192 	/*
193 	 * If there is no board data file bases on board id, the default
194 	 * board data file should be used.
195 	 * For factory mode, the sequence for file selection should be
196 	 * utfbd.board_id -> utfbd.bin -> bd.board_id -> bd.bin. So we
197 	 * need to cache 4 file names.
198 	 */
199 	uint32_t bd_files = 1;
200 	char *bd_id_filename[2] = {NULL, NULL};
201 	const char *bd_filename[2] = {NULL, NULL};
202 
203 	switch (file) {
204 	default:
205 		BMI_ERR("%s: Unknown file type", __func__);
206 		return -EINVAL;
207 	case ATH_OTP_FILE:
208 		filename = bmi_ctx->fw_files.otp_data;
209 		if (SIGNED_SPLIT_BINARY_VALUE)
210 			bin_sign = true;
211 
212 		break;
213 	case ATH_FIRMWARE_FILE:
214 		if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
215 			filename = bmi_ctx->fw_files.epping_file;
216 			BMI_INFO("%s: Loading epping firmware file %s",
217 						__func__, filename);
218 			break;
219 		}
220 #ifdef QCA_WIFI_FTM
221 		if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) {
222 			filename = bmi_ctx->fw_files.utf_file;
223 			if (SIGNED_SPLIT_BINARY_VALUE)
224 				bin_sign = true;
225 			BMI_INFO("%s: Loading firmware file %s",
226 						__func__, filename);
227 			break;
228 		}
229 #endif
230 		if (cds_get_conparam() == QDF_GLOBAL_IBSS_MODE &&
231 		    (bmi_ctx->fw_files.ibss_image_file[0] != '\0')) {
232 			filename = bmi_ctx->fw_files.ibss_image_file;
233 		} else {
234 			filename = bmi_ctx->fw_files.image_file;
235 		}
236 
237 		if (SIGNED_SPLIT_BINARY_VALUE)
238 			bin_sign = true;
239 		break;
240 	case ATH_PATCH_FILE:
241 		BMI_INFO("%s: no Patch file defined", __func__);
242 		return 0;
243 	case ATH_BOARD_DATA_FILE:
244 		filename = bmi_ctx->fw_files.board_data;
245 #ifdef QCA_WIFI_FTM
246 		if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) {
247 			filename = bmi_ctx->fw_files.utf_board_data;
248 			if (SIGNED_SPLIT_BINARY_VALUE)
249 				bin_sign = true;
250 
251 			BMI_INFO("%s: Loading board data file %s",
252 						__func__, filename);
253 
254 			/*
255 			 * In FTM mode, if utf files do not exit.
256 			 * bdwlan should be used.
257 			 */
258 			bd_files = 2;
259 		}
260 #endif /* QCA_WIFI_FTM */
261 		if (SIGNED_SPLIT_BINARY_VALUE)
262 			bin_sign = false;
263 
264 		bd_filename[0] = filename;
265 
266 		/*
267 		 * For factory mode, we should cache 2 group of file names.
268 		 * For mission mode, bd_files==1, only one group of file names.
269 		 */
270 		bd_filename[bd_files - 1] =
271 					bmi_ctx->fw_files.board_data;
272 		for (i = 0; i < bd_files; i++) {
273 			bd_id_filename[i] =
274 				ol_board_id_to_filename(bd_filename[i],
275 							bmi_ctx->board_id);
276 			if (bd_id_filename[i]) {
277 				BMI_INFO("%s: board data file is %s",
278 					 __func__, bd_id_filename[i]);
279 			} else {
280 				BMI_ERR("%s: Fail to allocate board filename",
281 					__func__);
282 			}
283 		}
284 		break;
285 	case ATH_SETUP_FILE:
286 		if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE &&
287 		    !QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
288 			filename = bmi_ctx->fw_files.setup_file;
289 			if (filename[0] == 0) {
290 				BMI_INFO("%s: no Setup file defined", __func__);
291 				return -EPERM;
292 			}
293 
294 			if (SIGNED_SPLIT_BINARY_VALUE)
295 				bin_sign = true;
296 
297 			BMI_INFO("%s: Loading setup file %s",
298 			       __func__, filename);
299 		} else {
300 			BMI_INFO("%s: no Setup file needed", __func__);
301 			return -EPERM;
302 		}
303 		break;
304 	}
305 
306 	/* For FTM mode. bd.bin is used if there is no utf.bin */
307 	if (file == ATH_BOARD_DATA_FILE) {
308 		for (i = 0; i < bd_files; i++) {
309 			if (bd_id_filename[i]) {
310 				BMI_DBG("%s: Trying to load %s",
311 					 __func__, bd_id_filename[i]);
312 				status = request_firmware(&fw_entry,
313 							  bd_id_filename[i],
314 							  qdf_dev->dev);
315 				if (!status)
316 					break;
317 				BMI_ERR("%s: Failed to get %s:%d",
318 					__func__, bd_id_filename[i],
319 					status);
320 			}
321 
322 			/* bd.board_id not exits, using bd.bin */
323 			BMI_DBG("%s: Trying to load default %s",
324 				 __func__, bd_filename[i]);
325 			status = request_firmware(&fw_entry, bd_filename[i],
326 						  qdf_dev->dev);
327 			if (!status)
328 				break;
329 			BMI_ERR("%s: Failed to get default %s:%d",
330 				__func__, bd_filename[i], status);
331 		}
332 	} else {
333 		status = request_firmware(&fw_entry, filename, qdf_dev->dev);
334 	}
335 
336 	if (status) {
337 		BMI_ERR("%s: Failed to get %s", __func__, filename);
338 		status = -ENOENT;
339 		goto release_fw;
340 	}
341 
342 	if (!fw_entry || !fw_entry->data) {
343 		BMI_ERR("Invalid fw_entries");
344 		status = -ENOENT;
345 		goto release_fw;
346 	}
347 
348 	fw_entry_size = fw_entry->size;
349 	temp_eeprom = NULL;
350 
351 #ifdef FEATURE_SECURE_FIRMWARE
352 	if (ol_check_fw_hash(qdf_dev->dev, fw_entry->data,
353 			     fw_entry_size, file)) {
354 		BMI_ERR("Hash Check failed for file:%s", filename);
355 		status = -EINVAL;
356 		goto end;
357 	}
358 #endif
359 
360 	if (file == ATH_BOARD_DATA_FILE) {
361 		uint32_t board_ext_address = 0;
362 		int32_t board_ext_data_size;
363 
364 		temp_eeprom = qdf_mem_malloc(fw_entry_size);
365 		if (!temp_eeprom) {
366 			status = -ENOMEM;
367 			goto release_fw;
368 		}
369 
370 		qdf_mem_copy(temp_eeprom, (uint8_t *) fw_entry->data,
371 			  fw_entry_size);
372 
373 		switch (target_type) {
374 		case TARGET_TYPE_AR6004:
375 			board_data_size = AR6004_BOARD_DATA_SZ;
376 			board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
377 			break;
378 		case TARGET_TYPE_AR9888:
379 			board_data_size = AR9888_BOARD_DATA_SZ;
380 			board_ext_data_size = AR9888_BOARD_EXT_DATA_SZ;
381 			break;
382 		default:
383 			board_data_size = 0;
384 			board_ext_data_size = 0;
385 			break;
386 		}
387 
388 		/* Determine where in Target RAM to write Board Data */
389 		bmi_read_memory(HOST_INTEREST_ITEM_ADDRESS(target_type,
390 							   hi_board_ext_data),
391 				(uint8_t *) &board_ext_address, 4, ol_ctx);
392 		BMI_INFO("Board extended Data download address: 0x%x",
393 		       board_ext_address);
394 
395 		/* Check whether the target has allocated memory for extended
396 		 * board data and file contains extended board data
397 		 */
398 
399 		if ((board_ext_address)
400 		    && (fw_entry_size ==
401 			(board_data_size + board_ext_data_size))) {
402 			uint32_t param;
403 
404 			status = bmi_write_memory(board_ext_address,
405 					(uint8_t *)(temp_eeprom +
406 					board_data_size),
407 					board_ext_data_size, ol_ctx);
408 
409 			if (status)
410 				goto end;
411 
412 			/* Record extended board Data initialized */
413 			param = (board_ext_data_size << 16) | 1;
414 			bmi_write_memory(
415 				HOST_INTEREST_ITEM_ADDRESS(target_type,
416 					hi_board_ext_data_config),
417 					(uint8_t *)&param, 4, ol_ctx);
418 
419 			fw_entry_size = board_data_size;
420 		}
421 	}
422 
423 	if (bin_sign && SIGNED_SPLIT_BINARY_VALUE) {
424 		uint32_t chip_id;
425 
426 		if (fw_entry_size < sizeof(SIGN_HEADER_T)) {
427 			BMI_ERR("Invalid binary size %d", fw_entry_size);
428 			status = -EINVAL;
429 			goto end;
430 		}
431 
432 		sign_header = (SIGN_HEADER_T *) fw_entry->data;
433 		chip_id = cpu_to_le32(sign_header->product_id);
434 		if (sign_header->magic_num == SIGN_HEADER_MAGIC
435 		    && (chip_id == AR6320_REV1_1_VERSION
436 			|| chip_id == AR6320_REV1_3_VERSION
437 			|| chip_id == AR6320_REV2_1_VERSION)) {
438 
439 			bin_off = sizeof(SIGN_HEADER_T);
440 			status = bmi_sign_stream_start(address,
441 						(uint8_t *)fw_entry->data,
442 						bin_off, ol_ctx);
443 			if (status) {
444 				BMI_ERR("unable to start sign stream");
445 				status = -EINVAL;
446 				goto end;
447 			}
448 
449 			bin_len = sign_header->rampatch_len - bin_off;
450 			if (bin_len <= 0 || bin_len > fw_entry_size - bin_off) {
451 				BMI_ERR("Invalid sign header");
452 				status = -EINVAL;
453 				goto end;
454 			}
455 		} else {
456 			bin_sign = false;
457 			bin_off = 0;
458 			bin_len = fw_entry_size;
459 		}
460 	} else {
461 		bin_len = fw_entry_size;
462 		bin_off = 0;
463 	}
464 
465 	if (compressed) {
466 		status = bmi_fast_download(address,
467 					   (uint8_t *) fw_entry->data + bin_off,
468 					   bin_len, ol_ctx);
469 	} else {
470 		if (file == ATH_BOARD_DATA_FILE && fw_entry->data) {
471 			status = bmi_write_memory(address,
472 						  (uint8_t *) temp_eeprom,
473 						  fw_entry_size, ol_ctx);
474 		} else {
475 			status = bmi_write_memory(address,
476 						  (uint8_t *) fw_entry->data
477 						  + bin_off, bin_len, ol_ctx);
478 		}
479 	}
480 
481 	if (bin_sign && SIGNED_SPLIT_BINARY_VALUE) {
482 		bin_off += bin_len;
483 		bin_len = sign_header->total_len - sign_header->rampatch_len;
484 
485 		if (bin_len > 0 && bin_len <= fw_entry_size - bin_off) {
486 			status = bmi_sign_stream_start(0,
487 					(uint8_t *)fw_entry->data +
488 					bin_off, bin_len, ol_ctx);
489 			if (status)
490 				BMI_ERR("sign stream error");
491 		}
492 	}
493 
494 end:
495 	if (temp_eeprom)
496 		qdf_mem_free(temp_eeprom);
497 
498 release_fw:
499 	if (fw_entry)
500 		release_firmware(fw_entry);
501 
502 	for (i = 0; i < bd_files; i++) {
503 		if (bd_id_filename[i]) {
504 			qdf_mem_free(bd_id_filename[i]);
505 			bd_id_filename[i] = NULL;
506 		}
507 	}
508 
509 	if (status)
510 		BMI_ERR("%s, BMI operation failed: %d", __func__, __LINE__);
511 	else
512 		BMI_INFO("transferring file: %s size %d bytes done!",
513 			 (filename) ? filename : " ", fw_entry_size);
514 	return status;
515 }
516 
517 static int
ol_transfer_bin_file(struct ol_context * ol_ctx,enum ATH_BIN_FILE file,uint32_t address,bool compressed)518 ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
519 		     uint32_t address, bool compressed)
520 {
521 #define MAX_WAKELOCK_FOR_FW_DOWNLOAD 1000	//1s
522 	int ret;
523 
524 	qdf_wake_lock_timeout_acquire(&ol_ctx->fw_dl_wakelock,
525 				      MAX_WAKELOCK_FOR_FW_DOWNLOAD);
526 
527 	ret = __ol_transfer_bin_file(ol_ctx, file, address, compressed);
528 
529 	qdf_wake_lock_release(&ol_ctx->fw_dl_wakelock, 0);
530 
531 	return ret;
532 }
533 
534 /**
535  * struct ramdump_info: Structure to hold ramdump information
536  * @base: Base address for Ramdump collection
537  * @size: Size of the dump
538  *
539  * Ramdump information.
540  */
541 struct ramdump_info {
542 	void *base;
543 	unsigned long size;
544 };
545 
546 /*
547  * if have platform driver support, reinit will be called by CNSS.
548  * recovery flag will be cleaned and CRASHED indication will be sent
549  * to user space by reinit function. If not support, clean recovery
550  * flag and send CRASHED indication in CLD driver.
551  */
ol_check_clean_recovery_flag(struct ol_context * ol_ctx)552 static inline void ol_check_clean_recovery_flag(struct ol_context *ol_ctx)
553 {
554 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
555 
556 	if (!pld_have_platform_driver_support(qdf_dev->dev)) {
557 		if (ol_ctx->fw_crashed_cb)
558 			ol_ctx->fw_crashed_cb();
559 	}
560 }
561 
562 #if !defined(QCA_WIFI_3_0)
ol_get_ramdump_mem(struct device * dev,struct ramdump_info * info)563 static inline void ol_get_ramdump_mem(struct device *dev,
564 				      struct ramdump_info *info)
565 {
566 	info->base = pld_get_virt_ramdump_mem(dev, &info->size);
567 }
568 
ol_release_ramdump_mem(struct device * dev,struct ramdump_info * info)569 static inline void ol_release_ramdump_mem(struct device *dev,
570 					  struct ramdump_info *info)
571 {
572 	pld_release_virt_ramdump_mem(dev, info->base);
573 }
574 #else
ol_get_ramdump_mem(struct device * dev,struct ramdump_info * info)575 static inline void ol_get_ramdump_mem(struct device *dev,
576 				      struct ramdump_info *info) { }
ol_release_ramdump_mem(struct device * dev,struct ramdump_info * info)577 static inline void ol_release_ramdump_mem(struct device *dev,
578 					  struct ramdump_info *info) { }
579 #endif
580 
ol_copy_ramdump(struct hif_opaque_softc * scn)581 int ol_copy_ramdump(struct hif_opaque_softc *scn)
582 {
583 	int ret = -1;
584 	struct ramdump_info *info;
585 	qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
586 
587 	if (!qdf_dev)
588 		return -EINVAL;
589 
590 	if (pld_is_fw_dump_skipped(qdf_dev->dev)) {
591 		BMI_INFO("%s ssr enabled, skip ramdump", __func__);
592 		return 0;
593 	}
594 	info = qdf_mem_malloc(sizeof(struct ramdump_info));
595 	if (!info)
596 		return -ENOMEM;
597 
598 	ol_get_ramdump_mem(qdf_dev->dev, info);
599 
600 	if (!info->base || !info->size) {
601 		BMI_ERR("%s:ramdump collection fail", __func__);
602 		qdf_mem_free(info);
603 		return -EACCES;
604 	}
605 
606 	ret = ol_target_coredump(scn, info->base, info->size);
607 
608 	ol_release_ramdump_mem(qdf_dev->dev, info);
609 	qdf_mem_free(info);
610 	return ret;
611 }
612 
__ramdump_work_handler(void * data)613 static void __ramdump_work_handler(void *data)
614 {
615 	int ret;
616 	uint32_t host_interest_address;
617 	uint32_t dram_dump_values[4];
618 	uint32_t target_type;
619 	struct hif_target_info *tgt_info;
620 	struct ol_context *ol_ctx = data;
621 	struct hif_opaque_softc *ramdump_scn = ol_ctx->scn;
622 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
623 	struct ol_config_info *ini_cfg = ol_get_ini_handle(ol_ctx);
624 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
625 
626 	if (!ramdump_scn) {
627 		BMI_ERR("%s:Ramdump_scn is null:", __func__);
628 		goto out_fail;
629 	}
630 	tgt_info = hif_get_target_info_handle(ramdump_scn);
631 	target_type = tgt_info->target_type;
632 #ifdef WLAN_DEBUG
633 	ret = hif_check_soc_status(ramdump_scn);
634 	if (ret)
635 		goto out_fail;
636 
637 	ret = hif_dump_registers(ramdump_scn);
638 	if (ret)
639 		goto out_fail;
640 
641 #endif
642 
643 	if (hif_diag_read_mem(ramdump_scn,
644 			hif_hia_item_address(target_type,
645 			offsetof(struct host_interest_s, hi_failure_state)),
646 			(uint8_t *)&host_interest_address,
647 			sizeof(uint32_t)) != QDF_STATUS_SUCCESS) {
648 		BMI_ERR("HifDiagReadiMem FW Dump Area Pointer failed!");
649 		ol_copy_ramdump(ramdump_scn);
650 		pld_device_crashed(qdf_dev->dev);
651 		ol_check_clean_recovery_flag(ol_ctx);
652 
653 		return;
654 	}
655 
656 	BMI_ERR("Host interest item address: 0x%08x", host_interest_address);
657 
658 	if (hif_diag_read_mem(ramdump_scn, host_interest_address,
659 			      (uint8_t *) &dram_dump_values[0],
660 			      4 * sizeof(uint32_t)) != QDF_STATUS_SUCCESS) {
661 		BMI_ERR("HifDiagReadiMem FW Dump Area failed!");
662 		goto out_fail;
663 	}
664 	BMI_ERR("FW Assertion at PC: 0x%08x BadVA: 0x%08x TargetID: 0x%08x",
665 	       dram_dump_values[2], dram_dump_values[3], dram_dump_values[0]);
666 
667 	if (ol_copy_ramdump(ramdump_scn))
668 		goto out_fail;
669 
670 	BMI_ERR("%s: RAM dump collecting completed!", __func__);
671 	qdf_event_set(&wma->recovery_event);
672 
673 	/*
674 	 * if unloading is in progress, then skip SSR,
675 	 * otherwise notify SSR framework the target has crashed.
676 	 */
677 	if (cds_is_load_or_unload_in_progress())
678 		cds_set_recovery_in_progress(false);
679 	else {
680 		pld_device_crashed(qdf_dev->dev);
681 		ol_check_clean_recovery_flag(ol_ctx);
682 	}
683 	return;
684 
685 out_fail:
686 	qdf_event_set(&wma->recovery_event);
687 	/* Silent SSR on dump failure */
688 	if (ini_cfg->enable_self_recovery)
689 		pld_device_self_recovery(qdf_dev->dev,
690 					 PLD_REASON_DEFAULT);
691 	else
692 		pld_device_crashed(qdf_dev->dev);
693 
694 	ol_check_clean_recovery_flag(ol_ctx);
695 }
696 
ramdump_work_handler(void * data)697 void ramdump_work_handler(void *data)
698 {
699 	struct qdf_op_sync *op_sync;
700 
701 	if (qdf_op_protect(&op_sync))
702 		return;
703 
704 	__ramdump_work_handler(data);
705 
706 	qdf_op_unprotect(op_sync);
707 }
708 
fw_indication_work_handler(void * data)709 void fw_indication_work_handler(void *data)
710 {
711 	struct ol_context *ol_ctx = data;
712 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
713 
714 	pld_device_self_recovery(qdf_dev->dev,
715 				 PLD_REASON_DEFAULT);
716 
717 	ol_check_clean_recovery_flag(ol_ctx);
718 }
719 
ol_target_failure(void * instance,QDF_STATUS status)720 void ol_target_failure(void *instance, QDF_STATUS status)
721 {
722 	struct ol_context *ol_ctx = instance;
723 	struct hif_opaque_softc *scn = ol_ctx->scn;
724 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
725 	struct ol_config_info *ini_cfg = ol_get_ini_handle(ol_ctx);
726 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
727 	int ret;
728 	bool skip_recovering_check = false;
729 	enum hif_target_status target_status = hif_get_target_status(scn);
730 
731 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_SNOC) {
732 		BMI_ERR("SNOC doesn't support this code path!");
733 		return;
734 	}
735 
736 	/* If Host driver trigger target failure, skip recovering check */
737 	if (cds_is_target_asserting())
738 		skip_recovering_check = true;
739 
740 	if (TARGET_STATUS_RESET == target_status) {
741 		BMI_ERR("Target is already asserted, ignore!");
742 		goto out;
743 	}
744 
745 	hif_set_target_status(scn, TARGET_STATUS_RESET);
746 
747 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB) {
748 		if (status == QDF_STATUS_E_USB_ERROR)
749 			hif_ramdump_handler(scn);
750 		goto out;
751 	}
752 
753 	if (!skip_recovering_check && cds_is_driver_recovering()) {
754 		BMI_ERR("%s: Recovery in progress, ignore!\n", __func__);
755 		return;
756 	}
757 
758 	if (cds_is_driver_in_bad_state()) {
759 		BMI_ERR("%s: Driver in bad state, ignore!\n", __func__);
760 		goto out;
761 	}
762 
763 	if (cds_is_load_or_unload_in_progress()) {
764 		BMI_ERR("%s: Loading/Unloading is in progress, ignore!",
765 		       __func__);
766 		goto out;
767 	}
768 	cds_set_target_ready(false);
769 	cds_set_recovery_in_progress(true);
770 
771 	ret = hif_check_fw_reg(scn);
772 	if (0 == ret) {
773 		if (ini_cfg->enable_self_recovery) {
774 			qdf_sched_work(0, &ol_ctx->fw_indication_work);
775 			goto out;
776 		}
777 	} else if (-1 == ret) {
778 		goto out;
779 	}
780 
781 	BMI_ERR("XXX TARGET ASSERTED XXX");
782 
783 	cds_svc_fw_shutdown_ind(qdf_dev->dev);
784 	/* Collect the RAM dump through a workqueue */
785 	if (ini_cfg->enable_ramdump_collection) {
786 		qdf_sched_work(0, &ol_ctx->ramdump_work);
787 	} else {
788 		pr_debug("%s: athdiag read for target reg\n", __func__);
789 		qdf_event_set(&wma->recovery_event);
790 	}
791 
792 	return;
793 out:
794 	qdf_event_set(&wma->recovery_event);
795 	return;
796 }
797 
798 #ifdef CONFIG_DISABLE_CDC_MAX_PERF_WAR
ol_disable_cdc_max_perf(struct ol_context * ol_ctx)799 static QDF_STATUS ol_disable_cdc_max_perf(struct ol_context *ol_ctx)
800 {
801 	uint32_t param;
802 	struct hif_opaque_softc *scn = ol_ctx->scn;
803 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
804 	uint32_t target_type = tgt_info->target_type;
805 
806 	/* set the firmware to disable CDC max perf WAR */
807 		if (bmi_read_memory(hif_hia_item_address(target_type,
808 			offsetof(struct host_interest_s, hi_option_flag2)),
809 			(uint8_t *) &param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
810 			BMI_ERR("BMI READ for setting cdc max perf failed");
811 			return QDF_STATUS_E_FAILURE;
812 		}
813 
814 		param |= HI_OPTION_DISABLE_CDC_MAX_PERF_WAR;
815 		if (bmi_write_memory(
816 			hif_hia_item_address(target_type,
817 			offsetof(struct host_interest_s, hi_option_flag2)),
818 			(uint8_t *)&param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
819 			BMI_ERR("setting cdc max perf failed");
820 			return QDF_STATUS_E_FAILURE;
821 		}
822 
823 	return QDF_STATUS_SUCCESS;
824 }
825 
826 #else
ol_disable_cdc_max_perf(struct ol_context * ol_ctx)827 static QDF_STATUS ol_disable_cdc_max_perf(struct ol_context *ol_ctx)
828 {
829 	return QDF_STATUS_SUCCESS;
830 }
831 
832 #endif
833 
834 #ifdef WLAN_FEATURE_LPSS
ol_set_lpass_support(struct ol_context * ol_ctx)835 static QDF_STATUS ol_set_lpass_support(struct ol_context *ol_ctx)
836 {
837 	uint32_t param;
838 	struct hif_opaque_softc *scn = ol_ctx->scn;
839 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
840 	struct ol_config_info *ini_cfg = ol_get_ini_handle(ol_ctx);
841 	uint32_t target_type = tgt_info->target_type;
842 
843 	if (ini_cfg->enable_lpass_support) {
844 		if (bmi_read_memory(hif_hia_item_address(target_type,
845 			offsetof(struct host_interest_s, hi_option_flag2)),
846 			(uint8_t *) &param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
847 			BMI_ERR("BMI READ:Setting LPASS Support failed");
848 			return QDF_STATUS_E_FAILURE;
849 		}
850 
851 		param |= HI_OPTION_DBUART_SUPPORT;
852 		if (bmi_write_memory(
853 			hif_hia_item_address(target_type,
854 			offsetof(struct host_interest_s, hi_option_flag2)),
855 			(uint8_t *)&param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
856 			BMI_ERR("BMI_READ for setting LPASS Support fail");
857 			return QDF_STATUS_E_FAILURE;
858 		}
859 	}
860 
861 	return QDF_STATUS_SUCCESS;
862 }
863 
864 #else
ol_set_lpass_support(struct ol_context * ol_ctx)865 static QDF_STATUS ol_set_lpass_support(struct ol_context *ol_ctx)
866 {
867 	return QDF_STATUS_SUCCESS;
868 }
869 
870 #endif
871 
872 
ol_configure_target(struct ol_context * ol_ctx)873 QDF_STATUS ol_configure_target(struct ol_context *ol_ctx)
874 {
875 	uint32_t param;
876 	struct pld_platform_cap cap = {0};
877 	int ret;
878 	struct hif_opaque_softc *scn = ol_ctx->scn;
879 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
880 	uint32_t target_type = tgt_info->target_type;
881 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
882 
883 	/* Tell target which HTC version it is used */
884 	param = HTC_PROTOCOL_VERSION;
885 	if (bmi_write_memory(
886 		hif_hia_item_address(target_type,
887 		offsetof(struct host_interest_s, hi_app_host_interest)),
888 		(uint8_t *) &param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
889 		BMI_ERR("bmi_write_memory for htc version failed");
890 		return QDF_STATUS_E_FAILURE;
891 	}
892 
893 	/* set the firmware mode to STA/IBSS/AP */
894 	{
895 		if (bmi_read_memory(hif_hia_item_address(target_type,
896 			offsetof(struct host_interest_s, hi_option_flag)),
897 			(uint8_t *)&param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
898 			BMI_ERR("bmi_read_memory for setting fwmode failed");
899 			return QDF_STATUS_E_FAILURE;
900 		}
901 
902 		/* TODO following parameters need to be re-visited. */
903 		param |= (1 << HI_OPTION_NUM_DEV_SHIFT); /* num_device */
904 		/* Firmware mode ?? */
905 		param |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT);
906 		/* mac_addr_method */
907 		param |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
908 		/* firmware_bridge */
909 		param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
910 		/* fwsubmode */
911 		param |= (0 << HI_OPTION_FW_SUBMODE_SHIFT);
912 
913 		BMI_INFO("NUM_DEV=%d FWMODE=0x%x FWSUBMODE=0x%x FWBR_BUF %d",
914 		       1, HI_OPTION_FW_MODE_AP, 0, 0);
915 
916 		if (bmi_write_memory(
917 			hif_hia_item_address(target_type,
918 			offsetof(struct host_interest_s, hi_option_flag)),
919 			(uint8_t *)&param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
920 			BMI_ERR("BMI WRITE for setting fwmode failed");
921 			return QDF_STATUS_E_FAILURE;
922 		}
923 	}
924 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_PCI) {
925 		if (ol_disable_cdc_max_perf(ol_ctx))
926 			return QDF_STATUS_E_FAILURE;
927 
928 		qdf_mem_zero(&cap, sizeof(cap));
929 
930 		ret = pld_get_platform_cap(qdf_dev->dev, &cap);
931 		if (ret)
932 			BMI_ERR("platform capability info not available");
933 
934 		if (!ret && cap.cap_flag & PLD_HAS_EXTERNAL_SWREG) {
935 			if (bmi_read_memory(hif_hia_item_address(target_type,
936 				offsetof(struct host_interest_s,
937 					 hi_option_flag2)),
938 				(uint8_t *)&param, 4, ol_ctx) !=
939 							QDF_STATUS_SUCCESS) {
940 				BMI_ERR("BMI READ failed for external SWREG");
941 				return QDF_STATUS_E_FAILURE;
942 			}
943 
944 			param |= HI_OPTION_USE_EXT_LDO;
945 			if (bmi_write_memory(
946 				hif_hia_item_address(target_type,
947 					offsetof(struct host_interest_s,
948 						 hi_option_flag2)),
949 					(uint8_t *)&param, 4, ol_ctx) !=
950 							QDF_STATUS_SUCCESS) {
951 				BMI_ERR("BMI WRITE failed for external SWREG");
952 				return QDF_STATUS_E_FAILURE;
953 			}
954 		}
955 
956 		if (ol_set_lpass_support(ol_ctx))
957 			return QDF_STATUS_E_FAILURE;
958 	}
959 
960 	/* If host is running on a BE CPU, set the host interest area */
961 	{
962 #ifdef BIG_ENDIAN_HOST
963 		param = 1;
964 #else
965 		param = 0;
966 #endif
967 		if (bmi_write_memory(
968 			hif_hia_item_address(target_type,
969 			offsetof(struct host_interest_s, hi_be)),
970 			(uint8_t *) &param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
971 			BMI_ERR("setting host CPU BE mode failed");
972 			return QDF_STATUS_E_FAILURE;
973 		}
974 	}
975 
976 	/* FW descriptor/Data swap flags */
977 	param = 0;
978 	if (bmi_write_memory(
979 		hif_hia_item_address(target_type,
980 		offsetof(struct host_interest_s, hi_fw_swap)),
981 		(uint8_t *) &param, 4, ol_ctx) != QDF_STATUS_SUCCESS) {
982 		BMI_ERR("BMI WRITE failed setting FW data/desc swap flags");
983 		return QDF_STATUS_E_FAILURE;
984 	}
985 
986 	return QDF_STATUS_SUCCESS;
987 }
988 
989 static int
ol_check_dataset_patch(struct hif_opaque_softc * scn,uint32_t * address)990 ol_check_dataset_patch(struct hif_opaque_softc *scn, uint32_t *address)
991 {
992 	/* Check if patch file needed for this target type/version. */
993 	return 0;
994 }
995 
ol_fw_populate_clk_settings(enum a_refclk_speed_t refclk,struct cmnos_clock_s * clock_s)996 static QDF_STATUS ol_fw_populate_clk_settings(enum a_refclk_speed_t refclk,
997 					      struct cmnos_clock_s *clock_s)
998 {
999 	if (!clock_s)
1000 		return QDF_STATUS_E_FAILURE;
1001 
1002 	switch (refclk) {
1003 	case SOC_REFCLK_48_MHZ:
1004 		clock_s->wlan_pll.div = 0xE;
1005 		clock_s->wlan_pll.rnfrac = 0x2AAA8;
1006 		clock_s->pll_settling_time = 2400;
1007 		break;
1008 	case SOC_REFCLK_19_2_MHZ:
1009 		clock_s->wlan_pll.div = 0x24;
1010 		clock_s->wlan_pll.rnfrac = 0x2AAA8;
1011 		clock_s->pll_settling_time = 960;
1012 		break;
1013 	case SOC_REFCLK_24_MHZ:
1014 		clock_s->wlan_pll.div = 0x1D;
1015 		clock_s->wlan_pll.rnfrac = 0x15551;
1016 		clock_s->pll_settling_time = 1200;
1017 		break;
1018 	case SOC_REFCLK_26_MHZ:
1019 		clock_s->wlan_pll.div = 0x1B;
1020 		clock_s->wlan_pll.rnfrac = 0x4EC4;
1021 		clock_s->pll_settling_time = 1300;
1022 		break;
1023 	case SOC_REFCLK_37_4_MHZ:
1024 		clock_s->wlan_pll.div = 0x12;
1025 		clock_s->wlan_pll.rnfrac = 0x34B49;
1026 		clock_s->pll_settling_time = 1870;
1027 		break;
1028 	case SOC_REFCLK_38_4_MHZ:
1029 		clock_s->wlan_pll.div = 0x12;
1030 		clock_s->wlan_pll.rnfrac = 0x15551;
1031 		clock_s->pll_settling_time = 1920;
1032 		break;
1033 	case SOC_REFCLK_40_MHZ:
1034 		clock_s->wlan_pll.div = 0x11;
1035 		clock_s->wlan_pll.rnfrac = 0x26665;
1036 		clock_s->pll_settling_time = 2000;
1037 		break;
1038 	case SOC_REFCLK_52_MHZ:
1039 		clock_s->wlan_pll.div = 0x1B;
1040 		clock_s->wlan_pll.rnfrac = 0x4EC4;
1041 		clock_s->pll_settling_time = 2600;
1042 		break;
1043 	case SOC_REFCLK_UNKNOWN:
1044 		clock_s->wlan_pll.refdiv = 0;
1045 		clock_s->wlan_pll.div = 0;
1046 		clock_s->wlan_pll.rnfrac = 0;
1047 		clock_s->wlan_pll.outdiv = 0;
1048 		clock_s->pll_settling_time = 1024;
1049 		clock_s->refclk_hz = 0;
1050 		fallthrough;
1051 	default:
1052 		return QDF_STATUS_E_FAILURE;
1053 	}
1054 
1055 	clock_s->refclk_hz = refclk_speed_to_hz[refclk];
1056 	clock_s->wlan_pll.refdiv = 0;
1057 	clock_s->wlan_pll.outdiv = 1;
1058 
1059 	return QDF_STATUS_SUCCESS;
1060 }
1061 
ol_patch_pll_switch(struct ol_context * ol_ctx)1062 static QDF_STATUS ol_patch_pll_switch(struct ol_context *ol_ctx)
1063 {
1064 	struct hif_opaque_softc *hif = ol_ctx->scn;
1065 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1066 	uint32_t addr = 0;
1067 	uint32_t reg_val = 0;
1068 	uint32_t mem_val = 0;
1069 	struct cmnos_clock_s clock_s;
1070 	uint32_t cmnos_core_clk_div_addr = 0;
1071 	uint32_t cmnos_cpu_pll_init_done_addr = 0;
1072 	uint32_t cmnos_cpu_speed_addr = 0;
1073 	struct hif_target_info *tgt_info = hif_get_target_info_handle(hif);
1074 	uint32_t target_version = tgt_info->target_version;
1075 	struct targetdef_t *scn = &ol_ctx->tgt_def;
1076 
1077 	switch (target_version) {
1078 	case AR6320_REV1_1_VERSION:
1079 		cmnos_core_clk_div_addr = AR6320_CORE_CLK_DIV_ADDR;
1080 		cmnos_cpu_pll_init_done_addr = AR6320_CPU_PLL_INIT_DONE_ADDR;
1081 		cmnos_cpu_speed_addr = AR6320_CPU_SPEED_ADDR;
1082 		break;
1083 	case AR6320_REV1_3_VERSION:
1084 	case AR6320_REV2_1_VERSION:
1085 		cmnos_core_clk_div_addr = AR6320V2_CORE_CLK_DIV_ADDR;
1086 		cmnos_cpu_pll_init_done_addr = AR6320V2_CPU_PLL_INIT_DONE_ADDR;
1087 		cmnos_cpu_speed_addr = AR6320V2_CPU_SPEED_ADDR;
1088 		break;
1089 	case AR6320_REV3_VERSION:
1090 	case AR6320_REV3_2_VERSION:
1091 	case QCA9379_REV1_VERSION:
1092 	case QCA9377_REV1_1_VERSION:
1093 		cmnos_core_clk_div_addr = AR6320V3_CORE_CLK_DIV_ADDR;
1094 		cmnos_cpu_pll_init_done_addr = AR6320V3_CPU_PLL_INIT_DONE_ADDR;
1095 		cmnos_cpu_speed_addr = AR6320V3_CPU_SPEED_ADDR;
1096 		break;
1097 	default:
1098 		BMI_ERR("%s: Unsupported target version %x", __func__,
1099 							target_version);
1100 		goto end;
1101 	}
1102 
1103 	addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET);
1104 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1105 	if (status != QDF_STATUS_SUCCESS) {
1106 		BMI_ERR("Failed to read EFUSE Addr");
1107 		goto end;
1108 	}
1109 
1110 	status = ol_fw_populate_clk_settings(EFUSE_XTAL_SEL_GET(reg_val),
1111 					     &clock_s);
1112 	if (status != QDF_STATUS_SUCCESS) {
1113 		BMI_ERR("Failed to set clock settings");
1114 		goto end;
1115 	}
1116 	BMI_DBG("crystal_freq: %dHz", clock_s.refclk_hz);
1117 
1118 	/* ------Step 1---- */
1119 	reg_val = 0;
1120 	addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET);
1121 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1122 	if (status != QDF_STATUS_SUCCESS) {
1123 		BMI_ERR("Failed to read PLL_CONFIG Addr");
1124 		goto end;
1125 	}
1126 	BMI_DBG("Step 1a: %8X", reg_val);
1127 
1128 	reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK);
1129 	reg_val |= (BB_PLL_CONFIG_FRAC_SET(clock_s.wlan_pll.rnfrac) |
1130 		    BB_PLL_CONFIG_OUTDIV_SET(clock_s.wlan_pll.outdiv));
1131 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1132 	if (status != QDF_STATUS_SUCCESS) {
1133 		BMI_ERR("Failed to write PLL_CONFIG Addr");
1134 		goto end;
1135 	}
1136 
1137 	reg_val = 0;
1138 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1139 	if (status != QDF_STATUS_SUCCESS) {
1140 		BMI_ERR("Failed to read back PLL_CONFIG Addr");
1141 		goto end;
1142 	}
1143 	BMI_DBG("Step 1b: %8X", reg_val);
1144 
1145 	/* ------Step 2---- */
1146 	reg_val = 0;
1147 	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET);
1148 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1149 	if (status != QDF_STATUS_SUCCESS) {
1150 		BMI_ERR("Failed to read PLL_SETTLE Addr");
1151 		goto end;
1152 	}
1153 	BMI_DBG("Step 2a: %8X", reg_val);
1154 
1155 	reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK;
1156 	reg_val |= WLAN_PLL_SETTLE_TIME_SET(clock_s.pll_settling_time);
1157 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1158 	if (status != QDF_STATUS_SUCCESS) {
1159 		BMI_ERR("Failed to write PLL_SETTLE Addr");
1160 		goto end;
1161 	}
1162 
1163 	reg_val = 0;
1164 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1165 	if (status != QDF_STATUS_SUCCESS) {
1166 		BMI_ERR("Failed to read back PLL_SETTLE Addr");
1167 		goto end;
1168 	}
1169 	BMI_DBG("Step 2b: %8X", reg_val);
1170 
1171 	/* ------Step 3---- */
1172 	reg_val = 0;
1173 	addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET);
1174 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1175 	if (status != QDF_STATUS_SUCCESS) {
1176 		BMI_ERR("Failed to read CLK_CTRL Addr");
1177 		goto end;
1178 	}
1179 	BMI_DBG("Step 3a: %8X", reg_val);
1180 
1181 	reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK;
1182 	reg_val |= SOC_CORE_CLK_CTRL_DIV_SET(1);
1183 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1184 	if (status != QDF_STATUS_SUCCESS) {
1185 		BMI_ERR("Failed to write CLK_CTRL Addr");
1186 		goto end;
1187 	}
1188 
1189 	reg_val = 0;
1190 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1191 	if (status != QDF_STATUS_SUCCESS) {
1192 		BMI_ERR("Failed to read back CLK_CTRL Addr");
1193 		goto end;
1194 	}
1195 	BMI_DBG("Step 3b: %8X", reg_val);
1196 
1197 	/* ------Step 4----- */
1198 	mem_val = 1;
1199 	status = bmi_write_memory(cmnos_core_clk_div_addr,
1200 				  (uint8_t *) &mem_val, 4, ol_ctx);
1201 	if (status != QDF_STATUS_SUCCESS) {
1202 		BMI_ERR("Failed to write CLK_DIV Addr");
1203 		goto end;
1204 	}
1205 
1206 	/* ------Step 5----- */
1207 	reg_val = 0;
1208 	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
1209 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1210 	if (status != QDF_STATUS_SUCCESS) {
1211 		BMI_ERR("Failed to read PLL_CTRL Addr");
1212 		goto end;
1213 	}
1214 	BMI_DBG("Step 5a: %8X", reg_val);
1215 
1216 	reg_val &= ~(WLAN_PLL_CONTROL_REFDIV_MASK | WLAN_PLL_CONTROL_DIV_MASK |
1217 		     WLAN_PLL_CONTROL_NOPWD_MASK);
1218 	reg_val |= (WLAN_PLL_CONTROL_REFDIV_SET(clock_s.wlan_pll.refdiv) |
1219 		    WLAN_PLL_CONTROL_DIV_SET(clock_s.wlan_pll.div) |
1220 		    WLAN_PLL_CONTROL_NOPWD_SET(1));
1221 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1222 	if (status != QDF_STATUS_SUCCESS) {
1223 		BMI_ERR("Failed to write PLL_CTRL Addr");
1224 		goto end;
1225 	}
1226 
1227 	reg_val = 0;
1228 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1229 	if (status != QDF_STATUS_SUCCESS) {
1230 		BMI_ERR("Failed to read back PLL_CTRL Addr");
1231 		goto end;
1232 	}
1233 	qdf_udelay(100);
1234 	BMI_DBG("Step 5b: %8X", reg_val);
1235 
1236 	/* ------Step 6------- */
1237 	do {
1238 		reg_val = 0;
1239 		status = bmi_read_soc_register((RTC_WMAC_BASE_ADDRESS |
1240 				RTC_SYNC_STATUS_OFFSET), &reg_val, ol_ctx);
1241 		if (status != QDF_STATUS_SUCCESS) {
1242 			BMI_ERR("Failed to read RTC_SYNC_STATUS Addr");
1243 			goto end;
1244 		}
1245 	} while (RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val));
1246 
1247 	/* ------Step 7------- */
1248 	reg_val = 0;
1249 	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
1250 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1251 	if (status != QDF_STATUS_SUCCESS) {
1252 		BMI_ERR("Failed to read PLL_CTRL Addr for CTRL_BYPASS");
1253 		goto end;
1254 	}
1255 	BMI_DBG("Step 7a: %8X", reg_val);
1256 
1257 	reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK;
1258 	reg_val |= WLAN_PLL_CONTROL_BYPASS_SET(0);
1259 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1260 	if (status != QDF_STATUS_SUCCESS) {
1261 		BMI_ERR("Failed to write PLL_CTRL Addr for CTRL_BYPASS");
1262 		goto end;
1263 	}
1264 
1265 	reg_val = 0;
1266 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1267 	if (status != QDF_STATUS_SUCCESS) {
1268 		BMI_ERR("Failed to read back PLL_CTRL Addr for CTRL_BYPASS");
1269 		goto end;
1270 	}
1271 	BMI_DBG("Step 7b: %8X", reg_val);
1272 
1273 	/* ------Step 8-------- */
1274 	do {
1275 		reg_val = 0;
1276 		status = bmi_read_soc_register((RTC_WMAC_BASE_ADDRESS |
1277 				RTC_SYNC_STATUS_OFFSET), &reg_val, ol_ctx);
1278 		if (status != QDF_STATUS_SUCCESS) {
1279 			BMI_ERR("Failed to read SYNC_STATUS Addr");
1280 			goto end;
1281 		}
1282 	} while (RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val));
1283 
1284 	/* ------Step 9-------- */
1285 	reg_val = 0;
1286 	addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET);
1287 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1288 	if (status != QDF_STATUS_SUCCESS) {
1289 		BMI_ERR("Failed to read CPU_CLK Addr");
1290 		goto end;
1291 	}
1292 	BMI_DBG("Step 9a: %8X", reg_val);
1293 
1294 	reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK;
1295 	reg_val |= SOC_CPU_CLOCK_STANDARD_SET(1);
1296 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1297 	if (status != QDF_STATUS_SUCCESS) {
1298 		BMI_ERR("Failed to write CPU_CLK Addr");
1299 		goto end;
1300 	}
1301 
1302 	reg_val = 0;
1303 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1304 	if (status != QDF_STATUS_SUCCESS) {
1305 		BMI_ERR("Failed to read back CPU_CLK Addr");
1306 		goto end;
1307 	}
1308 	BMI_DBG("Step 9b: %8X", reg_val);
1309 
1310 	/* ------Step 10------- */
1311 	reg_val = 0;
1312 	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
1313 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1314 	if (status != QDF_STATUS_SUCCESS) {
1315 		BMI_ERR("Failed to read PLL_CTRL Addr for NOPWD");
1316 		goto end;
1317 	}
1318 	BMI_DBG("Step 10a: %8X", reg_val);
1319 
1320 	reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK;
1321 	status = bmi_write_soc_register(addr, reg_val, ol_ctx);
1322 	if (status != QDF_STATUS_SUCCESS) {
1323 		BMI_ERR("Failed to write PLL_CTRL Addr for NOPWD");
1324 		goto end;
1325 	}
1326 	reg_val = 0;
1327 	status = bmi_read_soc_register(addr, &reg_val, ol_ctx);
1328 	if (status != QDF_STATUS_SUCCESS) {
1329 		BMI_ERR("Failed to read back PLL_CTRL Addr for NOPWD");
1330 		goto end;
1331 	}
1332 	BMI_DBG("Step 10b: %8X", reg_val);
1333 
1334 	/* ------Step 11------- */
1335 	mem_val = 1;
1336 	status = bmi_write_memory(cmnos_cpu_pll_init_done_addr,
1337 				  (uint8_t *) &mem_val, 4, ol_ctx);
1338 	if (status != QDF_STATUS_SUCCESS) {
1339 		BMI_ERR("Failed to write PLL_INIT Addr");
1340 		goto end;
1341 	}
1342 
1343 	mem_val = TARGET_CPU_FREQ;
1344 	status = bmi_write_memory(cmnos_cpu_speed_addr,
1345 				  (uint8_t *) &mem_val, 4, ol_ctx);
1346 	if (status != QDF_STATUS_SUCCESS) {
1347 		BMI_ERR("Failed to write CPU_SPEED Addr");
1348 		goto end;
1349 	}
1350 
1351 end:
1352 	return status;
1353 }
1354 
ol_download_firmware(struct ol_context * ol_ctx)1355 QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx)
1356 {
1357 	struct hif_opaque_softc *scn = ol_ctx->scn;
1358 	uint32_t param, address = 0;
1359 	QDF_STATUS status = !QDF_STATUS_SUCCESS;
1360 	QDF_STATUS ret;
1361 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
1362 	struct ol_config_info *ini_cfg = ol_get_ini_handle(ol_ctx);
1363 	uint32_t target_type = tgt_info->target_type;
1364 	uint32_t target_version = tgt_info->target_version;
1365 	struct bmi_info *bmi_ctx = GET_BMI_CONTEXT(ol_ctx);
1366 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
1367 
1368 	if (0 != pld_get_fw_files_for_target(qdf_dev->dev,
1369 					     &bmi_ctx->fw_files,
1370 					      target_type,
1371 					      target_version)) {
1372 		BMI_ERR("%s: No FW files from platform driver", __func__);
1373 		return QDF_STATUS_E_FAILURE;
1374 	}
1375 
1376 	/* Transfer Board Data from Target EEPROM to Target RAM */
1377 	/* Determine where in Target RAM to write Board Data */
1378 	bmi_read_memory(hif_hia_item_address(target_type,
1379 			offsetof(struct host_interest_s, hi_board_data)),
1380 			(uint8_t *)&address, 4, ol_ctx);
1381 
1382 	if (!address) {
1383 		address = AR6004_REV5_BOARD_DATA_ADDRESS;
1384 		BMI_DBG("%s: Target address not known! Using 0x%x",
1385 						__func__, address);
1386 	}
1387 
1388 	if (hif_get_bus_type(scn) != QDF_BUS_TYPE_USB) {
1389 		ret = ol_patch_pll_switch(ol_ctx);
1390 		if (ret != QDF_STATUS_SUCCESS) {
1391 			BMI_ERR("pll switch failed. status %d", ret);
1392 			return ret;
1393 		}
1394 	}
1395 
1396 	if (ol_ctx->cal_in_flash) {
1397 		/* Write EEPROM or Flash data to Target RAM */
1398 		status = ol_transfer_bin_file(ol_ctx, ATH_FLASH_FILE,
1399 						address, false);
1400 	}
1401 
1402 	if (!status) {
1403 		/* Record the fact that Board Data is initialized */
1404 		param = 1;
1405 		bmi_write_memory(
1406 			hif_hia_item_address(target_type,
1407 			offsetof(struct host_interest_s,
1408 				hi_board_data_initialized)),
1409 				(uint8_t *) &param, 4, ol_ctx);
1410 	} else {
1411 		/* Transfer One Time Programmable data */
1412 		address = BMI_SEGMENTED_WRITE_ADDR;
1413 		BMI_INFO("%s: Using 0x%x for the remainder of init",
1414 				__func__, address);
1415 
1416 		status = ol_transfer_bin_file(ol_ctx, ATH_OTP_FILE,
1417 					      address, true);
1418 		/* Execute the OTP code only if entry found and downloaded */
1419 		if (!status) {
1420 			uint16_t board_id = 0xffff;
1421 			/* get board id */
1422 			param = 0x10;
1423 			bmi_execute(address, &param, ol_ctx);
1424 			if (!(param & 0xff))
1425 				board_id = (param >> 8) & 0xffff;
1426 			BMI_INFO("%s: board ID is 0x%0x", __func__, board_id);
1427 			bmi_ctx->board_id = board_id;
1428 		} else if (status < 0) {
1429 			return status;
1430 		}
1431 
1432 		bmi_read_memory(hif_hia_item_address(target_type,
1433 				offsetof(struct host_interest_s,
1434 					hi_board_data)),
1435 				(uint8_t *)&address, 4, ol_ctx);
1436 
1437 		if (!address) {
1438 			address = AR6004_REV5_BOARD_DATA_ADDRESS;
1439 			pr_err("%s: Target address not known! Using 0x%x\n",
1440 			       __func__, address);
1441 		}
1442 
1443 		/* Flash is either not available or invalid */
1444 		if (ol_transfer_bin_file(ol_ctx, ATH_BOARD_DATA_FILE,
1445 					 address, false)) {
1446 			return QDF_STATUS_E_FAILURE;
1447 		}
1448 
1449 		/* Record the fact that Board Data is initialized */
1450 		param = 1;
1451 		bmi_write_memory(hif_hia_item_address(target_type,
1452 				 offsetof(struct host_interest_s,
1453 					  hi_board_data_initialized)),
1454 				 (uint8_t *) &param, 4, ol_ctx);
1455 		address = BMI_SEGMENTED_WRITE_ADDR;
1456 		param = 0;
1457 		bmi_execute(address, &param, ol_ctx);
1458 	}
1459 
1460 	if (!ol_transfer_bin_file(ol_ctx, ATH_SETUP_FILE,
1461 				  BMI_SEGMENTED_WRITE_ADDR, true)) {
1462 		param = 0;
1463 		bmi_execute(address, &param, ol_ctx);
1464 	}
1465 
1466 	/* Download Target firmware
1467 	 * TODO point to target specific files in runtime
1468 	 */
1469 	address = BMI_SEGMENTED_WRITE_ADDR;
1470 	if (ol_transfer_bin_file(ol_ctx, ATH_FIRMWARE_FILE,
1471 				 address, true)) {
1472 		return QDF_STATUS_E_FAILURE;
1473 	}
1474 
1475 	/* Apply the patches */
1476 	if (ol_check_dataset_patch(scn, &address)) {
1477 		if (ol_transfer_bin_file(ol_ctx, ATH_PATCH_FILE, address,
1478 					 false)) {
1479 			return QDF_STATUS_E_FAILURE;
1480 		}
1481 		bmi_write_memory(hif_hia_item_address(target_type,
1482 			offsetof(struct host_interest_s, hi_dset_list_head)),
1483 			(uint8_t *) &address, 4, ol_ctx);
1484 	}
1485 
1486 	switch (target_version) {
1487 	case AR6004_VERSION_REV1_3:
1488 		param = 11;
1489 		break;
1490 	case AR6320_REV1_VERSION:
1491 	case AR6320_REV2_VERSION:
1492 	case AR6320_REV3_VERSION:
1493 	case AR6320_REV3_2_VERSION:
1494 	case QCA9377_REV1_1_VERSION:
1495 	case QCA9379_REV1_VERSION:
1496 	case AR6320_REV4_VERSION:
1497 	case AR6320_DEV_VERSION:
1498 		/*
1499 		 * In sdio interface chip, both sdio_data2 and uart_tx pin
1500 		 * will use GPIO6. It is set by fw rom code, which will cause
1501 		 * sdio CRC error when there is sdio transaction.
1502 		 * Override uart tx pin to avoid side effect to sdio pin.
1503 		 */
1504 		if (hif_get_bus_type(scn) == QDF_BUS_TYPE_SDIO)
1505 			param = 19;
1506 		else
1507 			param = 6;
1508 		break;
1509 	default:
1510 	/* Configure GPIO AR9888 UART */
1511 		param = 7;
1512 	}
1513 
1514 	bmi_write_memory(hif_hia_item_address(target_type,
1515 		offsetof(struct host_interest_s, hi_dbg_uart_txpin)),
1516 		(uint8_t *)&param, 4, ol_ctx);
1517 
1518 	if (ini_cfg->enable_uart_print) {
1519 		param = 1;
1520 		bmi_write_memory(hif_hia_item_address(target_type,
1521 			offsetof(struct host_interest_s, hi_serial_enable)),
1522 			(uint8_t *)&param, 4, ol_ctx);
1523 	} else {
1524 		/*
1525 		 * Explicitly setting UART prints to zero as target turns it on
1526 		 * based on scratch registers.
1527 		 */
1528 		param = 0;
1529 		bmi_write_memory(hif_hia_item_address(target_type,
1530 			offsetof(struct host_interest_s, hi_serial_enable)),
1531 			(uint8_t *)&param, 4, ol_ctx);
1532 	}
1533 
1534 	if (ini_cfg->enable_fw_log) {
1535 		bmi_read_memory(hif_hia_item_address(target_type,
1536 			offsetof(struct host_interest_s, hi_option_flag)),
1537 			(uint8_t *)&param, 4, ol_ctx);
1538 
1539 		param &= ~(HI_OPTION_DISABLE_DBGLOG);
1540 		bmi_write_memory(hif_hia_item_address(target_type,
1541 			offsetof(struct host_interest_s, hi_option_flag)),
1542 			(uint8_t *)&param, 4, ol_ctx);
1543 	} else {
1544 		/*
1545 		 * Explicitly setting fwlog prints to zero as target turns it on
1546 		 * based on scratch registers.
1547 		 */
1548 		bmi_read_memory(hif_hia_item_address(target_type,
1549 			offsetof(struct host_interest_s, hi_option_flag)),
1550 			(uint8_t *)&param, 4, ol_ctx);
1551 
1552 		param |= HI_OPTION_DISABLE_DBGLOG;
1553 		bmi_write_memory(hif_hia_item_address(target_type,
1554 			offsetof(struct host_interest_s, hi_option_flag)),
1555 			(uint8_t *) &param, 4, ol_ctx);
1556 	}
1557 	status = ol_extra_initialization(ol_ctx);
1558 
1559 	return status;
1560 }
1561 
ol_diag_read(struct hif_opaque_softc * scn,uint8_t * buffer,uint32_t pos,size_t count)1562 static int ol_diag_read(struct hif_opaque_softc *scn, uint8_t *buffer,
1563 			uint32_t pos, size_t count)
1564 {
1565 	int result = 0;
1566 
1567 	if ((4 == count) && ((pos & 3) == 0)) {
1568 		result = hif_diag_read_access(scn, pos,
1569 					      (uint32_t *) buffer);
1570 	} else {
1571 		size_t amount_read = 0;
1572 		size_t readSize = PCIE_READ_LIMIT;
1573 		size_t remainder = 0;
1574 
1575 		if (count > PCIE_READ_LIMIT) {
1576 			while ((amount_read < count) && (0 == result)) {
1577 				result = hif_diag_read_mem(scn, pos,
1578 							   buffer, readSize);
1579 				if (0 == result) {
1580 					buffer += readSize;
1581 					pos += readSize;
1582 					amount_read += readSize;
1583 					remainder = count - amount_read;
1584 					if (remainder < PCIE_READ_LIMIT)
1585 						readSize = remainder;
1586 				}
1587 			}
1588 		} else {
1589 		result = hif_diag_read_mem(scn, pos,
1590 					   buffer, count);
1591 		}
1592 	}
1593 
1594 	if (!result)
1595 		return count;
1596 	else
1597 		return -EIO;
1598 }
1599 
ol_ath_get_reg_table(struct hif_opaque_softc * scn,uint32_t target_version,struct tgt_reg_table * reg_table)1600 static int ol_ath_get_reg_table(struct hif_opaque_softc *scn,
1601 				uint32_t target_version,
1602 				struct tgt_reg_table *reg_table)
1603 {
1604 	int section_len = 0;
1605 
1606 	if (!reg_table) {
1607 		qdf_assert(0);
1608 		return section_len;
1609 	}
1610 
1611 	if (hif_get_bus_type(scn) != QDF_BUS_TYPE_PCI &&
1612 	    hif_get_bus_type(scn) != QDF_BUS_TYPE_SDIO)
1613 		return section_len;
1614 
1615 	switch (target_version) {
1616 	case AR6320_REV2_1_VERSION:
1617 		reg_table->section = ar6320v2_reg_table;
1618 		reg_table->section_size = ARRAY_SIZE(ar6320v2_reg_table);
1619 		section_len = AR6320_REV2_1_REG_SIZE;
1620 		break;
1621 	case AR6320_REV3_VERSION:
1622 	case AR6320_REV3_2_VERSION:
1623 	case QCA9379_REV1_VERSION:
1624 	case QCA9377_REV1_1_VERSION:
1625 		reg_table->section = ar6320v3_reg_table;
1626 		reg_table->section_size = ARRAY_SIZE(ar6320v3_reg_table);
1627 		section_len = AR6320_REV3_REG_SIZE;
1628 		break;
1629 	default:
1630 		reg_table->section = NULL;
1631 		reg_table->section_size = 0;
1632 		section_len = 0;
1633 	}
1634 
1635 	return section_len;
1636 }
1637 
ol_diag_read_reg_loc(struct hif_opaque_softc * scn,uint8_t * buffer,uint32_t buffer_len)1638 static int ol_diag_read_reg_loc(struct hif_opaque_softc *scn, uint8_t *buffer,
1639 				uint32_t buffer_len)
1640 {
1641 	int i, len, section_len, fill_len;
1642 	int dump_len, result = 0;
1643 	struct tgt_reg_table reg_table;
1644 	const struct tgt_reg_section *curr_sec, *next_sec;
1645 	struct hif_target_info *tgt_info = hif_get_target_info_handle(scn);
1646 	uint32_t target_version =  tgt_info->target_version;
1647 
1648 	reg_table.section = NULL;
1649 	reg_table.section_size = 0;
1650 
1651 	section_len = ol_ath_get_reg_table(scn, target_version, &reg_table);
1652 
1653 	if (!reg_table.section || !reg_table.section_size || !section_len) {
1654 		BMI_ERR("%s: failed to get reg table", __func__);
1655 		result = -EIO;
1656 		goto out;
1657 	}
1658 
1659 	curr_sec = reg_table.section;
1660 	for (i = 0; i < reg_table.section_size; i++) {
1661 
1662 		dump_len = curr_sec->end_addr - curr_sec->start_addr;
1663 
1664 		if ((buffer_len - result) < dump_len) {
1665 			BMI_ERR("No buffer to dump regs:%d: 0x%08x-0x%08x",
1666 				i, curr_sec->start_addr, curr_sec->end_addr);
1667 			goto out;
1668 		}
1669 
1670 		len = ol_diag_read(scn, buffer, curr_sec->start_addr, dump_len);
1671 
1672 		if (len != -EIO) {
1673 			buffer += len;
1674 			result += len;
1675 		} else {
1676 			BMI_ERR("%s: can't read reg 0x%08x len = %d",
1677 				__func__, curr_sec->start_addr, dump_len);
1678 			result = -EIO;
1679 			goto out;
1680 		}
1681 
1682 		if (result < section_len) {
1683 			next_sec = (struct tgt_reg_section *) ((uint8_t *)
1684 						 curr_sec + sizeof(*curr_sec));
1685 			fill_len = next_sec->start_addr - curr_sec->end_addr;
1686 			if ((buffer_len - result) < fill_len) {
1687 				BMI_ERR("No buf to fill regs:%d: 0x%08x-0x%08x",
1688 					i, curr_sec->end_addr,
1689 					next_sec->start_addr);
1690 				goto out;
1691 			}
1692 
1693 			if (fill_len) {
1694 				buffer += fill_len;
1695 				result += fill_len;
1696 			}
1697 		}
1698 		curr_sec++;
1699 	}
1700 
1701 out:
1702 	return result;
1703 }
1704 
1705 static
ol_dump_target_memory(struct hif_opaque_softc * scn,void * memory_block)1706 void ol_dump_target_memory(struct hif_opaque_softc *scn, void *memory_block)
1707 {
1708 	char *buffer_loc = memory_block;
1709 	u_int32_t section_count = 0;
1710 	u_int32_t address = 0;
1711 	u_int32_t size = 0;
1712 
1713 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_SDIO ||
1714 	    hif_get_bus_type(scn) == QDF_BUS_TYPE_USB)
1715 		return;
1716 
1717 	for (; section_count < 2; section_count++) {
1718 		switch (section_count) {
1719 		case 0:
1720 			address = DRAM_LOCAL_BASE_ADDR;
1721 			size = DRAM_SIZE;
1722 			break;
1723 		case 1:
1724 			address = AXI_LOCATION;
1725 			size = AXI_SIZE;
1726 			break;
1727 		default:
1728 			break;
1729 		}
1730 		hif_dump_target_memory(scn, buffer_loc, address, size);
1731 		buffer_loc += size;
1732 	}
1733 }
1734 
1735 static int
ol_dump_ce_register(struct hif_opaque_softc * scn,void * memory_block)1736 ol_dump_ce_register(struct hif_opaque_softc *scn, void *memory_block)
1737 {
1738 	int ret;
1739 
1740 	BMI_ERR("Could not read dump section!");
1741 
1742 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_SDIO ||
1743 	    hif_get_bus_type(scn) == QDF_BUS_TYPE_USB)
1744 		return 0;
1745 
1746 	if (hif_dump_registers(scn))
1747 		BMI_ERR("Failed to dump bus registers");
1748 
1749 	ol_dump_target_memory(scn, memory_block);
1750 	ret = -EACCES;
1751 
1752 	return ret;
1753 }
1754 
1755 static inline uint32_t
ol_get_max_section_count(struct hif_opaque_softc * scn)1756 ol_get_max_section_count(struct hif_opaque_softc *scn)
1757 {
1758 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_PCI)
1759 		return 5;
1760 	else
1761 		return 4;
1762 }
1763 
1764 /**
1765  * ol_set_ram_config_reg() - set target RAM configuration register
1766  * @scn: pointer of hif_softc context
1767  * @config: value to be written to the register
1768  *
1769  * This function will write the given value to target RAM configuration
1770  * register which is bit[23-20] of target CPU inbound address in order to
1771  * provide correct address mapping.
1772  *
1773  * Return: 0 for success or reasons for failure
1774  */
ol_set_ram_config_reg(struct hif_opaque_softc * scn,uint32_t config)1775 static int ol_set_ram_config_reg(struct hif_opaque_softc *scn, uint32_t config)
1776 {
1777 	QDF_STATUS status;
1778 	uint32_t val;
1779 	struct targetdef_s *targetdef =
1780 		(struct targetdef_s *)hif_get_targetdef(scn);
1781 	uint32_t ram_config_addr =
1782 		targetdef->d_SOC_CORE_BASE_ADDRESS + FW_RAM_CONFIG_ADDRESS;
1783 
1784 	if (hif_get_bus_type(scn) != QDF_BUS_TYPE_PCI)
1785 		return -EACCES;
1786 
1787 	status = hif_diag_write_access(scn, ram_config_addr, config);
1788 	if (QDF_IS_STATUS_ERROR(status)) {
1789 		return -EACCES;
1790 	}
1791 	status = hif_diag_read_access(scn, ram_config_addr, &val);
1792 	if (QDF_IS_STATUS_ERROR(status)) {
1793 		return -EACCES;
1794 	}
1795 	if (val != config) {
1796 		BMI_ERR("%s: Failed to set RAM config reg from 0x%x to 0x%x",
1797 			__func__, val, config);
1798 		return -EACCES;
1799 	}
1800 	return 0;
1801 }
1802 
1803 static int
ol_get_iram_len_and_pos(struct hif_opaque_softc * scn,uint32_t * pos,uint32_t * len,uint32_t section)1804 ol_get_iram_len_and_pos(struct hif_opaque_softc *scn, uint32_t *pos,
1805 			uint32_t *len, uint32_t section)
1806 {
1807 	enum hif_target_status status;
1808 	uint32_t iram_addr, iram_size;
1809 	int ret;
1810 
1811 	if (hif_get_bus_type(scn) != QDF_BUS_TYPE_PCI) {
1812 		*pos = IRAM_LOCATION;
1813 		*len = IRAM_SIZE;
1814 		BMI_ERR("%s: Dumping IRAM Section", __func__);
1815 		return 0;
1816 	}
1817 
1818 	status = hif_get_target_status(scn);
1819 	if (status != TARGET_STATUS_RESET) {
1820 		BMI_ERR("%s: Target status invalid: %d", __func__, status);
1821 		return -EBUSY;
1822 	}
1823 
1824 	switch (section) {
1825 	case 3:
1826 		BMI_ERR("%s: Dumping IRAM1 section", __func__);
1827 		iram_addr = IRAM1_LOCATION;
1828 		iram_size = IRAM1_SIZE;
1829 		break;
1830 	case 4:
1831 		BMI_ERR("%s: Dumping IRAM2 section", __func__);
1832 		iram_addr = IRAM2_LOCATION;
1833 		iram_size = IRAM2_SIZE;
1834 		break;
1835 	default:
1836 		BMI_ERR("%s: Invalid input iram section %d",
1837 			__func__, section);
1838 		return A_EINVAL;
1839 	}
1840 
1841 	ret = ol_set_ram_config_reg(scn, iram_addr >> 20);
1842 	if (ret) {
1843 		BMI_ERR("%s: Skip IRAM1 ret:%d", __func__, ret);
1844 		return -EBUSY;
1845 	}
1846 
1847 	*pos = iram_addr;
1848 	*len = iram_size;
1849 	return 0;
1850 }
1851 
1852 /**
1853  * ol_target_coredump() - API to collect target ramdump
1854  * @inst: private context
1855  * @memory_block: non-NULL reserved memory location
1856  * @block_len: size of the dump to collect
1857  *
1858  * Function to perform core dump for the target.
1859  *
1860  * Return: int
1861  */
ol_target_coredump(void * inst,void * memory_block,uint32_t block_len)1862 static int ol_target_coredump(void *inst, void *memory_block,
1863 					uint32_t block_len)
1864 {
1865 	struct hif_opaque_softc *scn = (struct hif_opaque_softc *)inst;
1866 	int8_t *buffer_loc = memory_block;
1867 	int result = 0;
1868 	int ret = 0;
1869 	uint32_t amount_read = 0;
1870 	uint32_t section_count = 0;
1871 	uint32_t pos = 0;
1872 	uint32_t read_len = 0;
1873 	uint32_t max_count = ol_get_max_section_count(scn);
1874 
1875 	while ((section_count < max_count) && (amount_read < block_len)) {
1876 		switch (section_count) {
1877 		case 0:
1878 			pos = DRAM_LOCATION;
1879 			read_len = DRAM_SIZE;
1880 			BMI_ERR("%s: Dumping DRAM section...", __func__);
1881 			break;
1882 		case 1:
1883 			pos = AXI_LOCATION;
1884 			read_len = AXI_SIZE;
1885 			BMI_ERR("%s: Dumping AXI section...", __func__);
1886 			break;
1887 		case 2:
1888 			pos = REGISTER_LOCATION;
1889 			/* ol_diag_read_reg_loc checks for buffer overrun */
1890 			read_len = 0;
1891 			BMI_ERR("%s: Dumping Register section...", __func__);
1892 			break;
1893 		case 3:
1894 		case 4:
1895 			ret = ol_get_iram_len_and_pos(scn, &pos, &read_len,
1896 						      section_count);
1897 			if (ret) {
1898 				BMI_ERR("%s: Fail to Dump IRAM Section "
1899 					"ret:%d", __func__, ret);
1900 				return ret;
1901 			}
1902 			break;
1903 		default:
1904 			BMI_ERR("%s: INVALID SECTION_:%d", __func__,
1905 				section_count);
1906 			return 0;
1907 		}
1908 
1909 		if (block_len - amount_read < read_len) {
1910 			BMI_ERR("%s: No memory to dump section:%d buffer!",
1911 				__func__, section_count);
1912 			return -ENOMEM;
1913 		}
1914 
1915 		if (((hif_get_bus_type(scn) == QDF_BUS_TYPE_PCI) ||
1916 		     (hif_get_bus_type(scn) == QDF_BUS_TYPE_SDIO)) &&
1917 		    pos == REGISTER_LOCATION)
1918 			result = ol_diag_read_reg_loc(scn, buffer_loc,
1919 						      block_len - amount_read);
1920 		else
1921 			result = ol_diag_read(scn, buffer_loc, pos, read_len);
1922 
1923 		if (result == -EIO)
1924 			return ol_dump_ce_register(scn, memory_block);
1925 
1926 		BMI_INFO("%s: Section:%d Bytes Read:%0x", __func__,
1927 			 section_count, result);
1928 
1929 		amount_read += result;
1930 		buffer_loc += result;
1931 		section_count++;
1932 	}
1933 	return ret;
1934 }
1935 
1936 /**
1937  * ol_get_ini_handle() - API to get Ol INI configuration
1938  * @ol_ctx: OL Context
1939  *
1940  * Return: pointer to OL configuration
1941  */
ol_get_ini_handle(struct ol_context * ol_ctx)1942 struct ol_config_info *ol_get_ini_handle(struct ol_context *ol_ctx)
1943 {
1944 	return &ol_ctx->cfg_info;
1945 }
1946 
1947 /**
1948  * ol_init_ini_config() - API to initialize INI configuration
1949  * @ol_ctx: OL Context
1950  * @cfg: OL ini configuration
1951  *
1952  * Return: void
1953  */
ol_init_ini_config(struct ol_context * ol_ctx,struct ol_config_info * cfg)1954 void ol_init_ini_config(struct ol_context *ol_ctx,
1955 			struct ol_config_info *cfg)
1956 {
1957 	qdf_mem_copy(&ol_ctx->cfg_info, cfg, sizeof(struct ol_config_info));
1958 }
1959 
ol_set_fw_crashed_cb(struct ol_context * ol_ctx,void (* callback_fn)(void))1960 void ol_set_fw_crashed_cb(struct ol_context *ol_ctx,
1961 			  void (*callback_fn)(void))
1962 {
1963 	ol_ctx->fw_crashed_cb = callback_fn;
1964 }
1965