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