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