18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/types.h> 78c2ecf20Sopenharmony_ci#include <linux/bitops.h> 88c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 98c2ecf20Sopenharmony_ci#include "core.h" 108c2ecf20Sopenharmony_ci#include "hw.h" 118c2ecf20Sopenharmony_ci#include "hif.h" 128c2ecf20Sopenharmony_ci#include "wmi-ops.h" 138c2ecf20Sopenharmony_ci#include "bmi.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciconst struct ath10k_hw_regs qca988x_regs = { 168c2ecf20Sopenharmony_ci .rtc_soc_base_address = 0x00004000, 178c2ecf20Sopenharmony_ci .rtc_wmac_base_address = 0x00005000, 188c2ecf20Sopenharmony_ci .soc_core_base_address = 0x00009000, 198c2ecf20Sopenharmony_ci .wlan_mac_base_address = 0x00020000, 208c2ecf20Sopenharmony_ci .ce_wrapper_base_address = 0x00057000, 218c2ecf20Sopenharmony_ci .ce0_base_address = 0x00057400, 228c2ecf20Sopenharmony_ci .ce1_base_address = 0x00057800, 238c2ecf20Sopenharmony_ci .ce2_base_address = 0x00057c00, 248c2ecf20Sopenharmony_ci .ce3_base_address = 0x00058000, 258c2ecf20Sopenharmony_ci .ce4_base_address = 0x00058400, 268c2ecf20Sopenharmony_ci .ce5_base_address = 0x00058800, 278c2ecf20Sopenharmony_ci .ce6_base_address = 0x00058c00, 288c2ecf20Sopenharmony_ci .ce7_base_address = 0x00059000, 298c2ecf20Sopenharmony_ci .soc_reset_control_si0_rst_mask = 0x00000001, 308c2ecf20Sopenharmony_ci .soc_reset_control_ce_rst_mask = 0x00040000, 318c2ecf20Sopenharmony_ci .soc_chip_id_address = 0x000000ec, 328c2ecf20Sopenharmony_ci .scratch_3_address = 0x00000030, 338c2ecf20Sopenharmony_ci .fw_indicator_address = 0x00009030, 348c2ecf20Sopenharmony_ci .pcie_local_base_address = 0x00080000, 358c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_lsb = 0x00000008, 368c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_mask = 0x0000ff00, 378c2ecf20Sopenharmony_ci .pcie_intr_fw_mask = 0x00000400, 388c2ecf20Sopenharmony_ci .pcie_intr_ce_mask_all = 0x0007f800, 398c2ecf20Sopenharmony_ci .pcie_intr_clr_address = 0x00000014, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciconst struct ath10k_hw_regs qca6174_regs = { 438c2ecf20Sopenharmony_ci .rtc_soc_base_address = 0x00000800, 448c2ecf20Sopenharmony_ci .rtc_wmac_base_address = 0x00001000, 458c2ecf20Sopenharmony_ci .soc_core_base_address = 0x0003a000, 468c2ecf20Sopenharmony_ci .wlan_mac_base_address = 0x00010000, 478c2ecf20Sopenharmony_ci .ce_wrapper_base_address = 0x00034000, 488c2ecf20Sopenharmony_ci .ce0_base_address = 0x00034400, 498c2ecf20Sopenharmony_ci .ce1_base_address = 0x00034800, 508c2ecf20Sopenharmony_ci .ce2_base_address = 0x00034c00, 518c2ecf20Sopenharmony_ci .ce3_base_address = 0x00035000, 528c2ecf20Sopenharmony_ci .ce4_base_address = 0x00035400, 538c2ecf20Sopenharmony_ci .ce5_base_address = 0x00035800, 548c2ecf20Sopenharmony_ci .ce6_base_address = 0x00035c00, 558c2ecf20Sopenharmony_ci .ce7_base_address = 0x00036000, 568c2ecf20Sopenharmony_ci .soc_reset_control_si0_rst_mask = 0x00000000, 578c2ecf20Sopenharmony_ci .soc_reset_control_ce_rst_mask = 0x00000001, 588c2ecf20Sopenharmony_ci .soc_chip_id_address = 0x000000f0, 598c2ecf20Sopenharmony_ci .scratch_3_address = 0x00000028, 608c2ecf20Sopenharmony_ci .fw_indicator_address = 0x0003a028, 618c2ecf20Sopenharmony_ci .pcie_local_base_address = 0x00080000, 628c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_lsb = 0x00000008, 638c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_mask = 0x0000ff00, 648c2ecf20Sopenharmony_ci .pcie_intr_fw_mask = 0x00000400, 658c2ecf20Sopenharmony_ci .pcie_intr_ce_mask_all = 0x0007f800, 668c2ecf20Sopenharmony_ci .pcie_intr_clr_address = 0x00000014, 678c2ecf20Sopenharmony_ci .cpu_pll_init_address = 0x00404020, 688c2ecf20Sopenharmony_ci .cpu_speed_address = 0x00404024, 698c2ecf20Sopenharmony_ci .core_clk_div_address = 0x00404028, 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ciconst struct ath10k_hw_regs qca99x0_regs = { 738c2ecf20Sopenharmony_ci .rtc_soc_base_address = 0x00080000, 748c2ecf20Sopenharmony_ci .rtc_wmac_base_address = 0x00000000, 758c2ecf20Sopenharmony_ci .soc_core_base_address = 0x00082000, 768c2ecf20Sopenharmony_ci .wlan_mac_base_address = 0x00030000, 778c2ecf20Sopenharmony_ci .ce_wrapper_base_address = 0x0004d000, 788c2ecf20Sopenharmony_ci .ce0_base_address = 0x0004a000, 798c2ecf20Sopenharmony_ci .ce1_base_address = 0x0004a400, 808c2ecf20Sopenharmony_ci .ce2_base_address = 0x0004a800, 818c2ecf20Sopenharmony_ci .ce3_base_address = 0x0004ac00, 828c2ecf20Sopenharmony_ci .ce4_base_address = 0x0004b000, 838c2ecf20Sopenharmony_ci .ce5_base_address = 0x0004b400, 848c2ecf20Sopenharmony_ci .ce6_base_address = 0x0004b800, 858c2ecf20Sopenharmony_ci .ce7_base_address = 0x0004bc00, 868c2ecf20Sopenharmony_ci /* Note: qca99x0 supports upto 12 Copy Engines. Other than address of 878c2ecf20Sopenharmony_ci * CE0 and CE1 no other copy engine is directly referred in the code. 888c2ecf20Sopenharmony_ci * It is not really necessary to assign address for newly supported 898c2ecf20Sopenharmony_ci * CEs in this address table. 908c2ecf20Sopenharmony_ci * Copy Engine Address 918c2ecf20Sopenharmony_ci * CE8 0x0004c000 928c2ecf20Sopenharmony_ci * CE9 0x0004c400 938c2ecf20Sopenharmony_ci * CE10 0x0004c800 948c2ecf20Sopenharmony_ci * CE11 0x0004cc00 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci .soc_reset_control_si0_rst_mask = 0x00000001, 978c2ecf20Sopenharmony_ci .soc_reset_control_ce_rst_mask = 0x00000100, 988c2ecf20Sopenharmony_ci .soc_chip_id_address = 0x000000ec, 998c2ecf20Sopenharmony_ci .scratch_3_address = 0x00040050, 1008c2ecf20Sopenharmony_ci .fw_indicator_address = 0x00040050, 1018c2ecf20Sopenharmony_ci .pcie_local_base_address = 0x00000000, 1028c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, 1038c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, 1048c2ecf20Sopenharmony_ci .pcie_intr_fw_mask = 0x00100000, 1058c2ecf20Sopenharmony_ci .pcie_intr_ce_mask_all = 0x000fff00, 1068c2ecf20Sopenharmony_ci .pcie_intr_clr_address = 0x00000010, 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciconst struct ath10k_hw_regs qca4019_regs = { 1108c2ecf20Sopenharmony_ci .rtc_soc_base_address = 0x00080000, 1118c2ecf20Sopenharmony_ci .soc_core_base_address = 0x00082000, 1128c2ecf20Sopenharmony_ci .wlan_mac_base_address = 0x00030000, 1138c2ecf20Sopenharmony_ci .ce_wrapper_base_address = 0x0004d000, 1148c2ecf20Sopenharmony_ci .ce0_base_address = 0x0004a000, 1158c2ecf20Sopenharmony_ci .ce1_base_address = 0x0004a400, 1168c2ecf20Sopenharmony_ci .ce2_base_address = 0x0004a800, 1178c2ecf20Sopenharmony_ci .ce3_base_address = 0x0004ac00, 1188c2ecf20Sopenharmony_ci .ce4_base_address = 0x0004b000, 1198c2ecf20Sopenharmony_ci .ce5_base_address = 0x0004b400, 1208c2ecf20Sopenharmony_ci .ce6_base_address = 0x0004b800, 1218c2ecf20Sopenharmony_ci .ce7_base_address = 0x0004bc00, 1228c2ecf20Sopenharmony_ci /* qca4019 supports upto 12 copy engines. Since base address 1238c2ecf20Sopenharmony_ci * of ce8 to ce11 are not directly referred in the code, 1248c2ecf20Sopenharmony_ci * no need have them in separate members in this table. 1258c2ecf20Sopenharmony_ci * Copy Engine Address 1268c2ecf20Sopenharmony_ci * CE8 0x0004c000 1278c2ecf20Sopenharmony_ci * CE9 0x0004c400 1288c2ecf20Sopenharmony_ci * CE10 0x0004c800 1298c2ecf20Sopenharmony_ci * CE11 0x0004cc00 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci .soc_reset_control_si0_rst_mask = 0x00000001, 1328c2ecf20Sopenharmony_ci .soc_reset_control_ce_rst_mask = 0x00000100, 1338c2ecf20Sopenharmony_ci .soc_chip_id_address = 0x000000ec, 1348c2ecf20Sopenharmony_ci .fw_indicator_address = 0x0004f00c, 1358c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, 1368c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, 1378c2ecf20Sopenharmony_ci .pcie_intr_fw_mask = 0x00100000, 1388c2ecf20Sopenharmony_ci .pcie_intr_ce_mask_all = 0x000fff00, 1398c2ecf20Sopenharmony_ci .pcie_intr_clr_address = 0x00000010, 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ciconst struct ath10k_hw_values qca988x_values = { 1438c2ecf20Sopenharmony_ci .rtc_state_val_on = 3, 1448c2ecf20Sopenharmony_ci .ce_count = 8, 1458c2ecf20Sopenharmony_ci .msi_assign_ce_max = 7, 1468c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 7, 1478c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFFC, 1488c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 2, 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciconst struct ath10k_hw_values qca6174_values = { 1528c2ecf20Sopenharmony_ci .rtc_state_val_on = 3, 1538c2ecf20Sopenharmony_ci .ce_count = 8, 1548c2ecf20Sopenharmony_ci .msi_assign_ce_max = 7, 1558c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 7, 1568c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFFC, 1578c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 2, 1588c2ecf20Sopenharmony_ci .rfkill_pin = 16, 1598c2ecf20Sopenharmony_ci .rfkill_cfg = 0, 1608c2ecf20Sopenharmony_ci .rfkill_on_level = 1, 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ciconst struct ath10k_hw_values qca99x0_values = { 1648c2ecf20Sopenharmony_ci .rtc_state_val_on = 7, 1658c2ecf20Sopenharmony_ci .ce_count = 12, 1668c2ecf20Sopenharmony_ci .msi_assign_ce_max = 12, 1678c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 10, 1688c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFF0, 1698c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 4, 1708c2ecf20Sopenharmony_ci}; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciconst struct ath10k_hw_values qca9888_values = { 1738c2ecf20Sopenharmony_ci .rtc_state_val_on = 3, 1748c2ecf20Sopenharmony_ci .ce_count = 12, 1758c2ecf20Sopenharmony_ci .msi_assign_ce_max = 12, 1768c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 10, 1778c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFF0, 1788c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 4, 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ciconst struct ath10k_hw_values qca4019_values = { 1828c2ecf20Sopenharmony_ci .ce_count = 12, 1838c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 10, 1848c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFF0, 1858c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 4, 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ciconst struct ath10k_hw_regs wcn3990_regs = { 1898c2ecf20Sopenharmony_ci .rtc_soc_base_address = 0x00000000, 1908c2ecf20Sopenharmony_ci .rtc_wmac_base_address = 0x00000000, 1918c2ecf20Sopenharmony_ci .soc_core_base_address = 0x00000000, 1928c2ecf20Sopenharmony_ci .ce_wrapper_base_address = 0x0024C000, 1938c2ecf20Sopenharmony_ci .ce0_base_address = 0x00240000, 1948c2ecf20Sopenharmony_ci .ce1_base_address = 0x00241000, 1958c2ecf20Sopenharmony_ci .ce2_base_address = 0x00242000, 1968c2ecf20Sopenharmony_ci .ce3_base_address = 0x00243000, 1978c2ecf20Sopenharmony_ci .ce4_base_address = 0x00244000, 1988c2ecf20Sopenharmony_ci .ce5_base_address = 0x00245000, 1998c2ecf20Sopenharmony_ci .ce6_base_address = 0x00246000, 2008c2ecf20Sopenharmony_ci .ce7_base_address = 0x00247000, 2018c2ecf20Sopenharmony_ci .ce8_base_address = 0x00248000, 2028c2ecf20Sopenharmony_ci .ce9_base_address = 0x00249000, 2038c2ecf20Sopenharmony_ci .ce10_base_address = 0x0024A000, 2048c2ecf20Sopenharmony_ci .ce11_base_address = 0x0024B000, 2058c2ecf20Sopenharmony_ci .soc_chip_id_address = 0x000000f0, 2068c2ecf20Sopenharmony_ci .soc_reset_control_si0_rst_mask = 0x00000001, 2078c2ecf20Sopenharmony_ci .soc_reset_control_ce_rst_mask = 0x00000100, 2088c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, 2098c2ecf20Sopenharmony_ci .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, 2108c2ecf20Sopenharmony_ci .pcie_intr_fw_mask = 0x00100000, 2118c2ecf20Sopenharmony_ci}; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = { 2148c2ecf20Sopenharmony_ci .msb = 0x00000010, 2158c2ecf20Sopenharmony_ci .lsb = 0x00000010, 2168c2ecf20Sopenharmony_ci .mask = GENMASK(17, 17), 2178c2ecf20Sopenharmony_ci}; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = { 2208c2ecf20Sopenharmony_ci .msb = 0x00000012, 2218c2ecf20Sopenharmony_ci .lsb = 0x00000012, 2228c2ecf20Sopenharmony_ci .mask = GENMASK(18, 18), 2238c2ecf20Sopenharmony_ci}; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = { 2268c2ecf20Sopenharmony_ci .msb = 0x00000000, 2278c2ecf20Sopenharmony_ci .lsb = 0x00000000, 2288c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 2298c2ecf20Sopenharmony_ci}; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = { 2328c2ecf20Sopenharmony_ci .addr = 0x00000018, 2338c2ecf20Sopenharmony_ci .src_ring = &wcn3990_src_ring, 2348c2ecf20Sopenharmony_ci .dst_ring = &wcn3990_dst_ring, 2358c2ecf20Sopenharmony_ci .dmax = &wcn3990_dmax, 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = { 2398c2ecf20Sopenharmony_ci .mask = GENMASK(0, 0), 2408c2ecf20Sopenharmony_ci}; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_host_ie wcn3990_host_ie = { 2438c2ecf20Sopenharmony_ci .copy_complete = &wcn3990_host_ie_cc, 2448c2ecf20Sopenharmony_ci}; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = { 2478c2ecf20Sopenharmony_ci .dstr_lmask = 0x00000010, 2488c2ecf20Sopenharmony_ci .dstr_hmask = 0x00000008, 2498c2ecf20Sopenharmony_ci .srcr_lmask = 0x00000004, 2508c2ecf20Sopenharmony_ci .srcr_hmask = 0x00000002, 2518c2ecf20Sopenharmony_ci .cc_mask = 0x00000001, 2528c2ecf20Sopenharmony_ci .wm_mask = 0x0000001E, 2538c2ecf20Sopenharmony_ci .addr = 0x00000030, 2548c2ecf20Sopenharmony_ci}; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = { 2578c2ecf20Sopenharmony_ci .axi_err = 0x00000100, 2588c2ecf20Sopenharmony_ci .dstr_add_err = 0x00000200, 2598c2ecf20Sopenharmony_ci .srcr_len_err = 0x00000100, 2608c2ecf20Sopenharmony_ci .dstr_mlen_vio = 0x00000080, 2618c2ecf20Sopenharmony_ci .dstr_overflow = 0x00000040, 2628c2ecf20Sopenharmony_ci .srcr_overflow = 0x00000020, 2638c2ecf20Sopenharmony_ci .err_mask = 0x000003E0, 2648c2ecf20Sopenharmony_ci .addr = 0x00000038, 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = { 2688c2ecf20Sopenharmony_ci .msb = 0x00000000, 2698c2ecf20Sopenharmony_ci .lsb = 0x00000010, 2708c2ecf20Sopenharmony_ci .mask = GENMASK(31, 16), 2718c2ecf20Sopenharmony_ci}; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = { 2748c2ecf20Sopenharmony_ci .msb = 0x0000000f, 2758c2ecf20Sopenharmony_ci .lsb = 0x00000000, 2768c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 2778c2ecf20Sopenharmony_ci}; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = { 2808c2ecf20Sopenharmony_ci .addr = 0x0000004c, 2818c2ecf20Sopenharmony_ci .low_rst = 0x00000000, 2828c2ecf20Sopenharmony_ci .high_rst = 0x00000000, 2838c2ecf20Sopenharmony_ci .wm_low = &wcn3990_src_wm_low, 2848c2ecf20Sopenharmony_ci .wm_high = &wcn3990_src_wm_high, 2858c2ecf20Sopenharmony_ci}; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = { 2888c2ecf20Sopenharmony_ci .lsb = 0x00000010, 2898c2ecf20Sopenharmony_ci .mask = GENMASK(31, 16), 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = { 2938c2ecf20Sopenharmony_ci .msb = 0x0000000f, 2948c2ecf20Sopenharmony_ci .lsb = 0x00000000, 2958c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { 2998c2ecf20Sopenharmony_ci .addr = 0x00000050, 3008c2ecf20Sopenharmony_ci .low_rst = 0x00000000, 3018c2ecf20Sopenharmony_ci .high_rst = 0x00000000, 3028c2ecf20Sopenharmony_ci .wm_low = &wcn3990_dst_wm_low, 3038c2ecf20Sopenharmony_ci .wm_high = &wcn3990_dst_wm_high, 3048c2ecf20Sopenharmony_ci}; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = { 3078c2ecf20Sopenharmony_ci .shift = 19, 3088c2ecf20Sopenharmony_ci .mask = 0x00080000, 3098c2ecf20Sopenharmony_ci .enable = 0x00000000, 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ciconst struct ath10k_hw_ce_regs wcn3990_ce_regs = { 3138c2ecf20Sopenharmony_ci .sr_base_addr_lo = 0x00000000, 3148c2ecf20Sopenharmony_ci .sr_base_addr_hi = 0x00000004, 3158c2ecf20Sopenharmony_ci .sr_size_addr = 0x00000008, 3168c2ecf20Sopenharmony_ci .dr_base_addr_lo = 0x0000000c, 3178c2ecf20Sopenharmony_ci .dr_base_addr_hi = 0x00000010, 3188c2ecf20Sopenharmony_ci .dr_size_addr = 0x00000014, 3198c2ecf20Sopenharmony_ci .misc_ie_addr = 0x00000034, 3208c2ecf20Sopenharmony_ci .sr_wr_index_addr = 0x0000003c, 3218c2ecf20Sopenharmony_ci .dst_wr_index_addr = 0x00000040, 3228c2ecf20Sopenharmony_ci .current_srri_addr = 0x00000044, 3238c2ecf20Sopenharmony_ci .current_drri_addr = 0x00000048, 3248c2ecf20Sopenharmony_ci .ce_rri_low = 0x0024C004, 3258c2ecf20Sopenharmony_ci .ce_rri_high = 0x0024C008, 3268c2ecf20Sopenharmony_ci .host_ie_addr = 0x0000002c, 3278c2ecf20Sopenharmony_ci .ctrl1_regs = &wcn3990_ctrl1, 3288c2ecf20Sopenharmony_ci .host_ie = &wcn3990_host_ie, 3298c2ecf20Sopenharmony_ci .wm_regs = &wcn3990_wm_reg, 3308c2ecf20Sopenharmony_ci .misc_regs = &wcn3990_misc_reg, 3318c2ecf20Sopenharmony_ci .wm_srcr = &wcn3990_wm_src_ring, 3328c2ecf20Sopenharmony_ci .wm_dstr = &wcn3990_wm_dst_ring, 3338c2ecf20Sopenharmony_ci .upd = &wcn3990_ctrl1_upd, 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ciconst struct ath10k_hw_values wcn3990_values = { 3378c2ecf20Sopenharmony_ci .rtc_state_val_on = 5, 3388c2ecf20Sopenharmony_ci .ce_count = 12, 3398c2ecf20Sopenharmony_ci .msi_assign_ce_max = 12, 3408c2ecf20Sopenharmony_ci .num_target_ce_config_wlan = 12, 3418c2ecf20Sopenharmony_ci .ce_desc_meta_data_mask = 0xFFF0, 3428c2ecf20Sopenharmony_ci .ce_desc_meta_data_lsb = 4, 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_src_ring = { 3468c2ecf20Sopenharmony_ci .msb = 0x00000010, 3478c2ecf20Sopenharmony_ci .lsb = 0x00000010, 3488c2ecf20Sopenharmony_ci .mask = GENMASK(16, 16), 3498c2ecf20Sopenharmony_ci}; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = { 3528c2ecf20Sopenharmony_ci .msb = 0x00000011, 3538c2ecf20Sopenharmony_ci .lsb = 0x00000011, 3548c2ecf20Sopenharmony_ci .mask = GENMASK(17, 17), 3558c2ecf20Sopenharmony_ci}; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_dmax = { 3588c2ecf20Sopenharmony_ci .msb = 0x0000000f, 3598c2ecf20Sopenharmony_ci .lsb = 0x00000000, 3608c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 3618c2ecf20Sopenharmony_ci}; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = { 3648c2ecf20Sopenharmony_ci .addr = 0x00000010, 3658c2ecf20Sopenharmony_ci .hw_mask = 0x0007ffff, 3668c2ecf20Sopenharmony_ci .sw_mask = 0x0007ffff, 3678c2ecf20Sopenharmony_ci .hw_wr_mask = 0x00000000, 3688c2ecf20Sopenharmony_ci .sw_wr_mask = 0x0007ffff, 3698c2ecf20Sopenharmony_ci .reset_mask = 0xffffffff, 3708c2ecf20Sopenharmony_ci .reset = 0x00000080, 3718c2ecf20Sopenharmony_ci .src_ring = &qcax_src_ring, 3728c2ecf20Sopenharmony_ci .dst_ring = &qcax_dst_ring, 3738c2ecf20Sopenharmony_ci .dmax = &qcax_dmax, 3748c2ecf20Sopenharmony_ci}; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = { 3778c2ecf20Sopenharmony_ci .msb = 0x00000003, 3788c2ecf20Sopenharmony_ci .lsb = 0x00000003, 3798c2ecf20Sopenharmony_ci .mask = GENMASK(3, 3), 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = { 3838c2ecf20Sopenharmony_ci .msb = 0x00000000, 3848c2ecf20Sopenharmony_ci .mask = GENMASK(0, 0), 3858c2ecf20Sopenharmony_ci .status_reset = 0x00000000, 3868c2ecf20Sopenharmony_ci .status = &qcax_cmd_halt_status, 3878c2ecf20Sopenharmony_ci}; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = { 3908c2ecf20Sopenharmony_ci .msb = 0x00000000, 3918c2ecf20Sopenharmony_ci .lsb = 0x00000000, 3928c2ecf20Sopenharmony_ci .mask = GENMASK(0, 0), 3938c2ecf20Sopenharmony_ci}; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_host_ie qcax_host_ie = { 3968c2ecf20Sopenharmony_ci .copy_complete_reset = 0x00000000, 3978c2ecf20Sopenharmony_ci .copy_complete = &qcax_host_ie_cc, 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = { 4018c2ecf20Sopenharmony_ci .dstr_lmask = 0x00000010, 4028c2ecf20Sopenharmony_ci .dstr_hmask = 0x00000008, 4038c2ecf20Sopenharmony_ci .srcr_lmask = 0x00000004, 4048c2ecf20Sopenharmony_ci .srcr_hmask = 0x00000002, 4058c2ecf20Sopenharmony_ci .cc_mask = 0x00000001, 4068c2ecf20Sopenharmony_ci .wm_mask = 0x0000001E, 4078c2ecf20Sopenharmony_ci .addr = 0x00000030, 4088c2ecf20Sopenharmony_ci}; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_misc_regs qcax_misc_reg = { 4118c2ecf20Sopenharmony_ci .axi_err = 0x00000400, 4128c2ecf20Sopenharmony_ci .dstr_add_err = 0x00000200, 4138c2ecf20Sopenharmony_ci .srcr_len_err = 0x00000100, 4148c2ecf20Sopenharmony_ci .dstr_mlen_vio = 0x00000080, 4158c2ecf20Sopenharmony_ci .dstr_overflow = 0x00000040, 4168c2ecf20Sopenharmony_ci .srcr_overflow = 0x00000020, 4178c2ecf20Sopenharmony_ci .err_mask = 0x000007E0, 4188c2ecf20Sopenharmony_ci .addr = 0x00000038, 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = { 4228c2ecf20Sopenharmony_ci .msb = 0x0000001f, 4238c2ecf20Sopenharmony_ci .lsb = 0x00000010, 4248c2ecf20Sopenharmony_ci .mask = GENMASK(31, 16), 4258c2ecf20Sopenharmony_ci}; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = { 4288c2ecf20Sopenharmony_ci .msb = 0x0000000f, 4298c2ecf20Sopenharmony_ci .lsb = 0x00000000, 4308c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 4318c2ecf20Sopenharmony_ci}; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = { 4348c2ecf20Sopenharmony_ci .addr = 0x0000004c, 4358c2ecf20Sopenharmony_ci .low_rst = 0x00000000, 4368c2ecf20Sopenharmony_ci .high_rst = 0x00000000, 4378c2ecf20Sopenharmony_ci .wm_low = &qcax_src_wm_low, 4388c2ecf20Sopenharmony_ci .wm_high = &qcax_src_wm_high, 4398c2ecf20Sopenharmony_ci}; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = { 4428c2ecf20Sopenharmony_ci .lsb = 0x00000010, 4438c2ecf20Sopenharmony_ci .mask = GENMASK(31, 16), 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = { 4478c2ecf20Sopenharmony_ci .msb = 0x0000000f, 4488c2ecf20Sopenharmony_ci .lsb = 0x00000000, 4498c2ecf20Sopenharmony_ci .mask = GENMASK(15, 0), 4508c2ecf20Sopenharmony_ci}; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = { 4538c2ecf20Sopenharmony_ci .addr = 0x00000050, 4548c2ecf20Sopenharmony_ci .low_rst = 0x00000000, 4558c2ecf20Sopenharmony_ci .high_rst = 0x00000000, 4568c2ecf20Sopenharmony_ci .wm_low = &qcax_dst_wm_low, 4578c2ecf20Sopenharmony_ci .wm_high = &qcax_dst_wm_high, 4588c2ecf20Sopenharmony_ci}; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ciconst struct ath10k_hw_ce_regs qcax_ce_regs = { 4618c2ecf20Sopenharmony_ci .sr_base_addr_lo = 0x00000000, 4628c2ecf20Sopenharmony_ci .sr_size_addr = 0x00000004, 4638c2ecf20Sopenharmony_ci .dr_base_addr_lo = 0x00000008, 4648c2ecf20Sopenharmony_ci .dr_size_addr = 0x0000000c, 4658c2ecf20Sopenharmony_ci .ce_cmd_addr = 0x00000018, 4668c2ecf20Sopenharmony_ci .misc_ie_addr = 0x00000034, 4678c2ecf20Sopenharmony_ci .sr_wr_index_addr = 0x0000003c, 4688c2ecf20Sopenharmony_ci .dst_wr_index_addr = 0x00000040, 4698c2ecf20Sopenharmony_ci .current_srri_addr = 0x00000044, 4708c2ecf20Sopenharmony_ci .current_drri_addr = 0x00000048, 4718c2ecf20Sopenharmony_ci .host_ie_addr = 0x0000002c, 4728c2ecf20Sopenharmony_ci .ctrl1_regs = &qcax_ctrl1, 4738c2ecf20Sopenharmony_ci .cmd_halt = &qcax_cmd_halt, 4748c2ecf20Sopenharmony_ci .host_ie = &qcax_host_ie, 4758c2ecf20Sopenharmony_ci .wm_regs = &qcax_wm_reg, 4768c2ecf20Sopenharmony_ci .misc_regs = &qcax_misc_reg, 4778c2ecf20Sopenharmony_ci .wm_srcr = &qcax_wm_src_ring, 4788c2ecf20Sopenharmony_ci .wm_dstr = &qcax_wm_dst_ring, 4798c2ecf20Sopenharmony_ci}; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ciconst struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = { 4828c2ecf20Sopenharmony_ci { 4838c2ecf20Sopenharmony_ci .refclk = 48000000, 4848c2ecf20Sopenharmony_ci .div = 0xe, 4858c2ecf20Sopenharmony_ci .rnfrac = 0x2aaa8, 4868c2ecf20Sopenharmony_ci .settle_time = 2400, 4878c2ecf20Sopenharmony_ci .refdiv = 0, 4888c2ecf20Sopenharmony_ci .outdiv = 1, 4898c2ecf20Sopenharmony_ci }, 4908c2ecf20Sopenharmony_ci { 4918c2ecf20Sopenharmony_ci .refclk = 19200000, 4928c2ecf20Sopenharmony_ci .div = 0x24, 4938c2ecf20Sopenharmony_ci .rnfrac = 0x2aaa8, 4948c2ecf20Sopenharmony_ci .settle_time = 960, 4958c2ecf20Sopenharmony_ci .refdiv = 0, 4968c2ecf20Sopenharmony_ci .outdiv = 1, 4978c2ecf20Sopenharmony_ci }, 4988c2ecf20Sopenharmony_ci { 4998c2ecf20Sopenharmony_ci .refclk = 24000000, 5008c2ecf20Sopenharmony_ci .div = 0x1d, 5018c2ecf20Sopenharmony_ci .rnfrac = 0x15551, 5028c2ecf20Sopenharmony_ci .settle_time = 1200, 5038c2ecf20Sopenharmony_ci .refdiv = 0, 5048c2ecf20Sopenharmony_ci .outdiv = 1, 5058c2ecf20Sopenharmony_ci }, 5068c2ecf20Sopenharmony_ci { 5078c2ecf20Sopenharmony_ci .refclk = 26000000, 5088c2ecf20Sopenharmony_ci .div = 0x1b, 5098c2ecf20Sopenharmony_ci .rnfrac = 0x4ec4, 5108c2ecf20Sopenharmony_ci .settle_time = 1300, 5118c2ecf20Sopenharmony_ci .refdiv = 0, 5128c2ecf20Sopenharmony_ci .outdiv = 1, 5138c2ecf20Sopenharmony_ci }, 5148c2ecf20Sopenharmony_ci { 5158c2ecf20Sopenharmony_ci .refclk = 37400000, 5168c2ecf20Sopenharmony_ci .div = 0x12, 5178c2ecf20Sopenharmony_ci .rnfrac = 0x34b49, 5188c2ecf20Sopenharmony_ci .settle_time = 1870, 5198c2ecf20Sopenharmony_ci .refdiv = 0, 5208c2ecf20Sopenharmony_ci .outdiv = 1, 5218c2ecf20Sopenharmony_ci }, 5228c2ecf20Sopenharmony_ci { 5238c2ecf20Sopenharmony_ci .refclk = 38400000, 5248c2ecf20Sopenharmony_ci .div = 0x12, 5258c2ecf20Sopenharmony_ci .rnfrac = 0x15551, 5268c2ecf20Sopenharmony_ci .settle_time = 1920, 5278c2ecf20Sopenharmony_ci .refdiv = 0, 5288c2ecf20Sopenharmony_ci .outdiv = 1, 5298c2ecf20Sopenharmony_ci }, 5308c2ecf20Sopenharmony_ci { 5318c2ecf20Sopenharmony_ci .refclk = 40000000, 5328c2ecf20Sopenharmony_ci .div = 0x12, 5338c2ecf20Sopenharmony_ci .rnfrac = 0x26665, 5348c2ecf20Sopenharmony_ci .settle_time = 2000, 5358c2ecf20Sopenharmony_ci .refdiv = 0, 5368c2ecf20Sopenharmony_ci .outdiv = 1, 5378c2ecf20Sopenharmony_ci }, 5388c2ecf20Sopenharmony_ci { 5398c2ecf20Sopenharmony_ci .refclk = 52000000, 5408c2ecf20Sopenharmony_ci .div = 0x1b, 5418c2ecf20Sopenharmony_ci .rnfrac = 0x4ec4, 5428c2ecf20Sopenharmony_ci .settle_time = 2600, 5438c2ecf20Sopenharmony_ci .refdiv = 0, 5448c2ecf20Sopenharmony_ci .outdiv = 1, 5458c2ecf20Sopenharmony_ci }, 5468c2ecf20Sopenharmony_ci}; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_civoid ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, 5498c2ecf20Sopenharmony_ci u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci u32 cc_fix = 0; 5528c2ecf20Sopenharmony_ci u32 rcc_fix = 0; 5538c2ecf20Sopenharmony_ci enum ath10k_hw_cc_wraparound_type wraparound_type; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci survey->filled |= SURVEY_INFO_TIME | 5568c2ecf20Sopenharmony_ci SURVEY_INFO_TIME_BUSY; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci wraparound_type = ar->hw_params.cc_wraparound_type; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (cc < cc_prev || rcc < rcc_prev) { 5618c2ecf20Sopenharmony_ci switch (wraparound_type) { 5628c2ecf20Sopenharmony_ci case ATH10K_HW_CC_WRAP_SHIFTED_ALL: 5638c2ecf20Sopenharmony_ci if (cc < cc_prev) { 5648c2ecf20Sopenharmony_ci cc_fix = 0x7fffffff; 5658c2ecf20Sopenharmony_ci survey->filled &= ~SURVEY_INFO_TIME_BUSY; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci case ATH10K_HW_CC_WRAP_SHIFTED_EACH: 5698c2ecf20Sopenharmony_ci if (cc < cc_prev) 5708c2ecf20Sopenharmony_ci cc_fix = 0x7fffffff; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci if (rcc < rcc_prev) 5738c2ecf20Sopenharmony_ci rcc_fix = 0x7fffffff; 5748c2ecf20Sopenharmony_ci break; 5758c2ecf20Sopenharmony_ci case ATH10K_HW_CC_WRAP_DISABLED: 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci cc -= cc_prev - cc_fix; 5818c2ecf20Sopenharmony_ci rcc -= rcc_prev - rcc_fix; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci survey->time = CCNT_TO_MSEC(ar, cc); 5848c2ecf20Sopenharmony_ci survey->time_busy = CCNT_TO_MSEC(ar, rcc); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/* The firmware does not support setting the coverage class. Instead this 5888c2ecf20Sopenharmony_ci * function monitors and modifies the corresponding MAC registers. 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_cistatic void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar, 5918c2ecf20Sopenharmony_ci s16 value) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci u32 slottime_reg; 5948c2ecf20Sopenharmony_ci u32 slottime; 5958c2ecf20Sopenharmony_ci u32 timeout_reg; 5968c2ecf20Sopenharmony_ci u32 ack_timeout; 5978c2ecf20Sopenharmony_ci u32 cts_timeout; 5988c2ecf20Sopenharmony_ci u32 phyclk_reg; 5998c2ecf20Sopenharmony_ci u32 phyclk; 6008c2ecf20Sopenharmony_ci u64 fw_dbglog_mask; 6018c2ecf20Sopenharmony_ci u32 fw_dbglog_level; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci mutex_lock(&ar->conf_mutex); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci /* Only modify registers if the core is started. */ 6068c2ecf20Sopenharmony_ci if ((ar->state != ATH10K_STATE_ON) && 6078c2ecf20Sopenharmony_ci (ar->state != ATH10K_STATE_RESTARTED)) { 6088c2ecf20Sopenharmony_ci spin_lock_bh(&ar->data_lock); 6098c2ecf20Sopenharmony_ci /* Store config value for when radio boots up */ 6108c2ecf20Sopenharmony_ci ar->fw_coverage.coverage_class = value; 6118c2ecf20Sopenharmony_ci spin_unlock_bh(&ar->data_lock); 6128c2ecf20Sopenharmony_ci goto unlock; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* Retrieve the current values of the two registers that need to be 6168c2ecf20Sopenharmony_ci * adjusted. 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_ci slottime_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + 6198c2ecf20Sopenharmony_ci WAVE1_PCU_GBL_IFS_SLOT); 6208c2ecf20Sopenharmony_ci timeout_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + 6218c2ecf20Sopenharmony_ci WAVE1_PCU_ACK_CTS_TIMEOUT); 6228c2ecf20Sopenharmony_ci phyclk_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS + 6238c2ecf20Sopenharmony_ci WAVE1_PHYCLK); 6248c2ecf20Sopenharmony_ci phyclk = MS(phyclk_reg, WAVE1_PHYCLK_USEC) + 1; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci if (value < 0) 6278c2ecf20Sopenharmony_ci value = ar->fw_coverage.coverage_class; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* Break out if the coverage class and registers have the expected 6308c2ecf20Sopenharmony_ci * value. 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ci if (value == ar->fw_coverage.coverage_class && 6338c2ecf20Sopenharmony_ci slottime_reg == ar->fw_coverage.reg_slottime_conf && 6348c2ecf20Sopenharmony_ci timeout_reg == ar->fw_coverage.reg_ack_cts_timeout_conf && 6358c2ecf20Sopenharmony_ci phyclk_reg == ar->fw_coverage.reg_phyclk) 6368c2ecf20Sopenharmony_ci goto unlock; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* Store new initial register values from the firmware. */ 6398c2ecf20Sopenharmony_ci if (slottime_reg != ar->fw_coverage.reg_slottime_conf) 6408c2ecf20Sopenharmony_ci ar->fw_coverage.reg_slottime_orig = slottime_reg; 6418c2ecf20Sopenharmony_ci if (timeout_reg != ar->fw_coverage.reg_ack_cts_timeout_conf) 6428c2ecf20Sopenharmony_ci ar->fw_coverage.reg_ack_cts_timeout_orig = timeout_reg; 6438c2ecf20Sopenharmony_ci ar->fw_coverage.reg_phyclk = phyclk_reg; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* Calculate new value based on the (original) firmware calculation. */ 6468c2ecf20Sopenharmony_ci slottime_reg = ar->fw_coverage.reg_slottime_orig; 6478c2ecf20Sopenharmony_ci timeout_reg = ar->fw_coverage.reg_ack_cts_timeout_orig; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* Do some sanity checks on the slottime register. */ 6508c2ecf20Sopenharmony_ci if (slottime_reg % phyclk) { 6518c2ecf20Sopenharmony_ci ath10k_warn(ar, 6528c2ecf20Sopenharmony_ci "failed to set coverage class: expected integer microsecond value in register\n"); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci goto store_regs; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT); 6588c2ecf20Sopenharmony_ci slottime = slottime / phyclk; 6598c2ecf20Sopenharmony_ci if (slottime != 9 && slottime != 20) { 6608c2ecf20Sopenharmony_ci ath10k_warn(ar, 6618c2ecf20Sopenharmony_ci "failed to set coverage class: expected slot time of 9 or 20us in HW register. It is %uus.\n", 6628c2ecf20Sopenharmony_ci slottime); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci goto store_regs; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci /* Recalculate the register values by adding the additional propagation 6688c2ecf20Sopenharmony_ci * delay (3us per coverage class). 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT); 6728c2ecf20Sopenharmony_ci slottime += value * 3 * phyclk; 6738c2ecf20Sopenharmony_ci slottime = min_t(u32, slottime, WAVE1_PCU_GBL_IFS_SLOT_MAX); 6748c2ecf20Sopenharmony_ci slottime = SM(slottime, WAVE1_PCU_GBL_IFS_SLOT); 6758c2ecf20Sopenharmony_ci slottime_reg = (slottime_reg & ~WAVE1_PCU_GBL_IFS_SLOT_MASK) | slottime; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci /* Update ack timeout (lower halfword). */ 6788c2ecf20Sopenharmony_ci ack_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK); 6798c2ecf20Sopenharmony_ci ack_timeout += 3 * value * phyclk; 6808c2ecf20Sopenharmony_ci ack_timeout = min_t(u32, ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX); 6818c2ecf20Sopenharmony_ci ack_timeout = SM(ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci /* Update cts timeout (upper halfword). */ 6848c2ecf20Sopenharmony_ci cts_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS); 6858c2ecf20Sopenharmony_ci cts_timeout += 3 * value * phyclk; 6868c2ecf20Sopenharmony_ci cts_timeout = min_t(u32, cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX); 6878c2ecf20Sopenharmony_ci cts_timeout = SM(cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci timeout_reg = ack_timeout | cts_timeout; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci ath10k_hif_write32(ar, 6928c2ecf20Sopenharmony_ci WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_GBL_IFS_SLOT, 6938c2ecf20Sopenharmony_ci slottime_reg); 6948c2ecf20Sopenharmony_ci ath10k_hif_write32(ar, 6958c2ecf20Sopenharmony_ci WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_ACK_CTS_TIMEOUT, 6968c2ecf20Sopenharmony_ci timeout_reg); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci /* Ensure we have a debug level of WARN set for the case that the 6998c2ecf20Sopenharmony_ci * coverage class is larger than 0. This is important as we need to 7008c2ecf20Sopenharmony_ci * set the registers again if the firmware does an internal reset and 7018c2ecf20Sopenharmony_ci * this way we will be notified of the event. 7028c2ecf20Sopenharmony_ci */ 7038c2ecf20Sopenharmony_ci fw_dbglog_mask = ath10k_debug_get_fw_dbglog_mask(ar); 7048c2ecf20Sopenharmony_ci fw_dbglog_level = ath10k_debug_get_fw_dbglog_level(ar); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci if (value > 0) { 7078c2ecf20Sopenharmony_ci if (fw_dbglog_level > ATH10K_DBGLOG_LEVEL_WARN) 7088c2ecf20Sopenharmony_ci fw_dbglog_level = ATH10K_DBGLOG_LEVEL_WARN; 7098c2ecf20Sopenharmony_ci fw_dbglog_mask = ~0; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci ath10k_wmi_dbglog_cfg(ar, fw_dbglog_mask, fw_dbglog_level); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistore_regs: 7158c2ecf20Sopenharmony_ci /* After an error we will not retry setting the coverage class. */ 7168c2ecf20Sopenharmony_ci spin_lock_bh(&ar->data_lock); 7178c2ecf20Sopenharmony_ci ar->fw_coverage.coverage_class = value; 7188c2ecf20Sopenharmony_ci spin_unlock_bh(&ar->data_lock); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci ar->fw_coverage.reg_slottime_conf = slottime_reg; 7218c2ecf20Sopenharmony_ci ar->fw_coverage.reg_ack_cts_timeout_conf = timeout_reg; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ciunlock: 7248c2ecf20Sopenharmony_ci mutex_unlock(&ar->conf_mutex); 7258c2ecf20Sopenharmony_ci} 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci/** 7288c2ecf20Sopenharmony_ci * ath10k_hw_qca6174_enable_pll_clock() - enable the qca6174 hw pll clock 7298c2ecf20Sopenharmony_ci * @ar: the ath10k blob 7308c2ecf20Sopenharmony_ci * 7318c2ecf20Sopenharmony_ci * This function is very hardware specific, the clock initialization 7328c2ecf20Sopenharmony_ci * steps is very sensitive and could lead to unknown crash, so they 7338c2ecf20Sopenharmony_ci * should be done in sequence. 7348c2ecf20Sopenharmony_ci * 7358c2ecf20Sopenharmony_ci * *** Be aware if you planned to refactor them. *** 7368c2ecf20Sopenharmony_ci * 7378c2ecf20Sopenharmony_ci * Return: 0 if successfully enable the pll, otherwise EINVAL 7388c2ecf20Sopenharmony_ci */ 7398c2ecf20Sopenharmony_cistatic int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci int ret, wait_limit; 7428c2ecf20Sopenharmony_ci u32 clk_div_addr, pll_init_addr, speed_addr; 7438c2ecf20Sopenharmony_ci u32 addr, reg_val, mem_val; 7448c2ecf20Sopenharmony_ci struct ath10k_hw_params *hw; 7458c2ecf20Sopenharmony_ci const struct ath10k_hw_clk_params *hw_clk; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci hw = &ar->hw_params; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci if (ar->regs->core_clk_div_address == 0 || 7508c2ecf20Sopenharmony_ci ar->regs->cpu_pll_init_address == 0 || 7518c2ecf20Sopenharmony_ci ar->regs->cpu_speed_address == 0) 7528c2ecf20Sopenharmony_ci return -EINVAL; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci clk_div_addr = ar->regs->core_clk_div_address; 7558c2ecf20Sopenharmony_ci pll_init_addr = ar->regs->cpu_pll_init_address; 7568c2ecf20Sopenharmony_ci speed_addr = ar->regs->cpu_speed_address; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* Read efuse register to find out the right hw clock configuration */ 7598c2ecf20Sopenharmony_ci addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET); 7608c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 7618c2ecf20Sopenharmony_ci if (ret) 7628c2ecf20Sopenharmony_ci return -EINVAL; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* sanitize if the hw refclk index is out of the boundary */ 7658c2ecf20Sopenharmony_ci if (MS(reg_val, EFUSE_XTAL_SEL) > ATH10K_HW_REFCLK_COUNT) 7668c2ecf20Sopenharmony_ci return -EINVAL; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci hw_clk = &hw->hw_clk[MS(reg_val, EFUSE_XTAL_SEL)]; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /* Set the rnfrac and outdiv params to bb_pll register */ 7718c2ecf20Sopenharmony_ci addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET); 7728c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 7738c2ecf20Sopenharmony_ci if (ret) 7748c2ecf20Sopenharmony_ci return -EINVAL; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK); 7778c2ecf20Sopenharmony_ci reg_val |= (SM(hw_clk->rnfrac, BB_PLL_CONFIG_FRAC) | 7788c2ecf20Sopenharmony_ci SM(hw_clk->outdiv, BB_PLL_CONFIG_OUTDIV)); 7798c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 7808c2ecf20Sopenharmony_ci if (ret) 7818c2ecf20Sopenharmony_ci return -EINVAL; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* Set the correct settle time value to pll_settle register */ 7848c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET); 7858c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 7868c2ecf20Sopenharmony_ci if (ret) 7878c2ecf20Sopenharmony_ci return -EINVAL; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK; 7908c2ecf20Sopenharmony_ci reg_val |= SM(hw_clk->settle_time, WLAN_PLL_SETTLE_TIME); 7918c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 7928c2ecf20Sopenharmony_ci if (ret) 7938c2ecf20Sopenharmony_ci return -EINVAL; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* Set the clock_ctrl div to core_clk_ctrl register */ 7968c2ecf20Sopenharmony_ci addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET); 7978c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 7988c2ecf20Sopenharmony_ci if (ret) 7998c2ecf20Sopenharmony_ci return -EINVAL; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK; 8028c2ecf20Sopenharmony_ci reg_val |= SM(1, SOC_CORE_CLK_CTRL_DIV); 8038c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 8048c2ecf20Sopenharmony_ci if (ret) 8058c2ecf20Sopenharmony_ci return -EINVAL; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci /* Set the clock_div register */ 8088c2ecf20Sopenharmony_ci mem_val = 1; 8098c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_memory(ar, clk_div_addr, &mem_val, 8108c2ecf20Sopenharmony_ci sizeof(mem_val)); 8118c2ecf20Sopenharmony_ci if (ret) 8128c2ecf20Sopenharmony_ci return -EINVAL; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci /* Configure the pll_control register */ 8158c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); 8168c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8178c2ecf20Sopenharmony_ci if (ret) 8188c2ecf20Sopenharmony_ci return -EINVAL; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) | 8218c2ecf20Sopenharmony_ci SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) | 8228c2ecf20Sopenharmony_ci SM(1, WLAN_PLL_CONTROL_NOPWD)); 8238c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 8248c2ecf20Sopenharmony_ci if (ret) 8258c2ecf20Sopenharmony_ci return -EINVAL; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci /* busy wait (max 1s) the rtc_sync status register indicate ready */ 8288c2ecf20Sopenharmony_ci wait_limit = 100000; 8298c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET); 8308c2ecf20Sopenharmony_ci do { 8318c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8328c2ecf20Sopenharmony_ci if (ret) 8338c2ecf20Sopenharmony_ci return -EINVAL; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING)) 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci wait_limit--; 8398c2ecf20Sopenharmony_ci udelay(10); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci } while (wait_limit > 0); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING)) 8448c2ecf20Sopenharmony_ci return -EINVAL; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci /* Unset the pll_bypass in pll_control register */ 8478c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); 8488c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8498c2ecf20Sopenharmony_ci if (ret) 8508c2ecf20Sopenharmony_ci return -EINVAL; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK; 8538c2ecf20Sopenharmony_ci reg_val |= SM(0, WLAN_PLL_CONTROL_BYPASS); 8548c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 8558c2ecf20Sopenharmony_ci if (ret) 8568c2ecf20Sopenharmony_ci return -EINVAL; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci /* busy wait (max 1s) the rtc_sync status register indicate ready */ 8598c2ecf20Sopenharmony_ci wait_limit = 100000; 8608c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET); 8618c2ecf20Sopenharmony_ci do { 8628c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8638c2ecf20Sopenharmony_ci if (ret) 8648c2ecf20Sopenharmony_ci return -EINVAL; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING)) 8678c2ecf20Sopenharmony_ci break; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci wait_limit--; 8708c2ecf20Sopenharmony_ci udelay(10); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci } while (wait_limit > 0); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING)) 8758c2ecf20Sopenharmony_ci return -EINVAL; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* Enable the hardware cpu clock register */ 8788c2ecf20Sopenharmony_ci addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET); 8798c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8808c2ecf20Sopenharmony_ci if (ret) 8818c2ecf20Sopenharmony_ci return -EINVAL; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK; 8848c2ecf20Sopenharmony_ci reg_val |= SM(1, SOC_CPU_CLOCK_STANDARD); 8858c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 8868c2ecf20Sopenharmony_ci if (ret) 8878c2ecf20Sopenharmony_ci return -EINVAL; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci /* unset the nopwd from pll_control register */ 8908c2ecf20Sopenharmony_ci addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); 8918c2ecf20Sopenharmony_ci ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val); 8928c2ecf20Sopenharmony_ci if (ret) 8938c2ecf20Sopenharmony_ci return -EINVAL; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK; 8968c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val); 8978c2ecf20Sopenharmony_ci if (ret) 8988c2ecf20Sopenharmony_ci return -EINVAL; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* enable the pll_init register */ 9018c2ecf20Sopenharmony_ci mem_val = 1; 9028c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_memory(ar, pll_init_addr, &mem_val, 9038c2ecf20Sopenharmony_ci sizeof(mem_val)); 9048c2ecf20Sopenharmony_ci if (ret) 9058c2ecf20Sopenharmony_ci return -EINVAL; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci /* set the target clock frequency to speed register */ 9088c2ecf20Sopenharmony_ci ret = ath10k_bmi_write_memory(ar, speed_addr, &hw->target_cpu_freq, 9098c2ecf20Sopenharmony_ci sizeof(hw->target_cpu_freq)); 9108c2ecf20Sopenharmony_ci if (ret) 9118c2ecf20Sopenharmony_ci return -EINVAL; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci return 0; 9148c2ecf20Sopenharmony_ci} 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci/* Program CPU_ADDR_MSB to allow different memory 9178c2ecf20Sopenharmony_ci * region access. 9188c2ecf20Sopenharmony_ci */ 9198c2ecf20Sopenharmony_cistatic void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb) 9208c2ecf20Sopenharmony_ci{ 9218c2ecf20Sopenharmony_ci u32 address = SOC_CORE_BASE_ADDRESS + FW_RAM_CONFIG_ADDRESS; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci ath10k_hif_write32(ar, address, msb); 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci/* 1. Write to memory region of target, such as IRAM adn DRAM. 9278c2ecf20Sopenharmony_ci * 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000) 9288c2ecf20Sopenharmony_ci * can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too. 9298c2ecf20Sopenharmony_ci * 3. In order to access the region other than the above, 9308c2ecf20Sopenharmony_ci * we need to set the value of register CPU_ADDR_MSB. 9318c2ecf20Sopenharmony_ci * 4. Target memory access space is limited to 1M size. If the size is larger 9328c2ecf20Sopenharmony_ci * than 1M, need to split it and program CPU_ADDR_MSB accordingly. 9338c2ecf20Sopenharmony_ci */ 9348c2ecf20Sopenharmony_cistatic int ath10k_hw_diag_segment_msb_download(struct ath10k *ar, 9358c2ecf20Sopenharmony_ci const void *buffer, 9368c2ecf20Sopenharmony_ci u32 address, 9378c2ecf20Sopenharmony_ci u32 length) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci u32 addr = address & REGION_ACCESS_SIZE_MASK; 9408c2ecf20Sopenharmony_ci int ret, remain_size, size; 9418c2ecf20Sopenharmony_ci const u8 *buf; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci ath10k_hw_map_target_mem(ar, CPU_ADDR_MSB_REGION_VAL(address)); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci if (addr + length > REGION_ACCESS_SIZE_LIMIT) { 9468c2ecf20Sopenharmony_ci size = REGION_ACCESS_SIZE_LIMIT - addr; 9478c2ecf20Sopenharmony_ci remain_size = length - size; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci ret = ath10k_hif_diag_write(ar, address, buffer, size); 9508c2ecf20Sopenharmony_ci if (ret) { 9518c2ecf20Sopenharmony_ci ath10k_warn(ar, 9528c2ecf20Sopenharmony_ci "failed to download the first %d bytes segment to address:0x%x: %d\n", 9538c2ecf20Sopenharmony_ci size, address, ret); 9548c2ecf20Sopenharmony_ci goto done; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci /* Change msb to the next memory region*/ 9588c2ecf20Sopenharmony_ci ath10k_hw_map_target_mem(ar, 9598c2ecf20Sopenharmony_ci CPU_ADDR_MSB_REGION_VAL(address) + 1); 9608c2ecf20Sopenharmony_ci buf = buffer + size; 9618c2ecf20Sopenharmony_ci ret = ath10k_hif_diag_write(ar, 9628c2ecf20Sopenharmony_ci address & ~REGION_ACCESS_SIZE_MASK, 9638c2ecf20Sopenharmony_ci buf, remain_size); 9648c2ecf20Sopenharmony_ci if (ret) { 9658c2ecf20Sopenharmony_ci ath10k_warn(ar, 9668c2ecf20Sopenharmony_ci "failed to download the second %d bytes segment to address:0x%x: %d\n", 9678c2ecf20Sopenharmony_ci remain_size, 9688c2ecf20Sopenharmony_ci address & ~REGION_ACCESS_SIZE_MASK, 9698c2ecf20Sopenharmony_ci ret); 9708c2ecf20Sopenharmony_ci goto done; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } else { 9738c2ecf20Sopenharmony_ci ret = ath10k_hif_diag_write(ar, address, buffer, length); 9748c2ecf20Sopenharmony_ci if (ret) { 9758c2ecf20Sopenharmony_ci ath10k_warn(ar, 9768c2ecf20Sopenharmony_ci "failed to download the only %d bytes segment to address:0x%x: %d\n", 9778c2ecf20Sopenharmony_ci length, address, ret); 9788c2ecf20Sopenharmony_ci goto done; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cidone: 9838c2ecf20Sopenharmony_ci /* Change msb to DRAM */ 9848c2ecf20Sopenharmony_ci ath10k_hw_map_target_mem(ar, 9858c2ecf20Sopenharmony_ci CPU_ADDR_MSB_REGION_VAL(DRAM_BASE_ADDRESS)); 9868c2ecf20Sopenharmony_ci return ret; 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_cistatic int ath10k_hw_diag_segment_download(struct ath10k *ar, 9908c2ecf20Sopenharmony_ci const void *buffer, 9918c2ecf20Sopenharmony_ci u32 address, 9928c2ecf20Sopenharmony_ci u32 length) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci if (address >= DRAM_BASE_ADDRESS + REGION_ACCESS_SIZE_LIMIT) 9958c2ecf20Sopenharmony_ci /* Needs to change MSB for memory write */ 9968c2ecf20Sopenharmony_ci return ath10k_hw_diag_segment_msb_download(ar, buffer, 9978c2ecf20Sopenharmony_ci address, length); 9988c2ecf20Sopenharmony_ci else 9998c2ecf20Sopenharmony_ci return ath10k_hif_diag_write(ar, address, buffer, length); 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ciint ath10k_hw_diag_fast_download(struct ath10k *ar, 10038c2ecf20Sopenharmony_ci u32 address, 10048c2ecf20Sopenharmony_ci const void *buffer, 10058c2ecf20Sopenharmony_ci u32 length) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci const u8 *buf = buffer; 10088c2ecf20Sopenharmony_ci bool sgmt_end = false; 10098c2ecf20Sopenharmony_ci u32 base_addr = 0; 10108c2ecf20Sopenharmony_ci u32 base_len = 0; 10118c2ecf20Sopenharmony_ci u32 left = 0; 10128c2ecf20Sopenharmony_ci struct bmi_segmented_file_header *hdr; 10138c2ecf20Sopenharmony_ci struct bmi_segmented_metadata *metadata; 10148c2ecf20Sopenharmony_ci int ret = 0; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (length < sizeof(*hdr)) 10178c2ecf20Sopenharmony_ci return -EINVAL; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci /* check firmware header. If it has no correct magic number 10208c2ecf20Sopenharmony_ci * or it's compressed, returns error. 10218c2ecf20Sopenharmony_ci */ 10228c2ecf20Sopenharmony_ci hdr = (struct bmi_segmented_file_header *)buf; 10238c2ecf20Sopenharmony_ci if (__le32_to_cpu(hdr->magic_num) != BMI_SGMTFILE_MAGIC_NUM) { 10248c2ecf20Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, 10258c2ecf20Sopenharmony_ci "Not a supported firmware, magic_num:0x%x\n", 10268c2ecf20Sopenharmony_ci hdr->magic_num); 10278c2ecf20Sopenharmony_ci return -EINVAL; 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci if (hdr->file_flags != 0) { 10318c2ecf20Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, 10328c2ecf20Sopenharmony_ci "Not a supported firmware, file_flags:0x%x\n", 10338c2ecf20Sopenharmony_ci hdr->file_flags); 10348c2ecf20Sopenharmony_ci return -EINVAL; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci metadata = (struct bmi_segmented_metadata *)hdr->data; 10388c2ecf20Sopenharmony_ci left = length - sizeof(*hdr); 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci while (left > 0) { 10418c2ecf20Sopenharmony_ci if (left < sizeof(*metadata)) { 10428c2ecf20Sopenharmony_ci ath10k_warn(ar, "firmware segment is truncated: %d\n", 10438c2ecf20Sopenharmony_ci left); 10448c2ecf20Sopenharmony_ci ret = -EINVAL; 10458c2ecf20Sopenharmony_ci break; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci base_addr = __le32_to_cpu(metadata->addr); 10488c2ecf20Sopenharmony_ci base_len = __le32_to_cpu(metadata->length); 10498c2ecf20Sopenharmony_ci buf = metadata->data; 10508c2ecf20Sopenharmony_ci left -= sizeof(*metadata); 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci switch (base_len) { 10538c2ecf20Sopenharmony_ci case BMI_SGMTFILE_BEGINADDR: 10548c2ecf20Sopenharmony_ci /* base_addr is the start address to run */ 10558c2ecf20Sopenharmony_ci ret = ath10k_bmi_set_start(ar, base_addr); 10568c2ecf20Sopenharmony_ci base_len = 0; 10578c2ecf20Sopenharmony_ci break; 10588c2ecf20Sopenharmony_ci case BMI_SGMTFILE_DONE: 10598c2ecf20Sopenharmony_ci /* no more segment */ 10608c2ecf20Sopenharmony_ci base_len = 0; 10618c2ecf20Sopenharmony_ci sgmt_end = true; 10628c2ecf20Sopenharmony_ci ret = 0; 10638c2ecf20Sopenharmony_ci break; 10648c2ecf20Sopenharmony_ci case BMI_SGMTFILE_BDDATA: 10658c2ecf20Sopenharmony_ci case BMI_SGMTFILE_EXEC: 10668c2ecf20Sopenharmony_ci ath10k_warn(ar, 10678c2ecf20Sopenharmony_ci "firmware has unsupported segment:%d\n", 10688c2ecf20Sopenharmony_ci base_len); 10698c2ecf20Sopenharmony_ci ret = -EINVAL; 10708c2ecf20Sopenharmony_ci break; 10718c2ecf20Sopenharmony_ci default: 10728c2ecf20Sopenharmony_ci if (base_len > left) { 10738c2ecf20Sopenharmony_ci /* sanity check */ 10748c2ecf20Sopenharmony_ci ath10k_warn(ar, 10758c2ecf20Sopenharmony_ci "firmware has invalid segment length, %d > %d\n", 10768c2ecf20Sopenharmony_ci base_len, left); 10778c2ecf20Sopenharmony_ci ret = -EINVAL; 10788c2ecf20Sopenharmony_ci break; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci ret = ath10k_hw_diag_segment_download(ar, 10828c2ecf20Sopenharmony_ci buf, 10838c2ecf20Sopenharmony_ci base_addr, 10848c2ecf20Sopenharmony_ci base_len); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (ret) 10878c2ecf20Sopenharmony_ci ath10k_warn(ar, 10888c2ecf20Sopenharmony_ci "failed to download firmware via diag interface:%d\n", 10898c2ecf20Sopenharmony_ci ret); 10908c2ecf20Sopenharmony_ci break; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci if (ret || sgmt_end) 10948c2ecf20Sopenharmony_ci break; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci metadata = (struct bmi_segmented_metadata *)(buf + base_len); 10978c2ecf20Sopenharmony_ci left -= base_len; 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (ret == 0) 11018c2ecf20Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, 11028c2ecf20Sopenharmony_ci "boot firmware fast diag download successfully.\n"); 11038c2ecf20Sopenharmony_ci return ret; 11048c2ecf20Sopenharmony_ci} 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_cistatic int ath10k_htt_tx_rssi_enable(struct htt_resp *resp) 11078c2ecf20Sopenharmony_ci{ 11088c2ecf20Sopenharmony_ci return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI); 11098c2ecf20Sopenharmony_ci} 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_cistatic int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp) 11128c2ecf20Sopenharmony_ci{ 11138c2ecf20Sopenharmony_ci return (resp->data_tx_completion.flags2 & 11148c2ecf20Sopenharmony_ci HTT_TX_DATA_RSSI_ENABLE_WCN3990); 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_cistatic int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci struct htt_data_tx_completion_ext extd; 11208c2ecf20Sopenharmony_ci int pad_bytes = 0; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES) 11238c2ecf20Sopenharmony_ci pad_bytes += sizeof(extd.a_retries) / 11248c2ecf20Sopenharmony_ci sizeof(extd.msdus_rssi[0]); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP) 11278c2ecf20Sopenharmony_ci pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci return pad_bytes; 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ciconst struct ath10k_hw_ops qca988x_ops = { 11338c2ecf20Sopenharmony_ci .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, 11348c2ecf20Sopenharmony_ci .is_rssi_enable = ath10k_htt_tx_rssi_enable, 11358c2ecf20Sopenharmony_ci}; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_cistatic int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci return MS(__le32_to_cpu(rxd->msdu_end.qca99x0.info1), 11408c2ecf20Sopenharmony_ci RX_MSDU_END_INFO1_L3_HDR_PAD); 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci return !!(rxd->msdu_end.common.info0 & 11468c2ecf20Sopenharmony_ci __cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR)); 11478c2ecf20Sopenharmony_ci} 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ciconst struct ath10k_hw_ops qca99x0_ops = { 11508c2ecf20Sopenharmony_ci .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes, 11518c2ecf20Sopenharmony_ci .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error, 11528c2ecf20Sopenharmony_ci .is_rssi_enable = ath10k_htt_tx_rssi_enable, 11538c2ecf20Sopenharmony_ci}; 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ciconst struct ath10k_hw_ops qca6174_ops = { 11568c2ecf20Sopenharmony_ci .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, 11578c2ecf20Sopenharmony_ci .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, 11588c2ecf20Sopenharmony_ci .is_rssi_enable = ath10k_htt_tx_rssi_enable, 11598c2ecf20Sopenharmony_ci}; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ciconst struct ath10k_hw_ops qca6174_sdio_ops = { 11628c2ecf20Sopenharmony_ci .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, 11638c2ecf20Sopenharmony_ci}; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ciconst struct ath10k_hw_ops wcn3990_ops = { 11668c2ecf20Sopenharmony_ci .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad, 11678c2ecf20Sopenharmony_ci .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990, 11688c2ecf20Sopenharmony_ci}; 1169