1da8fa4e3SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2da8fa4e3SBjoern A. Zeeb /*
3da8fa4e3SBjoern A. Zeeb * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
4da8fa4e3SBjoern A. Zeeb */
5da8fa4e3SBjoern A. Zeeb
6da8fa4e3SBjoern A. Zeeb #include <linux/types.h>
7da8fa4e3SBjoern A. Zeeb #include <linux/bitops.h>
8da8fa4e3SBjoern A. Zeeb #include <linux/bitfield.h>
9da8fa4e3SBjoern A. Zeeb #if defined(__FreeBSD__)
10da8fa4e3SBjoern A. Zeeb #include <linux/delay.h>
11da8fa4e3SBjoern A. Zeeb #endif
12da8fa4e3SBjoern A. Zeeb #include "core.h"
13da8fa4e3SBjoern A. Zeeb #include "hw.h"
14da8fa4e3SBjoern A. Zeeb #include "hif.h"
15da8fa4e3SBjoern A. Zeeb #include "wmi-ops.h"
16da8fa4e3SBjoern A. Zeeb #include "bmi.h"
17da8fa4e3SBjoern A. Zeeb #include "rx_desc.h"
18da8fa4e3SBjoern A. Zeeb
19da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_regs qca988x_regs = {
20da8fa4e3SBjoern A. Zeeb .rtc_soc_base_address = 0x00004000,
21da8fa4e3SBjoern A. Zeeb .rtc_wmac_base_address = 0x00005000,
22da8fa4e3SBjoern A. Zeeb .soc_core_base_address = 0x00009000,
23da8fa4e3SBjoern A. Zeeb .wlan_mac_base_address = 0x00020000,
24da8fa4e3SBjoern A. Zeeb .ce_wrapper_base_address = 0x00057000,
25da8fa4e3SBjoern A. Zeeb .ce0_base_address = 0x00057400,
26da8fa4e3SBjoern A. Zeeb .ce1_base_address = 0x00057800,
27da8fa4e3SBjoern A. Zeeb .ce2_base_address = 0x00057c00,
28da8fa4e3SBjoern A. Zeeb .ce3_base_address = 0x00058000,
29da8fa4e3SBjoern A. Zeeb .ce4_base_address = 0x00058400,
30da8fa4e3SBjoern A. Zeeb .ce5_base_address = 0x00058800,
31da8fa4e3SBjoern A. Zeeb .ce6_base_address = 0x00058c00,
32da8fa4e3SBjoern A. Zeeb .ce7_base_address = 0x00059000,
33da8fa4e3SBjoern A. Zeeb .soc_reset_control_si0_rst_mask = 0x00000001,
34da8fa4e3SBjoern A. Zeeb .soc_reset_control_ce_rst_mask = 0x00040000,
35da8fa4e3SBjoern A. Zeeb .soc_chip_id_address = 0x000000ec,
36da8fa4e3SBjoern A. Zeeb .scratch_3_address = 0x00000030,
37da8fa4e3SBjoern A. Zeeb .fw_indicator_address = 0x00009030,
38da8fa4e3SBjoern A. Zeeb .pcie_local_base_address = 0x00080000,
39da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_lsb = 0x00000008,
40da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_mask = 0x0000ff00,
41da8fa4e3SBjoern A. Zeeb .pcie_intr_fw_mask = 0x00000400,
42da8fa4e3SBjoern A. Zeeb .pcie_intr_ce_mask_all = 0x0007f800,
43da8fa4e3SBjoern A. Zeeb .pcie_intr_clr_address = 0x00000014,
44da8fa4e3SBjoern A. Zeeb };
45da8fa4e3SBjoern A. Zeeb
46da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_regs qca6174_regs = {
47da8fa4e3SBjoern A. Zeeb .rtc_soc_base_address = 0x00000800,
48da8fa4e3SBjoern A. Zeeb .rtc_wmac_base_address = 0x00001000,
49da8fa4e3SBjoern A. Zeeb .soc_core_base_address = 0x0003a000,
50da8fa4e3SBjoern A. Zeeb .wlan_mac_base_address = 0x00010000,
51da8fa4e3SBjoern A. Zeeb .ce_wrapper_base_address = 0x00034000,
52da8fa4e3SBjoern A. Zeeb .ce0_base_address = 0x00034400,
53da8fa4e3SBjoern A. Zeeb .ce1_base_address = 0x00034800,
54da8fa4e3SBjoern A. Zeeb .ce2_base_address = 0x00034c00,
55da8fa4e3SBjoern A. Zeeb .ce3_base_address = 0x00035000,
56da8fa4e3SBjoern A. Zeeb .ce4_base_address = 0x00035400,
57da8fa4e3SBjoern A. Zeeb .ce5_base_address = 0x00035800,
58da8fa4e3SBjoern A. Zeeb .ce6_base_address = 0x00035c00,
59da8fa4e3SBjoern A. Zeeb .ce7_base_address = 0x00036000,
60da8fa4e3SBjoern A. Zeeb .soc_reset_control_si0_rst_mask = 0x00000000,
61da8fa4e3SBjoern A. Zeeb .soc_reset_control_ce_rst_mask = 0x00000001,
62da8fa4e3SBjoern A. Zeeb .soc_chip_id_address = 0x000000f0,
63da8fa4e3SBjoern A. Zeeb .scratch_3_address = 0x00000028,
64da8fa4e3SBjoern A. Zeeb .fw_indicator_address = 0x0003a028,
65da8fa4e3SBjoern A. Zeeb .pcie_local_base_address = 0x00080000,
66da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_lsb = 0x00000008,
67da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_mask = 0x0000ff00,
68da8fa4e3SBjoern A. Zeeb .pcie_intr_fw_mask = 0x00000400,
69da8fa4e3SBjoern A. Zeeb .pcie_intr_ce_mask_all = 0x0007f800,
70da8fa4e3SBjoern A. Zeeb .pcie_intr_clr_address = 0x00000014,
71da8fa4e3SBjoern A. Zeeb .cpu_pll_init_address = 0x00404020,
72da8fa4e3SBjoern A. Zeeb .cpu_speed_address = 0x00404024,
73da8fa4e3SBjoern A. Zeeb .core_clk_div_address = 0x00404028,
74da8fa4e3SBjoern A. Zeeb };
75da8fa4e3SBjoern A. Zeeb
76da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_regs qca99x0_regs = {
77da8fa4e3SBjoern A. Zeeb .rtc_soc_base_address = 0x00080000,
78da8fa4e3SBjoern A. Zeeb .rtc_wmac_base_address = 0x00000000,
79da8fa4e3SBjoern A. Zeeb .soc_core_base_address = 0x00082000,
80da8fa4e3SBjoern A. Zeeb .wlan_mac_base_address = 0x00030000,
81da8fa4e3SBjoern A. Zeeb .ce_wrapper_base_address = 0x0004d000,
82da8fa4e3SBjoern A. Zeeb .ce0_base_address = 0x0004a000,
83da8fa4e3SBjoern A. Zeeb .ce1_base_address = 0x0004a400,
84da8fa4e3SBjoern A. Zeeb .ce2_base_address = 0x0004a800,
85da8fa4e3SBjoern A. Zeeb .ce3_base_address = 0x0004ac00,
86da8fa4e3SBjoern A. Zeeb .ce4_base_address = 0x0004b000,
87da8fa4e3SBjoern A. Zeeb .ce5_base_address = 0x0004b400,
88da8fa4e3SBjoern A. Zeeb .ce6_base_address = 0x0004b800,
89da8fa4e3SBjoern A. Zeeb .ce7_base_address = 0x0004bc00,
90da8fa4e3SBjoern A. Zeeb /* Note: qca99x0 supports up to 12 Copy Engines. Other than address of
91da8fa4e3SBjoern A. Zeeb * CE0 and CE1 no other copy engine is directly referred in the code.
92da8fa4e3SBjoern A. Zeeb * It is not really necessary to assign address for newly supported
93da8fa4e3SBjoern A. Zeeb * CEs in this address table.
94da8fa4e3SBjoern A. Zeeb * Copy Engine Address
95da8fa4e3SBjoern A. Zeeb * CE8 0x0004c000
96da8fa4e3SBjoern A. Zeeb * CE9 0x0004c400
97da8fa4e3SBjoern A. Zeeb * CE10 0x0004c800
98da8fa4e3SBjoern A. Zeeb * CE11 0x0004cc00
99da8fa4e3SBjoern A. Zeeb */
100da8fa4e3SBjoern A. Zeeb .soc_reset_control_si0_rst_mask = 0x00000001,
101da8fa4e3SBjoern A. Zeeb .soc_reset_control_ce_rst_mask = 0x00000100,
102da8fa4e3SBjoern A. Zeeb .soc_chip_id_address = 0x000000ec,
103da8fa4e3SBjoern A. Zeeb .scratch_3_address = 0x00040050,
104da8fa4e3SBjoern A. Zeeb .fw_indicator_address = 0x00040050,
105da8fa4e3SBjoern A. Zeeb .pcie_local_base_address = 0x00000000,
106da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
107da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
108da8fa4e3SBjoern A. Zeeb .pcie_intr_fw_mask = 0x00100000,
109da8fa4e3SBjoern A. Zeeb .pcie_intr_ce_mask_all = 0x000fff00,
110da8fa4e3SBjoern A. Zeeb .pcie_intr_clr_address = 0x00000010,
111da8fa4e3SBjoern A. Zeeb };
112da8fa4e3SBjoern A. Zeeb
113da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_regs qca4019_regs = {
114da8fa4e3SBjoern A. Zeeb .rtc_soc_base_address = 0x00080000,
115da8fa4e3SBjoern A. Zeeb .soc_core_base_address = 0x00082000,
116da8fa4e3SBjoern A. Zeeb .wlan_mac_base_address = 0x00030000,
117da8fa4e3SBjoern A. Zeeb .ce_wrapper_base_address = 0x0004d000,
118da8fa4e3SBjoern A. Zeeb .ce0_base_address = 0x0004a000,
119da8fa4e3SBjoern A. Zeeb .ce1_base_address = 0x0004a400,
120da8fa4e3SBjoern A. Zeeb .ce2_base_address = 0x0004a800,
121da8fa4e3SBjoern A. Zeeb .ce3_base_address = 0x0004ac00,
122da8fa4e3SBjoern A. Zeeb .ce4_base_address = 0x0004b000,
123da8fa4e3SBjoern A. Zeeb .ce5_base_address = 0x0004b400,
124da8fa4e3SBjoern A. Zeeb .ce6_base_address = 0x0004b800,
125da8fa4e3SBjoern A. Zeeb .ce7_base_address = 0x0004bc00,
126da8fa4e3SBjoern A. Zeeb /* qca4019 supports up to 12 copy engines. Since base address
127da8fa4e3SBjoern A. Zeeb * of ce8 to ce11 are not directly referred in the code,
128da8fa4e3SBjoern A. Zeeb * no need have them in separate members in this table.
129da8fa4e3SBjoern A. Zeeb * Copy Engine Address
130da8fa4e3SBjoern A. Zeeb * CE8 0x0004c000
131da8fa4e3SBjoern A. Zeeb * CE9 0x0004c400
132da8fa4e3SBjoern A. Zeeb * CE10 0x0004c800
133da8fa4e3SBjoern A. Zeeb * CE11 0x0004cc00
134da8fa4e3SBjoern A. Zeeb */
135da8fa4e3SBjoern A. Zeeb .soc_reset_control_si0_rst_mask = 0x00000001,
136da8fa4e3SBjoern A. Zeeb .soc_reset_control_ce_rst_mask = 0x00000100,
137da8fa4e3SBjoern A. Zeeb .soc_chip_id_address = 0x000000ec,
138da8fa4e3SBjoern A. Zeeb .fw_indicator_address = 0x0004f00c,
139da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
140da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
141da8fa4e3SBjoern A. Zeeb .pcie_intr_fw_mask = 0x00100000,
142da8fa4e3SBjoern A. Zeeb .pcie_intr_ce_mask_all = 0x000fff00,
143da8fa4e3SBjoern A. Zeeb .pcie_intr_clr_address = 0x00000010,
144da8fa4e3SBjoern A. Zeeb };
145da8fa4e3SBjoern A. Zeeb
146da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values qca988x_values = {
147da8fa4e3SBjoern A. Zeeb .rtc_state_val_on = 3,
148da8fa4e3SBjoern A. Zeeb .ce_count = 8,
149da8fa4e3SBjoern A. Zeeb .msi_assign_ce_max = 7,
150da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 7,
151da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFFC,
152da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 2,
153da8fa4e3SBjoern A. Zeeb };
154da8fa4e3SBjoern A. Zeeb
155da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values qca6174_values = {
156da8fa4e3SBjoern A. Zeeb .rtc_state_val_on = 3,
157da8fa4e3SBjoern A. Zeeb .ce_count = 8,
158da8fa4e3SBjoern A. Zeeb .msi_assign_ce_max = 7,
159da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 7,
160da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFFC,
161da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 2,
162da8fa4e3SBjoern A. Zeeb .rfkill_pin = 16,
163da8fa4e3SBjoern A. Zeeb .rfkill_cfg = 0,
164da8fa4e3SBjoern A. Zeeb .rfkill_on_level = 1,
165da8fa4e3SBjoern A. Zeeb };
166da8fa4e3SBjoern A. Zeeb
167da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values qca99x0_values = {
168da8fa4e3SBjoern A. Zeeb .rtc_state_val_on = 7,
169da8fa4e3SBjoern A. Zeeb .ce_count = 12,
170da8fa4e3SBjoern A. Zeeb .msi_assign_ce_max = 12,
171da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 10,
172da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFF0,
173da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 4,
174da8fa4e3SBjoern A. Zeeb };
175da8fa4e3SBjoern A. Zeeb
176da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values qca9888_values = {
177da8fa4e3SBjoern A. Zeeb .rtc_state_val_on = 3,
178da8fa4e3SBjoern A. Zeeb .ce_count = 12,
179da8fa4e3SBjoern A. Zeeb .msi_assign_ce_max = 12,
180da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 10,
181da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFF0,
182da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 4,
183da8fa4e3SBjoern A. Zeeb };
184da8fa4e3SBjoern A. Zeeb
185da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values qca4019_values = {
186da8fa4e3SBjoern A. Zeeb .ce_count = 12,
187da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 10,
188da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFF0,
189da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 4,
190da8fa4e3SBjoern A. Zeeb };
191da8fa4e3SBjoern A. Zeeb
192da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_regs wcn3990_regs = {
193da8fa4e3SBjoern A. Zeeb .rtc_soc_base_address = 0x00000000,
194da8fa4e3SBjoern A. Zeeb .rtc_wmac_base_address = 0x00000000,
195da8fa4e3SBjoern A. Zeeb .soc_core_base_address = 0x00000000,
196da8fa4e3SBjoern A. Zeeb .ce_wrapper_base_address = 0x0024C000,
197da8fa4e3SBjoern A. Zeeb .ce0_base_address = 0x00240000,
198da8fa4e3SBjoern A. Zeeb .ce1_base_address = 0x00241000,
199da8fa4e3SBjoern A. Zeeb .ce2_base_address = 0x00242000,
200da8fa4e3SBjoern A. Zeeb .ce3_base_address = 0x00243000,
201da8fa4e3SBjoern A. Zeeb .ce4_base_address = 0x00244000,
202da8fa4e3SBjoern A. Zeeb .ce5_base_address = 0x00245000,
203da8fa4e3SBjoern A. Zeeb .ce6_base_address = 0x00246000,
204da8fa4e3SBjoern A. Zeeb .ce7_base_address = 0x00247000,
205da8fa4e3SBjoern A. Zeeb .ce8_base_address = 0x00248000,
206da8fa4e3SBjoern A. Zeeb .ce9_base_address = 0x00249000,
207da8fa4e3SBjoern A. Zeeb .ce10_base_address = 0x0024A000,
208da8fa4e3SBjoern A. Zeeb .ce11_base_address = 0x0024B000,
209da8fa4e3SBjoern A. Zeeb .soc_chip_id_address = 0x000000f0,
210da8fa4e3SBjoern A. Zeeb .soc_reset_control_si0_rst_mask = 0x00000001,
211da8fa4e3SBjoern A. Zeeb .soc_reset_control_ce_rst_mask = 0x00000100,
212da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
213da8fa4e3SBjoern A. Zeeb .ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
214da8fa4e3SBjoern A. Zeeb .pcie_intr_fw_mask = 0x00100000,
215da8fa4e3SBjoern A. Zeeb };
216da8fa4e3SBjoern A. Zeeb
217da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = {
218da8fa4e3SBjoern A. Zeeb .msb = 0x00000010,
219da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
220da8fa4e3SBjoern A. Zeeb .mask = GENMASK(17, 17),
221da8fa4e3SBjoern A. Zeeb };
222da8fa4e3SBjoern A. Zeeb
223da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = {
224da8fa4e3SBjoern A. Zeeb .msb = 0x00000012,
225da8fa4e3SBjoern A. Zeeb .lsb = 0x00000012,
226da8fa4e3SBjoern A. Zeeb .mask = GENMASK(18, 18),
227da8fa4e3SBjoern A. Zeeb };
228da8fa4e3SBjoern A. Zeeb
229da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = {
230da8fa4e3SBjoern A. Zeeb .msb = 0x00000000,
231da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
232da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
233da8fa4e3SBjoern A. Zeeb };
234da8fa4e3SBjoern A. Zeeb
235da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = {
236da8fa4e3SBjoern A. Zeeb .addr = 0x00000018,
237da8fa4e3SBjoern A. Zeeb .src_ring = &wcn3990_src_ring,
238da8fa4e3SBjoern A. Zeeb .dst_ring = &wcn3990_dst_ring,
239da8fa4e3SBjoern A. Zeeb .dmax = &wcn3990_dmax,
240da8fa4e3SBjoern A. Zeeb };
241da8fa4e3SBjoern A. Zeeb
242da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = {
243da8fa4e3SBjoern A. Zeeb .mask = GENMASK(0, 0),
244da8fa4e3SBjoern A. Zeeb };
245da8fa4e3SBjoern A. Zeeb
246da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_host_ie wcn3990_host_ie = {
247da8fa4e3SBjoern A. Zeeb .copy_complete = &wcn3990_host_ie_cc,
248da8fa4e3SBjoern A. Zeeb };
249da8fa4e3SBjoern A. Zeeb
250da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = {
251da8fa4e3SBjoern A. Zeeb .dstr_lmask = 0x00000010,
252da8fa4e3SBjoern A. Zeeb .dstr_hmask = 0x00000008,
253da8fa4e3SBjoern A. Zeeb .srcr_lmask = 0x00000004,
254da8fa4e3SBjoern A. Zeeb .srcr_hmask = 0x00000002,
255da8fa4e3SBjoern A. Zeeb .cc_mask = 0x00000001,
256da8fa4e3SBjoern A. Zeeb .wm_mask = 0x0000001E,
257da8fa4e3SBjoern A. Zeeb .addr = 0x00000030,
258da8fa4e3SBjoern A. Zeeb };
259da8fa4e3SBjoern A. Zeeb
260da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = {
261da8fa4e3SBjoern A. Zeeb .axi_err = 0x00000100,
262da8fa4e3SBjoern A. Zeeb .dstr_add_err = 0x00000200,
263da8fa4e3SBjoern A. Zeeb .srcr_len_err = 0x00000100,
264da8fa4e3SBjoern A. Zeeb .dstr_mlen_vio = 0x00000080,
265da8fa4e3SBjoern A. Zeeb .dstr_overflow = 0x00000040,
266da8fa4e3SBjoern A. Zeeb .srcr_overflow = 0x00000020,
267da8fa4e3SBjoern A. Zeeb .err_mask = 0x000003E0,
268da8fa4e3SBjoern A. Zeeb .addr = 0x00000038,
269da8fa4e3SBjoern A. Zeeb };
270da8fa4e3SBjoern A. Zeeb
271da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = {
272da8fa4e3SBjoern A. Zeeb .msb = 0x00000000,
273da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
274da8fa4e3SBjoern A. Zeeb .mask = GENMASK(31, 16),
275da8fa4e3SBjoern A. Zeeb };
276da8fa4e3SBjoern A. Zeeb
277da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = {
278da8fa4e3SBjoern A. Zeeb .msb = 0x0000000f,
279da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
280da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
281da8fa4e3SBjoern A. Zeeb };
282da8fa4e3SBjoern A. Zeeb
283da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = {
284da8fa4e3SBjoern A. Zeeb .addr = 0x0000004c,
285da8fa4e3SBjoern A. Zeeb .low_rst = 0x00000000,
286da8fa4e3SBjoern A. Zeeb .high_rst = 0x00000000,
287da8fa4e3SBjoern A. Zeeb .wm_low = &wcn3990_src_wm_low,
288da8fa4e3SBjoern A. Zeeb .wm_high = &wcn3990_src_wm_high,
289da8fa4e3SBjoern A. Zeeb };
290da8fa4e3SBjoern A. Zeeb
291da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = {
292da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
293da8fa4e3SBjoern A. Zeeb .mask = GENMASK(31, 16),
294da8fa4e3SBjoern A. Zeeb };
295da8fa4e3SBjoern A. Zeeb
296da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = {
297da8fa4e3SBjoern A. Zeeb .msb = 0x0000000f,
298da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
299da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
300da8fa4e3SBjoern A. Zeeb };
301da8fa4e3SBjoern A. Zeeb
302da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = {
303da8fa4e3SBjoern A. Zeeb .addr = 0x00000050,
304da8fa4e3SBjoern A. Zeeb .low_rst = 0x00000000,
305da8fa4e3SBjoern A. Zeeb .high_rst = 0x00000000,
306da8fa4e3SBjoern A. Zeeb .wm_low = &wcn3990_dst_wm_low,
307da8fa4e3SBjoern A. Zeeb .wm_high = &wcn3990_dst_wm_high,
308da8fa4e3SBjoern A. Zeeb };
309da8fa4e3SBjoern A. Zeeb
310da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = {
311da8fa4e3SBjoern A. Zeeb .shift = 19,
312da8fa4e3SBjoern A. Zeeb .mask = 0x00080000,
313da8fa4e3SBjoern A. Zeeb .enable = 0x00000000,
314da8fa4e3SBjoern A. Zeeb };
315da8fa4e3SBjoern A. Zeeb
316da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ce_regs wcn3990_ce_regs = {
317da8fa4e3SBjoern A. Zeeb .sr_base_addr_lo = 0x00000000,
318da8fa4e3SBjoern A. Zeeb .sr_base_addr_hi = 0x00000004,
319da8fa4e3SBjoern A. Zeeb .sr_size_addr = 0x00000008,
320da8fa4e3SBjoern A. Zeeb .dr_base_addr_lo = 0x0000000c,
321da8fa4e3SBjoern A. Zeeb .dr_base_addr_hi = 0x00000010,
322da8fa4e3SBjoern A. Zeeb .dr_size_addr = 0x00000014,
323da8fa4e3SBjoern A. Zeeb .misc_ie_addr = 0x00000034,
324da8fa4e3SBjoern A. Zeeb .sr_wr_index_addr = 0x0000003c,
325da8fa4e3SBjoern A. Zeeb .dst_wr_index_addr = 0x00000040,
326da8fa4e3SBjoern A. Zeeb .current_srri_addr = 0x00000044,
327da8fa4e3SBjoern A. Zeeb .current_drri_addr = 0x00000048,
328da8fa4e3SBjoern A. Zeeb .ce_rri_low = 0x0024C004,
329da8fa4e3SBjoern A. Zeeb .ce_rri_high = 0x0024C008,
330da8fa4e3SBjoern A. Zeeb .host_ie_addr = 0x0000002c,
331da8fa4e3SBjoern A. Zeeb .ctrl1_regs = &wcn3990_ctrl1,
332da8fa4e3SBjoern A. Zeeb .host_ie = &wcn3990_host_ie,
333da8fa4e3SBjoern A. Zeeb .wm_regs = &wcn3990_wm_reg,
334da8fa4e3SBjoern A. Zeeb .misc_regs = &wcn3990_misc_reg,
335da8fa4e3SBjoern A. Zeeb .wm_srcr = &wcn3990_wm_src_ring,
336da8fa4e3SBjoern A. Zeeb .wm_dstr = &wcn3990_wm_dst_ring,
337da8fa4e3SBjoern A. Zeeb .upd = &wcn3990_ctrl1_upd,
338da8fa4e3SBjoern A. Zeeb };
339da8fa4e3SBjoern A. Zeeb
340da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_values wcn3990_values = {
341da8fa4e3SBjoern A. Zeeb .rtc_state_val_on = 5,
342da8fa4e3SBjoern A. Zeeb .ce_count = 12,
343da8fa4e3SBjoern A. Zeeb .msi_assign_ce_max = 12,
344da8fa4e3SBjoern A. Zeeb .num_target_ce_config_wlan = 12,
345da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_mask = 0xFFF0,
346da8fa4e3SBjoern A. Zeeb .ce_desc_meta_data_lsb = 4,
347da8fa4e3SBjoern A. Zeeb };
348da8fa4e3SBjoern A. Zeeb
349da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
350da8fa4e3SBjoern A. Zeeb .msb = 0x00000010,
351da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
352da8fa4e3SBjoern A. Zeeb .mask = GENMASK(16, 16),
353da8fa4e3SBjoern A. Zeeb };
354da8fa4e3SBjoern A. Zeeb
355da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
356da8fa4e3SBjoern A. Zeeb .msb = 0x00000011,
357da8fa4e3SBjoern A. Zeeb .lsb = 0x00000011,
358da8fa4e3SBjoern A. Zeeb .mask = GENMASK(17, 17),
359da8fa4e3SBjoern A. Zeeb };
360da8fa4e3SBjoern A. Zeeb
361da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
362da8fa4e3SBjoern A. Zeeb .msb = 0x0000000f,
363da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
364da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
365da8fa4e3SBjoern A. Zeeb };
366da8fa4e3SBjoern A. Zeeb
367da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
368da8fa4e3SBjoern A. Zeeb .addr = 0x00000010,
369da8fa4e3SBjoern A. Zeeb .hw_mask = 0x0007ffff,
370da8fa4e3SBjoern A. Zeeb .sw_mask = 0x0007ffff,
371da8fa4e3SBjoern A. Zeeb .hw_wr_mask = 0x00000000,
372da8fa4e3SBjoern A. Zeeb .sw_wr_mask = 0x0007ffff,
373da8fa4e3SBjoern A. Zeeb .reset_mask = 0xffffffff,
374da8fa4e3SBjoern A. Zeeb .reset = 0x00000080,
375da8fa4e3SBjoern A. Zeeb .src_ring = &qcax_src_ring,
376da8fa4e3SBjoern A. Zeeb .dst_ring = &qcax_dst_ring,
377da8fa4e3SBjoern A. Zeeb .dmax = &qcax_dmax,
378da8fa4e3SBjoern A. Zeeb };
379da8fa4e3SBjoern A. Zeeb
380da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
381da8fa4e3SBjoern A. Zeeb .msb = 0x00000003,
382da8fa4e3SBjoern A. Zeeb .lsb = 0x00000003,
383da8fa4e3SBjoern A. Zeeb .mask = GENMASK(3, 3),
384da8fa4e3SBjoern A. Zeeb };
385da8fa4e3SBjoern A. Zeeb
386da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
387da8fa4e3SBjoern A. Zeeb .msb = 0x00000000,
388da8fa4e3SBjoern A. Zeeb .mask = GENMASK(0, 0),
389da8fa4e3SBjoern A. Zeeb .status_reset = 0x00000000,
390da8fa4e3SBjoern A. Zeeb .status = &qcax_cmd_halt_status,
391da8fa4e3SBjoern A. Zeeb };
392da8fa4e3SBjoern A. Zeeb
393da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
394da8fa4e3SBjoern A. Zeeb .msb = 0x00000000,
395da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
396da8fa4e3SBjoern A. Zeeb .mask = GENMASK(0, 0),
397da8fa4e3SBjoern A. Zeeb };
398da8fa4e3SBjoern A. Zeeb
399da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_host_ie qcax_host_ie = {
400da8fa4e3SBjoern A. Zeeb .copy_complete_reset = 0x00000000,
401da8fa4e3SBjoern A. Zeeb .copy_complete = &qcax_host_ie_cc,
402da8fa4e3SBjoern A. Zeeb };
403da8fa4e3SBjoern A. Zeeb
404da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
405da8fa4e3SBjoern A. Zeeb .dstr_lmask = 0x00000010,
406da8fa4e3SBjoern A. Zeeb .dstr_hmask = 0x00000008,
407da8fa4e3SBjoern A. Zeeb .srcr_lmask = 0x00000004,
408da8fa4e3SBjoern A. Zeeb .srcr_hmask = 0x00000002,
409da8fa4e3SBjoern A. Zeeb .cc_mask = 0x00000001,
410da8fa4e3SBjoern A. Zeeb .wm_mask = 0x0000001E,
411da8fa4e3SBjoern A. Zeeb .addr = 0x00000030,
412da8fa4e3SBjoern A. Zeeb };
413da8fa4e3SBjoern A. Zeeb
414da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
415da8fa4e3SBjoern A. Zeeb .axi_err = 0x00000400,
416da8fa4e3SBjoern A. Zeeb .dstr_add_err = 0x00000200,
417da8fa4e3SBjoern A. Zeeb .srcr_len_err = 0x00000100,
418da8fa4e3SBjoern A. Zeeb .dstr_mlen_vio = 0x00000080,
419da8fa4e3SBjoern A. Zeeb .dstr_overflow = 0x00000040,
420da8fa4e3SBjoern A. Zeeb .srcr_overflow = 0x00000020,
421da8fa4e3SBjoern A. Zeeb .err_mask = 0x000007E0,
422da8fa4e3SBjoern A. Zeeb .addr = 0x00000038,
423da8fa4e3SBjoern A. Zeeb };
424da8fa4e3SBjoern A. Zeeb
425da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
426da8fa4e3SBjoern A. Zeeb .msb = 0x0000001f,
427da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
428da8fa4e3SBjoern A. Zeeb .mask = GENMASK(31, 16),
429da8fa4e3SBjoern A. Zeeb };
430da8fa4e3SBjoern A. Zeeb
431da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
432da8fa4e3SBjoern A. Zeeb .msb = 0x0000000f,
433da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
434da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
435da8fa4e3SBjoern A. Zeeb };
436da8fa4e3SBjoern A. Zeeb
437da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
438da8fa4e3SBjoern A. Zeeb .addr = 0x0000004c,
439da8fa4e3SBjoern A. Zeeb .low_rst = 0x00000000,
440da8fa4e3SBjoern A. Zeeb .high_rst = 0x00000000,
441da8fa4e3SBjoern A. Zeeb .wm_low = &qcax_src_wm_low,
442da8fa4e3SBjoern A. Zeeb .wm_high = &qcax_src_wm_high,
443da8fa4e3SBjoern A. Zeeb };
444da8fa4e3SBjoern A. Zeeb
445da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
446da8fa4e3SBjoern A. Zeeb .lsb = 0x00000010,
447da8fa4e3SBjoern A. Zeeb .mask = GENMASK(31, 16),
448da8fa4e3SBjoern A. Zeeb };
449da8fa4e3SBjoern A. Zeeb
450da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
451da8fa4e3SBjoern A. Zeeb .msb = 0x0000000f,
452da8fa4e3SBjoern A. Zeeb .lsb = 0x00000000,
453da8fa4e3SBjoern A. Zeeb .mask = GENMASK(15, 0),
454da8fa4e3SBjoern A. Zeeb };
455da8fa4e3SBjoern A. Zeeb
456da8fa4e3SBjoern A. Zeeb static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
457da8fa4e3SBjoern A. Zeeb .addr = 0x00000050,
458da8fa4e3SBjoern A. Zeeb .low_rst = 0x00000000,
459da8fa4e3SBjoern A. Zeeb .high_rst = 0x00000000,
460da8fa4e3SBjoern A. Zeeb .wm_low = &qcax_dst_wm_low,
461da8fa4e3SBjoern A. Zeeb .wm_high = &qcax_dst_wm_high,
462da8fa4e3SBjoern A. Zeeb };
463da8fa4e3SBjoern A. Zeeb
464da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ce_regs qcax_ce_regs = {
465da8fa4e3SBjoern A. Zeeb .sr_base_addr_lo = 0x00000000,
466da8fa4e3SBjoern A. Zeeb .sr_size_addr = 0x00000004,
467da8fa4e3SBjoern A. Zeeb .dr_base_addr_lo = 0x00000008,
468da8fa4e3SBjoern A. Zeeb .dr_size_addr = 0x0000000c,
469da8fa4e3SBjoern A. Zeeb .ce_cmd_addr = 0x00000018,
470da8fa4e3SBjoern A. Zeeb .misc_ie_addr = 0x00000034,
471da8fa4e3SBjoern A. Zeeb .sr_wr_index_addr = 0x0000003c,
472da8fa4e3SBjoern A. Zeeb .dst_wr_index_addr = 0x00000040,
473da8fa4e3SBjoern A. Zeeb .current_srri_addr = 0x00000044,
474da8fa4e3SBjoern A. Zeeb .current_drri_addr = 0x00000048,
475da8fa4e3SBjoern A. Zeeb .host_ie_addr = 0x0000002c,
476da8fa4e3SBjoern A. Zeeb .ctrl1_regs = &qcax_ctrl1,
477da8fa4e3SBjoern A. Zeeb .cmd_halt = &qcax_cmd_halt,
478da8fa4e3SBjoern A. Zeeb .host_ie = &qcax_host_ie,
479da8fa4e3SBjoern A. Zeeb .wm_regs = &qcax_wm_reg,
480da8fa4e3SBjoern A. Zeeb .misc_regs = &qcax_misc_reg,
481da8fa4e3SBjoern A. Zeeb .wm_srcr = &qcax_wm_src_ring,
482da8fa4e3SBjoern A. Zeeb .wm_dstr = &qcax_wm_dst_ring,
483da8fa4e3SBjoern A. Zeeb };
484da8fa4e3SBjoern A. Zeeb
485da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
486da8fa4e3SBjoern A. Zeeb {
487da8fa4e3SBjoern A. Zeeb .refclk = 48000000,
488da8fa4e3SBjoern A. Zeeb .div = 0xe,
489da8fa4e3SBjoern A. Zeeb .rnfrac = 0x2aaa8,
490da8fa4e3SBjoern A. Zeeb .settle_time = 2400,
491da8fa4e3SBjoern A. Zeeb .refdiv = 0,
492da8fa4e3SBjoern A. Zeeb .outdiv = 1,
493da8fa4e3SBjoern A. Zeeb },
494da8fa4e3SBjoern A. Zeeb {
495da8fa4e3SBjoern A. Zeeb .refclk = 19200000,
496da8fa4e3SBjoern A. Zeeb .div = 0x24,
497da8fa4e3SBjoern A. Zeeb .rnfrac = 0x2aaa8,
498da8fa4e3SBjoern A. Zeeb .settle_time = 960,
499da8fa4e3SBjoern A. Zeeb .refdiv = 0,
500da8fa4e3SBjoern A. Zeeb .outdiv = 1,
501da8fa4e3SBjoern A. Zeeb },
502da8fa4e3SBjoern A. Zeeb {
503da8fa4e3SBjoern A. Zeeb .refclk = 24000000,
504da8fa4e3SBjoern A. Zeeb .div = 0x1d,
505da8fa4e3SBjoern A. Zeeb .rnfrac = 0x15551,
506da8fa4e3SBjoern A. Zeeb .settle_time = 1200,
507da8fa4e3SBjoern A. Zeeb .refdiv = 0,
508da8fa4e3SBjoern A. Zeeb .outdiv = 1,
509da8fa4e3SBjoern A. Zeeb },
510da8fa4e3SBjoern A. Zeeb {
511da8fa4e3SBjoern A. Zeeb .refclk = 26000000,
512da8fa4e3SBjoern A. Zeeb .div = 0x1b,
513da8fa4e3SBjoern A. Zeeb .rnfrac = 0x4ec4,
514da8fa4e3SBjoern A. Zeeb .settle_time = 1300,
515da8fa4e3SBjoern A. Zeeb .refdiv = 0,
516da8fa4e3SBjoern A. Zeeb .outdiv = 1,
517da8fa4e3SBjoern A. Zeeb },
518da8fa4e3SBjoern A. Zeeb {
519da8fa4e3SBjoern A. Zeeb .refclk = 37400000,
520da8fa4e3SBjoern A. Zeeb .div = 0x12,
521da8fa4e3SBjoern A. Zeeb .rnfrac = 0x34b49,
522da8fa4e3SBjoern A. Zeeb .settle_time = 1870,
523da8fa4e3SBjoern A. Zeeb .refdiv = 0,
524da8fa4e3SBjoern A. Zeeb .outdiv = 1,
525da8fa4e3SBjoern A. Zeeb },
526da8fa4e3SBjoern A. Zeeb {
527da8fa4e3SBjoern A. Zeeb .refclk = 38400000,
528da8fa4e3SBjoern A. Zeeb .div = 0x12,
529da8fa4e3SBjoern A. Zeeb .rnfrac = 0x15551,
530da8fa4e3SBjoern A. Zeeb .settle_time = 1920,
531da8fa4e3SBjoern A. Zeeb .refdiv = 0,
532da8fa4e3SBjoern A. Zeeb .outdiv = 1,
533da8fa4e3SBjoern A. Zeeb },
534da8fa4e3SBjoern A. Zeeb {
535da8fa4e3SBjoern A. Zeeb .refclk = 40000000,
536da8fa4e3SBjoern A. Zeeb .div = 0x12,
537da8fa4e3SBjoern A. Zeeb .rnfrac = 0x26665,
538da8fa4e3SBjoern A. Zeeb .settle_time = 2000,
539da8fa4e3SBjoern A. Zeeb .refdiv = 0,
540da8fa4e3SBjoern A. Zeeb .outdiv = 1,
541da8fa4e3SBjoern A. Zeeb },
542da8fa4e3SBjoern A. Zeeb {
543da8fa4e3SBjoern A. Zeeb .refclk = 52000000,
544da8fa4e3SBjoern A. Zeeb .div = 0x1b,
545da8fa4e3SBjoern A. Zeeb .rnfrac = 0x4ec4,
546da8fa4e3SBjoern A. Zeeb .settle_time = 2600,
547da8fa4e3SBjoern A. Zeeb .refdiv = 0,
548da8fa4e3SBjoern A. Zeeb .outdiv = 1,
549da8fa4e3SBjoern A. Zeeb },
550da8fa4e3SBjoern A. Zeeb };
551da8fa4e3SBjoern A. Zeeb
ath10k_hw_fill_survey_time(struct ath10k * ar,struct survey_info * survey,u32 cc,u32 rcc,u32 cc_prev,u32 rcc_prev)552da8fa4e3SBjoern A. Zeeb void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
553da8fa4e3SBjoern A. Zeeb u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
554da8fa4e3SBjoern A. Zeeb {
555da8fa4e3SBjoern A. Zeeb u32 cc_fix = 0;
556da8fa4e3SBjoern A. Zeeb u32 rcc_fix = 0;
557da8fa4e3SBjoern A. Zeeb enum ath10k_hw_cc_wraparound_type wraparound_type;
558da8fa4e3SBjoern A. Zeeb
559da8fa4e3SBjoern A. Zeeb survey->filled |= SURVEY_INFO_TIME |
560da8fa4e3SBjoern A. Zeeb SURVEY_INFO_TIME_BUSY;
561da8fa4e3SBjoern A. Zeeb
562da8fa4e3SBjoern A. Zeeb wraparound_type = ar->hw_params.cc_wraparound_type;
563da8fa4e3SBjoern A. Zeeb
564da8fa4e3SBjoern A. Zeeb if (cc < cc_prev || rcc < rcc_prev) {
565da8fa4e3SBjoern A. Zeeb switch (wraparound_type) {
566da8fa4e3SBjoern A. Zeeb case ATH10K_HW_CC_WRAP_SHIFTED_ALL:
567da8fa4e3SBjoern A. Zeeb if (cc < cc_prev) {
568da8fa4e3SBjoern A. Zeeb cc_fix = 0x7fffffff;
569da8fa4e3SBjoern A. Zeeb survey->filled &= ~SURVEY_INFO_TIME_BUSY;
570da8fa4e3SBjoern A. Zeeb }
571da8fa4e3SBjoern A. Zeeb break;
572da8fa4e3SBjoern A. Zeeb case ATH10K_HW_CC_WRAP_SHIFTED_EACH:
573da8fa4e3SBjoern A. Zeeb if (cc < cc_prev)
574da8fa4e3SBjoern A. Zeeb cc_fix = 0x7fffffff;
575da8fa4e3SBjoern A. Zeeb
576da8fa4e3SBjoern A. Zeeb if (rcc < rcc_prev)
577da8fa4e3SBjoern A. Zeeb rcc_fix = 0x7fffffff;
578da8fa4e3SBjoern A. Zeeb break;
579da8fa4e3SBjoern A. Zeeb case ATH10K_HW_CC_WRAP_DISABLED:
580da8fa4e3SBjoern A. Zeeb break;
581da8fa4e3SBjoern A. Zeeb }
582da8fa4e3SBjoern A. Zeeb }
583da8fa4e3SBjoern A. Zeeb
584da8fa4e3SBjoern A. Zeeb cc -= cc_prev - cc_fix;
585da8fa4e3SBjoern A. Zeeb rcc -= rcc_prev - rcc_fix;
586da8fa4e3SBjoern A. Zeeb
587da8fa4e3SBjoern A. Zeeb survey->time = CCNT_TO_MSEC(ar, cc);
588da8fa4e3SBjoern A. Zeeb survey->time_busy = CCNT_TO_MSEC(ar, rcc);
589da8fa4e3SBjoern A. Zeeb }
590da8fa4e3SBjoern A. Zeeb
591da8fa4e3SBjoern A. Zeeb /* The firmware does not support setting the coverage class. Instead this
592da8fa4e3SBjoern A. Zeeb * function monitors and modifies the corresponding MAC registers.
593da8fa4e3SBjoern A. Zeeb */
ath10k_hw_qca988x_set_coverage_class(struct ath10k * ar,s16 value)594da8fa4e3SBjoern A. Zeeb static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
595da8fa4e3SBjoern A. Zeeb s16 value)
596da8fa4e3SBjoern A. Zeeb {
597da8fa4e3SBjoern A. Zeeb u32 slottime_reg;
598da8fa4e3SBjoern A. Zeeb u32 slottime;
599da8fa4e3SBjoern A. Zeeb u32 timeout_reg;
600da8fa4e3SBjoern A. Zeeb u32 ack_timeout;
601da8fa4e3SBjoern A. Zeeb u32 cts_timeout;
602da8fa4e3SBjoern A. Zeeb u32 phyclk_reg;
603da8fa4e3SBjoern A. Zeeb u32 phyclk;
604da8fa4e3SBjoern A. Zeeb u64 fw_dbglog_mask;
605da8fa4e3SBjoern A. Zeeb u32 fw_dbglog_level;
606da8fa4e3SBjoern A. Zeeb
607da8fa4e3SBjoern A. Zeeb mutex_lock(&ar->conf_mutex);
608da8fa4e3SBjoern A. Zeeb
609da8fa4e3SBjoern A. Zeeb /* Only modify registers if the core is started. */
610da8fa4e3SBjoern A. Zeeb if ((ar->state != ATH10K_STATE_ON) &&
611da8fa4e3SBjoern A. Zeeb (ar->state != ATH10K_STATE_RESTARTED)) {
612da8fa4e3SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
613da8fa4e3SBjoern A. Zeeb /* Store config value for when radio boots up */
614da8fa4e3SBjoern A. Zeeb ar->fw_coverage.coverage_class = value;
615da8fa4e3SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
616da8fa4e3SBjoern A. Zeeb goto unlock;
617da8fa4e3SBjoern A. Zeeb }
618da8fa4e3SBjoern A. Zeeb
619da8fa4e3SBjoern A. Zeeb /* Retrieve the current values of the two registers that need to be
620da8fa4e3SBjoern A. Zeeb * adjusted.
621da8fa4e3SBjoern A. Zeeb */
622da8fa4e3SBjoern A. Zeeb slottime_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
623da8fa4e3SBjoern A. Zeeb WAVE1_PCU_GBL_IFS_SLOT);
624da8fa4e3SBjoern A. Zeeb timeout_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
625da8fa4e3SBjoern A. Zeeb WAVE1_PCU_ACK_CTS_TIMEOUT);
626da8fa4e3SBjoern A. Zeeb phyclk_reg = ath10k_hif_read32(ar, WLAN_MAC_BASE_ADDRESS +
627da8fa4e3SBjoern A. Zeeb WAVE1_PHYCLK);
628da8fa4e3SBjoern A. Zeeb phyclk = MS(phyclk_reg, WAVE1_PHYCLK_USEC) + 1;
629da8fa4e3SBjoern A. Zeeb
630da8fa4e3SBjoern A. Zeeb if (value < 0)
631da8fa4e3SBjoern A. Zeeb value = ar->fw_coverage.coverage_class;
632da8fa4e3SBjoern A. Zeeb
633da8fa4e3SBjoern A. Zeeb /* Break out if the coverage class and registers have the expected
634da8fa4e3SBjoern A. Zeeb * value.
635da8fa4e3SBjoern A. Zeeb */
636da8fa4e3SBjoern A. Zeeb if (value == ar->fw_coverage.coverage_class &&
637da8fa4e3SBjoern A. Zeeb slottime_reg == ar->fw_coverage.reg_slottime_conf &&
638da8fa4e3SBjoern A. Zeeb timeout_reg == ar->fw_coverage.reg_ack_cts_timeout_conf &&
639da8fa4e3SBjoern A. Zeeb phyclk_reg == ar->fw_coverage.reg_phyclk)
640da8fa4e3SBjoern A. Zeeb goto unlock;
641da8fa4e3SBjoern A. Zeeb
642da8fa4e3SBjoern A. Zeeb /* Store new initial register values from the firmware. */
643da8fa4e3SBjoern A. Zeeb if (slottime_reg != ar->fw_coverage.reg_slottime_conf)
644da8fa4e3SBjoern A. Zeeb ar->fw_coverage.reg_slottime_orig = slottime_reg;
645da8fa4e3SBjoern A. Zeeb if (timeout_reg != ar->fw_coverage.reg_ack_cts_timeout_conf)
646da8fa4e3SBjoern A. Zeeb ar->fw_coverage.reg_ack_cts_timeout_orig = timeout_reg;
647da8fa4e3SBjoern A. Zeeb ar->fw_coverage.reg_phyclk = phyclk_reg;
648da8fa4e3SBjoern A. Zeeb
649da8fa4e3SBjoern A. Zeeb /* Calculate new value based on the (original) firmware calculation. */
650da8fa4e3SBjoern A. Zeeb slottime_reg = ar->fw_coverage.reg_slottime_orig;
651da8fa4e3SBjoern A. Zeeb timeout_reg = ar->fw_coverage.reg_ack_cts_timeout_orig;
652da8fa4e3SBjoern A. Zeeb
653da8fa4e3SBjoern A. Zeeb /* Do some sanity checks on the slottime register. */
654da8fa4e3SBjoern A. Zeeb if (slottime_reg % phyclk) {
655da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
656da8fa4e3SBjoern A. Zeeb "failed to set coverage class: expected integer microsecond value in register\n");
657da8fa4e3SBjoern A. Zeeb
658da8fa4e3SBjoern A. Zeeb goto store_regs;
659da8fa4e3SBjoern A. Zeeb }
660da8fa4e3SBjoern A. Zeeb
661da8fa4e3SBjoern A. Zeeb slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT);
662da8fa4e3SBjoern A. Zeeb slottime = slottime / phyclk;
663da8fa4e3SBjoern A. Zeeb if (slottime != 9 && slottime != 20) {
664da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
665da8fa4e3SBjoern A. Zeeb "failed to set coverage class: expected slot time of 9 or 20us in HW register. It is %uus.\n",
666da8fa4e3SBjoern A. Zeeb slottime);
667da8fa4e3SBjoern A. Zeeb
668da8fa4e3SBjoern A. Zeeb goto store_regs;
669da8fa4e3SBjoern A. Zeeb }
670da8fa4e3SBjoern A. Zeeb
671da8fa4e3SBjoern A. Zeeb /* Recalculate the register values by adding the additional propagation
672da8fa4e3SBjoern A. Zeeb * delay (3us per coverage class).
673da8fa4e3SBjoern A. Zeeb */
674da8fa4e3SBjoern A. Zeeb
675da8fa4e3SBjoern A. Zeeb slottime = MS(slottime_reg, WAVE1_PCU_GBL_IFS_SLOT);
676da8fa4e3SBjoern A. Zeeb slottime += value * 3 * phyclk;
677da8fa4e3SBjoern A. Zeeb slottime = min_t(u32, slottime, WAVE1_PCU_GBL_IFS_SLOT_MAX);
678da8fa4e3SBjoern A. Zeeb slottime = SM(slottime, WAVE1_PCU_GBL_IFS_SLOT);
679da8fa4e3SBjoern A. Zeeb slottime_reg = (slottime_reg & ~WAVE1_PCU_GBL_IFS_SLOT_MASK) | slottime;
680da8fa4e3SBjoern A. Zeeb
681da8fa4e3SBjoern A. Zeeb /* Update ack timeout (lower halfword). */
682da8fa4e3SBjoern A. Zeeb ack_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK);
683da8fa4e3SBjoern A. Zeeb ack_timeout += 3 * value * phyclk;
684da8fa4e3SBjoern A. Zeeb ack_timeout = min_t(u32, ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX);
685da8fa4e3SBjoern A. Zeeb ack_timeout = SM(ack_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_ACK);
686da8fa4e3SBjoern A. Zeeb
687da8fa4e3SBjoern A. Zeeb /* Update cts timeout (upper halfword). */
688da8fa4e3SBjoern A. Zeeb cts_timeout = MS(timeout_reg, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS);
689da8fa4e3SBjoern A. Zeeb cts_timeout += 3 * value * phyclk;
690da8fa4e3SBjoern A. Zeeb cts_timeout = min_t(u32, cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_MAX);
691da8fa4e3SBjoern A. Zeeb cts_timeout = SM(cts_timeout, WAVE1_PCU_ACK_CTS_TIMEOUT_CTS);
692da8fa4e3SBjoern A. Zeeb
693da8fa4e3SBjoern A. Zeeb timeout_reg = ack_timeout | cts_timeout;
694da8fa4e3SBjoern A. Zeeb
695da8fa4e3SBjoern A. Zeeb ath10k_hif_write32(ar,
696da8fa4e3SBjoern A. Zeeb WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_GBL_IFS_SLOT,
697da8fa4e3SBjoern A. Zeeb slottime_reg);
698da8fa4e3SBjoern A. Zeeb ath10k_hif_write32(ar,
699da8fa4e3SBjoern A. Zeeb WLAN_MAC_BASE_ADDRESS + WAVE1_PCU_ACK_CTS_TIMEOUT,
700da8fa4e3SBjoern A. Zeeb timeout_reg);
701da8fa4e3SBjoern A. Zeeb
702da8fa4e3SBjoern A. Zeeb /* Ensure we have a debug level of WARN set for the case that the
703da8fa4e3SBjoern A. Zeeb * coverage class is larger than 0. This is important as we need to
704da8fa4e3SBjoern A. Zeeb * set the registers again if the firmware does an internal reset and
705da8fa4e3SBjoern A. Zeeb * this way we will be notified of the event.
706da8fa4e3SBjoern A. Zeeb */
707da8fa4e3SBjoern A. Zeeb fw_dbglog_mask = ath10k_debug_get_fw_dbglog_mask(ar);
708da8fa4e3SBjoern A. Zeeb fw_dbglog_level = ath10k_debug_get_fw_dbglog_level(ar);
709da8fa4e3SBjoern A. Zeeb
710da8fa4e3SBjoern A. Zeeb if (value > 0) {
711da8fa4e3SBjoern A. Zeeb if (fw_dbglog_level > ATH10K_DBGLOG_LEVEL_WARN)
712da8fa4e3SBjoern A. Zeeb fw_dbglog_level = ATH10K_DBGLOG_LEVEL_WARN;
713da8fa4e3SBjoern A. Zeeb fw_dbglog_mask = ~0;
714da8fa4e3SBjoern A. Zeeb }
715da8fa4e3SBjoern A. Zeeb
716da8fa4e3SBjoern A. Zeeb ath10k_wmi_dbglog_cfg(ar, fw_dbglog_mask, fw_dbglog_level);
717da8fa4e3SBjoern A. Zeeb
718da8fa4e3SBjoern A. Zeeb store_regs:
719da8fa4e3SBjoern A. Zeeb /* After an error we will not retry setting the coverage class. */
720da8fa4e3SBjoern A. Zeeb spin_lock_bh(&ar->data_lock);
721da8fa4e3SBjoern A. Zeeb ar->fw_coverage.coverage_class = value;
722da8fa4e3SBjoern A. Zeeb spin_unlock_bh(&ar->data_lock);
723da8fa4e3SBjoern A. Zeeb
724da8fa4e3SBjoern A. Zeeb ar->fw_coverage.reg_slottime_conf = slottime_reg;
725da8fa4e3SBjoern A. Zeeb ar->fw_coverage.reg_ack_cts_timeout_conf = timeout_reg;
726da8fa4e3SBjoern A. Zeeb
727da8fa4e3SBjoern A. Zeeb unlock:
728da8fa4e3SBjoern A. Zeeb mutex_unlock(&ar->conf_mutex);
729da8fa4e3SBjoern A. Zeeb }
730da8fa4e3SBjoern A. Zeeb
731da8fa4e3SBjoern A. Zeeb /**
732da8fa4e3SBjoern A. Zeeb * ath10k_hw_qca6174_enable_pll_clock() - enable the qca6174 hw pll clock
733da8fa4e3SBjoern A. Zeeb * @ar: the ath10k blob
734da8fa4e3SBjoern A. Zeeb *
735da8fa4e3SBjoern A. Zeeb * This function is very hardware specific, the clock initialization
736da8fa4e3SBjoern A. Zeeb * steps is very sensitive and could lead to unknown crash, so they
737da8fa4e3SBjoern A. Zeeb * should be done in sequence.
738da8fa4e3SBjoern A. Zeeb *
739da8fa4e3SBjoern A. Zeeb * *** Be aware if you planned to refactor them. ***
740da8fa4e3SBjoern A. Zeeb *
741da8fa4e3SBjoern A. Zeeb * Return: 0 if successfully enable the pll, otherwise EINVAL
742da8fa4e3SBjoern A. Zeeb */
ath10k_hw_qca6174_enable_pll_clock(struct ath10k * ar)743da8fa4e3SBjoern A. Zeeb static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
744da8fa4e3SBjoern A. Zeeb {
745da8fa4e3SBjoern A. Zeeb int ret, wait_limit;
746da8fa4e3SBjoern A. Zeeb u32 clk_div_addr, pll_init_addr, speed_addr;
747da8fa4e3SBjoern A. Zeeb u32 addr, reg_val, mem_val;
748da8fa4e3SBjoern A. Zeeb struct ath10k_hw_params *hw;
749da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_clk_params *hw_clk;
750da8fa4e3SBjoern A. Zeeb
751da8fa4e3SBjoern A. Zeeb hw = &ar->hw_params;
752da8fa4e3SBjoern A. Zeeb
753da8fa4e3SBjoern A. Zeeb if (ar->regs->core_clk_div_address == 0 ||
754da8fa4e3SBjoern A. Zeeb ar->regs->cpu_pll_init_address == 0 ||
755da8fa4e3SBjoern A. Zeeb ar->regs->cpu_speed_address == 0)
756da8fa4e3SBjoern A. Zeeb return -EINVAL;
757da8fa4e3SBjoern A. Zeeb
758da8fa4e3SBjoern A. Zeeb clk_div_addr = ar->regs->core_clk_div_address;
759da8fa4e3SBjoern A. Zeeb pll_init_addr = ar->regs->cpu_pll_init_address;
760da8fa4e3SBjoern A. Zeeb speed_addr = ar->regs->cpu_speed_address;
761da8fa4e3SBjoern A. Zeeb
762da8fa4e3SBjoern A. Zeeb /* Read efuse register to find out the right hw clock configuration */
763da8fa4e3SBjoern A. Zeeb addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET);
764da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
765da8fa4e3SBjoern A. Zeeb if (ret)
766da8fa4e3SBjoern A. Zeeb return -EINVAL;
767da8fa4e3SBjoern A. Zeeb
768da8fa4e3SBjoern A. Zeeb /* sanitize if the hw refclk index is out of the boundary */
769da8fa4e3SBjoern A. Zeeb if (MS(reg_val, EFUSE_XTAL_SEL) > ATH10K_HW_REFCLK_COUNT)
770da8fa4e3SBjoern A. Zeeb return -EINVAL;
771da8fa4e3SBjoern A. Zeeb
772da8fa4e3SBjoern A. Zeeb hw_clk = &hw->hw_clk[MS(reg_val, EFUSE_XTAL_SEL)];
773da8fa4e3SBjoern A. Zeeb
774da8fa4e3SBjoern A. Zeeb /* Set the rnfrac and outdiv params to bb_pll register */
775da8fa4e3SBjoern A. Zeeb addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET);
776da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
777da8fa4e3SBjoern A. Zeeb if (ret)
778da8fa4e3SBjoern A. Zeeb return -EINVAL;
779da8fa4e3SBjoern A. Zeeb
780da8fa4e3SBjoern A. Zeeb reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK);
781da8fa4e3SBjoern A. Zeeb reg_val |= (SM(hw_clk->rnfrac, BB_PLL_CONFIG_FRAC) |
782da8fa4e3SBjoern A. Zeeb SM(hw_clk->outdiv, BB_PLL_CONFIG_OUTDIV));
783da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
784da8fa4e3SBjoern A. Zeeb if (ret)
785da8fa4e3SBjoern A. Zeeb return -EINVAL;
786da8fa4e3SBjoern A. Zeeb
787da8fa4e3SBjoern A. Zeeb /* Set the correct settle time value to pll_settle register */
788da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET);
789da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
790da8fa4e3SBjoern A. Zeeb if (ret)
791da8fa4e3SBjoern A. Zeeb return -EINVAL;
792da8fa4e3SBjoern A. Zeeb
793da8fa4e3SBjoern A. Zeeb reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK;
794da8fa4e3SBjoern A. Zeeb reg_val |= SM(hw_clk->settle_time, WLAN_PLL_SETTLE_TIME);
795da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
796da8fa4e3SBjoern A. Zeeb if (ret)
797da8fa4e3SBjoern A. Zeeb return -EINVAL;
798da8fa4e3SBjoern A. Zeeb
799da8fa4e3SBjoern A. Zeeb /* Set the clock_ctrl div to core_clk_ctrl register */
800da8fa4e3SBjoern A. Zeeb addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET);
801da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
802da8fa4e3SBjoern A. Zeeb if (ret)
803da8fa4e3SBjoern A. Zeeb return -EINVAL;
804da8fa4e3SBjoern A. Zeeb
805da8fa4e3SBjoern A. Zeeb reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK;
806da8fa4e3SBjoern A. Zeeb reg_val |= SM(1, SOC_CORE_CLK_CTRL_DIV);
807da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
808da8fa4e3SBjoern A. Zeeb if (ret)
809da8fa4e3SBjoern A. Zeeb return -EINVAL;
810da8fa4e3SBjoern A. Zeeb
811da8fa4e3SBjoern A. Zeeb /* Set the clock_div register */
812da8fa4e3SBjoern A. Zeeb mem_val = 1;
813da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
814da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, clk_div_addr, &mem_val,
815da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
816da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, clk_div_addr, (u8 *)&mem_val,
817da8fa4e3SBjoern A. Zeeb #endif
818da8fa4e3SBjoern A. Zeeb sizeof(mem_val));
819da8fa4e3SBjoern A. Zeeb if (ret)
820da8fa4e3SBjoern A. Zeeb return -EINVAL;
821da8fa4e3SBjoern A. Zeeb
822da8fa4e3SBjoern A. Zeeb /* Configure the pll_control register */
823da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
824da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
825da8fa4e3SBjoern A. Zeeb if (ret)
826da8fa4e3SBjoern A. Zeeb return -EINVAL;
827da8fa4e3SBjoern A. Zeeb
828da8fa4e3SBjoern A. Zeeb reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) |
829da8fa4e3SBjoern A. Zeeb SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) |
830da8fa4e3SBjoern A. Zeeb SM(1, WLAN_PLL_CONTROL_NOPWD));
831da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
832da8fa4e3SBjoern A. Zeeb if (ret)
833da8fa4e3SBjoern A. Zeeb return -EINVAL;
834da8fa4e3SBjoern A. Zeeb
835da8fa4e3SBjoern A. Zeeb /* busy wait (max 1s) the rtc_sync status register indicate ready */
836da8fa4e3SBjoern A. Zeeb wait_limit = 100000;
837da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
838da8fa4e3SBjoern A. Zeeb do {
839da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
840da8fa4e3SBjoern A. Zeeb if (ret)
841da8fa4e3SBjoern A. Zeeb return -EINVAL;
842da8fa4e3SBjoern A. Zeeb
843da8fa4e3SBjoern A. Zeeb if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
844da8fa4e3SBjoern A. Zeeb break;
845da8fa4e3SBjoern A. Zeeb
846da8fa4e3SBjoern A. Zeeb wait_limit--;
847da8fa4e3SBjoern A. Zeeb udelay(10);
848da8fa4e3SBjoern A. Zeeb
849da8fa4e3SBjoern A. Zeeb } while (wait_limit > 0);
850da8fa4e3SBjoern A. Zeeb
851da8fa4e3SBjoern A. Zeeb if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
852da8fa4e3SBjoern A. Zeeb return -EINVAL;
853da8fa4e3SBjoern A. Zeeb
854da8fa4e3SBjoern A. Zeeb /* Unset the pll_bypass in pll_control register */
855da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
856da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
857da8fa4e3SBjoern A. Zeeb if (ret)
858da8fa4e3SBjoern A. Zeeb return -EINVAL;
859da8fa4e3SBjoern A. Zeeb
860da8fa4e3SBjoern A. Zeeb reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK;
861da8fa4e3SBjoern A. Zeeb reg_val |= SM(0, WLAN_PLL_CONTROL_BYPASS);
862da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
863da8fa4e3SBjoern A. Zeeb if (ret)
864da8fa4e3SBjoern A. Zeeb return -EINVAL;
865da8fa4e3SBjoern A. Zeeb
866da8fa4e3SBjoern A. Zeeb /* busy wait (max 1s) the rtc_sync status register indicate ready */
867da8fa4e3SBjoern A. Zeeb wait_limit = 100000;
868da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
869da8fa4e3SBjoern A. Zeeb do {
870da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
871da8fa4e3SBjoern A. Zeeb if (ret)
872da8fa4e3SBjoern A. Zeeb return -EINVAL;
873da8fa4e3SBjoern A. Zeeb
874da8fa4e3SBjoern A. Zeeb if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
875da8fa4e3SBjoern A. Zeeb break;
876da8fa4e3SBjoern A. Zeeb
877da8fa4e3SBjoern A. Zeeb wait_limit--;
878da8fa4e3SBjoern A. Zeeb udelay(10);
879da8fa4e3SBjoern A. Zeeb
880da8fa4e3SBjoern A. Zeeb } while (wait_limit > 0);
881da8fa4e3SBjoern A. Zeeb
882da8fa4e3SBjoern A. Zeeb if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
883da8fa4e3SBjoern A. Zeeb return -EINVAL;
884da8fa4e3SBjoern A. Zeeb
885da8fa4e3SBjoern A. Zeeb /* Enable the hardware cpu clock register */
886da8fa4e3SBjoern A. Zeeb addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET);
887da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
888da8fa4e3SBjoern A. Zeeb if (ret)
889da8fa4e3SBjoern A. Zeeb return -EINVAL;
890da8fa4e3SBjoern A. Zeeb
891da8fa4e3SBjoern A. Zeeb reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK;
892da8fa4e3SBjoern A. Zeeb reg_val |= SM(1, SOC_CPU_CLOCK_STANDARD);
893da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
894da8fa4e3SBjoern A. Zeeb if (ret)
895da8fa4e3SBjoern A. Zeeb return -EINVAL;
896da8fa4e3SBjoern A. Zeeb
897da8fa4e3SBjoern A. Zeeb /* unset the nopwd from pll_control register */
898da8fa4e3SBjoern A. Zeeb addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
899da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
900da8fa4e3SBjoern A. Zeeb if (ret)
901da8fa4e3SBjoern A. Zeeb return -EINVAL;
902da8fa4e3SBjoern A. Zeeb
903da8fa4e3SBjoern A. Zeeb reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK;
904da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
905da8fa4e3SBjoern A. Zeeb if (ret)
906da8fa4e3SBjoern A. Zeeb return -EINVAL;
907da8fa4e3SBjoern A. Zeeb
908da8fa4e3SBjoern A. Zeeb /* enable the pll_init register */
909da8fa4e3SBjoern A. Zeeb mem_val = 1;
910da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
911da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, pll_init_addr, &mem_val,
912da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
913da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, pll_init_addr, (u8 *)&mem_val,
914da8fa4e3SBjoern A. Zeeb #endif
915da8fa4e3SBjoern A. Zeeb sizeof(mem_val));
916da8fa4e3SBjoern A. Zeeb if (ret)
917da8fa4e3SBjoern A. Zeeb return -EINVAL;
918da8fa4e3SBjoern A. Zeeb
919da8fa4e3SBjoern A. Zeeb /* set the target clock frequency to speed register */
920da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
921da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, speed_addr, &hw->target_cpu_freq,
922da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
923da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_write_memory(ar, speed_addr, (u8 *)&hw->target_cpu_freq,
924da8fa4e3SBjoern A. Zeeb #endif
925da8fa4e3SBjoern A. Zeeb sizeof(hw->target_cpu_freq));
926da8fa4e3SBjoern A. Zeeb if (ret)
927da8fa4e3SBjoern A. Zeeb return -EINVAL;
928da8fa4e3SBjoern A. Zeeb
929da8fa4e3SBjoern A. Zeeb return 0;
930da8fa4e3SBjoern A. Zeeb }
931da8fa4e3SBjoern A. Zeeb
932da8fa4e3SBjoern A. Zeeb /* Program CPU_ADDR_MSB to allow different memory
933da8fa4e3SBjoern A. Zeeb * region access.
934da8fa4e3SBjoern A. Zeeb */
ath10k_hw_map_target_mem(struct ath10k * ar,u32 msb)935da8fa4e3SBjoern A. Zeeb static void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb)
936da8fa4e3SBjoern A. Zeeb {
937da8fa4e3SBjoern A. Zeeb u32 address = SOC_CORE_BASE_ADDRESS + FW_RAM_CONFIG_ADDRESS;
938da8fa4e3SBjoern A. Zeeb
939da8fa4e3SBjoern A. Zeeb ath10k_hif_write32(ar, address, msb);
940da8fa4e3SBjoern A. Zeeb }
941da8fa4e3SBjoern A. Zeeb
942*07724ba6SBjoern A. Zeeb /* 1. Write to memory region of target, such as IRAM and DRAM.
943da8fa4e3SBjoern A. Zeeb * 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000)
944da8fa4e3SBjoern A. Zeeb * can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too.
945da8fa4e3SBjoern A. Zeeb * 3. In order to access the region other than the above,
946da8fa4e3SBjoern A. Zeeb * we need to set the value of register CPU_ADDR_MSB.
947da8fa4e3SBjoern A. Zeeb * 4. Target memory access space is limited to 1M size. If the size is larger
948da8fa4e3SBjoern A. Zeeb * than 1M, need to split it and program CPU_ADDR_MSB accordingly.
949da8fa4e3SBjoern A. Zeeb */
ath10k_hw_diag_segment_msb_download(struct ath10k * ar,const void * buffer,u32 address,u32 length)950da8fa4e3SBjoern A. Zeeb static int ath10k_hw_diag_segment_msb_download(struct ath10k *ar,
951da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
952da8fa4e3SBjoern A. Zeeb const void *buffer,
953da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
954da8fa4e3SBjoern A. Zeeb const u8 *buffer,
955da8fa4e3SBjoern A. Zeeb #endif
956da8fa4e3SBjoern A. Zeeb u32 address,
957da8fa4e3SBjoern A. Zeeb u32 length)
958da8fa4e3SBjoern A. Zeeb {
959da8fa4e3SBjoern A. Zeeb u32 addr = address & REGION_ACCESS_SIZE_MASK;
960da8fa4e3SBjoern A. Zeeb int ret, remain_size, size;
961da8fa4e3SBjoern A. Zeeb const u8 *buf;
962da8fa4e3SBjoern A. Zeeb
963da8fa4e3SBjoern A. Zeeb ath10k_hw_map_target_mem(ar, CPU_ADDR_MSB_REGION_VAL(address));
964da8fa4e3SBjoern A. Zeeb
965da8fa4e3SBjoern A. Zeeb if (addr + length > REGION_ACCESS_SIZE_LIMIT) {
966da8fa4e3SBjoern A. Zeeb size = REGION_ACCESS_SIZE_LIMIT - addr;
967da8fa4e3SBjoern A. Zeeb remain_size = length - size;
968da8fa4e3SBjoern A. Zeeb
969da8fa4e3SBjoern A. Zeeb ret = ath10k_hif_diag_write(ar, address, buffer, size);
970da8fa4e3SBjoern A. Zeeb if (ret) {
971da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
972da8fa4e3SBjoern A. Zeeb "failed to download the first %d bytes segment to address:0x%x: %d\n",
973da8fa4e3SBjoern A. Zeeb size, address, ret);
974da8fa4e3SBjoern A. Zeeb goto done;
975da8fa4e3SBjoern A. Zeeb }
976da8fa4e3SBjoern A. Zeeb
977da8fa4e3SBjoern A. Zeeb /* Change msb to the next memory region*/
978da8fa4e3SBjoern A. Zeeb ath10k_hw_map_target_mem(ar,
979da8fa4e3SBjoern A. Zeeb CPU_ADDR_MSB_REGION_VAL(address) + 1);
980da8fa4e3SBjoern A. Zeeb buf = buffer + size;
981da8fa4e3SBjoern A. Zeeb ret = ath10k_hif_diag_write(ar,
982da8fa4e3SBjoern A. Zeeb address & ~REGION_ACCESS_SIZE_MASK,
983da8fa4e3SBjoern A. Zeeb buf, remain_size);
984da8fa4e3SBjoern A. Zeeb if (ret) {
985da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
986da8fa4e3SBjoern A. Zeeb "failed to download the second %d bytes segment to address:0x%x: %d\n",
987da8fa4e3SBjoern A. Zeeb remain_size,
988da8fa4e3SBjoern A. Zeeb address & ~REGION_ACCESS_SIZE_MASK,
989da8fa4e3SBjoern A. Zeeb ret);
990da8fa4e3SBjoern A. Zeeb goto done;
991da8fa4e3SBjoern A. Zeeb }
992da8fa4e3SBjoern A. Zeeb } else {
993da8fa4e3SBjoern A. Zeeb ret = ath10k_hif_diag_write(ar, address, buffer, length);
994da8fa4e3SBjoern A. Zeeb if (ret) {
995da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
996da8fa4e3SBjoern A. Zeeb "failed to download the only %d bytes segment to address:0x%x: %d\n",
997da8fa4e3SBjoern A. Zeeb length, address, ret);
998da8fa4e3SBjoern A. Zeeb goto done;
999da8fa4e3SBjoern A. Zeeb }
1000da8fa4e3SBjoern A. Zeeb }
1001da8fa4e3SBjoern A. Zeeb
1002da8fa4e3SBjoern A. Zeeb done:
1003da8fa4e3SBjoern A. Zeeb /* Change msb to DRAM */
1004da8fa4e3SBjoern A. Zeeb ath10k_hw_map_target_mem(ar,
1005da8fa4e3SBjoern A. Zeeb CPU_ADDR_MSB_REGION_VAL(DRAM_BASE_ADDRESS));
1006da8fa4e3SBjoern A. Zeeb return ret;
1007da8fa4e3SBjoern A. Zeeb }
1008da8fa4e3SBjoern A. Zeeb
ath10k_hw_diag_segment_download(struct ath10k * ar,const void * buffer,u32 address,u32 length)1009da8fa4e3SBjoern A. Zeeb static int ath10k_hw_diag_segment_download(struct ath10k *ar,
1010da8fa4e3SBjoern A. Zeeb const void *buffer,
1011da8fa4e3SBjoern A. Zeeb u32 address,
1012da8fa4e3SBjoern A. Zeeb u32 length)
1013da8fa4e3SBjoern A. Zeeb {
1014da8fa4e3SBjoern A. Zeeb if (address >= DRAM_BASE_ADDRESS + REGION_ACCESS_SIZE_LIMIT)
1015da8fa4e3SBjoern A. Zeeb /* Needs to change MSB for memory write */
1016da8fa4e3SBjoern A. Zeeb return ath10k_hw_diag_segment_msb_download(ar, buffer,
1017da8fa4e3SBjoern A. Zeeb address, length);
1018da8fa4e3SBjoern A. Zeeb else
1019da8fa4e3SBjoern A. Zeeb return ath10k_hif_diag_write(ar, address, buffer, length);
1020da8fa4e3SBjoern A. Zeeb }
1021da8fa4e3SBjoern A. Zeeb
ath10k_hw_diag_fast_download(struct ath10k * ar,u32 address,const void * buffer,u32 length)1022da8fa4e3SBjoern A. Zeeb int ath10k_hw_diag_fast_download(struct ath10k *ar,
1023da8fa4e3SBjoern A. Zeeb u32 address,
1024da8fa4e3SBjoern A. Zeeb const void *buffer,
1025da8fa4e3SBjoern A. Zeeb u32 length)
1026da8fa4e3SBjoern A. Zeeb {
1027da8fa4e3SBjoern A. Zeeb const u8 *buf = buffer;
1028da8fa4e3SBjoern A. Zeeb bool sgmt_end = false;
1029da8fa4e3SBjoern A. Zeeb u32 base_addr = 0;
1030da8fa4e3SBjoern A. Zeeb u32 base_len = 0;
1031da8fa4e3SBjoern A. Zeeb u32 left = 0;
1032da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1033da8fa4e3SBjoern A. Zeeb struct bmi_segmented_file_header *hdr;
1034da8fa4e3SBjoern A. Zeeb struct bmi_segmented_metadata *metadata;
1035da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1036da8fa4e3SBjoern A. Zeeb const struct bmi_segmented_file_header *hdr;
1037da8fa4e3SBjoern A. Zeeb const struct bmi_segmented_metadata *metadata;
1038da8fa4e3SBjoern A. Zeeb #endif
1039da8fa4e3SBjoern A. Zeeb int ret = 0;
1040da8fa4e3SBjoern A. Zeeb
1041da8fa4e3SBjoern A. Zeeb if (length < sizeof(*hdr))
1042da8fa4e3SBjoern A. Zeeb return -EINVAL;
1043da8fa4e3SBjoern A. Zeeb
1044da8fa4e3SBjoern A. Zeeb /* check firmware header. If it has no correct magic number
1045da8fa4e3SBjoern A. Zeeb * or it's compressed, returns error.
1046da8fa4e3SBjoern A. Zeeb */
1047da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1048da8fa4e3SBjoern A. Zeeb hdr = (struct bmi_segmented_file_header *)buf;
1049da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1050da8fa4e3SBjoern A. Zeeb hdr = (const struct bmi_segmented_file_header *)buf;
1051da8fa4e3SBjoern A. Zeeb #endif
1052da8fa4e3SBjoern A. Zeeb if (__le32_to_cpu(hdr->magic_num) != BMI_SGMTFILE_MAGIC_NUM) {
1053da8fa4e3SBjoern A. Zeeb ath10k_dbg(ar, ATH10K_DBG_BOOT,
1054da8fa4e3SBjoern A. Zeeb "Not a supported firmware, magic_num:0x%x\n",
1055da8fa4e3SBjoern A. Zeeb hdr->magic_num);
1056da8fa4e3SBjoern A. Zeeb return -EINVAL;
1057da8fa4e3SBjoern A. Zeeb }
1058da8fa4e3SBjoern A. Zeeb
1059da8fa4e3SBjoern A. Zeeb if (hdr->file_flags != 0) {
1060da8fa4e3SBjoern A. Zeeb ath10k_dbg(ar, ATH10K_DBG_BOOT,
1061da8fa4e3SBjoern A. Zeeb "Not a supported firmware, file_flags:0x%x\n",
1062da8fa4e3SBjoern A. Zeeb hdr->file_flags);
1063da8fa4e3SBjoern A. Zeeb return -EINVAL;
1064da8fa4e3SBjoern A. Zeeb }
1065da8fa4e3SBjoern A. Zeeb
1066da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1067da8fa4e3SBjoern A. Zeeb metadata = (struct bmi_segmented_metadata *)hdr->data;
1068da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1069da8fa4e3SBjoern A. Zeeb metadata = (const struct bmi_segmented_metadata *)hdr->data;
1070da8fa4e3SBjoern A. Zeeb #endif
1071da8fa4e3SBjoern A. Zeeb left = length - sizeof(*hdr);
1072da8fa4e3SBjoern A. Zeeb
1073da8fa4e3SBjoern A. Zeeb while (left > 0) {
1074da8fa4e3SBjoern A. Zeeb if (left < sizeof(*metadata)) {
1075da8fa4e3SBjoern A. Zeeb ath10k_warn(ar, "firmware segment is truncated: %d\n",
1076da8fa4e3SBjoern A. Zeeb left);
1077da8fa4e3SBjoern A. Zeeb ret = -EINVAL;
1078da8fa4e3SBjoern A. Zeeb break;
1079da8fa4e3SBjoern A. Zeeb }
1080da8fa4e3SBjoern A. Zeeb base_addr = __le32_to_cpu(metadata->addr);
1081da8fa4e3SBjoern A. Zeeb base_len = __le32_to_cpu(metadata->length);
1082da8fa4e3SBjoern A. Zeeb buf = metadata->data;
1083da8fa4e3SBjoern A. Zeeb left -= sizeof(*metadata);
1084da8fa4e3SBjoern A. Zeeb
1085da8fa4e3SBjoern A. Zeeb switch (base_len) {
1086da8fa4e3SBjoern A. Zeeb case BMI_SGMTFILE_BEGINADDR:
1087da8fa4e3SBjoern A. Zeeb /* base_addr is the start address to run */
1088da8fa4e3SBjoern A. Zeeb ret = ath10k_bmi_set_start(ar, base_addr);
1089da8fa4e3SBjoern A. Zeeb base_len = 0;
1090da8fa4e3SBjoern A. Zeeb break;
1091da8fa4e3SBjoern A. Zeeb case BMI_SGMTFILE_DONE:
1092da8fa4e3SBjoern A. Zeeb /* no more segment */
1093da8fa4e3SBjoern A. Zeeb base_len = 0;
1094da8fa4e3SBjoern A. Zeeb sgmt_end = true;
1095da8fa4e3SBjoern A. Zeeb ret = 0;
1096da8fa4e3SBjoern A. Zeeb break;
1097da8fa4e3SBjoern A. Zeeb case BMI_SGMTFILE_BDDATA:
1098da8fa4e3SBjoern A. Zeeb case BMI_SGMTFILE_EXEC:
1099da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
1100da8fa4e3SBjoern A. Zeeb "firmware has unsupported segment:%d\n",
1101da8fa4e3SBjoern A. Zeeb base_len);
1102da8fa4e3SBjoern A. Zeeb ret = -EINVAL;
1103da8fa4e3SBjoern A. Zeeb break;
1104da8fa4e3SBjoern A. Zeeb default:
1105da8fa4e3SBjoern A. Zeeb if (base_len > left) {
1106da8fa4e3SBjoern A. Zeeb /* sanity check */
1107da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
1108da8fa4e3SBjoern A. Zeeb "firmware has invalid segment length, %d > %d\n",
1109da8fa4e3SBjoern A. Zeeb base_len, left);
1110da8fa4e3SBjoern A. Zeeb ret = -EINVAL;
1111da8fa4e3SBjoern A. Zeeb break;
1112da8fa4e3SBjoern A. Zeeb }
1113da8fa4e3SBjoern A. Zeeb
1114da8fa4e3SBjoern A. Zeeb ret = ath10k_hw_diag_segment_download(ar,
1115da8fa4e3SBjoern A. Zeeb buf,
1116da8fa4e3SBjoern A. Zeeb base_addr,
1117da8fa4e3SBjoern A. Zeeb base_len);
1118da8fa4e3SBjoern A. Zeeb
1119da8fa4e3SBjoern A. Zeeb if (ret)
1120da8fa4e3SBjoern A. Zeeb ath10k_warn(ar,
1121da8fa4e3SBjoern A. Zeeb "failed to download firmware via diag interface:%d\n",
1122da8fa4e3SBjoern A. Zeeb ret);
1123da8fa4e3SBjoern A. Zeeb break;
1124da8fa4e3SBjoern A. Zeeb }
1125da8fa4e3SBjoern A. Zeeb
1126da8fa4e3SBjoern A. Zeeb if (ret || sgmt_end)
1127da8fa4e3SBjoern A. Zeeb break;
1128da8fa4e3SBjoern A. Zeeb
1129da8fa4e3SBjoern A. Zeeb #if defined(__linux__)
1130da8fa4e3SBjoern A. Zeeb metadata = (struct bmi_segmented_metadata *)(buf + base_len);
1131da8fa4e3SBjoern A. Zeeb #elif defined(__FreeBSD__)
1132da8fa4e3SBjoern A. Zeeb metadata = (const struct bmi_segmented_metadata *)(buf + base_len);
1133da8fa4e3SBjoern A. Zeeb #endif
1134da8fa4e3SBjoern A. Zeeb left -= base_len;
1135da8fa4e3SBjoern A. Zeeb }
1136da8fa4e3SBjoern A. Zeeb
1137da8fa4e3SBjoern A. Zeeb if (ret == 0)
1138da8fa4e3SBjoern A. Zeeb ath10k_dbg(ar, ATH10K_DBG_BOOT,
1139da8fa4e3SBjoern A. Zeeb "boot firmware fast diag download successfully.\n");
1140da8fa4e3SBjoern A. Zeeb return ret;
1141da8fa4e3SBjoern A. Zeeb }
1142da8fa4e3SBjoern A. Zeeb
ath10k_htt_tx_rssi_enable(struct htt_resp * resp)1143da8fa4e3SBjoern A. Zeeb static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp)
1144da8fa4e3SBjoern A. Zeeb {
1145da8fa4e3SBjoern A. Zeeb return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI);
1146da8fa4e3SBjoern A. Zeeb }
1147da8fa4e3SBjoern A. Zeeb
ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp * resp)1148da8fa4e3SBjoern A. Zeeb static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp)
1149da8fa4e3SBjoern A. Zeeb {
1150da8fa4e3SBjoern A. Zeeb return (resp->data_tx_completion.flags2 &
1151da8fa4e3SBjoern A. Zeeb HTT_TX_DATA_RSSI_ENABLE_WCN3990);
1152da8fa4e3SBjoern A. Zeeb }
1153da8fa4e3SBjoern A. Zeeb
ath10k_get_htt_tx_data_rssi_pad(struct htt_resp * resp)1154da8fa4e3SBjoern A. Zeeb static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp)
1155da8fa4e3SBjoern A. Zeeb {
1156da8fa4e3SBjoern A. Zeeb struct htt_data_tx_completion_ext extd;
1157da8fa4e3SBjoern A. Zeeb int pad_bytes = 0;
1158da8fa4e3SBjoern A. Zeeb
1159da8fa4e3SBjoern A. Zeeb if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES)
1160da8fa4e3SBjoern A. Zeeb pad_bytes += sizeof(extd.a_retries) /
1161da8fa4e3SBjoern A. Zeeb sizeof(extd.msdus_rssi[0]);
1162da8fa4e3SBjoern A. Zeeb
1163da8fa4e3SBjoern A. Zeeb if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP)
1164da8fa4e3SBjoern A. Zeeb pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]);
1165da8fa4e3SBjoern A. Zeeb
1166da8fa4e3SBjoern A. Zeeb return pad_bytes;
1167da8fa4e3SBjoern A. Zeeb }
1168da8fa4e3SBjoern A. Zeeb
1169da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ops qca988x_ops = {
1170da8fa4e3SBjoern A. Zeeb .set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
1171da8fa4e3SBjoern A. Zeeb .is_rssi_enable = ath10k_htt_tx_rssi_enable,
1172da8fa4e3SBjoern A. Zeeb };
1173da8fa4e3SBjoern A. Zeeb
1174da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ops qca99x0_ops = {
1175da8fa4e3SBjoern A. Zeeb .is_rssi_enable = ath10k_htt_tx_rssi_enable,
1176da8fa4e3SBjoern A. Zeeb };
1177da8fa4e3SBjoern A. Zeeb
1178da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ops qca6174_ops = {
1179da8fa4e3SBjoern A. Zeeb .set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
1180da8fa4e3SBjoern A. Zeeb .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
1181da8fa4e3SBjoern A. Zeeb .is_rssi_enable = ath10k_htt_tx_rssi_enable,
1182da8fa4e3SBjoern A. Zeeb };
1183da8fa4e3SBjoern A. Zeeb
1184da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ops qca6174_sdio_ops = {
1185da8fa4e3SBjoern A. Zeeb .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
1186da8fa4e3SBjoern A. Zeeb };
1187da8fa4e3SBjoern A. Zeeb
1188da8fa4e3SBjoern A. Zeeb const struct ath10k_hw_ops wcn3990_ops = {
1189da8fa4e3SBjoern A. Zeeb .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
1190da8fa4e3SBjoern A. Zeeb .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
1191da8fa4e3SBjoern A. Zeeb };
1192