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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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