xref: /linux/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2 /*
3  * Copyright (C) 2023-2025 Intel Corporation
4  */
5 
6 #ifndef __fw_regulatory_h__
7 #define __fw_regulatory_h__
8 
9 #include "fw/img.h"
10 #include "fw/api/commands.h"
11 #include "fw/api/power.h"
12 #include "fw/api/phy.h"
13 #include "fw/api/config.h"
14 #include "fw/api/nvm-reg.h"
15 #include "fw/img.h"
16 #include "iwl-trans.h"
17 
18 #define BIOS_SAR_MAX_PROFILE_NUM	4
19 /*
20  * Each SAR profile has (up to, depends on the table revision) 4 chains:
21  * chain A, chain B, chain A when in CDB, chain B when in CDB
22  */
23 #define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
24 #define BIOS_SAR_NUM_CHAINS             2
25 #define BIOS_SAR_MAX_SUB_BANDS_NUM      11
26 
27 #define BIOS_GEO_NUM_CHAINS		2
28 #define BIOS_GEO_MAX_NUM_BANDS		3
29 #define BIOS_GEO_MAX_PROFILE_NUM	8
30 #define BIOS_GEO_MIN_PROFILE_NUM	3
31 
32 #define IWL_SAR_ENABLE_MSK		BIT(0)
33 
34 /* PPAG gain value bounds in 1/8 dBm */
35 #define IWL_PPAG_MIN_LB	-16
36 #define IWL_PPAG_MAX_LB 24
37 #define IWL_PPAG_MIN_HB -16
38 #define IWL_PPAG_MAX_HB 40
39 
40 #define IWL_PPAG_ETSI_CHINA_MASK	3
41 #define IWL_PPAG_REV3_MASK		0x7FF
42 
43 #define IWL_WTAS_ENABLED_MSK		BIT(0)
44 #define IWL_WTAS_OVERRIDE_IEC_MSK	BIT(1)
45 #define IWL_WTAS_ENABLE_IEC_MSK		BIT(2)
46 #define IWL_WTAS_CANADA_UHB_MSK		BIT(15)
47 #define IWL_WTAS_USA_UHB_MSK		BIT(16)
48 
49 struct iwl_tas_selection_data {
50 	u8 override_tas_iec:1,
51 	   enable_tas_iec:1,
52 	   usa_tas_uhb_allowed:1,
53 	   canada_tas_uhb_allowed:1;
54 };
55 
56 #define BIOS_MCC_CHINA 0x434e
57 
58 /*
59  * The profile for revision 2 is a superset of revision 1, which is in
60  * turn a superset of revision 0.  So we can store all revisions
61  * inside revision 2, which is what we represent here.
62  */
63 
64 /*
65  * struct iwl_sar_profile_chain - per-chain values of a SAR profile
66  * @subbands: the SAR value for each subband
67  */
68 struct iwl_sar_profile_chain {
69 	u8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
70 };
71 
72 /*
73  * struct iwl_sar_profile - SAR profile from SAR tables
74  * @enabled: whether the profile is enabled or not
75  * @chains: per-chain SAR values
76  */
77 struct iwl_sar_profile {
78 	bool enabled;
79 	struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
80 };
81 
82 /* Same thing as with SAR, all revisions fit in revision 2 */
83 
84 /*
85  * struct iwl_geo_profile_band - per-band geo SAR offsets
86  * @max: the max tx power allowed for the band
87  * @chains: SAR offsets values for each chain
88  */
89 struct iwl_geo_profile_band {
90 	u8 max;
91 	u8 chains[BIOS_GEO_NUM_CHAINS];
92 };
93 
94 /*
95  * struct iwl_geo_profile - geo profile
96  * @bands: per-band table of the SAR offsets
97  */
98 struct iwl_geo_profile {
99 	struct iwl_geo_profile_band bands[BIOS_GEO_MAX_NUM_BANDS];
100 };
101 
102 /* Same thing as with SAR, all revisions fit in revision 2 */
103 struct iwl_ppag_chain {
104 	s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
105 };
106 
107 struct iwl_tas_data {
108 	u8 block_list_size;
109 	u16 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
110 	u8 table_source;
111 	u8 table_revision;
112 	u32 tas_selection;
113 };
114 
115 /* For DSM revision 0 and 4 */
116 enum iwl_dsm_funcs {
117 	DSM_FUNC_QUERY = 0,
118 	DSM_FUNC_DISABLE_SRD = 1,
119 	DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
120 	DSM_FUNC_ENABLE_6E = 3,
121 	DSM_FUNC_REGULATORY_CONFIG = 4,
122 	DSM_FUNC_11AX_ENABLEMENT = 6,
123 	DSM_FUNC_ENABLE_UNII4_CHAN = 7,
124 	DSM_FUNC_ACTIVATE_CHANNEL = 8,
125 	DSM_FUNC_FORCE_DISABLE_CHANNELS = 9,
126 	DSM_FUNC_ENERGY_DETECTION_THRESHOLD = 10,
127 	DSM_FUNC_RFI_CONFIG = 11,
128 	DSM_FUNC_ENABLE_11BE = 12,
129 	DSM_FUNC_NUM_FUNCS = 13,
130 };
131 
132 enum iwl_dsm_values_srd {
133 	DSM_VALUE_SRD_ACTIVE,
134 	DSM_VALUE_SRD_PASSIVE,
135 	DSM_VALUE_SRD_DISABLE,
136 	DSM_VALUE_SRD_MAX
137 };
138 
139 enum iwl_dsm_values_indonesia {
140 	DSM_VALUE_INDONESIA_DISABLE,
141 	DSM_VALUE_INDONESIA_ENABLE,
142 	DSM_VALUE_INDONESIA_RESERVED,
143 	DSM_VALUE_INDONESIA_MAX
144 };
145 
146 enum iwl_dsm_unii4_bitmap {
147 	DSM_VALUE_UNII4_US_OVERRIDE_MSK		= BIT(0),
148 	DSM_VALUE_UNII4_US_EN_MSK		= BIT(1),
149 	DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK	= BIT(2),
150 	DSM_VALUE_UNII4_ETSI_EN_MSK		= BIT(3),
151 	DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK	= BIT(4),
152 	DSM_VALUE_UNII4_CANADA_EN_MSK		= BIT(5),
153 };
154 
155 #define DSM_UNII4_ALLOW_BITMAP (DSM_VALUE_UNII4_US_OVERRIDE_MSK		|\
156 				DSM_VALUE_UNII4_US_EN_MSK		|\
157 				DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK	|\
158 				DSM_VALUE_UNII4_ETSI_EN_MSK		|\
159 				DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK	|\
160 				DSM_VALUE_UNII4_CANADA_EN_MSK)
161 
162 #define DSM_11AX_ALLOW_BITMAP				0xF
163 #define DSM_EDT_ALLOWED_BITMAP				0x7ffff0
164 #define DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP	0x7FF
165 
166 enum iwl_dsm_values_rfi {
167 	DSM_VALUE_RFI_DLVR_DISABLE	= BIT(0),
168 	DSM_VALUE_RFI_DDR_DISABLE	= BIT(1),
169 };
170 
171 #define DSM_VALUE_RFI_DISABLE	(DSM_VALUE_RFI_DLVR_DISABLE |\
172 				 DSM_VALUE_RFI_DDR_DISABLE)
173 
174 bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt);
175 
176 enum iwl_dsm_masks_reg {
177 	DSM_MASK_CHINA_22_REG = BIT(2)
178 };
179 
180 struct iwl_fw_runtime;
181 
182 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
183 
184 int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
185 			   struct iwl_per_chain_offset *table,
186 			   u32 n_bands, u32 n_profiles);
187 
188 int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
189 			 __le16 *per_chain, u32 n_tables, u32 n_subbands,
190 			 int prof_a, int prof_b);
191 
192 int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
193 			union iwl_ppag_table_cmd *cmd,
194 			int *cmd_size);
195 
196 bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
197 
198 bool iwl_is_tas_approved(void);
199 bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc);
200 
201 struct iwl_tas_selection_data
202 iwl_parse_tas_selection(const u32 tas_selection, const u8 tbl_rev);
203 
204 int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt);
205 
206 int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt);
207 
208 int iwl_bios_get_wgds_table(struct iwl_fw_runtime *fwrt);
209 
210 int iwl_bios_get_ppag_table(struct iwl_fw_runtime *fwrt);
211 
212 int iwl_bios_get_tas_table(struct iwl_fw_runtime *fwrt,
213 			   struct iwl_tas_data *data);
214 
215 int iwl_bios_get_pwr_limit(struct iwl_fw_runtime *fwrt,
216 			   u64 *dflt_pwr_limit);
217 
218 int iwl_bios_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
219 int iwl_bios_get_eckv(struct iwl_fw_runtime *fwrt, u32 *ext_clk);
220 int iwl_bios_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
221 
222 __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
223 int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
224 			 struct iwl_lari_config_change_cmd *cmd,
225 			 size_t *cmd_size);
226 
227 int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
228 		     u32 *value);
229 
iwl_bios_get_ppag_flags(const u32 ppag_modes,const u8 ppag_bios_rev)230 static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes,
231 					  const u8 ppag_bios_rev)
232 {
233 	/* For revision 4 and above driver is pipe */
234 	if (ppag_bios_rev >= 4)
235 		return ppag_modes;
236 
237 	return ppag_modes & (ppag_bios_rev < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
238 						 IWL_PPAG_REV3_MASK);
239 }
240 
241 bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
242 
243 #define IWL_DSBR_FW_MODIFIED_URM_MASK	BIT(8)
244 #define IWL_DSBR_PERMANENT_URM_MASK	BIT(9)
245 
246 int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
247 int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt);
248 
iwl_bios_setup_step(struct iwl_trans * trans,struct iwl_fw_runtime * fwrt)249 static inline void iwl_bios_setup_step(struct iwl_trans *trans,
250 				       struct iwl_fw_runtime *fwrt)
251 {
252 	u32 dsbr;
253 
254 	if (!trans->mac_cfg->integrated)
255 		return;
256 
257 	if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
258 		return;
259 
260 	if (iwl_bios_get_dsbr(fwrt, &dsbr))
261 		dsbr = 0;
262 
263 	trans->conf.dsbr_urm_fw_dependent =
264 		!!(dsbr & IWL_DSBR_FW_MODIFIED_URM_MASK);
265 	trans->conf.dsbr_urm_permanent =
266 		!!(dsbr & IWL_DSBR_PERMANENT_URM_MASK);
267 }
268 #endif /* __fw_regulatory_h__ */
269