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 *)¶m, 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 *) ¶m, 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 *)¶m, 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 *) ¶m, 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 *)¶m, 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 *) ¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *) ¶m, 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 *) ¶m, 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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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), ®_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, ®_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, ®_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), ®_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, ®_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, ®_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, ®_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, ®_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 *) ¶m, 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, ¶m, 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 *) ¶m, 4, ol_ctx);
1455*5113495bSYour Name address = BMI_SEGMENTED_WRITE_ADDR;
1456*5113495bSYour Name param = 0;
1457*5113495bSYour Name bmi_execute(address, ¶m, 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, ¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *) ¶m, 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, ®_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