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