xref: /linux/drivers/net/wireless/realtek/rtw89/regd.c (revision 23ca32e4ead48f68e37000f2552b973ef1439acb)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020  Realtek Corporation
3  */
4 
5 #include "acpi.h"
6 #include "debug.h"
7 #include "ps.h"
8 #include "util.h"
9 
10 static
11 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
12 
13 #define COUNTRY_REGD(_alpha2, _rule_2ghz, _rule_5ghz, _rule_6ghz, _fmap) \
14 	{							\
15 		.alpha2 = _alpha2,				\
16 		.txpwr_regd[RTW89_BAND_2G] = _rule_2ghz,	\
17 		.txpwr_regd[RTW89_BAND_5G] = _rule_5ghz,	\
18 		.txpwr_regd[RTW89_BAND_6G] = _rule_6ghz,	\
19 		.func_bitmap = { _fmap, },	\
20 	}
21 
22 static_assert(BITS_PER_TYPE(unsigned long) >= NUM_OF_RTW89_REGD_FUNC);
23 
24 static const struct rtw89_regd rtw89_ww_regd =
25 	COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW, 0x0);
26 
27 static const struct rtw89_regd rtw89_regd_map[] = {
28 	COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
29 	COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
30 	COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
31 	COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE, 0x0),
32 	COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
33 	COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
34 	COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
35 	COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
36 	COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
37 	COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
38 	COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
39 	COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
40 	COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
41 	COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
42 	COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
43 	COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x1),
44 	COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
45 	COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
46 	COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
47 	COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
48 	COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
49 	COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
50 	COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
51 	COUNTRY_REGD("CZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
52 	COUNTRY_REGD("DK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
53 	COUNTRY_REGD("EE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
54 	COUNTRY_REGD("FI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
55 	COUNTRY_REGD("FR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
56 	COUNTRY_REGD("DE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
57 	COUNTRY_REGD("GR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
58 	COUNTRY_REGD("HU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
59 	COUNTRY_REGD("IS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
60 	COUNTRY_REGD("IE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
61 	COUNTRY_REGD("IT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
62 	COUNTRY_REGD("LV", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
63 	COUNTRY_REGD("LI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
64 	COUNTRY_REGD("LT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
65 	COUNTRY_REGD("LU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
66 	COUNTRY_REGD("MT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
67 	COUNTRY_REGD("MC", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
68 	COUNTRY_REGD("NL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
69 	COUNTRY_REGD("NO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
70 	COUNTRY_REGD("PL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
71 	COUNTRY_REGD("PT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
72 	COUNTRY_REGD("SK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
73 	COUNTRY_REGD("SI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
74 	COUNTRY_REGD("ES", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
75 	COUNTRY_REGD("SE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
76 	COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
77 	COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK, 0x0),
78 	COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
79 	COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
80 	COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
81 	COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
82 	COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
83 	COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
84 	COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
85 	COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
86 	COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
87 	COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
88 	COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
89 	COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
90 	COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
91 	COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
92 	COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
93 	COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
94 	COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
95 	COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
96 	COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
97 	COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
98 	COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
99 	COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
100 	COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
101 	COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR, 0x0),
102 	COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
103 	COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
104 	COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
105 	COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
106 	COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
107 	COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
108 	COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
109 	COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
110 	COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE, 0x0),
111 	COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
112 	COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
113 	COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
114 	COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
115 	COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
116 	COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN, 0x0),
117 	COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
118 	COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
119 	COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
120 	COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC, 0x1),
121 	COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
122 	COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
123 	COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
124 	COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
125 	COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
126 	COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI, 0x0),
127 	COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND, 0x0),
128 	COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
129 	COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
130 	COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
131 	COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
132 	COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC, 0x1),
133 	COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK, 0x0),
134 	COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
135 	COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
136 	COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
137 	COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
138 	COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
139 	COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
140 	COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
141 	COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
142 	COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
143 	COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
144 	COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
145 	COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
146 	COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
147 	COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
148 	COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
149 	COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
150 	COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
151 	COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
152 	COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
153 	COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
154 	COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
155 	COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
156 	COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
157 	COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
158 	COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
159 	COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
160 	COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
161 	COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
162 	COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
163 	COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
164 	COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
165 	COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
166 	COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
167 	COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
168 	COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
169 	COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
170 	COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
171 	COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
172 	COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
173 	COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
174 	COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
175 	COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
176 	COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
177 	COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
178 	COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
179 	COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
180 	COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
181 	COUNTRY_REGD("FO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
182 	COUNTRY_REGD("FJ", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
183 	COUNTRY_REGD("GF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
184 	COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
185 	COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
186 	COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
187 	COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
188 	COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
189 	COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
190 	COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
191 	COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
192 	COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
193 	COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
194 	COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
195 	COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
196 	COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
197 	COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
198 	COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
199 	COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
200 	COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
201 	COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
202 	COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
203 	COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
204 	COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
205 	COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
206 	COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
207 	COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
208 	COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
209 	COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
210 	COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
211 	COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
212 	COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
213 	COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
214 	COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
215 	COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
216 	COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
217 	COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
218 	COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
219 	COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
220 	COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
221 	COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
222 	COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
223 	COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
224 	COUNTRY_REGD("NC", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
225 	COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
226 	COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
227 	COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
228 	COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
229 	COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
230 	COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
231 	COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
232 	COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
233 	COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
234 	COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
235 	COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
236 	COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
237 	COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
238 	COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
239 	COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
240 	COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
241 	COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
242 	COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
243 	COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
244 	COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
245 	COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
246 	COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
247 	COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
248 	COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
249 	COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
250 	COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
251 	COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
252 	COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
253 	COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
254 	COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
255 	COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
256 	COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
257 	COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA, 0x0),
258 	COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
259 	COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
260 	COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
261 	COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
262 	COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
263 	COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
264 	COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
265 	COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
266 	COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
267 	COUNTRY_REGD("SY", RTW89_ETSI, RTW89_NA, RTW89_NA, 0x0),
268 	COUNTRY_REGD("SD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
269 	COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
270 };
271 
272 static const char rtw89_alpha2_list_eu[][3] = {
273 	"AT",
274 	"BE",
275 	"CY",
276 	"CZ",
277 	"DK",
278 	"EE",
279 	"FI",
280 	"FR",
281 	"DE",
282 	"GR",
283 	"HU",
284 	"IS",
285 	"IE",
286 	"IT",
287 	"LV",
288 	"LI",
289 	"LT",
290 	"LU",
291 	"MT",
292 	"MC",
293 	"NL",
294 	"NO",
295 	"PL",
296 	"PT",
297 	"SK",
298 	"SI",
299 	"ES",
300 	"SE",
301 	"CH",
302 	"BG",
303 	"HR",
304 	"RO",
305 };
306 
307 static const struct rtw89_regd *rtw89_regd_find_reg_by_name(struct rtw89_dev *rtwdev,
308 							    const char *alpha2)
309 {
310 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
311 	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
312 	u32 i;
313 
314 	for (i = 0; i < regd_ctrl->nr; i++) {
315 		if (!memcmp(regd_ctrl->map[i].alpha2, alpha2, 2))
316 			return &regd_ctrl->map[i];
317 	}
318 
319 	return &rtw89_ww_regd;
320 }
321 
322 static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
323 {
324 	return regd == &rtw89_ww_regd;
325 }
326 
327 static u8 rtw89_regd_get_index(struct rtw89_dev *rtwdev, const struct rtw89_regd *regd)
328 {
329 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
330 	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
331 
332 	BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
333 
334 	if (rtw89_regd_is_ww(regd))
335 		return RTW89_REGD_MAX_COUNTRY_NUM;
336 
337 	return regd - regd_ctrl->map;
338 }
339 
340 static u8 rtw89_regd_get_index_by_name(struct rtw89_dev *rtwdev, const char *alpha2)
341 {
342 	const struct rtw89_regd *regd;
343 
344 	regd = rtw89_regd_find_reg_by_name(rtwdev, alpha2);
345 	return rtw89_regd_get_index(rtwdev, regd);
346 }
347 
348 #define rtw89_debug_regd(_dev, _regd, _desc, _argv...) \
349 do { \
350 	typeof(_regd) __r = _regd; \
351 	rtw89_debug(_dev, RTW89_DBG_REGD, _desc \
352 		    ": %c%c: mapping txregd to {2g: %d, 5g: %d, 6g: %d}\n", \
353 		    ##_argv, __r->alpha2[0], __r->alpha2[1], \
354 		    __r->txpwr_regd[RTW89_BAND_2G], \
355 		    __r->txpwr_regd[RTW89_BAND_5G], \
356 		    __r->txpwr_regd[RTW89_BAND_6G]); \
357 } while (0)
358 
359 static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
360 				   struct wiphy *wiphy)
361 {
362 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
363 	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
364 	const struct rtw89_chip_info *chip = rtwdev->chip;
365 	struct ieee80211_supported_band *sband;
366 	struct rtw89_acpi_dsm_result res = {};
367 	bool enable_by_fcc;
368 	bool enable_by_ic;
369 	int ret;
370 	u8 val;
371 	int i;
372 
373 	sband = wiphy->bands[NL80211_BAND_5GHZ];
374 	if (!sband)
375 		return;
376 
377 	if (!chip->support_unii4) {
378 		sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
379 		return;
380 	}
381 
382 	bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
383 
384 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
385 	if (ret) {
386 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
387 			    "acpi: cannot eval unii 4: %d\n", ret);
388 		enable_by_fcc = true;
389 		enable_by_ic = false;
390 		goto bottom;
391 	}
392 
393 	val = res.u.value;
394 	enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC);
395 	enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC);
396 
397 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
398 		    "acpi: eval if allow unii-4: 0x%x\n", val);
399 
400 bottom:
401 	for (i = 0; i < regd_ctrl->nr; i++) {
402 		const struct rtw89_regd *regd = &regd_ctrl->map[i];
403 
404 		switch (regd->txpwr_regd[RTW89_BAND_5G]) {
405 		case RTW89_FCC:
406 			if (enable_by_fcc)
407 				clear_bit(i, regulatory->block_unii4);
408 			break;
409 		case RTW89_IC:
410 			if (enable_by_ic)
411 				clear_bit(i, regulatory->block_unii4);
412 			break;
413 		default:
414 			break;
415 		}
416 	}
417 }
418 
419 static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
420 					   const char *alpha2)
421 {
422 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
423 	u8 index;
424 
425 	index = rtw89_regd_get_index_by_name(rtwdev, alpha2);
426 	if (index == RTW89_REGD_MAX_COUNTRY_NUM) {
427 		rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n",
428 			    __func__, alpha2[0], alpha2[1]);
429 		return;
430 	}
431 
432 	if (block)
433 		set_bit(index, regulatory->block_6ghz);
434 	else
435 		clear_bit(index, regulatory->block_6ghz);
436 }
437 
438 static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev)
439 {
440 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
441 	const struct rtw89_acpi_country_code *country;
442 	const struct rtw89_acpi_policy_6ghz *ptr;
443 	struct rtw89_acpi_dsm_result res = {};
444 	bool to_block;
445 	int i, j;
446 	int ret;
447 
448 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res);
449 	if (ret) {
450 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
451 			    "acpi: cannot eval policy 6ghz: %d\n", ret);
452 		return;
453 	}
454 
455 	ptr = res.u.policy_6ghz;
456 
457 	switch (ptr->policy_mode) {
458 	case RTW89_ACPI_POLICY_BLOCK:
459 		to_block = true;
460 		break;
461 	case RTW89_ACPI_POLICY_ALLOW:
462 		to_block = false;
463 		/* only below list is allowed; block all first */
464 		bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
465 		break;
466 	default:
467 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
468 			    "%s: unknown policy mode: %d\n", __func__,
469 			    ptr->policy_mode);
470 		goto out;
471 	}
472 
473 	for (i = 0; i < ptr->country_count; i++) {
474 		country = &ptr->country_list[i];
475 		if (memcmp("EU", country->alpha2, 2) != 0) {
476 			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
477 						       country->alpha2);
478 			continue;
479 		}
480 
481 		for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++)
482 			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
483 						       rtw89_alpha2_list_eu[j]);
484 	}
485 
486 out:
487 	kfree(ptr);
488 }
489 
490 static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
491 {
492 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
493 	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
494 	const struct rtw89_acpi_policy_6ghz_sp *ptr;
495 	struct rtw89_acpi_dsm_result res = {};
496 	bool enable_by_us;
497 	int ret;
498 	int i;
499 
500 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
501 	if (ret) {
502 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
503 			    "acpi: cannot eval policy 6ghz-sp: %d\n", ret);
504 		return;
505 	}
506 
507 	ptr = res.u.policy_6ghz_sp;
508 
509 	switch (ptr->override) {
510 	default:
511 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
512 			    "%s: unknown override case: %d\n", __func__,
513 			    ptr->override);
514 		fallthrough;
515 	case 0:
516 		goto out;
517 	case 1:
518 		break;
519 	}
520 
521 	bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
522 
523 	enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
524 
525 	for (i = 0; i < regd_ctrl->nr; i++) {
526 		const struct rtw89_regd *tmp = &regd_ctrl->map[i];
527 
528 		if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0)
529 			clear_bit(i, regulatory->block_6ghz_sp);
530 	}
531 
532 out:
533 	kfree(ptr);
534 }
535 
536 static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
537 {
538 	const struct rtw89_chip_info *chip = rtwdev->chip;
539 	bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
540 	bool regd_allow_6ghz = chip_support_6ghz;
541 	struct ieee80211_supported_band *sband;
542 	struct rtw89_acpi_dsm_result res = {};
543 	int ret;
544 	u8 val;
545 
546 	if (!chip_support_6ghz)
547 		goto bottom;
548 
549 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res);
550 	if (ret) {
551 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
552 			    "acpi: cannot eval 6ghz: %d\n", ret);
553 		goto bottom;
554 	}
555 
556 	val = res.u.value;
557 
558 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
559 		    "acpi: eval if disallow 6ghz: %d\n", val);
560 
561 	switch (val) {
562 	case 0:
563 		regd_allow_6ghz = true;
564 		break;
565 	case 1:
566 		regd_allow_6ghz = false;
567 		break;
568 	default:
569 		break;
570 	}
571 
572 bottom:
573 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
574 		    regd_allow_6ghz);
575 
576 	if (regd_allow_6ghz) {
577 		rtw89_regd_setup_policy_6ghz(rtwdev);
578 		rtw89_regd_setup_policy_6ghz_sp(rtwdev);
579 		return;
580 	}
581 
582 	sband = wiphy->bands[NL80211_BAND_6GHZ];
583 	if (!sband)
584 		return;
585 
586 	wiphy->bands[NL80211_BAND_6GHZ] = NULL;
587 	kfree((__force void *)sband->iftype_data);
588 	kfree(sband);
589 }
590 
591 #define RTW89_DEF_REGD_STR(regd) \
592 	[RTW89_ ## regd] = #regd
593 
594 static const char * const rtw89_regd_string[] = {
595 	RTW89_DEF_REGD_STR(WW),
596 	RTW89_DEF_REGD_STR(ETSI),
597 	RTW89_DEF_REGD_STR(FCC),
598 	RTW89_DEF_REGD_STR(MKK),
599 	RTW89_DEF_REGD_STR(NA),
600 	RTW89_DEF_REGD_STR(IC),
601 	RTW89_DEF_REGD_STR(KCC),
602 	RTW89_DEF_REGD_STR(ACMA),
603 	RTW89_DEF_REGD_STR(NCC),
604 	RTW89_DEF_REGD_STR(MEXICO),
605 	RTW89_DEF_REGD_STR(CHILE),
606 	RTW89_DEF_REGD_STR(UKRAINE),
607 	RTW89_DEF_REGD_STR(CN),
608 	RTW89_DEF_REGD_STR(QATAR),
609 	RTW89_DEF_REGD_STR(UK),
610 	RTW89_DEF_REGD_STR(THAILAND),
611 };
612 
613 static_assert(ARRAY_SIZE(rtw89_regd_string) == RTW89_REGD_NUM);
614 
615 const char *rtw89_regd_get_string(enum rtw89_regulation_type regd)
616 {
617 	if (regd < 0 || regd >= RTW89_REGD_NUM)
618 		return "(unknown)";
619 
620 	return rtw89_regd_string[regd];
621 }
622 
623 int rtw89_regd_setup(struct rtw89_dev *rtwdev)
624 {
625 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
626 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
627 	const struct rtw89_regd_data *regd_data = elm_info->regd;
628 	struct wiphy *wiphy = rtwdev->hw->wiphy;
629 
630 	if (regd_data) {
631 		regulatory->ctrl.nr = regd_data->nr;
632 		regulatory->ctrl.map = regd_data->map;
633 	} else {
634 		regulatory->ctrl.nr = ARRAY_SIZE(rtw89_regd_map);
635 		regulatory->ctrl.map = rtw89_regd_map;
636 	}
637 
638 	regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
639 	regulatory->txpwr_uk_follow_etsi = true;
640 
641 	if (!wiphy)
642 		return -EINVAL;
643 
644 	rtw89_regd_setup_unii4(rtwdev, wiphy);
645 	rtw89_regd_setup_6ghz(rtwdev, wiphy);
646 
647 	wiphy->reg_notifier = rtw89_regd_notifier;
648 	return 0;
649 }
650 
651 int rtw89_regd_init_hint(struct rtw89_dev *rtwdev)
652 {
653 	const struct rtw89_regd *chip_regd;
654 	struct wiphy *wiphy = rtwdev->hw->wiphy;
655 	int ret;
656 
657 	if (!wiphy)
658 		return -EINVAL;
659 
660 	chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code);
661 	if (!rtw89_regd_is_ww(chip_regd)) {
662 		rtwdev->regulatory.regd = chip_regd;
663 		/* Ignore country ie if there is a country domain programmed in chip */
664 		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
665 		wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
666 
667 		ret = regulatory_hint(rtwdev->hw->wiphy,
668 				      rtwdev->regulatory.regd->alpha2);
669 		if (ret)
670 			rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
671 
672 		rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
673 		return 0;
674 	}
675 
676 	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
677 			 "worldwide roaming chip, follow the setting of stack");
678 	return 0;
679 }
680 
681 static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
682 					  struct wiphy *wiphy)
683 {
684 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
685 	const struct rtw89_chip_info *chip = rtwdev->chip;
686 	const struct rtw89_regd *regd = regulatory->regd;
687 	struct ieee80211_supported_band *sband;
688 	u8 index;
689 	int i;
690 
691 	sband = wiphy->bands[NL80211_BAND_5GHZ];
692 	if (!sband)
693 		return;
694 
695 	if (!chip->support_unii4)
696 		return;
697 
698 	index = rtw89_regd_get_index(rtwdev, regd);
699 	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
700 	    !test_bit(index, regulatory->block_unii4))
701 		return;
702 
703 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
704 		    regd->alpha2[0], regd->alpha2[1]);
705 
706 	for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
707 		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
708 }
709 
710 static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
711 {
712 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
713 	const struct rtw89_regd *regd = regulatory->regd;
714 	u8 index;
715 
716 	index = rtw89_regd_get_index(rtwdev, regd);
717 	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
718 	    !test_bit(index, regulatory->block_6ghz))
719 		return false;
720 
721 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
722 		    regd->alpha2[0], regd->alpha2[1]);
723 	return true;
724 }
725 
726 static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
727 {
728 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
729 	const struct rtw89_regd *regd = regulatory->regd;
730 
731 	if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
732 		return false;
733 
734 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
735 		    regd->alpha2[0], regd->alpha2[1]);
736 	return true;
737 }
738 
739 static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
740 					 struct wiphy *wiphy)
741 {
742 	struct ieee80211_supported_band *sband;
743 	int i;
744 
745 	if (!regd_is_6ghz_blocked(rtwdev) &&
746 	    !regd_is_6ghz_not_applicable(rtwdev))
747 		return;
748 
749 	sband = wiphy->bands[NL80211_BAND_6GHZ];
750 	if (!sband)
751 		return;
752 
753 	for (i = 0; i < sband->n_channels; i++)
754 		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
755 }
756 
757 static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
758 {
759 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
760 	const struct rtw89_regd *regd = regulatory->regd;
761 	struct rtw89_tas_info *tas = &rtwdev->tas;
762 	u8 tas_country;
763 
764 	if (!tas->enable)
765 		return;
766 
767 	if (memcmp("US", regd->alpha2, 2) == 0)
768 		tas_country = RTW89_ACPI_CONF_TAS_US;
769 	else if (memcmp("CA", regd->alpha2, 2) == 0)
770 		tas_country = RTW89_ACPI_CONF_TAS_CA;
771 	else if (memcmp("KR", regd->alpha2, 2) == 0)
772 		tas_country = RTW89_ACPI_CONF_TAS_KR;
773 	else
774 		tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
775 
776 	tas->block_regd = !(tas->enabled_countries & tas_country &&
777 			    test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
778 }
779 
780 static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
781 {
782 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
783 	struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
784 	const struct rtw89_chip_info *chip = rtwdev->chip;
785 	const struct rtw89_regd *regd = regulatory->regd;
786 
787 	if (!chip->support_ant_gain)
788 		return;
789 
790 	ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
791 }
792 
793 static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
794 				      struct wiphy *wiphy,
795 				      struct regulatory_request *request)
796 {
797 	rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
798 	/* This notification might be set from the system of distros,
799 	 * and it does not expect the regulatory will be modified by
800 	 * connecting to an AP (i.e. country ie).
801 	 */
802 	if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
803 	    !rtw89_regd_is_ww(rtwdev->regulatory.regd))
804 		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
805 	else
806 		wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
807 
808 	rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
809 	rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
810 	rtw89_regd_apply_policy_tas(rtwdev);
811 	rtw89_regd_apply_policy_ant_gain(rtwdev);
812 }
813 
814 static
815 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
816 {
817 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
818 	struct rtw89_dev *rtwdev = hw->priv;
819 
820 	wiphy_lock(wiphy);
821 	rtw89_leave_ps_mode(rtwdev);
822 
823 	if (wiphy->regd) {
824 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
825 			    "There is a country domain programmed in chip, ignore notifications\n");
826 		goto exit;
827 	}
828 	rtw89_regd_notifier_apply(rtwdev, wiphy, request);
829 	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
830 			 "get from initiator %d, alpha2",
831 			 request->initiator);
832 
833 	rtw89_core_set_chip_txpwr(rtwdev);
834 
835 exit:
836 	wiphy_unlock(wiphy);
837 }
838 
839 /* Maximum Transmit Power field (@raw) can be EIRP or PSD.
840  * Both units are 0.5 dB-based. Return a constraint in dB.
841  */
842 static s8 tpe_get_constraint(s8 raw)
843 {
844 	const u8 hw_deviation = 3; /* unit: 0.5 dB */
845 	const u8 antenna_gain = 10; /* unit: 0.5 dB */
846 	const u8 array_gain = 6; /* unit: 0.5 dB */
847 	const u8 offset = hw_deviation + antenna_gain + array_gain;
848 
849 	return (raw - offset) / 2;
850 }
851 
852 static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
853 {
854 	if (tpe->valid) {
855 		tpe->constraint = min(tpe->constraint, cstr);
856 		return;
857 	}
858 
859 	tpe->constraint = cstr;
860 	tpe->valid = true;
861 }
862 
863 static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
864 			       const struct ieee80211_parsed_tpe_eirp *eirp)
865 {
866 	unsigned int i;
867 	s8 cstr;
868 
869 	if (!eirp->valid)
870 		return;
871 
872 	for (i = 0; i < eirp->count; i++) {
873 		cstr = tpe_get_constraint(eirp->power[i]);
874 		tpe_intersect_constraint(tpe, cstr);
875 	}
876 }
877 
878 static s8 tpe_convert_psd_to_eirp(s8 psd)
879 {
880 	static const unsigned int mlog20 = 1301;
881 
882 	return psd + 10 * mlog20 / 1000;
883 }
884 
885 static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
886 			      const struct ieee80211_parsed_tpe_psd *psd)
887 {
888 	unsigned int i;
889 	s8 cstr_psd;
890 	s8 cstr;
891 
892 	if (!psd->valid)
893 		return;
894 
895 	for (i = 0; i < psd->count; i++) {
896 		cstr_psd = tpe_get_constraint(psd->power[i]);
897 		cstr = tpe_convert_psd_to_eirp(cstr_psd);
898 		tpe_intersect_constraint(tpe, cstr);
899 	}
900 }
901 
902 static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
903 				struct rtw89_reg_6ghz_tpe *result_tpe,
904 				const struct ieee80211_parsed_tpe *parsed_tpe)
905 {
906 	static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
907 
908 	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
909 	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
910 	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
911 	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
912 }
913 
914 static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
915 {
916 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
917 	struct rtw89_reg_6ghz_tpe new = {};
918 	struct rtw89_vif_link *rtwvif_link;
919 	struct rtw89_vif *rtwvif;
920 	unsigned int link_id;
921 	bool changed = false;
922 
923 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
924 		const struct rtw89_reg_6ghz_tpe *tmp;
925 		const struct rtw89_chan *chan;
926 
927 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
928 			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
929 			if (chan->band_type != RTW89_BAND_6G)
930 				continue;
931 
932 			tmp = &rtwvif_link->reg_6ghz_tpe;
933 			if (!tmp->valid)
934 				continue;
935 
936 			tpe_intersect_constraint(&new, tmp->constraint);
937 		}
938 	}
939 
940 	if (memcmp(&regulatory->reg_6ghz_tpe, &new,
941 		   sizeof(regulatory->reg_6ghz_tpe)) != 0)
942 		changed = true;
943 
944 	if (changed) {
945 		if (new.valid)
946 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
947 				    "recalc 6 GHz reg TPE to %d dBm\n",
948 				    new.constraint);
949 		else
950 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
951 				    "recalc 6 GHz reg TPE to none\n");
952 
953 		regulatory->reg_6ghz_tpe = new;
954 	}
955 
956 	return changed;
957 }
958 
959 static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
960 				     struct rtw89_vif_link *rtwvif_link, bool active,
961 				     unsigned int *changed)
962 {
963 	struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe;
964 	struct ieee80211_bss_conf *bss_conf;
965 
966 	memset(tpe, 0, sizeof(*tpe));
967 
968 	if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
969 		goto bottom;
970 
971 	rcu_read_lock();
972 
973 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
974 	rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
975 
976 	rcu_read_unlock();
977 
978 	if (!tpe->valid)
979 		goto bottom;
980 
981 	if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
982 		rtw89_err(rtwdev,
983 			  "%s: constraint %d dBm is less than min valid val\n",
984 			  __func__, tpe->constraint);
985 
986 		tpe->valid = false;
987 		return -EINVAL;
988 	}
989 
990 bottom:
991 	*changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
992 	return 0;
993 }
994 
995 static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
996 {
997 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
998 	const struct rtw89_regd *regd = regulatory->regd;
999 	enum rtw89_reg_6ghz_power sel;
1000 	const struct rtw89_chan *chan;
1001 	struct rtw89_vif_link *rtwvif_link;
1002 	struct rtw89_vif *rtwvif;
1003 	unsigned int link_id;
1004 	int count = 0;
1005 	u8 index;
1006 
1007 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
1008 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
1009 			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
1010 			if (chan->band_type != RTW89_BAND_6G)
1011 				continue;
1012 
1013 			if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
1014 				continue;
1015 
1016 			sel = rtwvif_link->reg_6ghz_power;
1017 			count++;
1018 		}
1019 	}
1020 
1021 	if (count != 1)
1022 		sel = RTW89_REG_6GHZ_POWER_DFLT;
1023 
1024 	if (sel == RTW89_REG_6GHZ_POWER_STD) {
1025 		index = rtw89_regd_get_index(rtwdev, regd);
1026 		if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
1027 		    test_bit(index, regulatory->block_6ghz_sp)) {
1028 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
1029 				    "%c%c 6 GHz SP is blocked by policy\n",
1030 				    regd->alpha2[0], regd->alpha2[1]);
1031 			sel = RTW89_REG_6GHZ_POWER_DFLT;
1032 		}
1033 	}
1034 
1035 	if (regulatory->reg_6ghz_power == sel)
1036 		return false;
1037 
1038 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
1039 		    "recalc 6 GHz reg power type to %d\n", sel);
1040 
1041 	regulatory->reg_6ghz_power = sel;
1042 	return true;
1043 }
1044 
1045 static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
1046 				       struct rtw89_vif_link *rtwvif_link, bool active,
1047 				       unsigned int *changed)
1048 {
1049 	struct ieee80211_bss_conf *bss_conf;
1050 
1051 	rcu_read_lock();
1052 
1053 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1054 
1055 	if (active) {
1056 		switch (bss_conf->power_type) {
1057 		case IEEE80211_REG_VLP_AP:
1058 			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
1059 			break;
1060 		case IEEE80211_REG_LPI_AP:
1061 			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
1062 			break;
1063 		case IEEE80211_REG_SP_AP:
1064 			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
1065 			break;
1066 		default:
1067 			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1068 			break;
1069 		}
1070 	} else {
1071 		rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1072 	}
1073 
1074 	rcu_read_unlock();
1075 
1076 	*changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
1077 	return 0;
1078 }
1079 
1080 int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
1081 			  bool active)
1082 {
1083 	unsigned int changed = 0;
1084 	int ret;
1085 
1086 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
1087 
1088 	/* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
1089 	 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
1090 	 */
1091 
1092 	ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
1093 	if (ret)
1094 		return ret;
1095 
1096 	ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
1097 	if (ret)
1098 		return ret;
1099 
1100 	if (changed)
1101 		rtw89_core_set_chip_txpwr(rtwdev);
1102 
1103 	return 0;
1104 }
1105