1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d5c65159SKalle Valo /*
3d5c65159SKalle Valo  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4b43310e4SGovindaraj Saminathan  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5d5c65159SKalle Valo  */
6d5c65159SKalle Valo 
7d5c65159SKalle Valo #include <linux/module.h>
8d5c65159SKalle Valo #include <linux/slab.h>
9d5c65159SKalle Valo #include <linux/remoteproc.h>
10d5c65159SKalle Valo #include <linux/firmware.h>
1114f43c5fSSven Eckelmann #include <linux/of.h>
129d97114dSWen Gong 
13d5c65159SKalle Valo #include "core.h"
14d5c65159SKalle Valo #include "dp_tx.h"
159c57d7e3SVasanthakumar Thiagarajan #include "dp_rx.h"
16d5c65159SKalle Valo #include "debug.h"
1731858805SGovind Singh #include "hif.h"
18d1b0c338SCarl Huang #include "wow.h"
19d5c65159SKalle Valo 
20d5c65159SKalle Valo unsigned int ath11k_debug_mask;
216e0355afSGovind Singh EXPORT_SYMBOL(ath11k_debug_mask);
22d5c65159SKalle Valo module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
23d5c65159SKalle Valo MODULE_PARM_DESC(debug_mask, "Debugging mask");
24d5c65159SKalle Valo 
25aa2092a9SVenkateswara Naralasetty static unsigned int ath11k_crypto_mode;
26aa2092a9SVenkateswara Naralasetty module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);
27aa2092a9SVenkateswara Naralasetty MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
28aa2092a9SVenkateswara Naralasetty 
29aa2092a9SVenkateswara Naralasetty /* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
30aa2092a9SVenkateswara Naralasetty unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
31aa2092a9SVenkateswara Naralasetty module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
32aa2092a9SVenkateswara Naralasetty MODULE_PARM_DESC(frame_mode,
33aa2092a9SVenkateswara Naralasetty 		 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
34aa2092a9SVenkateswara Naralasetty 
35b43310e4SGovindaraj Saminathan bool ath11k_ftm_mode;
36b43310e4SGovindaraj Saminathan module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
37b43310e4SGovindaraj Saminathan MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
38b43310e4SGovindaraj Saminathan 
39d3318abfSAnilkumar Kolli static const struct ath11k_hw_params ath11k_hw_params[] = {
40d3318abfSAnilkumar Kolli 	{
41d3318abfSAnilkumar Kolli 		.hw_rev = ATH11K_HW_IPQ8074,
42d3318abfSAnilkumar Kolli 		.name = "ipq8074 hw2.0",
43d5c65159SKalle Valo 		.fw = {
4434d9fc80SKalle Valo 			.dir = "IPQ8074/hw2.0",
45b3a18338SKalle Valo 			.board_size = 256 * 1024,
46c72aa32dSAnilkumar Kolli 			.cal_offset = 128 * 1024,
47d5c65159SKalle Valo 		},
48b1cc29e9SAnilkumar Kolli 		.max_radios = 3,
493b94ae4cSAnilkumar Kolli 		.bdf_addr = 0x4B0C0000,
50d547ca4cSAnilkumar Kolli 		.hw_ops = &ipq8074_ops,
5134d5a3a8SKalle Valo 		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
52727fae14SCarl Huang 		.internal_sleep_clock = false,
536976433cSCarl Huang 		.regs = &ipq8074_regs,
5416001e4bSAnilkumar Kolli 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
55e3396b8bSCarl Huang 		.host_ce_config = ath11k_host_ce_config_ipq8074,
56e3396b8bSCarl Huang 		.ce_count = 12,
57967c1d11SAnilkumar Kolli 		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
58967c1d11SAnilkumar Kolli 		.target_ce_count = 11,
59967c1d11SAnilkumar Kolli 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
60967c1d11SAnilkumar Kolli 		.svc_to_ce_map_len = 21,
61b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
625f859bc0SCarl Huang 		.single_pdev_only = false,
637f6fc1ebSCarl Huang 		.rxdma1_enable = true,
644152e420SCarl Huang 		.num_rxmda_per_pdev = 1,
654152e420SCarl Huang 		.rx_mac_buf_ring = false,
66e7495035SCarl Huang 		.vdev_start_delay = false,
67a6275302SCarl Huang 		.htt_peer_map_v2 = true,
68cc2ad754SKarthikeyan Periyasamy 
69cc2ad754SKarthikeyan Periyasamy 		.spectral = {
70cc2ad754SKarthikeyan Periyasamy 			.fft_sz = 2,
71cc2ad754SKarthikeyan Periyasamy 			/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes.
72cc2ad754SKarthikeyan Periyasamy 			 * so added pad size as 2 bytes to compensate the BIN size
73cc2ad754SKarthikeyan Periyasamy 			 */
74cc2ad754SKarthikeyan Periyasamy 			.fft_pad_sz = 2,
751cae9c00SKarthikeyan Periyasamy 			.summary_pad_sz = 0,
761cae9c00SKarthikeyan Periyasamy 			.fft_hdr_len = 16,
771cae9c00SKarthikeyan Periyasamy 			.max_fft_bins = 512,
78c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = true,
79cc2ad754SKarthikeyan Periyasamy 		},
802626c269SKalle Valo 
812626c269SKalle Valo 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
822626c269SKalle Valo 					BIT(NL80211_IFTYPE_AP) |
832626c269SKalle Valo 					BIT(NL80211_IFTYPE_MESH_POINT),
843f6e6c32SKalle Valo 		.supports_monitor = true,
855c1f74d2SAnilkumar Kolli 		.full_monitor_mode = false,
86e838c14aSCarl Huang 		.supports_shadow_regs = false,
87c83c500bSCarl Huang 		.idle_ps = false,
88b2beffa7SCarl Huang 		.supports_sta_ps = false,
89011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = true,
90011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = true,
916fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = true,
92beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 0,
93beefee71SSeevalamuthu Mariappan 		.num_vdevs = 16 + 1,
94beefee71SSeevalamuthu Mariappan 		.num_peers = 512,
95d1b0c338SCarl Huang 		.supports_suspend = false,
96e678fbd4SKarthikeyan Periyasamy 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
9701417e57SWen Gong 		.supports_regdb = false,
985088df05SBaochen Qiang 		.fix_l1ss = true,
99f951380aSP Praneesh 		.credit_flow = false,
10031582373SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
101734223d7SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_ipq8074,
10282c434c1SWen Gong 		.supports_dynamic_smps_6ghz = false,
1036452f0a3SP Praneesh 		.alloc_cacheable_memory = true,
104b488c766SWen Gong 		.supports_rssi_stats = false,
10542da1cc7SCheng Wang 		.fw_wmi_diag_event = false,
1060d6e997bSWen Gong 		.current_cc_support = false,
107691425b4SVenkateswara Naralasetty 		.dbr_debug_support = true,
1081e4ac717SBaochen Qiang 		.global_reset = false,
109652f69edSBaochen Qiang 		.bios_sar_capa = NULL,
11092c1858eSManikanta Pubbisetty 		.m3_fw_support = false,
11192c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = true,
11292c1858eSManikanta Pubbisetty 		.fixed_mem_region = true,
11392c1858eSManikanta Pubbisetty 		.static_window_map = false,
114d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
11573d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
1161d7f5145SBaochen Qiang 		.support_off_channel_tx = false,
1177d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = false,
118876eb848SBaochen Qiang 
119876eb848SBaochen Qiang 		.sram_dump = {},
1207636c9a6SManikanta Pubbisetty 
1217636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
12297c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
12369ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
124d3318abfSAnilkumar Kolli 	},
1259de2ad43SCarl Huang 	{
126b129699aSAnilkumar Kolli 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
127b129699aSAnilkumar Kolli 		.name = "ipq6018 hw1.0",
128b129699aSAnilkumar Kolli 		.fw = {
129b129699aSAnilkumar Kolli 			.dir = "IPQ6018/hw1.0",
130b129699aSAnilkumar Kolli 			.board_size = 256 * 1024,
131c72aa32dSAnilkumar Kolli 			.cal_offset = 128 * 1024,
132b129699aSAnilkumar Kolli 		},
133b129699aSAnilkumar Kolli 		.max_radios = 2,
134b129699aSAnilkumar Kolli 		.bdf_addr = 0x4ABC0000,
135b129699aSAnilkumar Kolli 		.hw_ops = &ipq6018_ops,
136b129699aSAnilkumar Kolli 		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
137b129699aSAnilkumar Kolli 		.internal_sleep_clock = false,
138b129699aSAnilkumar Kolli 		.regs = &ipq8074_regs,
13916001e4bSAnilkumar Kolli 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
140b129699aSAnilkumar Kolli 		.host_ce_config = ath11k_host_ce_config_ipq8074,
141b129699aSAnilkumar Kolli 		.ce_count = 12,
142b129699aSAnilkumar Kolli 		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
143b129699aSAnilkumar Kolli 		.target_ce_count = 11,
144b129699aSAnilkumar Kolli 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
145b129699aSAnilkumar Kolli 		.svc_to_ce_map_len = 19,
146b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
147b129699aSAnilkumar Kolli 		.single_pdev_only = false,
148b129699aSAnilkumar Kolli 		.rxdma1_enable = true,
149b129699aSAnilkumar Kolli 		.num_rxmda_per_pdev = 1,
150b129699aSAnilkumar Kolli 		.rx_mac_buf_ring = false,
151b129699aSAnilkumar Kolli 		.vdev_start_delay = false,
152b129699aSAnilkumar Kolli 		.htt_peer_map_v2 = true,
153cc2ad754SKarthikeyan Periyasamy 
154cc2ad754SKarthikeyan Periyasamy 		.spectral = {
155cc2ad754SKarthikeyan Periyasamy 			.fft_sz = 4,
156cc2ad754SKarthikeyan Periyasamy 			.fft_pad_sz = 0,
1571cae9c00SKarthikeyan Periyasamy 			.summary_pad_sz = 0,
1581cae9c00SKarthikeyan Periyasamy 			.fft_hdr_len = 16,
1591cae9c00SKarthikeyan Periyasamy 			.max_fft_bins = 512,
160c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = true,
161cc2ad754SKarthikeyan Periyasamy 		},
1622626c269SKalle Valo 
1632626c269SKalle Valo 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
1642626c269SKalle Valo 					BIT(NL80211_IFTYPE_AP) |
1652626c269SKalle Valo 					BIT(NL80211_IFTYPE_MESH_POINT),
1663f6e6c32SKalle Valo 		.supports_monitor = true,
1675c1f74d2SAnilkumar Kolli 		.full_monitor_mode = false,
168e838c14aSCarl Huang 		.supports_shadow_regs = false,
169c83c500bSCarl Huang 		.idle_ps = false,
170b2beffa7SCarl Huang 		.supports_sta_ps = false,
171011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = true,
172011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = true,
1736fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = true,
174beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 0,
175beefee71SSeevalamuthu Mariappan 		.num_vdevs = 16 + 1,
176beefee71SSeevalamuthu Mariappan 		.num_peers = 512,
177d1b0c338SCarl Huang 		.supports_suspend = false,
178e678fbd4SKarthikeyan Periyasamy 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
17901417e57SWen Gong 		.supports_regdb = false,
1805088df05SBaochen Qiang 		.fix_l1ss = true,
181f951380aSP Praneesh 		.credit_flow = false,
18231582373SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
183734223d7SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_ipq8074,
18482c434c1SWen Gong 		.supports_dynamic_smps_6ghz = false,
1856452f0a3SP Praneesh 		.alloc_cacheable_memory = true,
186b488c766SWen Gong 		.supports_rssi_stats = false,
18742da1cc7SCheng Wang 		.fw_wmi_diag_event = false,
1880d6e997bSWen Gong 		.current_cc_support = false,
189691425b4SVenkateswara Naralasetty 		.dbr_debug_support = true,
1901e4ac717SBaochen Qiang 		.global_reset = false,
191652f69edSBaochen Qiang 		.bios_sar_capa = NULL,
19292c1858eSManikanta Pubbisetty 		.m3_fw_support = false,
19392c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = true,
19492c1858eSManikanta Pubbisetty 		.fixed_mem_region = true,
19592c1858eSManikanta Pubbisetty 		.static_window_map = false,
196d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
19773d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
1981d7f5145SBaochen Qiang 		.support_off_channel_tx = false,
1997d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = false,
200876eb848SBaochen Qiang 
201876eb848SBaochen Qiang 		.sram_dump = {},
2027636c9a6SManikanta Pubbisetty 
2037636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
20497c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
20569ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
206a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = false,
207b129699aSAnilkumar Kolli 	},
208b129699aSAnilkumar Kolli 	{
2099de2ad43SCarl Huang 		.name = "qca6390 hw2.0",
2109de2ad43SCarl Huang 		.hw_rev = ATH11K_HW_QCA6390_HW20,
2119de2ad43SCarl Huang 		.fw = {
2129de2ad43SCarl Huang 			.dir = "QCA6390/hw2.0",
2139de2ad43SCarl Huang 			.board_size = 256 * 1024,
214c72aa32dSAnilkumar Kolli 			.cal_offset = 128 * 1024,
2159de2ad43SCarl Huang 		},
2169de2ad43SCarl Huang 		.max_radios = 3,
2179de2ad43SCarl Huang 		.bdf_addr = 0x4B0C0000,
2189de2ad43SCarl Huang 		.hw_ops = &qca6390_ops,
219d4ecb90bSCarl Huang 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
220727fae14SCarl Huang 		.internal_sleep_clock = true,
2216976433cSCarl Huang 		.regs = &qca6390_regs,
22216001e4bSAnilkumar Kolli 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
223e3396b8bSCarl Huang 		.host_ce_config = ath11k_host_ce_config_qca6390,
224e3396b8bSCarl Huang 		.ce_count = 9,
225967c1d11SAnilkumar Kolli 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
226967c1d11SAnilkumar Kolli 		.target_ce_count = 9,
227967c1d11SAnilkumar Kolli 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
228967c1d11SAnilkumar Kolli 		.svc_to_ce_map_len = 14,
229b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
2305f859bc0SCarl Huang 		.single_pdev_only = true,
2317f6fc1ebSCarl Huang 		.rxdma1_enable = false,
2324152e420SCarl Huang 		.num_rxmda_per_pdev = 2,
2334152e420SCarl Huang 		.rx_mac_buf_ring = true,
234e7495035SCarl Huang 		.vdev_start_delay = true,
235a6275302SCarl Huang 		.htt_peer_map_v2 = false,
236cc2ad754SKarthikeyan Periyasamy 
237cc2ad754SKarthikeyan Periyasamy 		.spectral = {
238cc2ad754SKarthikeyan Periyasamy 			.fft_sz = 0,
239cc2ad754SKarthikeyan Periyasamy 			.fft_pad_sz = 0,
2401cae9c00SKarthikeyan Periyasamy 			.summary_pad_sz = 0,
2411cae9c00SKarthikeyan Periyasamy 			.fft_hdr_len = 0,
2421cae9c00SKarthikeyan Periyasamy 			.max_fft_bins = 0,
243c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = false,
244cc2ad754SKarthikeyan Periyasamy 		},
2452626c269SKalle Valo 
2462626c269SKalle Valo 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
2472626c269SKalle Valo 					BIT(NL80211_IFTYPE_AP),
2483f6e6c32SKalle Valo 		.supports_monitor = false,
2495c1f74d2SAnilkumar Kolli 		.full_monitor_mode = false,
250e838c14aSCarl Huang 		.supports_shadow_regs = true,
251c83c500bSCarl Huang 		.idle_ps = true,
252b2beffa7SCarl Huang 		.supports_sta_ps = true,
253011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = false,
254011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = false,
2556fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = false,
256beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 0,
257beefee71SSeevalamuthu Mariappan 		.num_vdevs = 16 + 1,
258beefee71SSeevalamuthu Mariappan 		.num_peers = 512,
259d1b0c338SCarl Huang 		.supports_suspend = true,
260e678fbd4SKarthikeyan Periyasamy 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
2610c104b61SWen Gong 		.supports_regdb = false,
2625088df05SBaochen Qiang 		.fix_l1ss = true,
263f951380aSP Praneesh 		.credit_flow = true,
26431582373SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
265734223d7SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_qca6390,
26682c434c1SWen Gong 		.supports_dynamic_smps_6ghz = false,
2676452f0a3SP Praneesh 		.alloc_cacheable_memory = false,
268b488c766SWen Gong 		.supports_rssi_stats = true,
26942da1cc7SCheng Wang 		.fw_wmi_diag_event = true,
2700d6e997bSWen Gong 		.current_cc_support = true,
271691425b4SVenkateswara Naralasetty 		.dbr_debug_support = false,
2721e4ac717SBaochen Qiang 		.global_reset = true,
273652f69edSBaochen Qiang 		.bios_sar_capa = NULL,
27492c1858eSManikanta Pubbisetty 		.m3_fw_support = true,
27592c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = false,
27692c1858eSManikanta Pubbisetty 		.fixed_mem_region = false,
27792c1858eSManikanta Pubbisetty 		.static_window_map = false,
278d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
27973d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
2801d7f5145SBaochen Qiang 		.support_off_channel_tx = true,
2817d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = true,
282876eb848SBaochen Qiang 
283876eb848SBaochen Qiang 		.sram_dump = {
284876eb848SBaochen Qiang 			.start = 0x01400000,
285876eb848SBaochen Qiang 			.end = 0x0171ffff,
286876eb848SBaochen Qiang 		},
2877636c9a6SManikanta Pubbisetty 
2887636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
28997c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
29069ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
291a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = true,
2929de2ad43SCarl Huang 	},
293a233811eSAnilkumar Kolli 	{
294a233811eSAnilkumar Kolli 		.name = "qcn9074 hw1.0",
295a233811eSAnilkumar Kolli 		.hw_rev = ATH11K_HW_QCN9074_HW10,
296a233811eSAnilkumar Kolli 		.fw = {
297a233811eSAnilkumar Kolli 			.dir = "QCN9074/hw1.0",
298a233811eSAnilkumar Kolli 			.board_size = 256 * 1024,
299c72aa32dSAnilkumar Kolli 			.cal_offset = 128 * 1024,
300a233811eSAnilkumar Kolli 		},
301a233811eSAnilkumar Kolli 		.max_radios = 1,
302a233811eSAnilkumar Kolli 		.single_pdev_only = false,
303a233811eSAnilkumar Kolli 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074,
3046fe6f68fSKarthikeyan Periyasamy 		.hw_ops = &qcn9074_ops,
3057dc67af0SKarthikeyan Periyasamy 		.ring_mask = &ath11k_hw_ring_mask_qcn9074,
3066fe6f68fSKarthikeyan Periyasamy 		.internal_sleep_clock = false,
3076fe6f68fSKarthikeyan Periyasamy 		.regs = &qcn9074_regs,
3086289ac2bSKarthikeyan Periyasamy 		.host_ce_config = ath11k_host_ce_config_qcn9074,
3096289ac2bSKarthikeyan Periyasamy 		.ce_count = 6,
3106289ac2bSKarthikeyan Periyasamy 		.target_ce_config = ath11k_target_ce_config_wlan_qcn9074,
3116289ac2bSKarthikeyan Periyasamy 		.target_ce_count = 9,
3126289ac2bSKarthikeyan Periyasamy 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
3136289ac2bSKarthikeyan Periyasamy 		.svc_to_ce_map_len = 18,
314b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
3156fe6f68fSKarthikeyan Periyasamy 		.rxdma1_enable = true,
3166fe6f68fSKarthikeyan Periyasamy 		.num_rxmda_per_pdev = 1,
3176fe6f68fSKarthikeyan Periyasamy 		.rx_mac_buf_ring = false,
3186fe6f68fSKarthikeyan Periyasamy 		.vdev_start_delay = false,
3196fe6f68fSKarthikeyan Periyasamy 		.htt_peer_map_v2 = true,
320cc2ad754SKarthikeyan Periyasamy 
321cc2ad754SKarthikeyan Periyasamy 		.spectral = {
322b72e86c0SKarthikeyan Periyasamy 			.fft_sz = 2,
323cc2ad754SKarthikeyan Periyasamy 			.fft_pad_sz = 0,
324b72e86c0SKarthikeyan Periyasamy 			.summary_pad_sz = 16,
325b72e86c0SKarthikeyan Periyasamy 			.fft_hdr_len = 24,
326b72e86c0SKarthikeyan Periyasamy 			.max_fft_bins = 1024,
327c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = false,
328cc2ad754SKarthikeyan Periyasamy 		},
329cc2ad754SKarthikeyan Periyasamy 
3306fe6f68fSKarthikeyan Periyasamy 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
3316fe6f68fSKarthikeyan Periyasamy 					BIT(NL80211_IFTYPE_AP) |
3326fe6f68fSKarthikeyan Periyasamy 					BIT(NL80211_IFTYPE_MESH_POINT),
3336fe6f68fSKarthikeyan Periyasamy 		.supports_monitor = true,
3345c1f74d2SAnilkumar Kolli 		.full_monitor_mode = true,
3356fe6f68fSKarthikeyan Periyasamy 		.supports_shadow_regs = false,
3366fe6f68fSKarthikeyan Periyasamy 		.idle_ps = false,
337b2beffa7SCarl Huang 		.supports_sta_ps = false,
338011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = false,
339*bdfc967bSAnilkumar Kolli 		.coldboot_cal_ftm = true,
340*bdfc967bSAnilkumar Kolli 		.cbcal_restart_fw = true,
341beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 2,
342beefee71SSeevalamuthu Mariappan 		.num_vdevs = 8,
343beefee71SSeevalamuthu Mariappan 		.num_peers = 128,
3446fe6f68fSKarthikeyan Periyasamy 		.supports_suspend = false,
345e678fbd4SKarthikeyan Periyasamy 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
34601417e57SWen Gong 		.supports_regdb = false,
3475088df05SBaochen Qiang 		.fix_l1ss = true,
348f951380aSP Praneesh 		.credit_flow = false,
34931582373SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
350734223d7SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_ipq8074,
35182c434c1SWen Gong 		.supports_dynamic_smps_6ghz = true,
3526452f0a3SP Praneesh 		.alloc_cacheable_memory = true,
353b488c766SWen Gong 		.supports_rssi_stats = false,
35442da1cc7SCheng Wang 		.fw_wmi_diag_event = false,
3550d6e997bSWen Gong 		.current_cc_support = false,
356691425b4SVenkateswara Naralasetty 		.dbr_debug_support = true,
3571e4ac717SBaochen Qiang 		.global_reset = false,
358652f69edSBaochen Qiang 		.bios_sar_capa = NULL,
35992c1858eSManikanta Pubbisetty 		.m3_fw_support = true,
36092c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = false,
36192c1858eSManikanta Pubbisetty 		.fixed_mem_region = false,
36292c1858eSManikanta Pubbisetty 		.static_window_map = true,
363d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
36473d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
3651d7f5145SBaochen Qiang 		.support_off_channel_tx = false,
3667d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = false,
367876eb848SBaochen Qiang 
368876eb848SBaochen Qiang 		.sram_dump = {},
3697636c9a6SManikanta Pubbisetty 
3707636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
37197c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
37269ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
373a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = false,
374a233811eSAnilkumar Kolli 	},
3750fbf1957SBaochen Qiang 	{
3760fbf1957SBaochen Qiang 		.name = "wcn6855 hw2.0",
3770fbf1957SBaochen Qiang 		.hw_rev = ATH11K_HW_WCN6855_HW20,
3780fbf1957SBaochen Qiang 		.fw = {
3790fbf1957SBaochen Qiang 			.dir = "WCN6855/hw2.0",
3800fbf1957SBaochen Qiang 			.board_size = 256 * 1024,
381c72aa32dSAnilkumar Kolli 			.cal_offset = 128 * 1024,
3820fbf1957SBaochen Qiang 		},
3830fbf1957SBaochen Qiang 		.max_radios = 3,
3840fbf1957SBaochen Qiang 		.bdf_addr = 0x4B0C0000,
3850fbf1957SBaochen Qiang 		.hw_ops = &wcn6855_ops,
3860fbf1957SBaochen Qiang 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
3870fbf1957SBaochen Qiang 		.internal_sleep_clock = true,
3880fbf1957SBaochen Qiang 		.regs = &wcn6855_regs,
3890fbf1957SBaochen Qiang 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
3900fbf1957SBaochen Qiang 		.host_ce_config = ath11k_host_ce_config_qca6390,
3910fbf1957SBaochen Qiang 		.ce_count = 9,
3920fbf1957SBaochen Qiang 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
3930fbf1957SBaochen Qiang 		.target_ce_count = 9,
3940fbf1957SBaochen Qiang 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
3950fbf1957SBaochen Qiang 		.svc_to_ce_map_len = 14,
396b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
3970fbf1957SBaochen Qiang 		.single_pdev_only = true,
3980fbf1957SBaochen Qiang 		.rxdma1_enable = false,
3990fbf1957SBaochen Qiang 		.num_rxmda_per_pdev = 2,
4000fbf1957SBaochen Qiang 		.rx_mac_buf_ring = true,
4010fbf1957SBaochen Qiang 		.vdev_start_delay = true,
4020fbf1957SBaochen Qiang 		.htt_peer_map_v2 = false,
403cc2ad754SKarthikeyan Periyasamy 
404cc2ad754SKarthikeyan Periyasamy 		.spectral = {
405cc2ad754SKarthikeyan Periyasamy 			.fft_sz = 0,
406cc2ad754SKarthikeyan Periyasamy 			.fft_pad_sz = 0,
4071cae9c00SKarthikeyan Periyasamy 			.summary_pad_sz = 0,
4081cae9c00SKarthikeyan Periyasamy 			.fft_hdr_len = 0,
4091cae9c00SKarthikeyan Periyasamy 			.max_fft_bins = 0,
410c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = false,
411cc2ad754SKarthikeyan Periyasamy 		},
4120fbf1957SBaochen Qiang 
4130fbf1957SBaochen Qiang 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
4140fbf1957SBaochen Qiang 					BIT(NL80211_IFTYPE_AP),
4150fbf1957SBaochen Qiang 		.supports_monitor = false,
4165c1f74d2SAnilkumar Kolli 		.full_monitor_mode = false,
4170fbf1957SBaochen Qiang 		.supports_shadow_regs = true,
4180fbf1957SBaochen Qiang 		.idle_ps = true,
419b2beffa7SCarl Huang 		.supports_sta_ps = true,
420011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = false,
421011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = false,
4226fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = false,
423beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 0,
424beefee71SSeevalamuthu Mariappan 		.num_vdevs = 16 + 1,
425beefee71SSeevalamuthu Mariappan 		.num_peers = 512,
4260fbf1957SBaochen Qiang 		.supports_suspend = true,
4270fbf1957SBaochen Qiang 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
42801417e57SWen Gong 		.supports_regdb = true,
4295088df05SBaochen Qiang 		.fix_l1ss = false,
430f951380aSP Praneesh 		.credit_flow = true,
43131582373SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
432734223d7SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_qca6390,
43382c434c1SWen Gong 		.supports_dynamic_smps_6ghz = false,
4346452f0a3SP Praneesh 		.alloc_cacheable_memory = false,
435b488c766SWen Gong 		.supports_rssi_stats = true,
43642da1cc7SCheng Wang 		.fw_wmi_diag_event = true,
4370d6e997bSWen Gong 		.current_cc_support = true,
438691425b4SVenkateswara Naralasetty 		.dbr_debug_support = false,
4391e4ac717SBaochen Qiang 		.global_reset = true,
440652f69edSBaochen Qiang 		.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
44192c1858eSManikanta Pubbisetty 		.m3_fw_support = true,
44292c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = false,
44392c1858eSManikanta Pubbisetty 		.fixed_mem_region = false,
44492c1858eSManikanta Pubbisetty 		.static_window_map = false,
445d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
44673d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
4471d7f5145SBaochen Qiang 		.support_off_channel_tx = true,
4487d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = true,
449876eb848SBaochen Qiang 
450876eb848SBaochen Qiang 		.sram_dump = {
451876eb848SBaochen Qiang 			.start = 0x01400000,
452876eb848SBaochen Qiang 			.end = 0x0177ffff,
453876eb848SBaochen Qiang 		},
4547636c9a6SManikanta Pubbisetty 
4557636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
45697c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
45769ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
458a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = true,
4590fbf1957SBaochen Qiang 	},
460d1147a31SBaochen Qiang 	{
461d1147a31SBaochen Qiang 		.name = "wcn6855 hw2.1",
462d1147a31SBaochen Qiang 		.hw_rev = ATH11K_HW_WCN6855_HW21,
463d1147a31SBaochen Qiang 		.fw = {
464d1147a31SBaochen Qiang 			.dir = "WCN6855/hw2.1",
465d1147a31SBaochen Qiang 			.board_size = 256 * 1024,
466d1147a31SBaochen Qiang 			.cal_offset = 128 * 1024,
467d1147a31SBaochen Qiang 		},
468d1147a31SBaochen Qiang 		.max_radios = 3,
469d1147a31SBaochen Qiang 		.bdf_addr = 0x4B0C0000,
470d1147a31SBaochen Qiang 		.hw_ops = &wcn6855_ops,
471d1147a31SBaochen Qiang 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
472d1147a31SBaochen Qiang 		.internal_sleep_clock = true,
473d1147a31SBaochen Qiang 		.regs = &wcn6855_regs,
474d1147a31SBaochen Qiang 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
475d1147a31SBaochen Qiang 		.host_ce_config = ath11k_host_ce_config_qca6390,
476d1147a31SBaochen Qiang 		.ce_count = 9,
477d1147a31SBaochen Qiang 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
478d1147a31SBaochen Qiang 		.target_ce_count = 9,
479d1147a31SBaochen Qiang 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
480d1147a31SBaochen Qiang 		.svc_to_ce_map_len = 14,
481d1147a31SBaochen Qiang 		.single_pdev_only = true,
482d1147a31SBaochen Qiang 		.rxdma1_enable = false,
483d1147a31SBaochen Qiang 		.num_rxmda_per_pdev = 2,
484d1147a31SBaochen Qiang 		.rx_mac_buf_ring = true,
485d1147a31SBaochen Qiang 		.vdev_start_delay = true,
486d1147a31SBaochen Qiang 		.htt_peer_map_v2 = false,
487d1147a31SBaochen Qiang 
488d1147a31SBaochen Qiang 		.spectral = {
489d1147a31SBaochen Qiang 			.fft_sz = 0,
490d1147a31SBaochen Qiang 			.fft_pad_sz = 0,
491d1147a31SBaochen Qiang 			.summary_pad_sz = 0,
492d1147a31SBaochen Qiang 			.fft_hdr_len = 0,
493d1147a31SBaochen Qiang 			.max_fft_bins = 0,
494c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = false,
495d1147a31SBaochen Qiang 		},
496d1147a31SBaochen Qiang 
497d1147a31SBaochen Qiang 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
498d1147a31SBaochen Qiang 					BIT(NL80211_IFTYPE_AP),
499d1147a31SBaochen Qiang 		.supports_monitor = false,
500d1147a31SBaochen Qiang 		.supports_shadow_regs = true,
501d1147a31SBaochen Qiang 		.idle_ps = true,
502d1147a31SBaochen Qiang 		.supports_sta_ps = true,
503011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = false,
504011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = false,
5056fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = false,
506beefee71SSeevalamuthu Mariappan 		.fw_mem_mode = 0,
507beefee71SSeevalamuthu Mariappan 		.num_vdevs = 16 + 1,
508beefee71SSeevalamuthu Mariappan 		.num_peers = 512,
509d1147a31SBaochen Qiang 		.supports_suspend = true,
510d1147a31SBaochen Qiang 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
51101417e57SWen Gong 		.supports_regdb = true,
512d1147a31SBaochen Qiang 		.fix_l1ss = false,
513d1147a31SBaochen Qiang 		.credit_flow = true,
514d1147a31SBaochen Qiang 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
515d1147a31SBaochen Qiang 		.hal_params = &ath11k_hw_hal_params_qca6390,
516d1147a31SBaochen Qiang 		.supports_dynamic_smps_6ghz = false,
517d1147a31SBaochen Qiang 		.alloc_cacheable_memory = false,
518b488c766SWen Gong 		.supports_rssi_stats = true,
51942da1cc7SCheng Wang 		.fw_wmi_diag_event = true,
5200d6e997bSWen Gong 		.current_cc_support = true,
521691425b4SVenkateswara Naralasetty 		.dbr_debug_support = false,
5221e4ac717SBaochen Qiang 		.global_reset = true,
523652f69edSBaochen Qiang 		.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
52492c1858eSManikanta Pubbisetty 		.m3_fw_support = true,
52592c1858eSManikanta Pubbisetty 		.fixed_bdf_addr = false,
52692c1858eSManikanta Pubbisetty 		.fixed_mem_region = false,
52792c1858eSManikanta Pubbisetty 		.static_window_map = false,
528d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = false,
52973d3e713SManikanta Pubbisetty 		.fixed_fw_mem = false,
5301d7f5145SBaochen Qiang 		.support_off_channel_tx = true,
5317d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = true,
532876eb848SBaochen Qiang 
533876eb848SBaochen Qiang 		.sram_dump = {
534876eb848SBaochen Qiang 			.start = 0x01400000,
535876eb848SBaochen Qiang 			.end = 0x0177ffff,
536876eb848SBaochen Qiang 		},
5377636c9a6SManikanta Pubbisetty 
5387636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = true,
53997c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
54069ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = false,
541a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = true,
542d1e1edfdSManikanta Pubbisetty 	},
543d1e1edfdSManikanta Pubbisetty 	{
544d1e1edfdSManikanta Pubbisetty 		.name = "wcn6750 hw1.0",
545d1e1edfdSManikanta Pubbisetty 		.hw_rev = ATH11K_HW_WCN6750_HW10,
546d1e1edfdSManikanta Pubbisetty 		.fw = {
547d1e1edfdSManikanta Pubbisetty 			.dir = "WCN6750/hw1.0",
548d1e1edfdSManikanta Pubbisetty 			.board_size = 256 * 1024,
549d1e1edfdSManikanta Pubbisetty 			.cal_offset = 128 * 1024,
550d1e1edfdSManikanta Pubbisetty 		},
551d1e1edfdSManikanta Pubbisetty 		.max_radios = 1,
552d1e1edfdSManikanta Pubbisetty 		.bdf_addr = 0x4B0C0000,
55349890d9cSManikanta Pubbisetty 		.hw_ops = &wcn6750_ops,
5547636c9a6SManikanta Pubbisetty 		.ring_mask = &ath11k_hw_ring_mask_wcn6750,
555d1e1edfdSManikanta Pubbisetty 		.internal_sleep_clock = false,
55649890d9cSManikanta Pubbisetty 		.regs = &wcn6750_regs,
557d1e1edfdSManikanta Pubbisetty 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750,
558d1e1edfdSManikanta Pubbisetty 		.host_ce_config = ath11k_host_ce_config_qca6390,
559d1e1edfdSManikanta Pubbisetty 		.ce_count = 9,
560d1e1edfdSManikanta Pubbisetty 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
561d1e1edfdSManikanta Pubbisetty 		.target_ce_count = 9,
562d1e1edfdSManikanta Pubbisetty 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
563d1e1edfdSManikanta Pubbisetty 		.svc_to_ce_map_len = 14,
564b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
565d1e1edfdSManikanta Pubbisetty 		.single_pdev_only = true,
566d1e1edfdSManikanta Pubbisetty 		.rxdma1_enable = false,
567d1e1edfdSManikanta Pubbisetty 		.num_rxmda_per_pdev = 1,
568d1e1edfdSManikanta Pubbisetty 		.rx_mac_buf_ring = true,
569d1e1edfdSManikanta Pubbisetty 		.vdev_start_delay = true,
570d1e1edfdSManikanta Pubbisetty 		.htt_peer_map_v2 = false,
571d1e1edfdSManikanta Pubbisetty 
572d1e1edfdSManikanta Pubbisetty 		.spectral = {
573d1e1edfdSManikanta Pubbisetty 			.fft_sz = 0,
574d1e1edfdSManikanta Pubbisetty 			.fft_pad_sz = 0,
575d1e1edfdSManikanta Pubbisetty 			.summary_pad_sz = 0,
576d1e1edfdSManikanta Pubbisetty 			.fft_hdr_len = 0,
577d1e1edfdSManikanta Pubbisetty 			.max_fft_bins = 0,
578c92f774aSTamizh Chelvam Raja 			.fragment_160mhz = false,
579d1e1edfdSManikanta Pubbisetty 		},
580d1e1edfdSManikanta Pubbisetty 
581d1e1edfdSManikanta Pubbisetty 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
582d1e1edfdSManikanta Pubbisetty 					BIT(NL80211_IFTYPE_AP),
583d1e1edfdSManikanta Pubbisetty 		.supports_monitor = false,
584d1e1edfdSManikanta Pubbisetty 		.supports_shadow_regs = true,
585d1e1edfdSManikanta Pubbisetty 		.idle_ps = true,
586d1e1edfdSManikanta Pubbisetty 		.supports_sta_ps = true,
587011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = true,
588011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = true,
5896fe62a8cSManikanta Pubbisetty 		.cbcal_restart_fw = false,
590d1e1edfdSManikanta Pubbisetty 		.fw_mem_mode = 0,
591d1e1edfdSManikanta Pubbisetty 		.num_vdevs = 16 + 1,
592d1e1edfdSManikanta Pubbisetty 		.num_peers = 512,
593d1e1edfdSManikanta Pubbisetty 		.supports_suspend = false,
594e67ba197SManikanta Pubbisetty 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
595d1e1edfdSManikanta Pubbisetty 		.supports_regdb = true,
596d1e1edfdSManikanta Pubbisetty 		.fix_l1ss = false,
597d1e1edfdSManikanta Pubbisetty 		.credit_flow = true,
5987636c9a6SManikanta Pubbisetty 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
5997636c9a6SManikanta Pubbisetty 		.hal_params = &ath11k_hw_hal_params_wcn6750,
600d1e1edfdSManikanta Pubbisetty 		.supports_dynamic_smps_6ghz = false,
601d1e1edfdSManikanta Pubbisetty 		.alloc_cacheable_memory = false,
602d1e1edfdSManikanta Pubbisetty 		.supports_rssi_stats = true,
603d1e1edfdSManikanta Pubbisetty 		.fw_wmi_diag_event = false,
604d1e1edfdSManikanta Pubbisetty 		.current_cc_support = true,
605d1e1edfdSManikanta Pubbisetty 		.dbr_debug_support = false,
606d1e1edfdSManikanta Pubbisetty 		.global_reset = false,
607abf57d84SYoughandhar Chintala 		.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
608d1e1edfdSManikanta Pubbisetty 		.m3_fw_support = false,
609d1e1edfdSManikanta Pubbisetty 		.fixed_bdf_addr = false,
610d1e1edfdSManikanta Pubbisetty 		.fixed_mem_region = false,
611d1e1edfdSManikanta Pubbisetty 		.static_window_map = true,
612d1e1edfdSManikanta Pubbisetty 		.hybrid_bus_type = true,
61373d3e713SManikanta Pubbisetty 		.fixed_fw_mem = true,
61436893e45SManikanta Pubbisetty 		.support_off_channel_tx = true,
6157d992bd4SManikanta Pubbisetty 		.supports_multi_bssid = true,
616876eb848SBaochen Qiang 
617876eb848SBaochen Qiang 		.sram_dump = {},
6187636c9a6SManikanta Pubbisetty 
6197636c9a6SManikanta Pubbisetty 		.tcl_ring_retry = false,
62097c9e37cSManikanta Pubbisetty 		.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
62169ccee61SManikanta Pubbisetty 		.smp2p_wow_exit = true,
622a018750aSYoughandhar Chintala 		.support_fw_mac_sequence = true,
623d1147a31SBaochen Qiang 	},
6248dfe875aSSriram R 	{
6258dfe875aSSriram R 		.hw_rev = ATH11K_HW_IPQ5018_HW10,
6268dfe875aSSriram R 		.name = "ipq5018 hw1.0",
6278dfe875aSSriram R 		.fw = {
6288dfe875aSSriram R 			.dir = "IPQ5018/hw1.0",
6298dfe875aSSriram R 			.board_size = 256 * 1024,
6308dfe875aSSriram R 			.cal_offset = 128 * 1024,
6318dfe875aSSriram R 		},
6328dfe875aSSriram R 		.max_radios = MAX_RADIOS_5018,
6338dfe875aSSriram R 		.bdf_addr = 0x4BA00000,
6348dfe875aSSriram R 		/* hal_desc_sz and hw ops are similar to qcn9074 */
6358dfe875aSSriram R 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
6368dfe875aSSriram R 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
6378dfe875aSSriram R 		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
6388dfe875aSSriram R 		.credit_flow = false,
6398dfe875aSSriram R 		.max_tx_ring = 1,
6408dfe875aSSriram R 		.spectral = {
6418dfe875aSSriram R 			.fft_sz = 2,
6428dfe875aSSriram R 			.fft_pad_sz = 0,
6438dfe875aSSriram R 			.summary_pad_sz = 16,
6448dfe875aSSriram R 			.fft_hdr_len = 24,
6458dfe875aSSriram R 			.max_fft_bins = 1024,
6468dfe875aSSriram R 		},
6478dfe875aSSriram R 		.internal_sleep_clock = false,
648711b80acSSriram R 		.regs = &ipq5018_regs,
649ba60f279SSriram R 		.hw_ops = &ipq5018_ops,
6508dfe875aSSriram R 		.host_ce_config = ath11k_host_ce_config_qcn9074,
6518dfe875aSSriram R 		.ce_count = CE_CNT_5018,
65226af7aabSSriram R 		.target_ce_config = ath11k_target_ce_config_wlan_ipq5018,
65326af7aabSSriram R 		.target_ce_count = TARGET_CE_CNT_5018,
65426af7aabSSriram R 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018,
65526af7aabSSriram R 		.svc_to_ce_map_len = SVC_CE_MAP_LEN_5018,
656b42b3678SSriram R 		.ce_ie_addr = &ath11k_ce_ie_addr_ipq5018,
657b42b3678SSriram R 		.ce_remap = &ath11k_ce_remap_ipq5018,
6588dfe875aSSriram R 		.rxdma1_enable = true,
6598dfe875aSSriram R 		.num_rxmda_per_pdev = RXDMA_PER_PDEV_5018,
6608dfe875aSSriram R 		.rx_mac_buf_ring = false,
6618dfe875aSSriram R 		.vdev_start_delay = false,
6628dfe875aSSriram R 		.htt_peer_map_v2 = true,
6638dfe875aSSriram R 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
6648dfe875aSSriram R 			BIT(NL80211_IFTYPE_AP) |
6658dfe875aSSriram R 			BIT(NL80211_IFTYPE_MESH_POINT),
6668dfe875aSSriram R 		.supports_monitor = false,
6678dfe875aSSriram R 		.supports_sta_ps = false,
6688dfe875aSSriram R 		.supports_shadow_regs = false,
6698dfe875aSSriram R 		.fw_mem_mode = 0,
6708dfe875aSSriram R 		.num_vdevs = 16 + 1,
6718dfe875aSSriram R 		.num_peers = 512,
6728dfe875aSSriram R 		.supports_regdb = false,
6738dfe875aSSriram R 		.idle_ps = false,
6748dfe875aSSriram R 		.supports_suspend = false,
6758dfe875aSSriram R 		.hal_params = &ath11k_hw_hal_params_ipq8074,
6768dfe875aSSriram R 		.single_pdev_only = false,
677011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_mm = true,
678011e5a30SSeevalamuthu Mariappan 		.coldboot_cal_ftm = true,
67980c5390eSZiyang Huang 		.cbcal_restart_fw = true,
6808dfe875aSSriram R 		.fix_l1ss = true,
6818dfe875aSSriram R 		.supports_dynamic_smps_6ghz = false,
6828dfe875aSSriram R 		.alloc_cacheable_memory = true,
6838dfe875aSSriram R 		.supports_rssi_stats = false,
6848dfe875aSSriram R 		.fw_wmi_diag_event = false,
6858dfe875aSSriram R 		.current_cc_support = false,
6868dfe875aSSriram R 		.dbr_debug_support = true,
6878dfe875aSSriram R 		.global_reset = false,
6888dfe875aSSriram R 		.bios_sar_capa = NULL,
6898dfe875aSSriram R 		.m3_fw_support = false,
6908dfe875aSSriram R 		.fixed_bdf_addr = true,
6918dfe875aSSriram R 		.fixed_mem_region = true,
6928dfe875aSSriram R 		.static_window_map = false,
6938dfe875aSSriram R 		.hybrid_bus_type = false,
6948dfe875aSSriram R 		.fixed_fw_mem = false,
6958dfe875aSSriram R 		.support_off_channel_tx = false,
6968dfe875aSSriram R 		.supports_multi_bssid = false,
6978dfe875aSSriram R 
6988dfe875aSSriram R 		.sram_dump = {},
6998dfe875aSSriram R 
7008dfe875aSSriram R 		.tcl_ring_retry = true,
7018dfe875aSSriram R 		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
7028dfe875aSSriram R 		.smp2p_wow_exit = false,
7038dfe875aSSriram R 		.support_fw_mac_sequence = false,
7048dfe875aSSriram R 	},
705d5c65159SKalle Valo };
706d5c65159SKalle Valo 
ath11k_core_get_single_pdev(struct ath11k_base * ab)707ba9177fcSCarl Huang static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
708ba9177fcSCarl Huang {
709ba9177fcSCarl Huang 	WARN_ON(!ab->hw_params.single_pdev_only);
710ba9177fcSCarl Huang 
711ba9177fcSCarl Huang 	return &ab->pdevs[0];
712ba9177fcSCarl Huang }
713ba9177fcSCarl Huang 
ath11k_fw_stats_pdevs_free(struct list_head * head)714ec8918f9SAditya Kumar Singh void ath11k_fw_stats_pdevs_free(struct list_head *head)
715ec8918f9SAditya Kumar Singh {
716ec8918f9SAditya Kumar Singh 	struct ath11k_fw_stats_pdev *i, *tmp;
717ec8918f9SAditya Kumar Singh 
718ec8918f9SAditya Kumar Singh 	list_for_each_entry_safe(i, tmp, head, list) {
719ec8918f9SAditya Kumar Singh 		list_del(&i->list);
720ec8918f9SAditya Kumar Singh 		kfree(i);
721ec8918f9SAditya Kumar Singh 	}
722ec8918f9SAditya Kumar Singh }
723ec8918f9SAditya Kumar Singh 
ath11k_fw_stats_vdevs_free(struct list_head * head)724ec8918f9SAditya Kumar Singh void ath11k_fw_stats_vdevs_free(struct list_head *head)
725ec8918f9SAditya Kumar Singh {
726ec8918f9SAditya Kumar Singh 	struct ath11k_fw_stats_vdev *i, *tmp;
727ec8918f9SAditya Kumar Singh 
728ec8918f9SAditya Kumar Singh 	list_for_each_entry_safe(i, tmp, head, list) {
729ec8918f9SAditya Kumar Singh 		list_del(&i->list);
730ec8918f9SAditya Kumar Singh 		kfree(i);
731ec8918f9SAditya Kumar Singh 	}
732ec8918f9SAditya Kumar Singh }
733ec8918f9SAditya Kumar Singh 
ath11k_fw_stats_bcn_free(struct list_head * head)734ec8918f9SAditya Kumar Singh void ath11k_fw_stats_bcn_free(struct list_head *head)
735ec8918f9SAditya Kumar Singh {
736ec8918f9SAditya Kumar Singh 	struct ath11k_fw_stats_bcn *i, *tmp;
737ec8918f9SAditya Kumar Singh 
738ec8918f9SAditya Kumar Singh 	list_for_each_entry_safe(i, tmp, head, list) {
739ec8918f9SAditya Kumar Singh 		list_del(&i->list);
740ec8918f9SAditya Kumar Singh 		kfree(i);
741ec8918f9SAditya Kumar Singh 	}
742ec8918f9SAditya Kumar Singh }
743ec8918f9SAditya Kumar Singh 
ath11k_fw_stats_init(struct ath11k * ar)744ec8918f9SAditya Kumar Singh void ath11k_fw_stats_init(struct ath11k *ar)
745ec8918f9SAditya Kumar Singh {
746ec8918f9SAditya Kumar Singh 	INIT_LIST_HEAD(&ar->fw_stats.pdevs);
747ec8918f9SAditya Kumar Singh 	INIT_LIST_HEAD(&ar->fw_stats.vdevs);
748ec8918f9SAditya Kumar Singh 	INIT_LIST_HEAD(&ar->fw_stats.bcn);
749ec8918f9SAditya Kumar Singh 
750ec8918f9SAditya Kumar Singh 	init_completion(&ar->fw_stats_complete);
751ec8918f9SAditya Kumar Singh }
752ec8918f9SAditya Kumar Singh 
ath11k_fw_stats_free(struct ath11k_fw_stats * stats)753ec8918f9SAditya Kumar Singh void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
754ec8918f9SAditya Kumar Singh {
755ec8918f9SAditya Kumar Singh 	ath11k_fw_stats_pdevs_free(&stats->pdevs);
756ec8918f9SAditya Kumar Singh 	ath11k_fw_stats_vdevs_free(&stats->vdevs);
757ec8918f9SAditya Kumar Singh 	ath11k_fw_stats_bcn_free(&stats->bcn);
758ec8918f9SAditya Kumar Singh }
759ec8918f9SAditya Kumar Singh 
ath11k_core_coldboot_cal_support(struct ath11k_base * ab)760011e5a30SSeevalamuthu Mariappan bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab)
761011e5a30SSeevalamuthu Mariappan {
762011e5a30SSeevalamuthu Mariappan 	if (!ath11k_cold_boot_cal)
763011e5a30SSeevalamuthu Mariappan 		return false;
764011e5a30SSeevalamuthu Mariappan 
765011e5a30SSeevalamuthu Mariappan 	if (ath11k_ftm_mode)
766011e5a30SSeevalamuthu Mariappan 		return ab->hw_params.coldboot_cal_ftm;
767011e5a30SSeevalamuthu Mariappan 
768011e5a30SSeevalamuthu Mariappan 	else
769011e5a30SSeevalamuthu Mariappan 		return ab->hw_params.coldboot_cal_mm;
770011e5a30SSeevalamuthu Mariappan }
771011e5a30SSeevalamuthu Mariappan 
ath11k_core_suspend(struct ath11k_base * ab)772d1b0c338SCarl Huang int ath11k_core_suspend(struct ath11k_base *ab)
773d1b0c338SCarl Huang {
774d1b0c338SCarl Huang 	int ret;
775ba9177fcSCarl Huang 	struct ath11k_pdev *pdev;
776ba9177fcSCarl Huang 	struct ath11k *ar;
777d1b0c338SCarl Huang 
778d1b0c338SCarl Huang 	if (!ab->hw_params.supports_suspend)
779d1b0c338SCarl Huang 		return -EOPNOTSUPP;
780d1b0c338SCarl Huang 
781ba9177fcSCarl Huang 	/* so far single_pdev_only chips have supports_suspend as true
782ba9177fcSCarl Huang 	 * and only the first pdev is valid.
783ba9177fcSCarl Huang 	 */
784ba9177fcSCarl Huang 	pdev = ath11k_core_get_single_pdev(ab);
785ba9177fcSCarl Huang 	ar = pdev->ar;
786ba9177fcSCarl Huang 	if (!ar || ar->state != ATH11K_STATE_OFF)
787ba9177fcSCarl Huang 		return 0;
788ba9177fcSCarl Huang 
789d1b0c338SCarl Huang 	ret = ath11k_dp_rx_pktlog_stop(ab, true);
790d1b0c338SCarl Huang 	if (ret) {
791d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
792d1b0c338SCarl Huang 			    ret);
793d1b0c338SCarl Huang 		return ret;
794d1b0c338SCarl Huang 	}
795d1b0c338SCarl Huang 
796ba9177fcSCarl Huang 	ret = ath11k_mac_wait_tx_complete(ar);
797ba9177fcSCarl Huang 	if (ret) {
798ba9177fcSCarl Huang 		ath11k_warn(ab, "failed to wait tx complete: %d\n", ret);
799ba9177fcSCarl Huang 		return ret;
800ba9177fcSCarl Huang 	}
801ba9177fcSCarl Huang 
802d1b0c338SCarl Huang 	ret = ath11k_wow_enable(ab);
803d1b0c338SCarl Huang 	if (ret) {
804d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);
805d1b0c338SCarl Huang 		return ret;
806d1b0c338SCarl Huang 	}
807d1b0c338SCarl Huang 
808d1b0c338SCarl Huang 	ret = ath11k_dp_rx_pktlog_stop(ab, false);
809d1b0c338SCarl Huang 	if (ret) {
810d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
811d1b0c338SCarl Huang 			    ret);
812d1b0c338SCarl Huang 		return ret;
813d1b0c338SCarl Huang 	}
814d1b0c338SCarl Huang 
815d1b0c338SCarl Huang 	ath11k_ce_stop_shadow_timers(ab);
816d1b0c338SCarl Huang 	ath11k_dp_stop_shadow_timers(ab);
817d1b0c338SCarl Huang 
818d1b0c338SCarl Huang 	ath11k_hif_irq_disable(ab);
819d1b0c338SCarl Huang 	ath11k_hif_ce_irq_disable(ab);
820d1b0c338SCarl Huang 
821d1b0c338SCarl Huang 	ret = ath11k_hif_suspend(ab);
8229b094562SDan Carpenter 	if (ret) {
823d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
824d1b0c338SCarl Huang 		return ret;
825d1b0c338SCarl Huang 	}
826d1b0c338SCarl Huang 
827d1b0c338SCarl Huang 	return 0;
828d1b0c338SCarl Huang }
829d1b0c338SCarl Huang EXPORT_SYMBOL(ath11k_core_suspend);
830d1b0c338SCarl Huang 
ath11k_core_resume(struct ath11k_base * ab)831d1b0c338SCarl Huang int ath11k_core_resume(struct ath11k_base *ab)
832d1b0c338SCarl Huang {
833d1b0c338SCarl Huang 	int ret;
834ba9177fcSCarl Huang 	struct ath11k_pdev *pdev;
835ba9177fcSCarl Huang 	struct ath11k *ar;
836d1b0c338SCarl Huang 
837d1b0c338SCarl Huang 	if (!ab->hw_params.supports_suspend)
838d1b0c338SCarl Huang 		return -EOPNOTSUPP;
839d1b0c338SCarl Huang 
840ba9177fcSCarl Huang 	/* so far signle_pdev_only chips have supports_suspend as true
841ba9177fcSCarl Huang 	 * and only the first pdev is valid.
842ba9177fcSCarl Huang 	 */
843ba9177fcSCarl Huang 	pdev = ath11k_core_get_single_pdev(ab);
844ba9177fcSCarl Huang 	ar = pdev->ar;
845ba9177fcSCarl Huang 	if (!ar || ar->state != ATH11K_STATE_OFF)
846ba9177fcSCarl Huang 		return 0;
847ba9177fcSCarl Huang 
848d1b0c338SCarl Huang 	ret = ath11k_hif_resume(ab);
849d1b0c338SCarl Huang 	if (ret) {
850d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
851d1b0c338SCarl Huang 		return ret;
852d1b0c338SCarl Huang 	}
853d1b0c338SCarl Huang 
854d1b0c338SCarl Huang 	ath11k_hif_ce_irq_enable(ab);
855d1b0c338SCarl Huang 	ath11k_hif_irq_enable(ab);
856d1b0c338SCarl Huang 
857d1b0c338SCarl Huang 	ret = ath11k_dp_rx_pktlog_start(ab);
858d1b0c338SCarl Huang 	if (ret) {
859d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
860d1b0c338SCarl Huang 			    ret);
861d1b0c338SCarl Huang 		return ret;
862d1b0c338SCarl Huang 	}
863d1b0c338SCarl Huang 
864d1b0c338SCarl Huang 	ret = ath11k_wow_wakeup(ab);
865d1b0c338SCarl Huang 	if (ret) {
866d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);
867d1b0c338SCarl Huang 		return ret;
868d1b0c338SCarl Huang 	}
869d1b0c338SCarl Huang 
870d1b0c338SCarl Huang 	return 0;
871d1b0c338SCarl Huang }
872d1b0c338SCarl Huang EXPORT_SYMBOL(ath11k_core_resume);
873d1b0c338SCarl Huang 
ath11k_core_check_cc_code_bdfext(const struct dmi_header * hdr,void * data)87466721bb4SWen Gong static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)
8759d97114dSWen Gong {
8769d97114dSWen Gong 	struct ath11k_base *ab = data;
8779d97114dSWen Gong 	const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC;
8789d97114dSWen Gong 	struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr;
8799d97114dSWen Gong 	ssize_t copied;
8809d97114dSWen Gong 	size_t len;
8819d97114dSWen Gong 	int i;
8829d97114dSWen Gong 
8839d97114dSWen Gong 	if (ab->qmi.target.bdf_ext[0] != '\0')
8849d97114dSWen Gong 		return;
8859d97114dSWen Gong 
8869d97114dSWen Gong 	if (hdr->type != ATH11K_SMBIOS_BDF_EXT_TYPE)
8879d97114dSWen Gong 		return;
8889d97114dSWen Gong 
8899d97114dSWen Gong 	if (hdr->length != ATH11K_SMBIOS_BDF_EXT_LENGTH) {
8909d97114dSWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
8919d97114dSWen Gong 			   "wrong smbios bdf ext type length (%d).\n",
8929d97114dSWen Gong 			   hdr->length);
8939d97114dSWen Gong 		return;
8949d97114dSWen Gong 	}
8959d97114dSWen Gong 
89666721bb4SWen Gong 	spin_lock_bh(&ab->base_lock);
89766721bb4SWen Gong 
89866721bb4SWen Gong 	switch (smbios->country_code_flag) {
89966721bb4SWen Gong 	case ATH11K_SMBIOS_CC_ISO:
90066721bb4SWen Gong 		ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff;
90166721bb4SWen Gong 		ab->new_alpha2[1] = smbios->cc_code & 0xff;
902fc3b984aSKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios cc_code %c%c\n",
90366721bb4SWen Gong 			   ab->new_alpha2[0], ab->new_alpha2[1]);
90466721bb4SWen Gong 		break;
90566721bb4SWen Gong 	case ATH11K_SMBIOS_CC_WW:
90666721bb4SWen Gong 		ab->new_alpha2[0] = '0';
90766721bb4SWen Gong 		ab->new_alpha2[1] = '0';
908fc3b984aSKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios worldwide regdomain\n");
90966721bb4SWen Gong 		break;
91066721bb4SWen Gong 	default:
911fc3b984aSKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "ignore smbios country code setting %d\n",
91266721bb4SWen Gong 			   smbios->country_code_flag);
91366721bb4SWen Gong 		break;
91466721bb4SWen Gong 	}
91566721bb4SWen Gong 
91666721bb4SWen Gong 	spin_unlock_bh(&ab->base_lock);
91766721bb4SWen Gong 
9189d97114dSWen Gong 	if (!smbios->bdf_enabled) {
9199d97114dSWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "bdf variant name not found.\n");
9209d97114dSWen Gong 		return;
9219d97114dSWen Gong 	}
9229d97114dSWen Gong 
9239d97114dSWen Gong 	/* Only one string exists (per spec) */
9249d97114dSWen Gong 	if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
9259d97114dSWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
9269d97114dSWen Gong 			   "bdf variant magic does not match.\n");
9279d97114dSWen Gong 		return;
9289d97114dSWen Gong 	}
9299d97114dSWen Gong 
9309d97114dSWen Gong 	len = min_t(size_t,
9319d97114dSWen Gong 		    strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
9329d97114dSWen Gong 	for (i = 0; i < len; i++) {
9339d97114dSWen Gong 		if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
9349d97114dSWen Gong 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
9359d97114dSWen Gong 				   "bdf variant name contains non ascii chars.\n");
9369d97114dSWen Gong 			return;
9379d97114dSWen Gong 		}
9389d97114dSWen Gong 	}
9399d97114dSWen Gong 
9409d97114dSWen Gong 	/* Copy extension name without magic prefix */
9419d97114dSWen Gong 	copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
9429d97114dSWen Gong 			 sizeof(ab->qmi.target.bdf_ext));
9439d97114dSWen Gong 	if (copied < 0) {
9449d97114dSWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
9459d97114dSWen Gong 			   "bdf variant string is longer than the buffer can accommodate\n");
9469d97114dSWen Gong 		return;
9479d97114dSWen Gong 	}
9489d97114dSWen Gong 
9499d97114dSWen Gong 	ath11k_dbg(ab, ATH11K_DBG_BOOT,
9509d97114dSWen Gong 		   "found and validated bdf variant smbios_type 0x%x bdf %s\n",
9519d97114dSWen Gong 		   ATH11K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
9529d97114dSWen Gong }
9539d97114dSWen Gong 
ath11k_core_check_smbios(struct ath11k_base * ab)9549d97114dSWen Gong int ath11k_core_check_smbios(struct ath11k_base *ab)
9559d97114dSWen Gong {
9569d97114dSWen Gong 	ab->qmi.target.bdf_ext[0] = '\0';
95766721bb4SWen Gong 	dmi_walk(ath11k_core_check_cc_code_bdfext, ab);
9589d97114dSWen Gong 
9599d97114dSWen Gong 	if (ab->qmi.target.bdf_ext[0] == '\0')
9609d97114dSWen Gong 		return -ENODATA;
9619d97114dSWen Gong 
9629d97114dSWen Gong 	return 0;
9639d97114dSWen Gong }
9649d97114dSWen Gong 
ath11k_core_check_dt(struct ath11k_base * ab)96514f43c5fSSven Eckelmann int ath11k_core_check_dt(struct ath11k_base *ab)
96614f43c5fSSven Eckelmann {
96714f43c5fSSven Eckelmann 	size_t max_len = sizeof(ab->qmi.target.bdf_ext);
96814f43c5fSSven Eckelmann 	const char *variant = NULL;
96914f43c5fSSven Eckelmann 	struct device_node *node;
97014f43c5fSSven Eckelmann 
97114f43c5fSSven Eckelmann 	node = ab->dev->of_node;
97214f43c5fSSven Eckelmann 	if (!node)
97314f43c5fSSven Eckelmann 		return -ENOENT;
97414f43c5fSSven Eckelmann 
97514f43c5fSSven Eckelmann 	of_property_read_string(node, "qcom,ath11k-calibration-variant",
97614f43c5fSSven Eckelmann 				&variant);
97714f43c5fSSven Eckelmann 	if (!variant)
97814f43c5fSSven Eckelmann 		return -ENODATA;
97914f43c5fSSven Eckelmann 
98014f43c5fSSven Eckelmann 	if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0)
98114f43c5fSSven Eckelmann 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
98214f43c5fSSven Eckelmann 			   "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
98314f43c5fSSven Eckelmann 			    variant);
98414f43c5fSSven Eckelmann 
98514f43c5fSSven Eckelmann 	return 0;
98614f43c5fSSven Eckelmann }
98714f43c5fSSven Eckelmann 
__ath11k_core_create_board_name(struct ath11k_base * ab,char * name,size_t name_len,bool with_variant,bool bus_type_mode)98862abdc06SWen Gong static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
98988ca8920SWen Gong 					   size_t name_len, bool with_variant,
99088ca8920SWen Gong 					   bool bus_type_mode)
991d5c65159SKalle Valo {
99214f43c5fSSven Eckelmann 	/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
99314f43c5fSSven Eckelmann 	char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
99414f43c5fSSven Eckelmann 
99562abdc06SWen Gong 	if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')
99614f43c5fSSven Eckelmann 		scnprintf(variant, sizeof(variant), ",variant=%s",
99714f43c5fSSven Eckelmann 			  ab->qmi.target.bdf_ext);
99814f43c5fSSven Eckelmann 
999fc95d10aSWen Gong 	switch (ab->id.bdf_search) {
1000fc95d10aSWen Gong 	case ATH11K_BDF_SEARCH_BUS_AND_BOARD:
100188ca8920SWen Gong 		if (bus_type_mode)
100288ca8920SWen Gong 			scnprintf(name, name_len,
100388ca8920SWen Gong 				  "bus=%s",
100488ca8920SWen Gong 				  ath11k_bus_str(ab->hif.bus));
100588ca8920SWen Gong 		else
1006fc95d10aSWen Gong 			scnprintf(name, name_len,
1007fc95d10aSWen Gong 				  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
1008fc95d10aSWen Gong 				  ath11k_bus_str(ab->hif.bus),
1009fc95d10aSWen Gong 				  ab->id.vendor, ab->id.device,
1010fc95d10aSWen Gong 				  ab->id.subsystem_vendor,
1011fc95d10aSWen Gong 				  ab->id.subsystem_device,
1012fc95d10aSWen Gong 				  ab->qmi.target.chip_id,
1013fc95d10aSWen Gong 				  ab->qmi.target.board_id,
1014fc95d10aSWen Gong 				  variant);
1015fc95d10aSWen Gong 		break;
1016fc95d10aSWen Gong 	default:
1017d5c65159SKalle Valo 		scnprintf(name, name_len,
101814f43c5fSSven Eckelmann 			  "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
10196eb6ea51SGovind Singh 			  ath11k_bus_str(ab->hif.bus),
1020d5c65159SKalle Valo 			  ab->qmi.target.chip_id,
102114f43c5fSSven Eckelmann 			  ab->qmi.target.board_id, variant);
1022fc95d10aSWen Gong 		break;
1023fc95d10aSWen Gong 	}
1024d5c65159SKalle Valo 
1025fc3b984aSKalle Valo 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board name '%s'\n", name);
1026d5c65159SKalle Valo 
1027d5c65159SKalle Valo 	return 0;
1028d5c65159SKalle Valo }
1029d5c65159SKalle Valo 
ath11k_core_create_board_name(struct ath11k_base * ab,char * name,size_t name_len)103062abdc06SWen Gong static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
103162abdc06SWen Gong 					 size_t name_len)
103262abdc06SWen Gong {
103388ca8920SWen Gong 	return __ath11k_core_create_board_name(ab, name, name_len, true, false);
103462abdc06SWen Gong }
103562abdc06SWen Gong 
ath11k_core_create_fallback_board_name(struct ath11k_base * ab,char * name,size_t name_len)103662abdc06SWen Gong static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name,
103762abdc06SWen Gong 						  size_t name_len)
103862abdc06SWen Gong {
103988ca8920SWen Gong 	return __ath11k_core_create_board_name(ab, name, name_len, false, false);
104088ca8920SWen Gong }
104188ca8920SWen Gong 
ath11k_core_create_bus_type_board_name(struct ath11k_base * ab,char * name,size_t name_len)104288ca8920SWen Gong static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name,
104388ca8920SWen Gong 						  size_t name_len)
104488ca8920SWen Gong {
104588ca8920SWen Gong 	return __ath11k_core_create_board_name(ab, name, name_len, false, true);
104662abdc06SWen Gong }
104762abdc06SWen Gong 
ath11k_core_firmware_request(struct ath11k_base * ab,const char * file)10487b57b2ddSKalle Valo const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
1049d5c65159SKalle Valo 						    const char *file)
1050d5c65159SKalle Valo {
1051d5c65159SKalle Valo 	const struct firmware *fw;
105234d9fc80SKalle Valo 	char path[100];
1053d5c65159SKalle Valo 	int ret;
1054d5c65159SKalle Valo 
1055d5c65159SKalle Valo 	if (file == NULL)
1056d5c65159SKalle Valo 		return ERR_PTR(-ENOENT);
1057d5c65159SKalle Valo 
105834d9fc80SKalle Valo 	ath11k_core_create_firmware_path(ab, file, path, sizeof(path));
1059d5c65159SKalle Valo 
106034d9fc80SKalle Valo 	ret = firmware_request_nowarn(&fw, path, ab->dev);
1061d5c65159SKalle Valo 	if (ret)
1062d5c65159SKalle Valo 		return ERR_PTR(ret);
10637b57b2ddSKalle Valo 
1064fc3b984aSKalle Valo 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "firmware request %s size %zu\n",
106534d9fc80SKalle Valo 		   path, fw->size);
1066d5c65159SKalle Valo 
1067d5c65159SKalle Valo 	return fw;
1068d5c65159SKalle Valo }
1069d5c65159SKalle Valo 
ath11k_core_free_bdf(struct ath11k_base * ab,struct ath11k_board_data * bd)1070d5c65159SKalle Valo void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
1071d5c65159SKalle Valo {
1072d5c65159SKalle Valo 	if (!IS_ERR(bd->fw))
1073d5c65159SKalle Valo 		release_firmware(bd->fw);
1074d5c65159SKalle Valo 
1075d5c65159SKalle Valo 	memset(bd, 0, sizeof(*bd));
1076d5c65159SKalle Valo }
1077d5c65159SKalle Valo 
ath11k_core_parse_bd_ie_board(struct ath11k_base * ab,struct ath11k_board_data * bd,const void * buf,size_t buf_len,const char * boardname,int ie_id,int name_id,int data_id)1078d5c65159SKalle Valo static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
1079d5c65159SKalle Valo 					 struct ath11k_board_data *bd,
1080d5c65159SKalle Valo 					 const void *buf, size_t buf_len,
1081d5c65159SKalle Valo 					 const char *boardname,
1082801cb1d2SWen Gong 					 int ie_id,
1083801cb1d2SWen Gong 					 int name_id,
1084801cb1d2SWen Gong 					 int data_id)
1085d5c65159SKalle Valo {
1086d5c65159SKalle Valo 	const struct ath11k_fw_ie *hdr;
1087d5c65159SKalle Valo 	bool name_match_found;
1088d5c65159SKalle Valo 	int ret, board_ie_id;
1089d5c65159SKalle Valo 	size_t board_ie_len;
1090d5c65159SKalle Valo 	const void *board_ie_data;
1091d5c65159SKalle Valo 
1092d5c65159SKalle Valo 	name_match_found = false;
1093d5c65159SKalle Valo 
1094801cb1d2SWen Gong 	/* go through ATH11K_BD_IE_BOARD_/ATH11K_BD_IE_REGDB_ elements */
1095d5c65159SKalle Valo 	while (buf_len > sizeof(struct ath11k_fw_ie)) {
1096d5c65159SKalle Valo 		hdr = buf;
1097d5c65159SKalle Valo 		board_ie_id = le32_to_cpu(hdr->id);
1098d5c65159SKalle Valo 		board_ie_len = le32_to_cpu(hdr->len);
1099d5c65159SKalle Valo 		board_ie_data = hdr->data;
1100d5c65159SKalle Valo 
1101d5c65159SKalle Valo 		buf_len -= sizeof(*hdr);
1102d5c65159SKalle Valo 		buf += sizeof(*hdr);
1103d5c65159SKalle Valo 
1104d5c65159SKalle Valo 		if (buf_len < ALIGN(board_ie_len, 4)) {
1105801cb1d2SWen Gong 			ath11k_err(ab, "invalid %s length: %zu < %zu\n",
1106801cb1d2SWen Gong 				   ath11k_bd_ie_type_str(ie_id),
1107d5c65159SKalle Valo 				   buf_len, ALIGN(board_ie_len, 4));
1108d5c65159SKalle Valo 			ret = -EINVAL;
1109d5c65159SKalle Valo 			goto out;
1110d5c65159SKalle Valo 		}
1111d5c65159SKalle Valo 
1112801cb1d2SWen Gong 		if (board_ie_id == name_id) {
1113d5c65159SKalle Valo 			ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "",
1114d5c65159SKalle Valo 					board_ie_data, board_ie_len);
1115d5c65159SKalle Valo 
1116d5c65159SKalle Valo 			if (board_ie_len != strlen(boardname))
1117801cb1d2SWen Gong 				goto next;
1118d5c65159SKalle Valo 
1119d5c65159SKalle Valo 			ret = memcmp(board_ie_data, boardname, strlen(boardname));
1120d5c65159SKalle Valo 			if (ret)
1121801cb1d2SWen Gong 				goto next;
1122d5c65159SKalle Valo 
1123d5c65159SKalle Valo 			name_match_found = true;
1124d5c65159SKalle Valo 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
1125fc3b984aSKalle Valo 				   "found match %s for name '%s'",
1126801cb1d2SWen Gong 				   ath11k_bd_ie_type_str(ie_id),
1127d5c65159SKalle Valo 				   boardname);
1128801cb1d2SWen Gong 		} else if (board_ie_id == data_id) {
1129d5c65159SKalle Valo 			if (!name_match_found)
1130d5c65159SKalle Valo 				/* no match found */
1131801cb1d2SWen Gong 				goto next;
1132d5c65159SKalle Valo 
1133d5c65159SKalle Valo 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
1134fc3b984aSKalle Valo 				   "found %s for '%s'",
1135801cb1d2SWen Gong 				   ath11k_bd_ie_type_str(ie_id),
1136801cb1d2SWen Gong 				   boardname);
1137d5c65159SKalle Valo 
1138d5c65159SKalle Valo 			bd->data = board_ie_data;
1139d5c65159SKalle Valo 			bd->len = board_ie_len;
1140d5c65159SKalle Valo 
1141d5c65159SKalle Valo 			ret = 0;
1142d5c65159SKalle Valo 			goto out;
1143801cb1d2SWen Gong 		} else {
1144801cb1d2SWen Gong 			ath11k_warn(ab, "unknown %s id found: %d\n",
1145801cb1d2SWen Gong 				    ath11k_bd_ie_type_str(ie_id),
1146d5c65159SKalle Valo 				    board_ie_id);
1147d5c65159SKalle Valo 		}
1148801cb1d2SWen Gong next:
1149d5c65159SKalle Valo 		/* jump over the padding */
1150d5c65159SKalle Valo 		board_ie_len = ALIGN(board_ie_len, 4);
1151d5c65159SKalle Valo 
1152d5c65159SKalle Valo 		buf_len -= board_ie_len;
1153d5c65159SKalle Valo 		buf += board_ie_len;
1154d5c65159SKalle Valo 	}
1155d5c65159SKalle Valo 
1156d5c65159SKalle Valo 	/* no match found */
1157d5c65159SKalle Valo 	ret = -ENOENT;
1158d5c65159SKalle Valo 
1159d5c65159SKalle Valo out:
1160d5c65159SKalle Valo 	return ret;
1161d5c65159SKalle Valo }
1162d5c65159SKalle Valo 
ath11k_core_fetch_board_data_api_n(struct ath11k_base * ab,struct ath11k_board_data * bd,const char * boardname,int ie_id_match,int name_id,int data_id)1163d5c65159SKalle Valo static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
1164d5c65159SKalle Valo 					      struct ath11k_board_data *bd,
1165801cb1d2SWen Gong 					      const char *boardname,
1166801cb1d2SWen Gong 					      int ie_id_match,
1167801cb1d2SWen Gong 					      int name_id,
1168801cb1d2SWen Gong 					      int data_id)
1169d5c65159SKalle Valo {
1170d5c65159SKalle Valo 	size_t len, magic_len;
1171d5c65159SKalle Valo 	const u8 *data;
117231d78a3dSKalle Valo 	char *filename, filepath[100];
1173d5c65159SKalle Valo 	size_t ie_len;
1174d5c65159SKalle Valo 	struct ath11k_fw_ie *hdr;
1175d5c65159SKalle Valo 	int ret, ie_id;
1176d5c65159SKalle Valo 
117731d78a3dSKalle Valo 	filename = ATH11K_BOARD_API2_FILE;
117831d78a3dSKalle Valo 
1179d5c65159SKalle Valo 	if (!bd->fw)
118034d9fc80SKalle Valo 		bd->fw = ath11k_core_firmware_request(ab, filename);
118134d9fc80SKalle Valo 
1182d5c65159SKalle Valo 	if (IS_ERR(bd->fw))
1183d5c65159SKalle Valo 		return PTR_ERR(bd->fw);
1184d5c65159SKalle Valo 
1185d5c65159SKalle Valo 	data = bd->fw->data;
1186d5c65159SKalle Valo 	len = bd->fw->size;
1187d5c65159SKalle Valo 
118831d78a3dSKalle Valo 	ath11k_core_create_firmware_path(ab, filename,
118931d78a3dSKalle Valo 					 filepath, sizeof(filepath));
119031d78a3dSKalle Valo 
1191d5c65159SKalle Valo 	/* magic has extra null byte padded */
1192d5c65159SKalle Valo 	magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
1193d5c65159SKalle Valo 	if (len < magic_len) {
119431d78a3dSKalle Valo 		ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
119531d78a3dSKalle Valo 			   filepath, len);
1196d5c65159SKalle Valo 		ret = -EINVAL;
1197d5c65159SKalle Valo 		goto err;
1198d5c65159SKalle Valo 	}
1199d5c65159SKalle Valo 
1200d5c65159SKalle Valo 	if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) {
1201d5c65159SKalle Valo 		ath11k_err(ab, "found invalid board magic\n");
1202d5c65159SKalle Valo 		ret = -EINVAL;
1203d5c65159SKalle Valo 		goto err;
1204d5c65159SKalle Valo 	}
1205d5c65159SKalle Valo 
1206d5c65159SKalle Valo 	/* magic is padded to 4 bytes */
1207d5c65159SKalle Valo 	magic_len = ALIGN(magic_len, 4);
1208d5c65159SKalle Valo 	if (len < magic_len) {
120931d78a3dSKalle Valo 		ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
121031d78a3dSKalle Valo 			   filepath, len);
1211d5c65159SKalle Valo 		ret = -EINVAL;
1212d5c65159SKalle Valo 		goto err;
1213d5c65159SKalle Valo 	}
1214d5c65159SKalle Valo 
1215d5c65159SKalle Valo 	data += magic_len;
1216d5c65159SKalle Valo 	len -= magic_len;
1217d5c65159SKalle Valo 
1218d5c65159SKalle Valo 	while (len > sizeof(struct ath11k_fw_ie)) {
1219d5c65159SKalle Valo 		hdr = (struct ath11k_fw_ie *)data;
1220d5c65159SKalle Valo 		ie_id = le32_to_cpu(hdr->id);
1221d5c65159SKalle Valo 		ie_len = le32_to_cpu(hdr->len);
1222d5c65159SKalle Valo 
1223d5c65159SKalle Valo 		len -= sizeof(*hdr);
1224d5c65159SKalle Valo 		data = hdr->data;
1225d5c65159SKalle Valo 
1226d5c65159SKalle Valo 		if (len < ALIGN(ie_len, 4)) {
1227d5c65159SKalle Valo 			ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
1228d5c65159SKalle Valo 				   ie_id, ie_len, len);
1229515bda1dSChristophe JAILLET 			ret = -EINVAL;
1230515bda1dSChristophe JAILLET 			goto err;
1231d5c65159SKalle Valo 		}
1232d5c65159SKalle Valo 
1233801cb1d2SWen Gong 		if (ie_id == ie_id_match) {
1234d5c65159SKalle Valo 			ret = ath11k_core_parse_bd_ie_board(ab, bd, data,
1235d5c65159SKalle Valo 							    ie_len,
1236d5c65159SKalle Valo 							    boardname,
1237801cb1d2SWen Gong 							    ie_id_match,
1238801cb1d2SWen Gong 							    name_id,
1239801cb1d2SWen Gong 							    data_id);
1240d5c65159SKalle Valo 			if (ret == -ENOENT)
1241d5c65159SKalle Valo 				/* no match found, continue */
1242801cb1d2SWen Gong 				goto next;
1243d5c65159SKalle Valo 			else if (ret)
1244d5c65159SKalle Valo 				/* there was an error, bail out */
1245d5c65159SKalle Valo 				goto err;
1246d5c65159SKalle Valo 			/* either found or error, so stop searching */
1247d5c65159SKalle Valo 			goto out;
1248d5c65159SKalle Valo 		}
1249801cb1d2SWen Gong next:
1250d5c65159SKalle Valo 		/* jump over the padding */
1251d5c65159SKalle Valo 		ie_len = ALIGN(ie_len, 4);
1252d5c65159SKalle Valo 
1253d5c65159SKalle Valo 		len -= ie_len;
1254d5c65159SKalle Valo 		data += ie_len;
1255d5c65159SKalle Valo 	}
1256d5c65159SKalle Valo 
1257d5c65159SKalle Valo out:
1258d5c65159SKalle Valo 	if (!bd->data || !bd->len) {
125962abdc06SWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
1260801cb1d2SWen Gong 			   "failed to fetch %s for %s from %s\n",
1261801cb1d2SWen Gong 			   ath11k_bd_ie_type_str(ie_id_match),
126231d78a3dSKalle Valo 			   boardname, filepath);
1263d5c65159SKalle Valo 		ret = -ENODATA;
1264d5c65159SKalle Valo 		goto err;
1265d5c65159SKalle Valo 	}
1266d5c65159SKalle Valo 
1267d5c65159SKalle Valo 	return 0;
1268d5c65159SKalle Valo 
1269d5c65159SKalle Valo err:
1270d5c65159SKalle Valo 	ath11k_core_free_bdf(ab, bd);
1271d5c65159SKalle Valo 	return ret;
1272d5c65159SKalle Valo }
1273d5c65159SKalle Valo 
ath11k_core_fetch_board_data_api_1(struct ath11k_base * ab,struct ath11k_board_data * bd,const char * name)127401417e57SWen Gong int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
127501417e57SWen Gong 				       struct ath11k_board_data *bd,
127601417e57SWen Gong 				       const char *name)
1277d5c65159SKalle Valo {
127801417e57SWen Gong 	bd->fw = ath11k_core_firmware_request(ab, name);
127901417e57SWen Gong 
1280d5c65159SKalle Valo 	if (IS_ERR(bd->fw))
1281d5c65159SKalle Valo 		return PTR_ERR(bd->fw);
1282d5c65159SKalle Valo 
1283d5c65159SKalle Valo 	bd->data = bd->fw->data;
1284d5c65159SKalle Valo 	bd->len = bd->fw->size;
1285d5c65159SKalle Valo 
1286d5c65159SKalle Valo 	return 0;
1287d5c65159SKalle Valo }
1288d5c65159SKalle Valo 
1289fc95d10aSWen Gong #define BOARD_NAME_SIZE 200
ath11k_core_fetch_bdf(struct ath11k_base * ab,struct ath11k_board_data * bd)1290d5c65159SKalle Valo int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
1291d5c65159SKalle Valo {
129262abdc06SWen Gong 	char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE];
129362abdc06SWen Gong 	char *filename, filepath[100];
1294d5c65159SKalle Valo 	int ret;
1295d5c65159SKalle Valo 
129662abdc06SWen Gong 	filename = ATH11K_BOARD_API2_FILE;
129762abdc06SWen Gong 
129862abdc06SWen Gong 	ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname));
1299d5c65159SKalle Valo 	if (ret) {
1300d5c65159SKalle Valo 		ath11k_err(ab, "failed to create board name: %d", ret);
1301d5c65159SKalle Valo 		return ret;
1302d5c65159SKalle Valo 	}
1303d5c65159SKalle Valo 
1304d5c65159SKalle Valo 	ab->bd_api = 2;
1305801cb1d2SWen Gong 	ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,
1306801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD,
1307801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD_NAME,
1308801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD_DATA);
1309d5c65159SKalle Valo 	if (!ret)
1310d5c65159SKalle Valo 		goto success;
1311d5c65159SKalle Valo 
131262abdc06SWen Gong 	ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname,
131362abdc06SWen Gong 						     sizeof(fallback_boardname));
131462abdc06SWen Gong 	if (ret) {
131562abdc06SWen Gong 		ath11k_err(ab, "failed to create fallback board name: %d", ret);
131662abdc06SWen Gong 		return ret;
131762abdc06SWen Gong 	}
131862abdc06SWen Gong 
1319801cb1d2SWen Gong 	ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname,
1320801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD,
1321801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD_NAME,
1322801cb1d2SWen Gong 						 ATH11K_BD_IE_BOARD_DATA);
132362abdc06SWen Gong 	if (!ret)
132462abdc06SWen Gong 		goto success;
132562abdc06SWen Gong 
1326d5c65159SKalle Valo 	ab->bd_api = 1;
132701417e57SWen Gong 	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);
1328d5c65159SKalle Valo 	if (ret) {
132962abdc06SWen Gong 		ath11k_core_create_firmware_path(ab, filename,
133062abdc06SWen Gong 						 filepath, sizeof(filepath));
133162abdc06SWen Gong 		ath11k_err(ab, "failed to fetch board data for %s from %s\n",
133262abdc06SWen Gong 			   boardname, filepath);
133362abdc06SWen Gong 		if (memcmp(boardname, fallback_boardname, strlen(boardname)))
133462abdc06SWen Gong 			ath11k_err(ab, "failed to fetch board data for %s from %s\n",
133562abdc06SWen Gong 				   fallback_boardname, filepath);
133662abdc06SWen Gong 
133762abdc06SWen Gong 		ath11k_err(ab, "failed to fetch board.bin from %s\n",
1338d5c65159SKalle Valo 			   ab->hw_params.fw.dir);
1339d5c65159SKalle Valo 		return ret;
1340d5c65159SKalle Valo 	}
1341d5c65159SKalle Valo 
1342d5c65159SKalle Valo success:
1343d5c65159SKalle Valo 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
1344d5c65159SKalle Valo 	return 0;
1345d5c65159SKalle Valo }
1346d5c65159SKalle Valo 
ath11k_core_fetch_regdb(struct ath11k_base * ab,struct ath11k_board_data * bd)134701417e57SWen Gong int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
134801417e57SWen Gong {
134988ca8920SWen Gong 	char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];
135001417e57SWen Gong 	int ret;
135101417e57SWen Gong 
1352801cb1d2SWen Gong 	ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
1353801cb1d2SWen Gong 	if (ret) {
1354801cb1d2SWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
1355801cb1d2SWen Gong 			   "failed to create board name for regdb: %d", ret);
1356801cb1d2SWen Gong 		goto exit;
1357801cb1d2SWen Gong 	}
1358801cb1d2SWen Gong 
1359801cb1d2SWen Gong 	ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,
1360801cb1d2SWen Gong 						 ATH11K_BD_IE_REGDB,
1361801cb1d2SWen Gong 						 ATH11K_BD_IE_REGDB_NAME,
1362801cb1d2SWen Gong 						 ATH11K_BD_IE_REGDB_DATA);
1363801cb1d2SWen Gong 	if (!ret)
1364801cb1d2SWen Gong 		goto exit;
1365801cb1d2SWen Gong 
136688ca8920SWen Gong 	ret = ath11k_core_create_bus_type_board_name(ab, default_boardname,
136788ca8920SWen Gong 						     BOARD_NAME_SIZE);
136888ca8920SWen Gong 	if (ret) {
136988ca8920SWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
137088ca8920SWen Gong 			   "failed to create default board name for regdb: %d", ret);
137188ca8920SWen Gong 		goto exit;
137288ca8920SWen Gong 	}
137388ca8920SWen Gong 
137488ca8920SWen Gong 	ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname,
137588ca8920SWen Gong 						 ATH11K_BD_IE_REGDB,
137688ca8920SWen Gong 						 ATH11K_BD_IE_REGDB_NAME,
137788ca8920SWen Gong 						 ATH11K_BD_IE_REGDB_DATA);
137888ca8920SWen Gong 	if (!ret)
137988ca8920SWen Gong 		goto exit;
138088ca8920SWen Gong 
138101417e57SWen Gong 	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
138201417e57SWen Gong 	if (ret)
138301417e57SWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
138401417e57SWen Gong 			   ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir);
138501417e57SWen Gong 
1386801cb1d2SWen Gong exit:
1387801cb1d2SWen Gong 	if (!ret)
1388801cb1d2SWen Gong 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "fetched regdb\n");
1389801cb1d2SWen Gong 
139001417e57SWen Gong 	return ret;
139101417e57SWen Gong }
139201417e57SWen Gong 
ath11k_core_stop(struct ath11k_base * ab)1393d5c65159SKalle Valo static void ath11k_core_stop(struct ath11k_base *ab)
1394d5c65159SKalle Valo {
1395d5c65159SKalle Valo 	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
1396d5c65159SKalle Valo 		ath11k_qmi_firmware_stop(ab);
1397e838c14aSCarl Huang 
139831858805SGovind Singh 	ath11k_hif_stop(ab);
1399d5c65159SKalle Valo 	ath11k_wmi_detach(ab);
14009c57d7e3SVasanthakumar Thiagarajan 	ath11k_dp_pdev_reo_cleanup(ab);
1401d5c65159SKalle Valo 
1402d5c65159SKalle Valo 	/* De-Init of components as needed */
1403d5c65159SKalle Valo }
1404d5c65159SKalle Valo 
ath11k_core_soc_create(struct ath11k_base * ab)1405d5c65159SKalle Valo static int ath11k_core_soc_create(struct ath11k_base *ab)
1406d5c65159SKalle Valo {
1407d5c65159SKalle Valo 	int ret;
1408d5c65159SKalle Valo 
1409b43310e4SGovindaraj Saminathan 	if (ath11k_ftm_mode) {
1410b43310e4SGovindaraj Saminathan 		ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM;
1411b43310e4SGovindaraj Saminathan 		ath11k_info(ab, "Booting in factory test mode\n");
1412b43310e4SGovindaraj Saminathan 	}
1413b43310e4SGovindaraj Saminathan 
1414d5c65159SKalle Valo 	ret = ath11k_qmi_init_service(ab);
1415d5c65159SKalle Valo 	if (ret) {
1416d5c65159SKalle Valo 		ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
1417d5c65159SKalle Valo 		return ret;
1418d5c65159SKalle Valo 	}
1419d5c65159SKalle Valo 
1420cb4e57dbSKalle Valo 	ret = ath11k_debugfs_soc_create(ab);
1421d5c65159SKalle Valo 	if (ret) {
1422d5c65159SKalle Valo 		ath11k_err(ab, "failed to create ath11k debugfs\n");
1423d5c65159SKalle Valo 		goto err_qmi_deinit;
1424d5c65159SKalle Valo 	}
1425d5c65159SKalle Valo 
142631858805SGovind Singh 	ret = ath11k_hif_power_up(ab);
1427d5c65159SKalle Valo 	if (ret) {
1428d5c65159SKalle Valo 		ath11k_err(ab, "failed to power up :%d\n", ret);
1429d5c65159SKalle Valo 		goto err_debugfs_reg;
1430d5c65159SKalle Valo 	}
1431d5c65159SKalle Valo 
1432d5c65159SKalle Valo 	return 0;
1433d5c65159SKalle Valo 
1434d5c65159SKalle Valo err_debugfs_reg:
1435cb4e57dbSKalle Valo 	ath11k_debugfs_soc_destroy(ab);
1436d5c65159SKalle Valo err_qmi_deinit:
1437d5c65159SKalle Valo 	ath11k_qmi_deinit_service(ab);
1438d5c65159SKalle Valo 	return ret;
1439d5c65159SKalle Valo }
1440d5c65159SKalle Valo 
ath11k_core_soc_destroy(struct ath11k_base * ab)1441d5c65159SKalle Valo static void ath11k_core_soc_destroy(struct ath11k_base *ab)
1442d5c65159SKalle Valo {
1443cb4e57dbSKalle Valo 	ath11k_debugfs_soc_destroy(ab);
1444d5c65159SKalle Valo 	ath11k_dp_free(ab);
1445d5c65159SKalle Valo 	ath11k_reg_free(ab);
1446d5c65159SKalle Valo 	ath11k_qmi_deinit_service(ab);
1447d5c65159SKalle Valo }
1448d5c65159SKalle Valo 
ath11k_core_pdev_create(struct ath11k_base * ab)1449d5c65159SKalle Valo static int ath11k_core_pdev_create(struct ath11k_base *ab)
1450d5c65159SKalle Valo {
1451d5c65159SKalle Valo 	int ret;
1452d5c65159SKalle Valo 
1453cb4e57dbSKalle Valo 	ret = ath11k_debugfs_pdev_create(ab);
1454d5c65159SKalle Valo 	if (ret) {
1455d5c65159SKalle Valo 		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
1456d5c65159SKalle Valo 		return ret;
1457d5c65159SKalle Valo 	}
1458d5c65159SKalle Valo 
1459d5c65159SKalle Valo 	ret = ath11k_dp_pdev_alloc(ab);
1460d5c65159SKalle Valo 	if (ret) {
1461d5c65159SKalle Valo 		ath11k_err(ab, "failed to attach DP pdev: %d\n", ret);
1462d4ba1ff8SJohan Hovold 		goto err_pdev_debug;
1463d4ba1ff8SJohan Hovold 	}
1464d4ba1ff8SJohan Hovold 
1465d4ba1ff8SJohan Hovold 	ret = ath11k_mac_register(ab);
1466d4ba1ff8SJohan Hovold 	if (ret) {
1467d4ba1ff8SJohan Hovold 		ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
1468d4ba1ff8SJohan Hovold 		goto err_dp_pdev_free;
1469d5c65159SKalle Valo 	}
1470d5c65159SKalle Valo 
14712a63bbcaSPradeep Kumar Chitrapu 	ret = ath11k_thermal_register(ab);
14722a63bbcaSPradeep Kumar Chitrapu 	if (ret) {
14732a63bbcaSPradeep Kumar Chitrapu 		ath11k_err(ab, "could not register thermal device: %d\n",
14742a63bbcaSPradeep Kumar Chitrapu 			   ret);
1475d4ba1ff8SJohan Hovold 		goto err_mac_unregister;
14762a63bbcaSPradeep Kumar Chitrapu 	}
14772a63bbcaSPradeep Kumar Chitrapu 
14789d11b7bfSKarthikeyan Periyasamy 	ret = ath11k_spectral_init(ab);
14799d11b7bfSKarthikeyan Periyasamy 	if (ret) {
14809d11b7bfSKarthikeyan Periyasamy 		ath11k_err(ab, "failed to init spectral %d\n", ret);
14819d11b7bfSKarthikeyan Periyasamy 		goto err_thermal_unregister;
14829d11b7bfSKarthikeyan Periyasamy 	}
14839d11b7bfSKarthikeyan Periyasamy 
1484d5c65159SKalle Valo 	return 0;
1485d5c65159SKalle Valo 
14869d11b7bfSKarthikeyan Periyasamy err_thermal_unregister:
14879d11b7bfSKarthikeyan Periyasamy 	ath11k_thermal_unregister(ab);
14880366f426SVasanthakumar Thiagarajan err_mac_unregister:
14890366f426SVasanthakumar Thiagarajan 	ath11k_mac_unregister(ab);
1490d4ba1ff8SJohan Hovold err_dp_pdev_free:
1491d4ba1ff8SJohan Hovold 	ath11k_dp_pdev_free(ab);
1492d5c65159SKalle Valo err_pdev_debug:
1493cb4e57dbSKalle Valo 	ath11k_debugfs_pdev_destroy(ab);
1494d5c65159SKalle Valo 
1495d5c65159SKalle Valo 	return ret;
1496d5c65159SKalle Valo }
1497d5c65159SKalle Valo 
ath11k_core_pdev_destroy(struct ath11k_base * ab)1498d5c65159SKalle Valo static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
1499d5c65159SKalle Valo {
15009d11b7bfSKarthikeyan Periyasamy 	ath11k_spectral_deinit(ab);
15012a63bbcaSPradeep Kumar Chitrapu 	ath11k_thermal_unregister(ab);
1502d5c65159SKalle Valo 	ath11k_mac_unregister(ab);
150331858805SGovind Singh 	ath11k_hif_irq_disable(ab);
1504d5c65159SKalle Valo 	ath11k_dp_pdev_free(ab);
1505cb4e57dbSKalle Valo 	ath11k_debugfs_pdev_destroy(ab);
1506d5c65159SKalle Valo }
1507d5c65159SKalle Valo 
ath11k_core_start(struct ath11k_base * ab)150833b67a4bSManikanta Pubbisetty static int ath11k_core_start(struct ath11k_base *ab)
1509d5c65159SKalle Valo {
1510d5c65159SKalle Valo 	int ret;
1511d5c65159SKalle Valo 
1512d5c65159SKalle Valo 	ret = ath11k_wmi_attach(ab);
1513d5c65159SKalle Valo 	if (ret) {
1514d5c65159SKalle Valo 		ath11k_err(ab, "failed to attach wmi: %d\n", ret);
151533b67a4bSManikanta Pubbisetty 		return ret;
1516d5c65159SKalle Valo 	}
1517d5c65159SKalle Valo 
1518d5c65159SKalle Valo 	ret = ath11k_htc_init(ab);
1519d5c65159SKalle Valo 	if (ret) {
1520d5c65159SKalle Valo 		ath11k_err(ab, "failed to init htc: %d\n", ret);
1521d5c65159SKalle Valo 		goto err_wmi_detach;
1522d5c65159SKalle Valo 	}
1523d5c65159SKalle Valo 
152431858805SGovind Singh 	ret = ath11k_hif_start(ab);
1525d5c65159SKalle Valo 	if (ret) {
1526d5c65159SKalle Valo 		ath11k_err(ab, "failed to start HIF: %d\n", ret);
1527d5c65159SKalle Valo 		goto err_wmi_detach;
1528d5c65159SKalle Valo 	}
1529d5c65159SKalle Valo 
1530d5c65159SKalle Valo 	ret = ath11k_htc_wait_target(&ab->htc);
1531d5c65159SKalle Valo 	if (ret) {
1532d5c65159SKalle Valo 		ath11k_err(ab, "failed to connect to HTC: %d\n", ret);
1533d5c65159SKalle Valo 		goto err_hif_stop;
1534d5c65159SKalle Valo 	}
1535d5c65159SKalle Valo 
1536d5c65159SKalle Valo 	ret = ath11k_dp_htt_connect(&ab->dp);
1537d5c65159SKalle Valo 	if (ret) {
1538d5c65159SKalle Valo 		ath11k_err(ab, "failed to connect to HTT: %d\n", ret);
1539d5c65159SKalle Valo 		goto err_hif_stop;
1540d5c65159SKalle Valo 	}
1541d5c65159SKalle Valo 
1542d5c65159SKalle Valo 	ret = ath11k_wmi_connect(ab);
1543d5c65159SKalle Valo 	if (ret) {
1544d5c65159SKalle Valo 		ath11k_err(ab, "failed to connect wmi: %d\n", ret);
1545d5c65159SKalle Valo 		goto err_hif_stop;
1546d5c65159SKalle Valo 	}
1547d5c65159SKalle Valo 
1548d5c65159SKalle Valo 	ret = ath11k_htc_start(&ab->htc);
1549d5c65159SKalle Valo 	if (ret) {
1550d5c65159SKalle Valo 		ath11k_err(ab, "failed to start HTC: %d\n", ret);
1551d5c65159SKalle Valo 		goto err_hif_stop;
1552d5c65159SKalle Valo 	}
1553d5c65159SKalle Valo 
1554d5c65159SKalle Valo 	ret = ath11k_wmi_wait_for_service_ready(ab);
1555d5c65159SKalle Valo 	if (ret) {
1556d5c65159SKalle Valo 		ath11k_err(ab, "failed to receive wmi service ready event: %d\n",
1557d5c65159SKalle Valo 			   ret);
1558d5c65159SKalle Valo 		goto err_hif_stop;
1559d5c65159SKalle Valo 	}
1560d5c65159SKalle Valo 
15610366f426SVasanthakumar Thiagarajan 	ret = ath11k_mac_allocate(ab);
15620366f426SVasanthakumar Thiagarajan 	if (ret) {
15630366f426SVasanthakumar Thiagarajan 		ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n",
15640366f426SVasanthakumar Thiagarajan 			   ret);
15650366f426SVasanthakumar Thiagarajan 		goto err_hif_stop;
15660366f426SVasanthakumar Thiagarajan 	}
15670366f426SVasanthakumar Thiagarajan 
15689c57d7e3SVasanthakumar Thiagarajan 	ath11k_dp_pdev_pre_alloc(ab);
15699c57d7e3SVasanthakumar Thiagarajan 
15709c57d7e3SVasanthakumar Thiagarajan 	ret = ath11k_dp_pdev_reo_setup(ab);
15719c57d7e3SVasanthakumar Thiagarajan 	if (ret) {
15729c57d7e3SVasanthakumar Thiagarajan 		ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
15739c57d7e3SVasanthakumar Thiagarajan 		goto err_mac_destroy;
15749c57d7e3SVasanthakumar Thiagarajan 	}
15759c57d7e3SVasanthakumar Thiagarajan 
1576d5c65159SKalle Valo 	ret = ath11k_wmi_cmd_init(ab);
1577d5c65159SKalle Valo 	if (ret) {
1578d5c65159SKalle Valo 		ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret);
15799c57d7e3SVasanthakumar Thiagarajan 		goto err_reo_cleanup;
1580d5c65159SKalle Valo 	}
1581d5c65159SKalle Valo 
1582d5c65159SKalle Valo 	ret = ath11k_wmi_wait_for_unified_ready(ab);
1583d5c65159SKalle Valo 	if (ret) {
1584d5c65159SKalle Valo 		ath11k_err(ab, "failed to receive wmi unified ready event: %d\n",
1585d5c65159SKalle Valo 			   ret);
15869c57d7e3SVasanthakumar Thiagarajan 		goto err_reo_cleanup;
1587d5c65159SKalle Valo 	}
1588d5c65159SKalle Valo 
158943ed15e1SCarl Huang 	/* put hardware to DBS mode */
1590b6f63010SManikanta Pubbisetty 	if (ab->hw_params.single_pdev_only && ab->hw_params.num_rxmda_per_pdev > 1) {
159143ed15e1SCarl Huang 		ret = ath11k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
159243ed15e1SCarl Huang 		if (ret) {
159343ed15e1SCarl Huang 			ath11k_err(ab, "failed to send dbs mode: %d\n", ret);
159443ed15e1SCarl Huang 			goto err_hif_stop;
159543ed15e1SCarl Huang 		}
159643ed15e1SCarl Huang 	}
159743ed15e1SCarl Huang 
1598d5c65159SKalle Valo 	ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);
1599d5c65159SKalle Valo 	if (ret) {
1600d5c65159SKalle Valo 		ath11k_err(ab, "failed to send htt version request message: %d\n",
1601d5c65159SKalle Valo 			   ret);
16029c57d7e3SVasanthakumar Thiagarajan 		goto err_reo_cleanup;
1603d5c65159SKalle Valo 	}
1604d5c65159SKalle Valo 
1605d5c65159SKalle Valo 	return 0;
1606d5c65159SKalle Valo 
16079c57d7e3SVasanthakumar Thiagarajan err_reo_cleanup:
16089c57d7e3SVasanthakumar Thiagarajan 	ath11k_dp_pdev_reo_cleanup(ab);
16090366f426SVasanthakumar Thiagarajan err_mac_destroy:
16100366f426SVasanthakumar Thiagarajan 	ath11k_mac_destroy(ab);
1611d5c65159SKalle Valo err_hif_stop:
161231858805SGovind Singh 	ath11k_hif_stop(ab);
1613d5c65159SKalle Valo err_wmi_detach:
1614d5c65159SKalle Valo 	ath11k_wmi_detach(ab);
161533b67a4bSManikanta Pubbisetty 
161633b67a4bSManikanta Pubbisetty 	return ret;
161733b67a4bSManikanta Pubbisetty }
161833b67a4bSManikanta Pubbisetty 
ath11k_core_start_firmware(struct ath11k_base * ab,enum ath11k_firmware_mode mode)161933b67a4bSManikanta Pubbisetty static int ath11k_core_start_firmware(struct ath11k_base *ab,
162033b67a4bSManikanta Pubbisetty 				      enum ath11k_firmware_mode mode)
162133b67a4bSManikanta Pubbisetty {
162233b67a4bSManikanta Pubbisetty 	int ret;
162333b67a4bSManikanta Pubbisetty 
162433b67a4bSManikanta Pubbisetty 	ath11k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v2,
162533b67a4bSManikanta Pubbisetty 				    &ab->qmi.ce_cfg.shadow_reg_v2_len);
162633b67a4bSManikanta Pubbisetty 
162733b67a4bSManikanta Pubbisetty 	ret = ath11k_qmi_firmware_start(ab, mode);
162833b67a4bSManikanta Pubbisetty 	if (ret) {
162933b67a4bSManikanta Pubbisetty 		ath11k_err(ab, "failed to send firmware start: %d\n", ret);
163033b67a4bSManikanta Pubbisetty 		return ret;
163133b67a4bSManikanta Pubbisetty 	}
1632d5c65159SKalle Valo 
1633d5c65159SKalle Valo 	return ret;
1634d5c65159SKalle Valo }
1635d5c65159SKalle Valo 
ath11k_core_qmi_firmware_ready(struct ath11k_base * ab)1636d5c65159SKalle Valo int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
1637d5c65159SKalle Valo {
1638d5c65159SKalle Valo 	int ret;
1639d5c65159SKalle Valo 
1640b43310e4SGovindaraj Saminathan 	ret = ath11k_core_start_firmware(ab, ab->fw_mode);
164133b67a4bSManikanta Pubbisetty 	if (ret) {
164233b67a4bSManikanta Pubbisetty 		ath11k_err(ab, "failed to start firmware: %d\n", ret);
164333b67a4bSManikanta Pubbisetty 		return ret;
164433b67a4bSManikanta Pubbisetty 	}
164533b67a4bSManikanta Pubbisetty 
1646d5c65159SKalle Valo 	ret = ath11k_ce_init_pipes(ab);
1647d5c65159SKalle Valo 	if (ret) {
1648d5c65159SKalle Valo 		ath11k_err(ab, "failed to initialize CE: %d\n", ret);
164933b67a4bSManikanta Pubbisetty 		goto err_firmware_stop;
1650d5c65159SKalle Valo 	}
1651d5c65159SKalle Valo 
1652d5c65159SKalle Valo 	ret = ath11k_dp_alloc(ab);
1653d5c65159SKalle Valo 	if (ret) {
1654d5c65159SKalle Valo 		ath11k_err(ab, "failed to init DP: %d\n", ret);
165533b67a4bSManikanta Pubbisetty 		goto err_firmware_stop;
1656d5c65159SKalle Valo 	}
1657d5c65159SKalle Valo 
1658aa2092a9SVenkateswara Naralasetty 	switch (ath11k_crypto_mode) {
1659aa2092a9SVenkateswara Naralasetty 	case ATH11K_CRYPT_MODE_SW:
1660aa2092a9SVenkateswara Naralasetty 		set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1661aa2092a9SVenkateswara Naralasetty 		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1662aa2092a9SVenkateswara Naralasetty 		break;
1663aa2092a9SVenkateswara Naralasetty 	case ATH11K_CRYPT_MODE_HW:
1664aa2092a9SVenkateswara Naralasetty 		clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1665aa2092a9SVenkateswara Naralasetty 		clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1666aa2092a9SVenkateswara Naralasetty 		break;
1667aa2092a9SVenkateswara Naralasetty 	default:
1668aa2092a9SVenkateswara Naralasetty 		ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
1669aa2092a9SVenkateswara Naralasetty 		return -EINVAL;
1670aa2092a9SVenkateswara Naralasetty 	}
1671aa2092a9SVenkateswara Naralasetty 
1672aa2092a9SVenkateswara Naralasetty 	if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
1673aa2092a9SVenkateswara Naralasetty 		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1674aa2092a9SVenkateswara Naralasetty 
1675d5c65159SKalle Valo 	mutex_lock(&ab->core_lock);
167633b67a4bSManikanta Pubbisetty 	ret = ath11k_core_start(ab);
1677d5c65159SKalle Valo 	if (ret) {
1678d5c65159SKalle Valo 		ath11k_err(ab, "failed to start core: %d\n", ret);
1679d5c65159SKalle Valo 		goto err_dp_free;
1680d5c65159SKalle Valo 	}
1681d5c65159SKalle Valo 
1682d5c65159SKalle Valo 	ret = ath11k_core_pdev_create(ab);
1683d5c65159SKalle Valo 	if (ret) {
1684d5c65159SKalle Valo 		ath11k_err(ab, "failed to create pdev core: %d\n", ret);
1685d5c65159SKalle Valo 		goto err_core_stop;
1686d5c65159SKalle Valo 	}
168731858805SGovind Singh 	ath11k_hif_irq_enable(ab);
1688d5c65159SKalle Valo 	mutex_unlock(&ab->core_lock);
1689d5c65159SKalle Valo 
1690d5c65159SKalle Valo 	return 0;
1691d5c65159SKalle Valo 
1692d5c65159SKalle Valo err_core_stop:
1693d5c65159SKalle Valo 	ath11k_core_stop(ab);
16940366f426SVasanthakumar Thiagarajan 	ath11k_mac_destroy(ab);
1695d5c65159SKalle Valo err_dp_free:
1696d5c65159SKalle Valo 	ath11k_dp_free(ab);
1697ba479239SGovindaraj Saminathan 	mutex_unlock(&ab->core_lock);
169833b67a4bSManikanta Pubbisetty err_firmware_stop:
169933b67a4bSManikanta Pubbisetty 	ath11k_qmi_firmware_stop(ab);
170033b67a4bSManikanta Pubbisetty 
1701d5c65159SKalle Valo 	return ret;
1702d5c65159SKalle Valo }
1703d5c65159SKalle Valo 
ath11k_core_reconfigure_on_crash(struct ath11k_base * ab)1704d5c65159SKalle Valo static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
1705d5c65159SKalle Valo {
1706d5c65159SKalle Valo 	int ret;
1707d5c65159SKalle Valo 
1708d5c65159SKalle Valo 	mutex_lock(&ab->core_lock);
17092a63bbcaSPradeep Kumar Chitrapu 	ath11k_thermal_unregister(ab);
171031858805SGovind Singh 	ath11k_hif_irq_disable(ab);
1711d5c65159SKalle Valo 	ath11k_dp_pdev_free(ab);
17129d11b7bfSKarthikeyan Periyasamy 	ath11k_spectral_deinit(ab);
171331858805SGovind Singh 	ath11k_hif_stop(ab);
1714d5c65159SKalle Valo 	ath11k_wmi_detach(ab);
17159c57d7e3SVasanthakumar Thiagarajan 	ath11k_dp_pdev_reo_cleanup(ab);
1716d5c65159SKalle Valo 	mutex_unlock(&ab->core_lock);
1717d5c65159SKalle Valo 
1718d5c65159SKalle Valo 	ath11k_dp_free(ab);
1719d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
1720d5c65159SKalle Valo 
1721523aafd0SKalle Valo 	ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
1722d5c65159SKalle Valo 
1723d5c65159SKalle Valo 	ret = ath11k_hal_srng_init(ab);
1724d5c65159SKalle Valo 	if (ret)
1725d5c65159SKalle Valo 		return ret;
1726d5c65159SKalle Valo 
1727d5c65159SKalle Valo 	clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
1728d5c65159SKalle Valo 
1729d5c65159SKalle Valo 	ret = ath11k_core_qmi_firmware_ready(ab);
1730d5c65159SKalle Valo 	if (ret)
1731d5c65159SKalle Valo 		goto err_hal_srng_deinit;
1732d5c65159SKalle Valo 
1733d5c65159SKalle Valo 	clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
1734d5c65159SKalle Valo 
1735d5c65159SKalle Valo 	return 0;
1736d5c65159SKalle Valo 
1737d5c65159SKalle Valo err_hal_srng_deinit:
1738d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
1739d5c65159SKalle Valo 	return ret;
1740d5c65159SKalle Valo }
1741d5c65159SKalle Valo 
ath11k_core_halt(struct ath11k * ar)1742d5c65159SKalle Valo void ath11k_core_halt(struct ath11k *ar)
1743d5c65159SKalle Valo {
1744d5c65159SKalle Valo 	struct ath11k_base *ab = ar->ab;
1745d5c65159SKalle Valo 
1746d5c65159SKalle Valo 	lockdep_assert_held(&ar->conf_mutex);
1747d5c65159SKalle Valo 
1748d5c65159SKalle Valo 	ar->num_created_vdevs = 0;
174979c080dbSKarthikeyan Periyasamy 	ar->allocated_vdev_map = 0;
1750d5c65159SKalle Valo 
1751d5c65159SKalle Valo 	ath11k_mac_scan_finish(ar);
1752d5c65159SKalle Valo 	ath11k_mac_peer_cleanup_all(ar);
1753d5c65159SKalle Valo 	cancel_delayed_work_sync(&ar->scan.timeout);
1754d5c65159SKalle Valo 	cancel_work_sync(&ar->regd_update_work);
17559dcf6808SWen Gong 	cancel_work_sync(&ab->update_11d_work);
1756d5c65159SKalle Valo 
1757d5c65159SKalle Valo 	rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
1758d5c65159SKalle Valo 	synchronize_rcu();
1759d5c65159SKalle Valo 	INIT_LIST_HEAD(&ar->arvifs);
1760d5c65159SKalle Valo 	idr_init(&ar->txmgmt_idr);
1761d5c65159SKalle Valo }
1762d5c65159SKalle Valo 
ath11k_update_11d(struct work_struct * work)17639dcf6808SWen Gong static void ath11k_update_11d(struct work_struct *work)
17649dcf6808SWen Gong {
17659dcf6808SWen Gong 	struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
17669dcf6808SWen Gong 	struct ath11k *ar;
17679dcf6808SWen Gong 	struct ath11k_pdev *pdev;
17689dcf6808SWen Gong 	struct wmi_set_current_country_params set_current_param = {};
17699dcf6808SWen Gong 	int ret, i;
17709dcf6808SWen Gong 
17719dcf6808SWen Gong 	spin_lock_bh(&ab->base_lock);
17729dcf6808SWen Gong 	memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);
17739dcf6808SWen Gong 	spin_unlock_bh(&ab->base_lock);
17749dcf6808SWen Gong 
17759dcf6808SWen Gong 	ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",
17769dcf6808SWen Gong 		   set_current_param.alpha2[0],
17779dcf6808SWen Gong 		   set_current_param.alpha2[1]);
17789dcf6808SWen Gong 
17799dcf6808SWen Gong 	for (i = 0; i < ab->num_radios; i++) {
17809dcf6808SWen Gong 		pdev = &ab->pdevs[i];
17819dcf6808SWen Gong 		ar = pdev->ar;
17829dcf6808SWen Gong 
1783b2beae32SWen Gong 		memcpy(&ar->alpha2, &set_current_param.alpha2, 2);
17849dcf6808SWen Gong 		ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
17859dcf6808SWen Gong 		if (ret)
17869dcf6808SWen Gong 			ath11k_warn(ar->ab,
17879dcf6808SWen Gong 				    "pdev id %d failed set current country code: %d\n",
17889dcf6808SWen Gong 				    i, ret);
17899dcf6808SWen Gong 	}
17909dcf6808SWen Gong }
17919dcf6808SWen Gong 
ath11k_core_pre_reconfigure_recovery(struct ath11k_base * ab)179281e60b2dSAditya Kumar Singh void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
1793d5c65159SKalle Valo {
1794d5c65159SKalle Valo 	struct ath11k *ar;
1795d5c65159SKalle Valo 	struct ath11k_pdev *pdev;
179638194f3aSWen Gong 	int i;
1797d5c65159SKalle Valo 
1798d5c65159SKalle Valo 	spin_lock_bh(&ab->base_lock);
1799d5c65159SKalle Valo 	ab->stats.fw_crash_counter++;
1800d5c65159SKalle Valo 	spin_unlock_bh(&ab->base_lock);
1801d5c65159SKalle Valo 
1802d5c65159SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
1803d5c65159SKalle Valo 		pdev = &ab->pdevs[i];
1804d5c65159SKalle Valo 		ar = pdev->ar;
1805b43310e4SGovindaraj Saminathan 		if (!ar || ar->state == ATH11K_STATE_OFF ||
1806b43310e4SGovindaraj Saminathan 		    ar->state == ATH11K_STATE_FTM)
1807d5c65159SKalle Valo 			continue;
1808d5c65159SKalle Valo 
1809d5c65159SKalle Valo 		ieee80211_stop_queues(ar->hw);
1810d5c65159SKalle Valo 		ath11k_mac_drain_tx(ar);
18119497b788SWen Gong 		ar->state_11d = ATH11K_11D_IDLE;
18121f682dc9SWen Gong 		complete(&ar->completed_11d_scan);
1813d5c65159SKalle Valo 		complete(&ar->scan.started);
18147855a6edSWen Gong 		complete_all(&ar->scan.completed);
18153a5627b9SBaochen Qiang 		complete(&ar->scan.on_channel);
1816d5c65159SKalle Valo 		complete(&ar->peer_assoc_done);
1817690ace20SRitesh Singh 		complete(&ar->peer_delete_done);
1818d5c65159SKalle Valo 		complete(&ar->install_key_done);
1819d5c65159SKalle Valo 		complete(&ar->vdev_setup_done);
18203cbbdfbeSRitesh Singh 		complete(&ar->vdev_delete_done);
1821d5c65159SKalle Valo 		complete(&ar->bss_survey_done);
1822a41d1034SPradeep Kumar Chitrapu 		complete(&ar->thermal.wmi_sync);
1823d5c65159SKalle Valo 
1824d5c65159SKalle Valo 		wake_up(&ar->dp.tx_empty_waitq);
1825d5c65159SKalle Valo 		idr_for_each(&ar->txmgmt_idr,
1826d5c65159SKalle Valo 			     ath11k_mac_tx_mgmt_pending_free, ar);
1827d5c65159SKalle Valo 		idr_destroy(&ar->txmgmt_idr);
1828dddaa64dSWen Gong 		wake_up(&ar->txmgmt_empty_waitq);
1829f3ca72b0SNagarajan Maran 
1830f3ca72b0SNagarajan Maran 		ar->monitor_vdev_id = -1;
1831f3ca72b0SNagarajan Maran 		clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1832f3ca72b0SNagarajan Maran 		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1833d5c65159SKalle Valo 	}
1834d5c65159SKalle Valo 
18356bc9d6f7SJohn Crispin 	wake_up(&ab->wmi_ab.tx_credits_wq);
1836d5c65159SKalle Valo 	wake_up(&ab->peer_mapping_wq);
1837ac41c2b6SManikanta Pubbisetty 
1838ac41c2b6SManikanta Pubbisetty 	reinit_completion(&ab->driver_recovery);
1839d5c65159SKalle Valo }
1840d5c65159SKalle Valo 
ath11k_core_post_reconfigure_recovery(struct ath11k_base * ab)184138194f3aSWen Gong static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
184238194f3aSWen Gong {
184338194f3aSWen Gong 	struct ath11k *ar;
184438194f3aSWen Gong 	struct ath11k_pdev *pdev;
184538194f3aSWen Gong 	int i;
184638194f3aSWen Gong 
1847d5c65159SKalle Valo 	for (i = 0; i < ab->num_radios; i++) {
1848d5c65159SKalle Valo 		pdev = &ab->pdevs[i];
1849d5c65159SKalle Valo 		ar = pdev->ar;
1850d5c65159SKalle Valo 		if (!ar || ar->state == ATH11K_STATE_OFF)
1851d5c65159SKalle Valo 			continue;
1852d5c65159SKalle Valo 
1853d5c65159SKalle Valo 		mutex_lock(&ar->conf_mutex);
1854d5c65159SKalle Valo 
1855d5c65159SKalle Valo 		switch (ar->state) {
1856d5c65159SKalle Valo 		case ATH11K_STATE_ON:
1857d5c65159SKalle Valo 			ar->state = ATH11K_STATE_RESTARTING;
1858d5c65159SKalle Valo 			ath11k_core_halt(ar);
1859d5c65159SKalle Valo 			ieee80211_restart_hw(ar->hw);
1860d5c65159SKalle Valo 			break;
1861d5c65159SKalle Valo 		case ATH11K_STATE_OFF:
1862d5c65159SKalle Valo 			ath11k_warn(ab,
1863d5c65159SKalle Valo 				    "cannot restart radio %d that hasn't been started\n",
1864d5c65159SKalle Valo 				    i);
1865d5c65159SKalle Valo 			break;
1866d5c65159SKalle Valo 		case ATH11K_STATE_RESTARTING:
1867d5c65159SKalle Valo 			break;
1868d5c65159SKalle Valo 		case ATH11K_STATE_RESTARTED:
1869d5c65159SKalle Valo 			ar->state = ATH11K_STATE_WEDGED;
18700b294aebSGustavo A. R. Silva 			fallthrough;
1871d5c65159SKalle Valo 		case ATH11K_STATE_WEDGED:
1872d5c65159SKalle Valo 			ath11k_warn(ab,
1873d5c65159SKalle Valo 				    "device is wedged, will not restart radio %d\n", i);
1874d5c65159SKalle Valo 			break;
1875b43310e4SGovindaraj Saminathan 		case ATH11K_STATE_FTM:
1876b43310e4SGovindaraj Saminathan 			ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
1877b43310e4SGovindaraj Saminathan 				   "fw mode reset done radio %d\n", i);
1878b43310e4SGovindaraj Saminathan 			break;
1879d5c65159SKalle Valo 		}
1880b43310e4SGovindaraj Saminathan 
1881d5c65159SKalle Valo 		mutex_unlock(&ar->conf_mutex);
1882d5c65159SKalle Valo 	}
1883d5c65159SKalle Valo 	complete(&ab->driver_recovery);
1884d5c65159SKalle Valo }
1885d5c65159SKalle Valo 
ath11k_core_restart(struct work_struct * work)188638194f3aSWen Gong static void ath11k_core_restart(struct work_struct *work)
188738194f3aSWen Gong {
188838194f3aSWen Gong 	struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
188938194f3aSWen Gong 	int ret;
189038194f3aSWen Gong 
189138194f3aSWen Gong 	ret = ath11k_core_reconfigure_on_crash(ab);
189238194f3aSWen Gong 	if (ret) {
189338194f3aSWen Gong 		ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
189438194f3aSWen Gong 		return;
189538194f3aSWen Gong 	}
189638194f3aSWen Gong 
189738194f3aSWen Gong 	if (ab->is_reset)
189838194f3aSWen Gong 		complete_all(&ab->reconfigure_complete);
189938194f3aSWen Gong 
190038194f3aSWen Gong 	if (!ab->is_reset)
190138194f3aSWen Gong 		ath11k_core_post_reconfigure_recovery(ab);
190238194f3aSWen Gong }
190338194f3aSWen Gong 
ath11k_core_reset(struct work_struct * work)190413da397fSWen Gong static void ath11k_core_reset(struct work_struct *work)
190513da397fSWen Gong {
190613da397fSWen Gong 	struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work);
190713da397fSWen Gong 	int reset_count, fail_cont_count;
190813da397fSWen Gong 	long time_left;
190913da397fSWen Gong 
191013da397fSWen Gong 	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) {
191113da397fSWen Gong 		ath11k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags);
191213da397fSWen Gong 		return;
191313da397fSWen Gong 	}
191413da397fSWen Gong 
191513da397fSWen Gong 	/* Sometimes the recovery will fail and then the next all recovery fail,
191613da397fSWen Gong 	 * this is to avoid infinite recovery since it can not recovery success.
191713da397fSWen Gong 	 */
191813da397fSWen Gong 	fail_cont_count = atomic_read(&ab->fail_cont_count);
191913da397fSWen Gong 
192013da397fSWen Gong 	if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FINAL)
192113da397fSWen Gong 		return;
192213da397fSWen Gong 
192313da397fSWen Gong 	if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FIRST &&
192413da397fSWen Gong 	    time_before(jiffies, ab->reset_fail_timeout))
192513da397fSWen Gong 		return;
192613da397fSWen Gong 
192713da397fSWen Gong 	reset_count = atomic_inc_return(&ab->reset_count);
192813da397fSWen Gong 
192913da397fSWen Gong 	if (reset_count > 1) {
193013da397fSWen Gong 		/* Sometimes it happened another reset worker before the previous one
193113da397fSWen Gong 		 * completed, then the second reset worker will destroy the previous one,
193213da397fSWen Gong 		 * thus below is to avoid that.
193313da397fSWen Gong 		 */
1934405342ebSColin Ian King 		ath11k_warn(ab, "already resetting count %d\n", reset_count);
193513da397fSWen Gong 
193613da397fSWen Gong 		reinit_completion(&ab->reset_complete);
193713da397fSWen Gong 		time_left = wait_for_completion_timeout(&ab->reset_complete,
193813da397fSWen Gong 							ATH11K_RESET_TIMEOUT_HZ);
193913da397fSWen Gong 
194013da397fSWen Gong 		if (time_left) {
194113da397fSWen Gong 			ath11k_dbg(ab, ATH11K_DBG_BOOT, "to skip reset\n");
194213da397fSWen Gong 			atomic_dec(&ab->reset_count);
194313da397fSWen Gong 			return;
194413da397fSWen Gong 		}
194513da397fSWen Gong 
194613da397fSWen Gong 		ab->reset_fail_timeout = jiffies + ATH11K_RESET_FAIL_TIMEOUT_HZ;
194713da397fSWen Gong 		/* Record the continuous recovery fail count when recovery failed*/
194813da397fSWen Gong 		atomic_inc(&ab->fail_cont_count);
194913da397fSWen Gong 	}
195013da397fSWen Gong 
195113da397fSWen Gong 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset starting\n");
195213da397fSWen Gong 
195313da397fSWen Gong 	ab->is_reset = true;
195413da397fSWen Gong 	atomic_set(&ab->recovery_count, 0);
195538194f3aSWen Gong 	reinit_completion(&ab->recovery_start);
195638194f3aSWen Gong 	atomic_set(&ab->recovery_start_count, 0);
195738194f3aSWen Gong 
195838194f3aSWen Gong 	ath11k_core_pre_reconfigure_recovery(ab);
195938194f3aSWen Gong 
196038194f3aSWen Gong 	reinit_completion(&ab->reconfigure_complete);
196138194f3aSWen Gong 	ath11k_core_post_reconfigure_recovery(ab);
196238194f3aSWen Gong 
196338194f3aSWen Gong 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "waiting recovery start...\n");
196438194f3aSWen Gong 
196538194f3aSWen Gong 	time_left = wait_for_completion_timeout(&ab->recovery_start,
196638194f3aSWen Gong 						ATH11K_RECOVER_START_TIMEOUT_HZ);
196713da397fSWen Gong 
196813da397fSWen Gong 	ath11k_hif_power_down(ab);
196913da397fSWen Gong 	ath11k_hif_power_up(ab);
197013da397fSWen Gong 
197113da397fSWen Gong 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
197213da397fSWen Gong }
197313da397fSWen Gong 
ath11k_init_hw_params(struct ath11k_base * ab)1974d3318abfSAnilkumar Kolli static int ath11k_init_hw_params(struct ath11k_base *ab)
1975d3318abfSAnilkumar Kolli {
1976d3318abfSAnilkumar Kolli 	const struct ath11k_hw_params *hw_params = NULL;
1977d3318abfSAnilkumar Kolli 	int i;
1978d3318abfSAnilkumar Kolli 
1979d3318abfSAnilkumar Kolli 	for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
1980d3318abfSAnilkumar Kolli 		hw_params = &ath11k_hw_params[i];
1981d3318abfSAnilkumar Kolli 
1982d3318abfSAnilkumar Kolli 		if (hw_params->hw_rev == ab->hw_rev)
1983d3318abfSAnilkumar Kolli 			break;
1984d3318abfSAnilkumar Kolli 	}
1985d3318abfSAnilkumar Kolli 
1986d3318abfSAnilkumar Kolli 	if (i == ARRAY_SIZE(ath11k_hw_params)) {
1987d3318abfSAnilkumar Kolli 		ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);
1988d3318abfSAnilkumar Kolli 		return -EINVAL;
1989d3318abfSAnilkumar Kolli 	}
1990d3318abfSAnilkumar Kolli 
1991d3318abfSAnilkumar Kolli 	ab->hw_params = *hw_params;
1992d3318abfSAnilkumar Kolli 
19936b7abacbSKalle Valo 	ath11k_info(ab, "%s\n", ab->hw_params.name);
1994d3318abfSAnilkumar Kolli 
1995d3318abfSAnilkumar Kolli 	return 0;
1996d3318abfSAnilkumar Kolli }
1997d3318abfSAnilkumar Kolli 
ath11k_core_pre_init(struct ath11k_base * ab)1998b8246f88SKalle Valo int ath11k_core_pre_init(struct ath11k_base *ab)
1999b8246f88SKalle Valo {
2000b8246f88SKalle Valo 	int ret;
2001b8246f88SKalle Valo 
2002b8246f88SKalle Valo 	ret = ath11k_init_hw_params(ab);
2003b8246f88SKalle Valo 	if (ret) {
2004b8246f88SKalle Valo 		ath11k_err(ab, "failed to get hw params: %d\n", ret);
2005b8246f88SKalle Valo 		return ret;
2006b8246f88SKalle Valo 	}
2007b8246f88SKalle Valo 
2008b8246f88SKalle Valo 	return 0;
2009b8246f88SKalle Valo }
2010b8246f88SKalle Valo EXPORT_SYMBOL(ath11k_core_pre_init);
2011b8246f88SKalle Valo 
ath11k_core_init(struct ath11k_base * ab)20121ff8ed78SGovind Singh int ath11k_core_init(struct ath11k_base *ab)
20131ff8ed78SGovind Singh {
20141ff8ed78SGovind Singh 	int ret;
20151ff8ed78SGovind Singh 
2016d5c65159SKalle Valo 	ret = ath11k_core_soc_create(ab);
2017d5c65159SKalle Valo 	if (ret) {
2018d5c65159SKalle Valo 		ath11k_err(ab, "failed to create soc core: %d\n", ret);
2019d5c65159SKalle Valo 		return ret;
2020d5c65159SKalle Valo 	}
2021d5c65159SKalle Valo 
2022d5c65159SKalle Valo 	return 0;
2023d5c65159SKalle Valo }
20247f4beda2SGovind Singh EXPORT_SYMBOL(ath11k_core_init);
2025d5c65159SKalle Valo 
ath11k_core_deinit(struct ath11k_base * ab)2026d5c65159SKalle Valo void ath11k_core_deinit(struct ath11k_base *ab)
2027d5c65159SKalle Valo {
2028d5c65159SKalle Valo 	mutex_lock(&ab->core_lock);
2029d5c65159SKalle Valo 
2030d5c65159SKalle Valo 	ath11k_core_pdev_destroy(ab);
2031d5c65159SKalle Valo 	ath11k_core_stop(ab);
2032d5c65159SKalle Valo 
2033d5c65159SKalle Valo 	mutex_unlock(&ab->core_lock);
2034d5c65159SKalle Valo 
203531858805SGovind Singh 	ath11k_hif_power_down(ab);
2036d5c65159SKalle Valo 	ath11k_mac_destroy(ab);
2037d5c65159SKalle Valo 	ath11k_core_soc_destroy(ab);
2038d5c65159SKalle Valo }
20396e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_deinit);
2040d5c65159SKalle Valo 
ath11k_core_free(struct ath11k_base * ab)2041d5c65159SKalle Valo void ath11k_core_free(struct ath11k_base *ab)
2042d5c65159SKalle Valo {
204313da397fSWen Gong 	destroy_workqueue(ab->workqueue_aux);
20449f4ecacfSAditya Kumar Singh 	destroy_workqueue(ab->workqueue);
20459f4ecacfSAditya Kumar Singh 
2046d5c65159SKalle Valo 	kfree(ab);
2047d5c65159SKalle Valo }
20486e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_free);
2049d5c65159SKalle Valo 
ath11k_core_alloc(struct device * dev,size_t priv_size,enum ath11k_bus bus)2050630ad41cSGovind Singh struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
205192c1858eSManikanta Pubbisetty 				      enum ath11k_bus bus)
2052d5c65159SKalle Valo {
2053d5c65159SKalle Valo 	struct ath11k_base *ab;
2054d5c65159SKalle Valo 
2055630ad41cSGovind Singh 	ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);
2056d5c65159SKalle Valo 	if (!ab)
2057d5c65159SKalle Valo 		return NULL;
2058d5c65159SKalle Valo 
2059d5c65159SKalle Valo 	init_completion(&ab->driver_recovery);
2060d5c65159SKalle Valo 
2061d5c65159SKalle Valo 	ab->workqueue = create_singlethread_workqueue("ath11k_wq");
2062d5c65159SKalle Valo 	if (!ab->workqueue)
2063d5c65159SKalle Valo 		goto err_sc_free;
2064d5c65159SKalle Valo 
206513da397fSWen Gong 	ab->workqueue_aux = create_singlethread_workqueue("ath11k_aux_wq");
206613da397fSWen Gong 	if (!ab->workqueue_aux)
206713da397fSWen Gong 		goto err_free_wq;
206813da397fSWen Gong 
2069d5c65159SKalle Valo 	mutex_init(&ab->core_lock);
20707b0c70d9SKarthikeyan Periyasamy 	mutex_init(&ab->tbl_mtx_lock);
2071d5c65159SKalle Valo 	spin_lock_init(&ab->base_lock);
20729dcf6808SWen Gong 	mutex_init(&ab->vdev_id_11d_lock);
207313da397fSWen Gong 	init_completion(&ab->reset_complete);
207438194f3aSWen Gong 	init_completion(&ab->reconfigure_complete);
207538194f3aSWen Gong 	init_completion(&ab->recovery_start);
2076d5c65159SKalle Valo 
2077d5c65159SKalle Valo 	INIT_LIST_HEAD(&ab->peers);
2078d5c65159SKalle Valo 	init_waitqueue_head(&ab->peer_mapping_wq);
20796bc9d6f7SJohn Crispin 	init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
208002f9d3c1SGovindaraj Saminathan 	init_waitqueue_head(&ab->qmi.cold_boot_waitq);
2081d5c65159SKalle Valo 	INIT_WORK(&ab->restart_work, ath11k_core_restart);
20829dcf6808SWen Gong 	INIT_WORK(&ab->update_11d_work, ath11k_update_11d);
208313da397fSWen Gong 	INIT_WORK(&ab->reset_work, ath11k_core_reset);
2084d5c65159SKalle Valo 	timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
20858733d835SCarl Huang 	init_completion(&ab->htc_suspend);
208679802b13SCarl Huang 	init_completion(&ab->wow.wakeup_completed);
20878733d835SCarl Huang 
2088d5c65159SKalle Valo 	ab->dev = dev;
20896eb6ea51SGovind Singh 	ab->hif.bus = bus;
2090d5c65159SKalle Valo 
2091d5c65159SKalle Valo 	return ab;
2092d5c65159SKalle Valo 
209313da397fSWen Gong err_free_wq:
209413da397fSWen Gong 	destroy_workqueue(ab->workqueue);
2095d5c65159SKalle Valo err_sc_free:
2096d5c65159SKalle Valo 	kfree(ab);
2097d5c65159SKalle Valo 	return NULL;
2098d5c65159SKalle Valo }
20996e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_alloc);
21006e0355afSGovind Singh 
21016e0355afSGovind Singh MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
21026e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
2103